diff options
Diffstat (limited to 'net')
479 files changed, 24624 insertions, 8140 deletions
diff --git a/net/802/garp.c b/net/802/garp.c index 9ed7c0e7dc17..941f2a324d3a 100644 --- a/net/802/garp.c +++ b/net/802/garp.c | |||
@@ -576,7 +576,7 @@ int garp_init_applicant(struct net_device *dev, struct garp_application *appl) | |||
576 | if (!app) | 576 | if (!app) |
577 | goto err2; | 577 | goto err2; |
578 | 578 | ||
579 | err = dev_mc_add(dev, appl->proto.group_address, ETH_ALEN, 0); | 579 | err = dev_mc_add(dev, appl->proto.group_address); |
580 | if (err < 0) | 580 | if (err < 0) |
581 | goto err3; | 581 | goto err3; |
582 | 582 | ||
@@ -616,7 +616,7 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl | |||
616 | garp_pdu_queue(app); | 616 | garp_pdu_queue(app); |
617 | garp_queue_xmit(app); | 617 | garp_queue_xmit(app); |
618 | 618 | ||
619 | dev_mc_delete(dev, appl->proto.group_address, ETH_ALEN, 0); | 619 | dev_mc_del(dev, appl->proto.group_address); |
620 | kfree(app); | 620 | kfree(app); |
621 | garp_release_port(dev); | 621 | garp_release_port(dev); |
622 | } | 622 | } |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 97da977c2a23..3c1c8c14e929 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -357,13 +357,13 @@ static void vlan_sync_address(struct net_device *dev, | |||
357 | * the new address */ | 357 | * the new address */ |
358 | if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && | 358 | if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && |
359 | !compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) | 359 | !compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) |
360 | dev_unicast_delete(dev, vlandev->dev_addr); | 360 | dev_uc_del(dev, vlandev->dev_addr); |
361 | 361 | ||
362 | /* vlan address was equal to the old address and is different from | 362 | /* vlan address was equal to the old address and is different from |
363 | * the new address */ | 363 | * the new address */ |
364 | if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && | 364 | if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && |
365 | compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) | 365 | compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) |
366 | dev_unicast_add(dev, vlandev->dev_addr); | 366 | dev_uc_add(dev, vlandev->dev_addr); |
367 | 367 | ||
368 | memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); | 368 | memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); |
369 | } | 369 | } |
@@ -533,6 +533,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
533 | } | 533 | } |
534 | unregister_netdevice_many(&list); | 534 | unregister_netdevice_many(&list); |
535 | break; | 535 | break; |
536 | |||
537 | case NETDEV_PRE_TYPE_CHANGE: | ||
538 | /* Forbid underlaying device to change its type. */ | ||
539 | return NOTIFY_BAD; | ||
536 | } | 540 | } |
537 | 541 | ||
538 | out: | 542 | out: |
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index c584a0af77d3..bd537fc10254 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
@@ -61,7 +61,7 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb) | |||
61 | dev->dev_addr)) | 61 | dev->dev_addr)) |
62 | skb->pkt_type = PACKET_HOST; | 62 | skb->pkt_type = PACKET_HOST; |
63 | break; | 63 | break; |
64 | }; | 64 | } |
65 | return 0; | 65 | return 0; |
66 | } | 66 | } |
67 | 67 | ||
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 29b6348c8d4d..55be90826f5f 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -327,7 +327,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, | |||
327 | len = skb->len; | 327 | len = skb->len; |
328 | ret = dev_queue_xmit(skb); | 328 | ret = dev_queue_xmit(skb); |
329 | 329 | ||
330 | if (likely(ret == NET_XMIT_SUCCESS)) { | 330 | if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { |
331 | txq->tx_packets++; | 331 | txq->tx_packets++; |
332 | txq->tx_bytes += len; | 332 | txq->tx_bytes += len; |
333 | } else | 333 | } else |
@@ -353,7 +353,7 @@ static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, | |||
353 | len = skb->len; | 353 | len = skb->len; |
354 | ret = dev_queue_xmit(skb); | 354 | ret = dev_queue_xmit(skb); |
355 | 355 | ||
356 | if (likely(ret == NET_XMIT_SUCCESS)) { | 356 | if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { |
357 | txq->tx_packets++; | 357 | txq->tx_packets++; |
358 | txq->tx_bytes += len; | 358 | txq->tx_bytes += len; |
359 | } else | 359 | } else |
@@ -470,7 +470,7 @@ static int vlan_dev_open(struct net_device *dev) | |||
470 | return -ENETDOWN; | 470 | return -ENETDOWN; |
471 | 471 | ||
472 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) { | 472 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) { |
473 | err = dev_unicast_add(real_dev, dev->dev_addr); | 473 | err = dev_uc_add(real_dev, dev->dev_addr); |
474 | if (err < 0) | 474 | if (err < 0) |
475 | goto out; | 475 | goto out; |
476 | } | 476 | } |
@@ -499,7 +499,7 @@ clear_allmulti: | |||
499 | dev_set_allmulti(real_dev, -1); | 499 | dev_set_allmulti(real_dev, -1); |
500 | del_unicast: | 500 | del_unicast: |
501 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) | 501 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) |
502 | dev_unicast_delete(real_dev, dev->dev_addr); | 502 | dev_uc_del(real_dev, dev->dev_addr); |
503 | out: | 503 | out: |
504 | netif_carrier_off(dev); | 504 | netif_carrier_off(dev); |
505 | return err; | 505 | return err; |
@@ -514,14 +514,14 @@ static int vlan_dev_stop(struct net_device *dev) | |||
514 | vlan_gvrp_request_leave(dev); | 514 | vlan_gvrp_request_leave(dev); |
515 | 515 | ||
516 | dev_mc_unsync(real_dev, dev); | 516 | dev_mc_unsync(real_dev, dev); |
517 | dev_unicast_unsync(real_dev, dev); | 517 | dev_uc_unsync(real_dev, dev); |
518 | if (dev->flags & IFF_ALLMULTI) | 518 | if (dev->flags & IFF_ALLMULTI) |
519 | dev_set_allmulti(real_dev, -1); | 519 | dev_set_allmulti(real_dev, -1); |
520 | if (dev->flags & IFF_PROMISC) | 520 | if (dev->flags & IFF_PROMISC) |
521 | dev_set_promiscuity(real_dev, -1); | 521 | dev_set_promiscuity(real_dev, -1); |
522 | 522 | ||
523 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) | 523 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) |
524 | dev_unicast_delete(real_dev, dev->dev_addr); | 524 | dev_uc_del(real_dev, dev->dev_addr); |
525 | 525 | ||
526 | netif_carrier_off(dev); | 526 | netif_carrier_off(dev); |
527 | return 0; | 527 | return 0; |
@@ -540,13 +540,13 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p) | |||
540 | goto out; | 540 | goto out; |
541 | 541 | ||
542 | if (compare_ether_addr(addr->sa_data, real_dev->dev_addr)) { | 542 | if (compare_ether_addr(addr->sa_data, real_dev->dev_addr)) { |
543 | err = dev_unicast_add(real_dev, addr->sa_data); | 543 | err = dev_uc_add(real_dev, addr->sa_data); |
544 | if (err < 0) | 544 | if (err < 0) |
545 | return err; | 545 | return err; |
546 | } | 546 | } |
547 | 547 | ||
548 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) | 548 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) |
549 | dev_unicast_delete(real_dev, dev->dev_addr); | 549 | dev_uc_del(real_dev, dev->dev_addr); |
550 | 550 | ||
551 | out: | 551 | out: |
552 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 552 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
@@ -663,7 +663,7 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) | |||
663 | static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) | 663 | static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) |
664 | { | 664 | { |
665 | dev_mc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); | 665 | dev_mc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); |
666 | dev_unicast_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); | 666 | dev_uc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); |
667 | } | 667 | } |
668 | 668 | ||
669 | /* | 669 | /* |
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 041101ab4aa5..0ea20c30466c 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c | |||
@@ -308,7 +308,6 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, | |||
308 | req, err, status); | 308 | req, err, status); |
309 | rdma->state = P9_RDMA_FLUSHING; | 309 | rdma->state = P9_RDMA_FLUSHING; |
310 | client->status = Disconnected; | 310 | client->status = Disconnected; |
311 | return; | ||
312 | } | 311 | } |
313 | 312 | ||
314 | static void | 313 | static void |
diff --git a/net/Kconfig b/net/Kconfig index 041c35edb763..0d68b40fc0e6 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -186,6 +186,7 @@ source "net/sctp/Kconfig" | |||
186 | source "net/rds/Kconfig" | 186 | source "net/rds/Kconfig" |
187 | source "net/tipc/Kconfig" | 187 | source "net/tipc/Kconfig" |
188 | source "net/atm/Kconfig" | 188 | source "net/atm/Kconfig" |
189 | source "net/l2tp/Kconfig" | ||
189 | source "net/802/Kconfig" | 190 | source "net/802/Kconfig" |
190 | source "net/bridge/Kconfig" | 191 | source "net/bridge/Kconfig" |
191 | source "net/dsa/Kconfig" | 192 | source "net/dsa/Kconfig" |
@@ -203,6 +204,11 @@ source "net/ieee802154/Kconfig" | |||
203 | source "net/sched/Kconfig" | 204 | source "net/sched/Kconfig" |
204 | source "net/dcb/Kconfig" | 205 | source "net/dcb/Kconfig" |
205 | 206 | ||
207 | config RPS | ||
208 | boolean | ||
209 | depends on SMP && SYSFS | ||
210 | default y | ||
211 | |||
206 | menu "Network testing" | 212 | menu "Network testing" |
207 | 213 | ||
208 | config NET_PKTGEN | 214 | config NET_PKTGEN |
@@ -275,5 +281,7 @@ source "net/wimax/Kconfig" | |||
275 | 281 | ||
276 | source "net/rfkill/Kconfig" | 282 | source "net/rfkill/Kconfig" |
277 | source "net/9p/Kconfig" | 283 | source "net/9p/Kconfig" |
284 | source "net/caif/Kconfig" | ||
285 | |||
278 | 286 | ||
279 | endif # if NET | 287 | endif # if NET |
diff --git a/net/Makefile b/net/Makefile index 1542e7268a7b..cb7bdc1210cb 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -40,6 +40,7 @@ obj-$(CONFIG_BT) += bluetooth/ | |||
40 | obj-$(CONFIG_SUNRPC) += sunrpc/ | 40 | obj-$(CONFIG_SUNRPC) += sunrpc/ |
41 | obj-$(CONFIG_AF_RXRPC) += rxrpc/ | 41 | obj-$(CONFIG_AF_RXRPC) += rxrpc/ |
42 | obj-$(CONFIG_ATM) += atm/ | 42 | obj-$(CONFIG_ATM) += atm/ |
43 | obj-$(CONFIG_L2TP) += l2tp/ | ||
43 | obj-$(CONFIG_DECNET) += decnet/ | 44 | obj-$(CONFIG_DECNET) += decnet/ |
44 | obj-$(CONFIG_ECONET) += econet/ | 45 | obj-$(CONFIG_ECONET) += econet/ |
45 | obj-$(CONFIG_PHONET) += phonet/ | 46 | obj-$(CONFIG_PHONET) += phonet/ |
@@ -56,6 +57,7 @@ obj-$(CONFIG_NETLABEL) += netlabel/ | |||
56 | obj-$(CONFIG_IUCV) += iucv/ | 57 | obj-$(CONFIG_IUCV) += iucv/ |
57 | obj-$(CONFIG_RFKILL) += rfkill/ | 58 | obj-$(CONFIG_RFKILL) += rfkill/ |
58 | obj-$(CONFIG_NET_9P) += 9p/ | 59 | obj-$(CONFIG_NET_9P) += 9p/ |
60 | obj-$(CONFIG_CAIF) += caif/ | ||
59 | ifneq ($(CONFIG_DCB),) | 61 | ifneq ($(CONFIG_DCB),) |
60 | obj-y += dcb/ | 62 | obj-y += dcb/ |
61 | endif | 63 | endif |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 7b02967fbbe7..c410b93fda2e 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -782,7 +782,7 @@ static int atif_ioctl(int cmd, void __user *arg) | |||
782 | atrtr_create(&rtdef, dev); | 782 | atrtr_create(&rtdef, dev); |
783 | } | 783 | } |
784 | } | 784 | } |
785 | dev_mc_add(dev, aarp_mcast, 6, 1); | 785 | dev_mc_add_global(dev, aarp_mcast); |
786 | return 0; | 786 | return 0; |
787 | 787 | ||
788 | case SIOCGIFADDR: | 788 | case SIOCGIFADDR: |
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index d6c7ceaf13e9..6719af6a59fa 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -446,7 +446,6 @@ error: | |||
446 | net_dev->stats.rx_errors++; | 446 | net_dev->stats.rx_errors++; |
447 | free_skb: | 447 | free_skb: |
448 | dev_kfree_skb(skb); | 448 | dev_kfree_skb(skb); |
449 | return; | ||
450 | } | 449 | } |
451 | 450 | ||
452 | /* | 451 | /* |
diff --git a/net/atm/common.c b/net/atm/common.c index 97ed94aa0cbc..b43feb1a3995 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -90,10 +90,13 @@ static void vcc_sock_destruct(struct sock *sk) | |||
90 | 90 | ||
91 | static void vcc_def_wakeup(struct sock *sk) | 91 | static void vcc_def_wakeup(struct sock *sk) |
92 | { | 92 | { |
93 | read_lock(&sk->sk_callback_lock); | 93 | struct socket_wq *wq; |
94 | if (sk_has_sleeper(sk)) | 94 | |
95 | wake_up(sk->sk_sleep); | 95 | rcu_read_lock(); |
96 | read_unlock(&sk->sk_callback_lock); | 96 | wq = rcu_dereference(sk->sk_wq); |
97 | if (wq_has_sleeper(wq)) | ||
98 | wake_up(&wq->wait); | ||
99 | rcu_read_unlock(); | ||
97 | } | 100 | } |
98 | 101 | ||
99 | static inline int vcc_writable(struct sock *sk) | 102 | static inline int vcc_writable(struct sock *sk) |
@@ -106,16 +109,19 @@ static inline int vcc_writable(struct sock *sk) | |||
106 | 109 | ||
107 | static void vcc_write_space(struct sock *sk) | 110 | static void vcc_write_space(struct sock *sk) |
108 | { | 111 | { |
109 | read_lock(&sk->sk_callback_lock); | 112 | struct socket_wq *wq; |
113 | |||
114 | rcu_read_lock(); | ||
110 | 115 | ||
111 | if (vcc_writable(sk)) { | 116 | if (vcc_writable(sk)) { |
112 | if (sk_has_sleeper(sk)) | 117 | wq = rcu_dereference(sk->sk_wq); |
113 | wake_up_interruptible(sk->sk_sleep); | 118 | if (wq_has_sleeper(wq)) |
119 | wake_up_interruptible(&wq->wait); | ||
114 | 120 | ||
115 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 121 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
116 | } | 122 | } |
117 | 123 | ||
118 | read_unlock(&sk->sk_callback_lock); | 124 | rcu_read_unlock(); |
119 | } | 125 | } |
120 | 126 | ||
121 | static struct proto vcc_proto = { | 127 | static struct proto vcc_proto = { |
@@ -549,7 +555,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, | |||
549 | } | 555 | } |
550 | 556 | ||
551 | eff = (size+3) & ~3; /* align to word boundary */ | 557 | eff = (size+3) & ~3; /* align to word boundary */ |
552 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 558 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
553 | error = 0; | 559 | error = 0; |
554 | while (!(skb = alloc_tx(vcc, eff))) { | 560 | while (!(skb = alloc_tx(vcc, eff))) { |
555 | if (m->msg_flags & MSG_DONTWAIT) { | 561 | if (m->msg_flags & MSG_DONTWAIT) { |
@@ -568,9 +574,9 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, | |||
568 | send_sig(SIGPIPE, current, 0); | 574 | send_sig(SIGPIPE, current, 0); |
569 | break; | 575 | break; |
570 | } | 576 | } |
571 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 577 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
572 | } | 578 | } |
573 | finish_wait(sk->sk_sleep, &wait); | 579 | finish_wait(sk_sleep(sk), &wait); |
574 | if (error) | 580 | if (error) |
575 | goto out; | 581 | goto out; |
576 | skb->dev = NULL; /* for paths shared with net_device interfaces */ | 582 | skb->dev = NULL; /* for paths shared with net_device interfaces */ |
@@ -595,7 +601,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
595 | struct atm_vcc *vcc; | 601 | struct atm_vcc *vcc; |
596 | unsigned int mask; | 602 | unsigned int mask; |
597 | 603 | ||
598 | sock_poll_wait(file, sk->sk_sleep, wait); | 604 | sock_poll_wait(file, sk_sleep(sk), wait); |
599 | mask = 0; | 605 | mask = 0; |
600 | 606 | ||
601 | vcc = ATM_SD(sock); | 607 | vcc = ATM_SD(sock); |
diff --git a/net/atm/lec.c b/net/atm/lec.c index feeaf5718472..d98bde1a0ac8 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -161,8 +161,6 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) | |||
161 | skb_queue_tail(&sk->sk_receive_queue, skb2); | 161 | skb_queue_tail(&sk->sk_receive_queue, skb2); |
162 | sk->sk_data_ready(sk, skb2->len); | 162 | sk->sk_data_ready(sk, skb2->len); |
163 | } | 163 | } |
164 | |||
165 | return; | ||
166 | } | 164 | } |
167 | #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ | 165 | #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ |
168 | 166 | ||
@@ -640,7 +638,6 @@ static void lec_set_multicast_list(struct net_device *dev) | |||
640 | * by default, all multicast frames arrive over the bus. | 638 | * by default, all multicast frames arrive over the bus. |
641 | * eventually support selective multicast service | 639 | * eventually support selective multicast service |
642 | */ | 640 | */ |
643 | return; | ||
644 | } | 641 | } |
645 | 642 | ||
646 | static const struct net_device_ops lec_netdev_ops = { | 643 | static const struct net_device_ops lec_netdev_ops = { |
@@ -1199,8 +1196,6 @@ static void __exit lane_module_cleanup(void) | |||
1199 | dev_lec[i] = NULL; | 1196 | dev_lec[i] = NULL; |
1200 | } | 1197 | } |
1201 | } | 1198 | } |
1202 | |||
1203 | return; | ||
1204 | } | 1199 | } |
1205 | 1200 | ||
1206 | module_init(lane_module_init); | 1201 | module_init(lane_module_init); |
@@ -1334,7 +1329,6 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr, | |||
1334 | priv->lane2_ops->associate_indicator(dev, mac_addr, | 1329 | priv->lane2_ops->associate_indicator(dev, mac_addr, |
1335 | tlvs, sizeoftlvs); | 1330 | tlvs, sizeoftlvs); |
1336 | } | 1331 | } |
1337 | return; | ||
1338 | } | 1332 | } |
1339 | 1333 | ||
1340 | /* | 1334 | /* |
diff --git a/net/atm/mpc.c b/net/atm/mpc.c index 436f2e177657..622b471e14e0 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c | |||
@@ -455,7 +455,6 @@ static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr, | |||
455 | if (end_of_tlvs - tlvs != 0) | 455 | if (end_of_tlvs - tlvs != 0) |
456 | pr_info("(%s) ignoring %Zd bytes of trailing TLV garbage\n", | 456 | pr_info("(%s) ignoring %Zd bytes of trailing TLV garbage\n", |
457 | dev->name, end_of_tlvs - tlvs); | 457 | dev->name, end_of_tlvs - tlvs); |
458 | return; | ||
459 | } | 458 | } |
460 | 459 | ||
461 | /* | 460 | /* |
@@ -684,8 +683,6 @@ static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev) | |||
684 | 683 | ||
685 | if (in_entry == NULL && eg_entry == NULL) | 684 | if (in_entry == NULL && eg_entry == NULL) |
686 | dprintk("(%s) unused vcc closed\n", dev->name); | 685 | dprintk("(%s) unused vcc closed\n", dev->name); |
687 | |||
688 | return; | ||
689 | } | 686 | } |
690 | 687 | ||
691 | static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) | 688 | static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) |
@@ -783,8 +780,6 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
783 | 780 | ||
784 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); | 781 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); |
785 | netif_rx(new_skb); | 782 | netif_rx(new_skb); |
786 | |||
787 | return; | ||
788 | } | 783 | } |
789 | 784 | ||
790 | static struct atmdev_ops mpc_ops = { /* only send is required */ | 785 | static struct atmdev_ops mpc_ops = { /* only send is required */ |
@@ -873,8 +868,6 @@ static void send_set_mps_ctrl_addr(const char *addr, struct mpoa_client *mpc) | |||
873 | mesg.type = SET_MPS_CTRL_ADDR; | 868 | mesg.type = SET_MPS_CTRL_ADDR; |
874 | memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN); | 869 | memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN); |
875 | msg_to_mpoad(&mesg, mpc); | 870 | msg_to_mpoad(&mesg, mpc); |
876 | |||
877 | return; | ||
878 | } | 871 | } |
879 | 872 | ||
880 | static void mpoad_close(struct atm_vcc *vcc) | 873 | static void mpoad_close(struct atm_vcc *vcc) |
@@ -911,8 +904,6 @@ static void mpoad_close(struct atm_vcc *vcc) | |||
911 | pr_info("(%s) going down\n", | 904 | pr_info("(%s) going down\n", |
912 | (mpc->dev) ? mpc->dev->name : "<unknown>"); | 905 | (mpc->dev) ? mpc->dev->name : "<unknown>"); |
913 | module_put(THIS_MODULE); | 906 | module_put(THIS_MODULE); |
914 | |||
915 | return; | ||
916 | } | 907 | } |
917 | 908 | ||
918 | /* | 909 | /* |
@@ -1122,7 +1113,6 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc) | |||
1122 | pr_info("(%s) entry already in resolving state\n", | 1113 | pr_info("(%s) entry already in resolving state\n", |
1123 | (mpc->dev) ? mpc->dev->name : "<unknown>"); | 1114 | (mpc->dev) ? mpc->dev->name : "<unknown>"); |
1124 | mpc->in_ops->put(entry); | 1115 | mpc->in_ops->put(entry); |
1125 | return; | ||
1126 | } | 1116 | } |
1127 | 1117 | ||
1128 | /* | 1118 | /* |
@@ -1166,7 +1156,6 @@ static void check_qos_and_open_shortcut(struct k_message *msg, | |||
1166 | } else | 1156 | } else |
1167 | memset(&msg->qos, 0, sizeof(struct atm_qos)); | 1157 | memset(&msg->qos, 0, sizeof(struct atm_qos)); |
1168 | msg_to_mpoad(msg, client); | 1158 | msg_to_mpoad(msg, client); |
1169 | return; | ||
1170 | } | 1159 | } |
1171 | 1160 | ||
1172 | static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) | 1161 | static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) |
@@ -1240,8 +1229,6 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) | |||
1240 | mpc->in_ops->put(entry); | 1229 | mpc->in_ops->put(entry); |
1241 | entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask); | 1230 | entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask); |
1242 | } while (entry != NULL); | 1231 | } while (entry != NULL); |
1243 | |||
1244 | return; | ||
1245 | } | 1232 | } |
1246 | 1233 | ||
1247 | static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) | 1234 | static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) |
@@ -1260,8 +1247,6 @@ static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) | |||
1260 | write_unlock_irq(&mpc->egress_lock); | 1247 | write_unlock_irq(&mpc->egress_lock); |
1261 | 1248 | ||
1262 | mpc->eg_ops->put(entry); | 1249 | mpc->eg_ops->put(entry); |
1263 | |||
1264 | return; | ||
1265 | } | 1250 | } |
1266 | 1251 | ||
1267 | static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) | 1252 | static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) |
@@ -1295,8 +1280,6 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) | |||
1295 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1280 | skb_queue_tail(&sk->sk_receive_queue, skb); |
1296 | sk->sk_data_ready(sk, skb->len); | 1281 | sk->sk_data_ready(sk, skb->len); |
1297 | dprintk("exiting\n"); | 1282 | dprintk("exiting\n"); |
1298 | |||
1299 | return; | ||
1300 | } | 1283 | } |
1301 | 1284 | ||
1302 | /* | 1285 | /* |
@@ -1325,8 +1308,6 @@ static void mps_death(struct k_message *msg, struct mpoa_client *mpc) | |||
1325 | 1308 | ||
1326 | mpc->in_ops->destroy_cache(mpc); | 1309 | mpc->in_ops->destroy_cache(mpc); |
1327 | mpc->eg_ops->destroy_cache(mpc); | 1310 | mpc->eg_ops->destroy_cache(mpc); |
1328 | |||
1329 | return; | ||
1330 | } | 1311 | } |
1331 | 1312 | ||
1332 | static void MPOA_cache_impos_rcvd(struct k_message *msg, | 1313 | static void MPOA_cache_impos_rcvd(struct k_message *msg, |
@@ -1353,8 +1334,6 @@ static void MPOA_cache_impos_rcvd(struct k_message *msg, | |||
1353 | write_unlock_irq(&mpc->egress_lock); | 1334 | write_unlock_irq(&mpc->egress_lock); |
1354 | 1335 | ||
1355 | mpc->eg_ops->put(entry); | 1336 | mpc->eg_ops->put(entry); |
1356 | |||
1357 | return; | ||
1358 | } | 1337 | } |
1359 | 1338 | ||
1360 | static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, | 1339 | static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, |
@@ -1392,8 +1371,6 @@ static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, | |||
1392 | pr_info("(%s) targetless LE_ARP request failed\n", | 1371 | pr_info("(%s) targetless LE_ARP request failed\n", |
1393 | mpc->dev->name); | 1372 | mpc->dev->name); |
1394 | } | 1373 | } |
1395 | |||
1396 | return; | ||
1397 | } | 1374 | } |
1398 | 1375 | ||
1399 | static void set_mps_mac_addr_rcvd(struct k_message *msg, | 1376 | static void set_mps_mac_addr_rcvd(struct k_message *msg, |
@@ -1409,8 +1386,6 @@ static void set_mps_mac_addr_rcvd(struct k_message *msg, | |||
1409 | return; | 1386 | return; |
1410 | } | 1387 | } |
1411 | client->number_of_mps_macs = 1; | 1388 | client->number_of_mps_macs = 1; |
1412 | |||
1413 | return; | ||
1414 | } | 1389 | } |
1415 | 1390 | ||
1416 | /* | 1391 | /* |
@@ -1436,7 +1411,6 @@ static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action) | |||
1436 | 1411 | ||
1437 | msg->type = action; | 1412 | msg->type = action; |
1438 | msg_to_mpoad(msg, mpc); | 1413 | msg_to_mpoad(msg, mpc); |
1439 | return; | ||
1440 | } | 1414 | } |
1441 | 1415 | ||
1442 | static void mpc_timer_refresh(void) | 1416 | static void mpc_timer_refresh(void) |
@@ -1445,8 +1419,6 @@ static void mpc_timer_refresh(void) | |||
1445 | mpc_timer.data = mpc_timer.expires; | 1419 | mpc_timer.data = mpc_timer.expires; |
1446 | mpc_timer.function = mpc_cache_check; | 1420 | mpc_timer.function = mpc_cache_check; |
1447 | add_timer(&mpc_timer); | 1421 | add_timer(&mpc_timer); |
1448 | |||
1449 | return; | ||
1450 | } | 1422 | } |
1451 | 1423 | ||
1452 | static void mpc_cache_check(unsigned long checking_time) | 1424 | static void mpc_cache_check(unsigned long checking_time) |
@@ -1471,8 +1443,6 @@ static void mpc_cache_check(unsigned long checking_time) | |||
1471 | mpc = mpc->next; | 1443 | mpc = mpc->next; |
1472 | } | 1444 | } |
1473 | mpc_timer_refresh(); | 1445 | mpc_timer_refresh(); |
1474 | |||
1475 | return; | ||
1476 | } | 1446 | } |
1477 | 1447 | ||
1478 | static int atm_mpoa_ioctl(struct socket *sock, unsigned int cmd, | 1448 | static int atm_mpoa_ioctl(struct socket *sock, unsigned int cmd, |
@@ -1561,8 +1531,6 @@ static void __exit atm_mpoa_cleanup(void) | |||
1561 | kfree(qos); | 1531 | kfree(qos); |
1562 | qos = nextqos; | 1532 | qos = nextqos; |
1563 | } | 1533 | } |
1564 | |||
1565 | return; | ||
1566 | } | 1534 | } |
1567 | 1535 | ||
1568 | module_init(atm_mpoa_init); | 1536 | module_init(atm_mpoa_init); |
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c index e773d8336918..d1b2d9a03144 100644 --- a/net/atm/mpoa_caches.c +++ b/net/atm/mpoa_caches.c | |||
@@ -182,8 +182,6 @@ static void in_cache_put(in_cache_entry *entry) | |||
182 | memset(entry, 0, sizeof(in_cache_entry)); | 182 | memset(entry, 0, sizeof(in_cache_entry)); |
183 | kfree(entry); | 183 | kfree(entry); |
184 | } | 184 | } |
185 | |||
186 | return; | ||
187 | } | 185 | } |
188 | 186 | ||
189 | /* | 187 | /* |
@@ -221,8 +219,6 @@ static void in_cache_remove_entry(in_cache_entry *entry, | |||
221 | } | 219 | } |
222 | vcc_release_async(vcc, -EPIPE); | 220 | vcc_release_async(vcc, -EPIPE); |
223 | } | 221 | } |
224 | |||
225 | return; | ||
226 | } | 222 | } |
227 | 223 | ||
228 | /* Call this every MPC-p2 seconds... Not exactly correct solution, | 224 | /* Call this every MPC-p2 seconds... Not exactly correct solution, |
@@ -248,8 +244,6 @@ static void clear_count_and_expired(struct mpoa_client *client) | |||
248 | entry = next_entry; | 244 | entry = next_entry; |
249 | } | 245 | } |
250 | write_unlock_bh(&client->ingress_lock); | 246 | write_unlock_bh(&client->ingress_lock); |
251 | |||
252 | return; | ||
253 | } | 247 | } |
254 | 248 | ||
255 | /* Call this every MPC-p4 seconds. */ | 249 | /* Call this every MPC-p4 seconds. */ |
@@ -334,8 +328,6 @@ static void in_destroy_cache(struct mpoa_client *mpc) | |||
334 | while (mpc->in_cache != NULL) | 328 | while (mpc->in_cache != NULL) |
335 | mpc->in_ops->remove_entry(mpc->in_cache, mpc); | 329 | mpc->in_ops->remove_entry(mpc->in_cache, mpc); |
336 | write_unlock_irq(&mpc->ingress_lock); | 330 | write_unlock_irq(&mpc->ingress_lock); |
337 | |||
338 | return; | ||
339 | } | 331 | } |
340 | 332 | ||
341 | static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id, | 333 | static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id, |
@@ -427,8 +419,6 @@ static void eg_cache_put(eg_cache_entry *entry) | |||
427 | memset(entry, 0, sizeof(eg_cache_entry)); | 419 | memset(entry, 0, sizeof(eg_cache_entry)); |
428 | kfree(entry); | 420 | kfree(entry); |
429 | } | 421 | } |
430 | |||
431 | return; | ||
432 | } | 422 | } |
433 | 423 | ||
434 | /* | 424 | /* |
@@ -463,8 +453,6 @@ static void eg_cache_remove_entry(eg_cache_entry *entry, | |||
463 | } | 453 | } |
464 | vcc_release_async(vcc, -EPIPE); | 454 | vcc_release_async(vcc, -EPIPE); |
465 | } | 455 | } |
466 | |||
467 | return; | ||
468 | } | 456 | } |
469 | 457 | ||
470 | static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, | 458 | static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, |
@@ -509,8 +497,6 @@ static void update_eg_cache_entry(eg_cache_entry *entry, uint16_t holding_time) | |||
509 | do_gettimeofday(&(entry->tv)); | 497 | do_gettimeofday(&(entry->tv)); |
510 | entry->entry_state = EGRESS_RESOLVED; | 498 | entry->entry_state = EGRESS_RESOLVED; |
511 | entry->ctrl_info.holding_time = holding_time; | 499 | entry->ctrl_info.holding_time = holding_time; |
512 | |||
513 | return; | ||
514 | } | 500 | } |
515 | 501 | ||
516 | static void clear_expired(struct mpoa_client *client) | 502 | static void clear_expired(struct mpoa_client *client) |
@@ -537,8 +523,6 @@ static void clear_expired(struct mpoa_client *client) | |||
537 | entry = next_entry; | 523 | entry = next_entry; |
538 | } | 524 | } |
539 | write_unlock_irq(&client->egress_lock); | 525 | write_unlock_irq(&client->egress_lock); |
540 | |||
541 | return; | ||
542 | } | 526 | } |
543 | 527 | ||
544 | static void eg_destroy_cache(struct mpoa_client *mpc) | 528 | static void eg_destroy_cache(struct mpoa_client *mpc) |
@@ -547,8 +531,6 @@ static void eg_destroy_cache(struct mpoa_client *mpc) | |||
547 | while (mpc->eg_cache != NULL) | 531 | while (mpc->eg_cache != NULL) |
548 | mpc->eg_ops->remove_entry(mpc->eg_cache, mpc); | 532 | mpc->eg_ops->remove_entry(mpc->eg_cache, mpc); |
549 | write_unlock_irq(&mpc->egress_lock); | 533 | write_unlock_irq(&mpc->egress_lock); |
550 | |||
551 | return; | ||
552 | } | 534 | } |
553 | 535 | ||
554 | 536 | ||
@@ -584,6 +566,4 @@ void atm_mpoa_init_cache(struct mpoa_client *mpc) | |||
584 | { | 566 | { |
585 | mpc->in_ops = &ingress_ops; | 567 | mpc->in_ops = &ingress_ops; |
586 | mpc->eg_ops = &egress_ops; | 568 | mpc->eg_ops = &egress_ops; |
587 | |||
588 | return; | ||
589 | } | 569 | } |
diff --git a/net/atm/proc.c b/net/atm/proc.c index 696e218436e5..6262aeae398e 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c | |||
@@ -407,7 +407,6 @@ EXPORT_SYMBOL(atm_proc_root); | |||
407 | 407 | ||
408 | int atm_proc_dev_register(struct atm_dev *dev) | 408 | int atm_proc_dev_register(struct atm_dev *dev) |
409 | { | 409 | { |
410 | int digits, num; | ||
411 | int error; | 410 | int error; |
412 | 411 | ||
413 | /* No proc info */ | 412 | /* No proc info */ |
@@ -415,16 +414,9 @@ int atm_proc_dev_register(struct atm_dev *dev) | |||
415 | return 0; | 414 | return 0; |
416 | 415 | ||
417 | error = -ENOMEM; | 416 | error = -ENOMEM; |
418 | digits = 0; | 417 | dev->proc_name = kasprintf(GFP_KERNEL, "%s:%d", dev->type, dev->number); |
419 | for (num = dev->number; num; num /= 10) | ||
420 | digits++; | ||
421 | if (!digits) | ||
422 | digits++; | ||
423 | |||
424 | dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_KERNEL); | ||
425 | if (!dev->proc_name) | 418 | if (!dev->proc_name) |
426 | goto err_out; | 419 | goto err_out; |
427 | sprintf(dev->proc_name, "%s:%d", dev->type, dev->number); | ||
428 | 420 | ||
429 | dev->proc_entry = proc_create_data(dev->proc_name, 0, atm_proc_root, | 421 | dev->proc_entry = proc_create_data(dev->proc_name, 0, atm_proc_root, |
430 | &proc_atm_dev_ops, dev); | 422 | &proc_atm_dev_ops, dev); |
diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 6ba6e466ee54..509c8ac02b63 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c | |||
@@ -131,7 +131,7 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb) | |||
131 | } | 131 | } |
132 | sk->sk_ack_backlog++; | 132 | sk->sk_ack_backlog++; |
133 | skb_queue_tail(&sk->sk_receive_queue, skb); | 133 | skb_queue_tail(&sk->sk_receive_queue, skb); |
134 | pr_debug("waking sk->sk_sleep 0x%p\n", sk->sk_sleep); | 134 | pr_debug("waking sk_sleep(sk) 0x%p\n", sk_sleep(sk)); |
135 | sk->sk_state_change(sk); | 135 | sk->sk_state_change(sk); |
136 | as_indicate_complete: | 136 | as_indicate_complete: |
137 | release_sock(sk); | 137 | release_sock(sk); |
diff --git a/net/atm/svc.c b/net/atm/svc.c index 3ba9a45a51ac..754ee4791d96 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c | |||
@@ -49,14 +49,14 @@ static void svc_disconnect(struct atm_vcc *vcc) | |||
49 | 49 | ||
50 | pr_debug("%p\n", vcc); | 50 | pr_debug("%p\n", vcc); |
51 | if (test_bit(ATM_VF_REGIS, &vcc->flags)) { | 51 | if (test_bit(ATM_VF_REGIS, &vcc->flags)) { |
52 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 52 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
53 | sigd_enq(vcc, as_close, NULL, NULL, NULL); | 53 | sigd_enq(vcc, as_close, NULL, NULL, NULL); |
54 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { | 54 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { |
55 | schedule(); | 55 | schedule(); |
56 | prepare_to_wait(sk->sk_sleep, &wait, | 56 | prepare_to_wait(sk_sleep(sk), &wait, |
57 | TASK_UNINTERRUPTIBLE); | 57 | TASK_UNINTERRUPTIBLE); |
58 | } | 58 | } |
59 | finish_wait(sk->sk_sleep, &wait); | 59 | finish_wait(sk_sleep(sk), &wait); |
60 | } | 60 | } |
61 | /* beware - socket is still in use by atmsigd until the last | 61 | /* beware - socket is still in use by atmsigd until the last |
62 | as_indicate has been answered */ | 62 | as_indicate has been answered */ |
@@ -125,13 +125,13 @@ static int svc_bind(struct socket *sock, struct sockaddr *sockaddr, | |||
125 | } | 125 | } |
126 | vcc->local = *addr; | 126 | vcc->local = *addr; |
127 | set_bit(ATM_VF_WAITING, &vcc->flags); | 127 | set_bit(ATM_VF_WAITING, &vcc->flags); |
128 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 128 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
129 | sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); | 129 | sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); |
130 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 130 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
131 | schedule(); | 131 | schedule(); |
132 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 132 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
133 | } | 133 | } |
134 | finish_wait(sk->sk_sleep, &wait); | 134 | finish_wait(sk_sleep(sk), &wait); |
135 | clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ | 135 | clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ |
136 | if (!sigd) { | 136 | if (!sigd) { |
137 | error = -EUNATCH; | 137 | error = -EUNATCH; |
@@ -201,10 +201,10 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
201 | } | 201 | } |
202 | vcc->remote = *addr; | 202 | vcc->remote = *addr; |
203 | set_bit(ATM_VF_WAITING, &vcc->flags); | 203 | set_bit(ATM_VF_WAITING, &vcc->flags); |
204 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 204 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
205 | sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); | 205 | sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); |
206 | if (flags & O_NONBLOCK) { | 206 | if (flags & O_NONBLOCK) { |
207 | finish_wait(sk->sk_sleep, &wait); | 207 | finish_wait(sk_sleep(sk), &wait); |
208 | sock->state = SS_CONNECTING; | 208 | sock->state = SS_CONNECTING; |
209 | error = -EINPROGRESS; | 209 | error = -EINPROGRESS; |
210 | goto out; | 210 | goto out; |
@@ -213,7 +213,7 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
213 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 213 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
214 | schedule(); | 214 | schedule(); |
215 | if (!signal_pending(current)) { | 215 | if (!signal_pending(current)) { |
216 | prepare_to_wait(sk->sk_sleep, &wait, | 216 | prepare_to_wait(sk_sleep(sk), &wait, |
217 | TASK_INTERRUPTIBLE); | 217 | TASK_INTERRUPTIBLE); |
218 | continue; | 218 | continue; |
219 | } | 219 | } |
@@ -232,14 +232,14 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
232 | */ | 232 | */ |
233 | sigd_enq(vcc, as_close, NULL, NULL, NULL); | 233 | sigd_enq(vcc, as_close, NULL, NULL, NULL); |
234 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 234 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
235 | prepare_to_wait(sk->sk_sleep, &wait, | 235 | prepare_to_wait(sk_sleep(sk), &wait, |
236 | TASK_INTERRUPTIBLE); | 236 | TASK_INTERRUPTIBLE); |
237 | schedule(); | 237 | schedule(); |
238 | } | 238 | } |
239 | if (!sk->sk_err) | 239 | if (!sk->sk_err) |
240 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && | 240 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && |
241 | sigd) { | 241 | sigd) { |
242 | prepare_to_wait(sk->sk_sleep, &wait, | 242 | prepare_to_wait(sk_sleep(sk), &wait, |
243 | TASK_INTERRUPTIBLE); | 243 | TASK_INTERRUPTIBLE); |
244 | schedule(); | 244 | schedule(); |
245 | } | 245 | } |
@@ -250,7 +250,7 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
250 | error = -EINTR; | 250 | error = -EINTR; |
251 | break; | 251 | break; |
252 | } | 252 | } |
253 | finish_wait(sk->sk_sleep, &wait); | 253 | finish_wait(sk_sleep(sk), &wait); |
254 | if (error) | 254 | if (error) |
255 | goto out; | 255 | goto out; |
256 | if (!sigd) { | 256 | if (!sigd) { |
@@ -302,13 +302,13 @@ static int svc_listen(struct socket *sock, int backlog) | |||
302 | goto out; | 302 | goto out; |
303 | } | 303 | } |
304 | set_bit(ATM_VF_WAITING, &vcc->flags); | 304 | set_bit(ATM_VF_WAITING, &vcc->flags); |
305 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 305 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
306 | sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); | 306 | sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); |
307 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 307 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
308 | schedule(); | 308 | schedule(); |
309 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 309 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
310 | } | 310 | } |
311 | finish_wait(sk->sk_sleep, &wait); | 311 | finish_wait(sk_sleep(sk), &wait); |
312 | if (!sigd) { | 312 | if (!sigd) { |
313 | error = -EUNATCH; | 313 | error = -EUNATCH; |
314 | goto out; | 314 | goto out; |
@@ -343,7 +343,7 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags) | |||
343 | while (1) { | 343 | while (1) { |
344 | DEFINE_WAIT(wait); | 344 | DEFINE_WAIT(wait); |
345 | 345 | ||
346 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 346 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
347 | while (!(skb = skb_dequeue(&sk->sk_receive_queue)) && | 347 | while (!(skb = skb_dequeue(&sk->sk_receive_queue)) && |
348 | sigd) { | 348 | sigd) { |
349 | if (test_bit(ATM_VF_RELEASED, &old_vcc->flags)) | 349 | if (test_bit(ATM_VF_RELEASED, &old_vcc->flags)) |
@@ -363,10 +363,10 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags) | |||
363 | error = -ERESTARTSYS; | 363 | error = -ERESTARTSYS; |
364 | break; | 364 | break; |
365 | } | 365 | } |
366 | prepare_to_wait(sk->sk_sleep, &wait, | 366 | prepare_to_wait(sk_sleep(sk), &wait, |
367 | TASK_INTERRUPTIBLE); | 367 | TASK_INTERRUPTIBLE); |
368 | } | 368 | } |
369 | finish_wait(sk->sk_sleep, &wait); | 369 | finish_wait(sk_sleep(sk), &wait); |
370 | if (error) | 370 | if (error) |
371 | goto out; | 371 | goto out; |
372 | if (!skb) { | 372 | if (!skb) { |
@@ -392,17 +392,17 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags) | |||
392 | } | 392 | } |
393 | /* wait should be short, so we ignore the non-blocking flag */ | 393 | /* wait should be short, so we ignore the non-blocking flag */ |
394 | set_bit(ATM_VF_WAITING, &new_vcc->flags); | 394 | set_bit(ATM_VF_WAITING, &new_vcc->flags); |
395 | prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, | 395 | prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, |
396 | TASK_UNINTERRUPTIBLE); | 396 | TASK_UNINTERRUPTIBLE); |
397 | sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); | 397 | sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); |
398 | while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) { | 398 | while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) { |
399 | release_sock(sk); | 399 | release_sock(sk); |
400 | schedule(); | 400 | schedule(); |
401 | lock_sock(sk); | 401 | lock_sock(sk); |
402 | prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, | 402 | prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, |
403 | TASK_UNINTERRUPTIBLE); | 403 | TASK_UNINTERRUPTIBLE); |
404 | } | 404 | } |
405 | finish_wait(sk_atm(new_vcc)->sk_sleep, &wait); | 405 | finish_wait(sk_sleep(sk_atm(new_vcc)), &wait); |
406 | if (!sigd) { | 406 | if (!sigd) { |
407 | error = -EUNATCH; | 407 | error = -EUNATCH; |
408 | goto out; | 408 | goto out; |
@@ -438,14 +438,14 @@ int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) | |||
438 | DEFINE_WAIT(wait); | 438 | DEFINE_WAIT(wait); |
439 | 439 | ||
440 | set_bit(ATM_VF_WAITING, &vcc->flags); | 440 | set_bit(ATM_VF_WAITING, &vcc->flags); |
441 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 441 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
442 | sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); | 442 | sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); |
443 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && | 443 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && |
444 | !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { | 444 | !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { |
445 | schedule(); | 445 | schedule(); |
446 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 446 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
447 | } | 447 | } |
448 | finish_wait(sk->sk_sleep, &wait); | 448 | finish_wait(sk_sleep(sk), &wait); |
449 | if (!sigd) | 449 | if (!sigd) |
450 | return -EUNATCH; | 450 | return -EUNATCH; |
451 | return -sk->sk_err; | 451 | return -sk->sk_err; |
@@ -534,20 +534,20 @@ static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, | |||
534 | 534 | ||
535 | lock_sock(sk); | 535 | lock_sock(sk); |
536 | set_bit(ATM_VF_WAITING, &vcc->flags); | 536 | set_bit(ATM_VF_WAITING, &vcc->flags); |
537 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 537 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
538 | sigd_enq(vcc, as_addparty, NULL, NULL, | 538 | sigd_enq(vcc, as_addparty, NULL, NULL, |
539 | (struct sockaddr_atmsvc *) sockaddr); | 539 | (struct sockaddr_atmsvc *) sockaddr); |
540 | if (flags & O_NONBLOCK) { | 540 | if (flags & O_NONBLOCK) { |
541 | finish_wait(sk->sk_sleep, &wait); | 541 | finish_wait(sk_sleep(sk), &wait); |
542 | error = -EINPROGRESS; | 542 | error = -EINPROGRESS; |
543 | goto out; | 543 | goto out; |
544 | } | 544 | } |
545 | pr_debug("added wait queue\n"); | 545 | pr_debug("added wait queue\n"); |
546 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 546 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
547 | schedule(); | 547 | schedule(); |
548 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 548 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
549 | } | 549 | } |
550 | finish_wait(sk->sk_sleep, &wait); | 550 | finish_wait(sk_sleep(sk), &wait); |
551 | error = xchg(&sk->sk_err_soft, 0); | 551 | error = xchg(&sk->sk_err_soft, 0); |
552 | out: | 552 | out: |
553 | release_sock(sk); | 553 | release_sock(sk); |
@@ -563,13 +563,13 @@ static int svc_dropparty(struct socket *sock, int ep_ref) | |||
563 | 563 | ||
564 | lock_sock(sk); | 564 | lock_sock(sk); |
565 | set_bit(ATM_VF_WAITING, &vcc->flags); | 565 | set_bit(ATM_VF_WAITING, &vcc->flags); |
566 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 566 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
567 | sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref); | 567 | sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref); |
568 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 568 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
569 | schedule(); | 569 | schedule(); |
570 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 570 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
571 | } | 571 | } |
572 | finish_wait(sk->sk_sleep, &wait); | 572 | finish_wait(sk_sleep(sk), &wait); |
573 | if (!sigd) { | 573 | if (!sigd) { |
574 | error = -EUNATCH; | 574 | error = -EUNATCH; |
575 | goto out; | 575 | goto out; |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 65c5801261f9..cfdfd7e2a172 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -1281,7 +1281,7 @@ static int __must_check ax25_connect(struct socket *sock, | |||
1281 | DEFINE_WAIT(wait); | 1281 | DEFINE_WAIT(wait); |
1282 | 1282 | ||
1283 | for (;;) { | 1283 | for (;;) { |
1284 | prepare_to_wait(sk->sk_sleep, &wait, | 1284 | prepare_to_wait(sk_sleep(sk), &wait, |
1285 | TASK_INTERRUPTIBLE); | 1285 | TASK_INTERRUPTIBLE); |
1286 | if (sk->sk_state != TCP_SYN_SENT) | 1286 | if (sk->sk_state != TCP_SYN_SENT) |
1287 | break; | 1287 | break; |
@@ -1294,7 +1294,7 @@ static int __must_check ax25_connect(struct socket *sock, | |||
1294 | err = -ERESTARTSYS; | 1294 | err = -ERESTARTSYS; |
1295 | break; | 1295 | break; |
1296 | } | 1296 | } |
1297 | finish_wait(sk->sk_sleep, &wait); | 1297 | finish_wait(sk_sleep(sk), &wait); |
1298 | 1298 | ||
1299 | if (err) | 1299 | if (err) |
1300 | goto out_release; | 1300 | goto out_release; |
@@ -1346,7 +1346,7 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
1346 | * hooked into the SABM we saved | 1346 | * hooked into the SABM we saved |
1347 | */ | 1347 | */ |
1348 | for (;;) { | 1348 | for (;;) { |
1349 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1349 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1350 | skb = skb_dequeue(&sk->sk_receive_queue); | 1350 | skb = skb_dequeue(&sk->sk_receive_queue); |
1351 | if (skb) | 1351 | if (skb) |
1352 | break; | 1352 | break; |
@@ -1364,7 +1364,7 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
1364 | err = -ERESTARTSYS; | 1364 | err = -ERESTARTSYS; |
1365 | break; | 1365 | break; |
1366 | } | 1366 | } |
1367 | finish_wait(sk->sk_sleep, &wait); | 1367 | finish_wait(sk_sleep(sk), &wait); |
1368 | 1368 | ||
1369 | if (err) | 1369 | if (err) |
1370 | goto out; | 1370 | goto out; |
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index ed371684c133..ee3b3049d385 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
@@ -43,6 +43,19 @@ config BT_L2CAP | |||
43 | Say Y here to compile L2CAP support into the kernel or say M to | 43 | Say Y here to compile L2CAP support into the kernel or say M to |
44 | compile it as module (l2cap). | 44 | compile it as module (l2cap). |
45 | 45 | ||
46 | config BT_L2CAP_EXT_FEATURES | ||
47 | bool "L2CAP Extended Features support (EXPERIMENTAL)" | ||
48 | depends on BT_L2CAP && EXPERIMENTAL | ||
49 | help | ||
50 | This option enables the L2CAP Extended Features support. These | ||
51 | new features include the Enhanced Retransmission and Streaming | ||
52 | Modes, the Frame Check Sequence (FCS), and Segmentation and | ||
53 | Reassembly (SAR) for L2CAP packets. They are a required for the | ||
54 | new Alternate MAC/PHY and the Bluetooth Medical Profile. | ||
55 | |||
56 | You should say N unless you know what you are doing. Note that | ||
57 | this is in an experimental state yet. | ||
58 | |||
46 | config BT_SCO | 59 | config BT_SCO |
47 | tristate "SCO links support" | 60 | tristate "SCO links support" |
48 | depends on BT | 61 | depends on BT |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 404a8500fd03..421c45bd1b95 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -288,7 +288,7 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w | |||
288 | 288 | ||
289 | BT_DBG("sock %p, sk %p", sock, sk); | 289 | BT_DBG("sock %p, sk %p", sock, sk); |
290 | 290 | ||
291 | poll_wait(file, sk->sk_sleep, wait); | 291 | poll_wait(file, sk_sleep(sk), wait); |
292 | 292 | ||
293 | if (sk->sk_state == BT_LISTEN) | 293 | if (sk->sk_state == BT_LISTEN) |
294 | return bt_accept_poll(sk); | 294 | return bt_accept_poll(sk); |
@@ -378,7 +378,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) | |||
378 | 378 | ||
379 | BT_DBG("sk %p", sk); | 379 | BT_DBG("sk %p", sk); |
380 | 380 | ||
381 | add_wait_queue(sk->sk_sleep, &wait); | 381 | add_wait_queue(sk_sleep(sk), &wait); |
382 | while (sk->sk_state != state) { | 382 | while (sk->sk_state != state) { |
383 | set_current_state(TASK_INTERRUPTIBLE); | 383 | set_current_state(TASK_INTERRUPTIBLE); |
384 | 384 | ||
@@ -401,7 +401,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) | |||
401 | break; | 401 | break; |
402 | } | 402 | } |
403 | set_current_state(TASK_RUNNING); | 403 | set_current_state(TASK_RUNNING); |
404 | remove_wait_queue(sk->sk_sleep, &wait); | 404 | remove_wait_queue(sk_sleep(sk), &wait); |
405 | return err; | 405 | return err; |
406 | } | 406 | } |
407 | EXPORT_SYMBOL(bt_sock_wait_state); | 407 | EXPORT_SYMBOL(bt_sock_wait_state); |
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 8062dad6d10d..f10b41fb05a0 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -474,7 +474,7 @@ static int bnep_session(void *arg) | |||
474 | set_user_nice(current, -15); | 474 | set_user_nice(current, -15); |
475 | 475 | ||
476 | init_waitqueue_entry(&wait, current); | 476 | init_waitqueue_entry(&wait, current); |
477 | add_wait_queue(sk->sk_sleep, &wait); | 477 | add_wait_queue(sk_sleep(sk), &wait); |
478 | while (!atomic_read(&s->killed)) { | 478 | while (!atomic_read(&s->killed)) { |
479 | set_current_state(TASK_INTERRUPTIBLE); | 479 | set_current_state(TASK_INTERRUPTIBLE); |
480 | 480 | ||
@@ -496,7 +496,7 @@ static int bnep_session(void *arg) | |||
496 | schedule(); | 496 | schedule(); |
497 | } | 497 | } |
498 | set_current_state(TASK_RUNNING); | 498 | set_current_state(TASK_RUNNING); |
499 | remove_wait_queue(sk->sk_sleep, &wait); | 499 | remove_wait_queue(sk_sleep(sk), &wait); |
500 | 500 | ||
501 | /* Cleanup session */ | 501 | /* Cleanup session */ |
502 | down_write(&bnep_session_sem); | 502 | down_write(&bnep_session_sem); |
@@ -507,7 +507,7 @@ static int bnep_session(void *arg) | |||
507 | /* Wakeup user-space polling for socket errors */ | 507 | /* Wakeup user-space polling for socket errors */ |
508 | s->sock->sk->sk_err = EUNATCH; | 508 | s->sock->sk->sk_err = EUNATCH; |
509 | 509 | ||
510 | wake_up_interruptible(s->sock->sk->sk_sleep); | 510 | wake_up_interruptible(sk_sleep(s->sock->sk)); |
511 | 511 | ||
512 | /* Release the socket */ | 512 | /* Release the socket */ |
513 | fput(s->sock->file); | 513 | fput(s->sock->file); |
@@ -638,7 +638,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) | |||
638 | 638 | ||
639 | /* Kill session thread */ | 639 | /* Kill session thread */ |
640 | atomic_inc(&s->killed); | 640 | atomic_inc(&s->killed); |
641 | wake_up_interruptible(s->sock->sk->sk_sleep); | 641 | wake_up_interruptible(sk_sleep(s->sock->sk)); |
642 | } else | 642 | } else |
643 | err = -ENOENT; | 643 | err = -ENOENT; |
644 | 644 | ||
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 5643a2391e76..0faad5ce6dc4 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c | |||
@@ -88,7 +88,7 @@ static void bnep_net_set_mc_list(struct net_device *dev) | |||
88 | memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); | 88 | memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); |
89 | r->len = htons(ETH_ALEN * 2); | 89 | r->len = htons(ETH_ALEN * 2); |
90 | } else { | 90 | } else { |
91 | struct dev_mc_list *dmi = dev->mc_list; | 91 | struct netdev_hw_addr *ha; |
92 | int i, len = skb->len; | 92 | int i, len = skb->len; |
93 | 93 | ||
94 | if (dev->flags & IFF_BROADCAST) { | 94 | if (dev->flags & IFF_BROADCAST) { |
@@ -98,18 +98,18 @@ static void bnep_net_set_mc_list(struct net_device *dev) | |||
98 | 98 | ||
99 | /* FIXME: We should group addresses here. */ | 99 | /* FIXME: We should group addresses here. */ |
100 | 100 | ||
101 | for (i = 0; | 101 | i = 0; |
102 | i < netdev_mc_count(dev) && i < BNEP_MAX_MULTICAST_FILTERS; | 102 | netdev_for_each_mc_addr(ha, dev) { |
103 | i++) { | 103 | if (i == BNEP_MAX_MULTICAST_FILTERS) |
104 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); | 104 | break; |
105 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); | 105 | memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); |
106 | dmi = dmi->next; | 106 | memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); |
107 | } | 107 | } |
108 | r->len = htons(skb->len - len); | 108 | r->len = htons(skb->len - len); |
109 | } | 109 | } |
110 | 110 | ||
111 | skb_queue_tail(&sk->sk_write_queue, skb); | 111 | skb_queue_tail(&sk->sk_write_queue, skb); |
112 | wake_up_interruptible(sk->sk_sleep); | 112 | wake_up_interruptible(sk_sleep(sk)); |
113 | #endif | 113 | #endif |
114 | } | 114 | } |
115 | 115 | ||
@@ -193,11 +193,11 @@ static netdev_tx_t bnep_net_xmit(struct sk_buff *skb, | |||
193 | /* | 193 | /* |
194 | * We cannot send L2CAP packets from here as we are potentially in a bh. | 194 | * We cannot send L2CAP packets from here as we are potentially in a bh. |
195 | * So we have to queue them and wake up session thread which is sleeping | 195 | * So we have to queue them and wake up session thread which is sleeping |
196 | * on the sk->sk_sleep. | 196 | * on the sk_sleep(sk). |
197 | */ | 197 | */ |
198 | dev->trans_start = jiffies; | 198 | dev->trans_start = jiffies; |
199 | skb_queue_tail(&sk->sk_write_queue, skb); | 199 | skb_queue_tail(&sk->sk_write_queue, skb); |
200 | wake_up_interruptible(sk->sk_sleep); | 200 | wake_up_interruptible(sk_sleep(sk)); |
201 | 201 | ||
202 | if (skb_queue_len(&sk->sk_write_queue) >= BNEP_TX_QUEUE_LEN) { | 202 | if (skb_queue_len(&sk->sk_write_queue) >= BNEP_TX_QUEUE_LEN) { |
203 | BT_DBG("tx queue is full"); | 203 | BT_DBG("tx queue is full"); |
diff --git a/net/bluetooth/cmtp/cmtp.h b/net/bluetooth/cmtp/cmtp.h index e4663aa14d26..785e79e953c5 100644 --- a/net/bluetooth/cmtp/cmtp.h +++ b/net/bluetooth/cmtp/cmtp.h | |||
@@ -125,7 +125,7 @@ static inline void cmtp_schedule(struct cmtp_session *session) | |||
125 | { | 125 | { |
126 | struct sock *sk = session->sock->sk; | 126 | struct sock *sk = session->sock->sk; |
127 | 127 | ||
128 | wake_up_interruptible(sk->sk_sleep); | 128 | wake_up_interruptible(sk_sleep(sk)); |
129 | } | 129 | } |
130 | 130 | ||
131 | /* CMTP init defines */ | 131 | /* CMTP init defines */ |
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 0073ec8495da..d4c6af082d48 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
@@ -284,7 +284,7 @@ static int cmtp_session(void *arg) | |||
284 | set_user_nice(current, -15); | 284 | set_user_nice(current, -15); |
285 | 285 | ||
286 | init_waitqueue_entry(&wait, current); | 286 | init_waitqueue_entry(&wait, current); |
287 | add_wait_queue(sk->sk_sleep, &wait); | 287 | add_wait_queue(sk_sleep(sk), &wait); |
288 | while (!atomic_read(&session->terminate)) { | 288 | while (!atomic_read(&session->terminate)) { |
289 | set_current_state(TASK_INTERRUPTIBLE); | 289 | set_current_state(TASK_INTERRUPTIBLE); |
290 | 290 | ||
@@ -301,7 +301,7 @@ static int cmtp_session(void *arg) | |||
301 | schedule(); | 301 | schedule(); |
302 | } | 302 | } |
303 | set_current_state(TASK_RUNNING); | 303 | set_current_state(TASK_RUNNING); |
304 | remove_wait_queue(sk->sk_sleep, &wait); | 304 | remove_wait_queue(sk_sleep(sk), &wait); |
305 | 305 | ||
306 | down_write(&cmtp_session_sem); | 306 | down_write(&cmtp_session_sem); |
307 | 307 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4ad23192c7a5..2f768de87011 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/fcntl.h> | 37 | #include <linux/fcntl.h> |
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
40 | #include <linux/workqueue.h> | ||
40 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
41 | #include <linux/notifier.h> | 42 | #include <linux/notifier.h> |
42 | #include <linux/rfkill.h> | 43 | #include <linux/rfkill.h> |
@@ -928,6 +929,10 @@ int hci_register_dev(struct hci_dev *hdev) | |||
928 | 929 | ||
929 | write_unlock_bh(&hci_dev_list_lock); | 930 | write_unlock_bh(&hci_dev_list_lock); |
930 | 931 | ||
932 | hdev->workqueue = create_singlethread_workqueue(hdev->name); | ||
933 | if (!hdev->workqueue) | ||
934 | goto nomem; | ||
935 | |||
931 | hci_register_sysfs(hdev); | 936 | hci_register_sysfs(hdev); |
932 | 937 | ||
933 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, | 938 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, |
@@ -942,6 +947,13 @@ int hci_register_dev(struct hci_dev *hdev) | |||
942 | hci_notify(hdev, HCI_DEV_REG); | 947 | hci_notify(hdev, HCI_DEV_REG); |
943 | 948 | ||
944 | return id; | 949 | return id; |
950 | |||
951 | nomem: | ||
952 | write_lock_bh(&hci_dev_list_lock); | ||
953 | list_del(&hdev->list); | ||
954 | write_unlock_bh(&hci_dev_list_lock); | ||
955 | |||
956 | return -ENOMEM; | ||
945 | } | 957 | } |
946 | EXPORT_SYMBOL(hci_register_dev); | 958 | EXPORT_SYMBOL(hci_register_dev); |
947 | 959 | ||
@@ -970,6 +982,8 @@ int hci_unregister_dev(struct hci_dev *hdev) | |||
970 | 982 | ||
971 | hci_unregister_sysfs(hdev); | 983 | hci_unregister_sysfs(hdev); |
972 | 984 | ||
985 | destroy_workqueue(hdev->workqueue); | ||
986 | |||
973 | __hci_dev_put(hdev); | 987 | __hci_dev_put(hdev); |
974 | 988 | ||
975 | return 0; | 989 | return 0; |
@@ -1260,7 +1274,7 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags) | |||
1260 | hdr->dlen = cpu_to_le16(len); | 1274 | hdr->dlen = cpu_to_le16(len); |
1261 | } | 1275 | } |
1262 | 1276 | ||
1263 | int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) | 1277 | void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) |
1264 | { | 1278 | { |
1265 | struct hci_dev *hdev = conn->hdev; | 1279 | struct hci_dev *hdev = conn->hdev; |
1266 | struct sk_buff *list; | 1280 | struct sk_buff *list; |
@@ -1302,24 +1316,17 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) | |||
1302 | } | 1316 | } |
1303 | 1317 | ||
1304 | tasklet_schedule(&hdev->tx_task); | 1318 | tasklet_schedule(&hdev->tx_task); |
1305 | |||
1306 | return 0; | ||
1307 | } | 1319 | } |
1308 | EXPORT_SYMBOL(hci_send_acl); | 1320 | EXPORT_SYMBOL(hci_send_acl); |
1309 | 1321 | ||
1310 | /* Send SCO data */ | 1322 | /* Send SCO data */ |
1311 | int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) | 1323 | void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) |
1312 | { | 1324 | { |
1313 | struct hci_dev *hdev = conn->hdev; | 1325 | struct hci_dev *hdev = conn->hdev; |
1314 | struct hci_sco_hdr hdr; | 1326 | struct hci_sco_hdr hdr; |
1315 | 1327 | ||
1316 | BT_DBG("%s len %d", hdev->name, skb->len); | 1328 | BT_DBG("%s len %d", hdev->name, skb->len); |
1317 | 1329 | ||
1318 | if (skb->len > hdev->sco_mtu) { | ||
1319 | kfree_skb(skb); | ||
1320 | return -EINVAL; | ||
1321 | } | ||
1322 | |||
1323 | hdr.handle = cpu_to_le16(conn->handle); | 1330 | hdr.handle = cpu_to_le16(conn->handle); |
1324 | hdr.dlen = skb->len; | 1331 | hdr.dlen = skb->len; |
1325 | 1332 | ||
@@ -1332,8 +1339,6 @@ int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) | |||
1332 | 1339 | ||
1333 | skb_queue_tail(&conn->data_q, skb); | 1340 | skb_queue_tail(&conn->data_q, skb); |
1334 | tasklet_schedule(&hdev->tx_task); | 1341 | tasklet_schedule(&hdev->tx_task); |
1335 | |||
1336 | return 0; | ||
1337 | } | 1342 | } |
1338 | EXPORT_SYMBOL(hci_send_sco); | 1343 | EXPORT_SYMBOL(hci_send_sco); |
1339 | 1344 | ||
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 0e8e1a59856c..463ffa4fe042 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -14,8 +14,6 @@ static struct class *bt_class; | |||
14 | struct dentry *bt_debugfs = NULL; | 14 | struct dentry *bt_debugfs = NULL; |
15 | EXPORT_SYMBOL_GPL(bt_debugfs); | 15 | EXPORT_SYMBOL_GPL(bt_debugfs); |
16 | 16 | ||
17 | static struct workqueue_struct *bt_workq; | ||
18 | |||
19 | static inline char *link_typetostr(int type) | 17 | static inline char *link_typetostr(int type) |
20 | { | 18 | { |
21 | switch (type) { | 19 | switch (type) { |
@@ -161,14 +159,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn) | |||
161 | { | 159 | { |
162 | BT_DBG("conn %p", conn); | 160 | BT_DBG("conn %p", conn); |
163 | 161 | ||
164 | queue_work(bt_workq, &conn->work_add); | 162 | queue_work(conn->hdev->workqueue, &conn->work_add); |
165 | } | 163 | } |
166 | 164 | ||
167 | void hci_conn_del_sysfs(struct hci_conn *conn) | 165 | void hci_conn_del_sysfs(struct hci_conn *conn) |
168 | { | 166 | { |
169 | BT_DBG("conn %p", conn); | 167 | BT_DBG("conn %p", conn); |
170 | 168 | ||
171 | queue_work(bt_workq, &conn->work_del); | 169 | queue_work(conn->hdev->workqueue, &conn->work_del); |
172 | } | 170 | } |
173 | 171 | ||
174 | static inline char *host_bustostr(int bus) | 172 | static inline char *host_bustostr(int bus) |
@@ -283,11 +281,9 @@ static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *at | |||
283 | static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 281 | static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
284 | { | 282 | { |
285 | struct hci_dev *hdev = dev_get_drvdata(dev); | 283 | struct hci_dev *hdev = dev_get_drvdata(dev); |
286 | char *ptr; | 284 | unsigned long val; |
287 | __u32 val; | ||
288 | 285 | ||
289 | val = simple_strtoul(buf, &ptr, 10); | 286 | if (strict_strtoul(buf, 0, &val) < 0) |
290 | if (ptr == buf) | ||
291 | return -EINVAL; | 287 | return -EINVAL; |
292 | 288 | ||
293 | if (val != 0 && (val < 500 || val > 3600000)) | 289 | if (val != 0 && (val < 500 || val > 3600000)) |
@@ -307,11 +303,9 @@ static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribu | |||
307 | static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 303 | static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
308 | { | 304 | { |
309 | struct hci_dev *hdev = dev_get_drvdata(dev); | 305 | struct hci_dev *hdev = dev_get_drvdata(dev); |
310 | char *ptr; | 306 | unsigned long val; |
311 | __u16 val; | ||
312 | 307 | ||
313 | val = simple_strtoul(buf, &ptr, 10); | 308 | if (strict_strtoul(buf, 0, &val) < 0) |
314 | if (ptr == buf) | ||
315 | return -EINVAL; | 309 | return -EINVAL; |
316 | 310 | ||
317 | if (val < 0x0002 || val > 0xFFFE || val % 2) | 311 | if (val < 0x0002 || val > 0xFFFE || val % 2) |
@@ -334,11 +328,9 @@ static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribu | |||
334 | static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 328 | static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
335 | { | 329 | { |
336 | struct hci_dev *hdev = dev_get_drvdata(dev); | 330 | struct hci_dev *hdev = dev_get_drvdata(dev); |
337 | char *ptr; | 331 | unsigned long val; |
338 | __u16 val; | ||
339 | 332 | ||
340 | val = simple_strtoul(buf, &ptr, 10); | 333 | if (strict_strtoul(buf, 0, &val) < 0) |
341 | if (ptr == buf) | ||
342 | return -EINVAL; | 334 | return -EINVAL; |
343 | 335 | ||
344 | if (val < 0x0002 || val > 0xFFFE || val % 2) | 336 | if (val < 0x0002 || val > 0xFFFE || val % 2) |
@@ -487,17 +479,11 @@ void hci_unregister_sysfs(struct hci_dev *hdev) | |||
487 | 479 | ||
488 | int __init bt_sysfs_init(void) | 480 | int __init bt_sysfs_init(void) |
489 | { | 481 | { |
490 | bt_workq = create_singlethread_workqueue("bluetooth"); | ||
491 | if (!bt_workq) | ||
492 | return -ENOMEM; | ||
493 | |||
494 | bt_debugfs = debugfs_create_dir("bluetooth", NULL); | 482 | bt_debugfs = debugfs_create_dir("bluetooth", NULL); |
495 | 483 | ||
496 | bt_class = class_create(THIS_MODULE, "bluetooth"); | 484 | bt_class = class_create(THIS_MODULE, "bluetooth"); |
497 | if (IS_ERR(bt_class)) { | 485 | if (IS_ERR(bt_class)) |
498 | destroy_workqueue(bt_workq); | ||
499 | return PTR_ERR(bt_class); | 486 | return PTR_ERR(bt_class); |
500 | } | ||
501 | 487 | ||
502 | return 0; | 488 | return 0; |
503 | } | 489 | } |
@@ -507,6 +493,4 @@ void bt_sysfs_cleanup(void) | |||
507 | class_destroy(bt_class); | 493 | class_destroy(bt_class); |
508 | 494 | ||
509 | debugfs_remove_recursive(bt_debugfs); | 495 | debugfs_remove_recursive(bt_debugfs); |
510 | |||
511 | destroy_workqueue(bt_workq); | ||
512 | } | 496 | } |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 280529ad9274..bfe641b7dfaf 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -561,8 +561,8 @@ static int hidp_session(void *arg) | |||
561 | 561 | ||
562 | init_waitqueue_entry(&ctrl_wait, current); | 562 | init_waitqueue_entry(&ctrl_wait, current); |
563 | init_waitqueue_entry(&intr_wait, current); | 563 | init_waitqueue_entry(&intr_wait, current); |
564 | add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait); | 564 | add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait); |
565 | add_wait_queue(intr_sk->sk_sleep, &intr_wait); | 565 | add_wait_queue(sk_sleep(intr_sk), &intr_wait); |
566 | while (!atomic_read(&session->terminate)) { | 566 | while (!atomic_read(&session->terminate)) { |
567 | set_current_state(TASK_INTERRUPTIBLE); | 567 | set_current_state(TASK_INTERRUPTIBLE); |
568 | 568 | ||
@@ -584,8 +584,8 @@ static int hidp_session(void *arg) | |||
584 | schedule(); | 584 | schedule(); |
585 | } | 585 | } |
586 | set_current_state(TASK_RUNNING); | 586 | set_current_state(TASK_RUNNING); |
587 | remove_wait_queue(intr_sk->sk_sleep, &intr_wait); | 587 | remove_wait_queue(sk_sleep(intr_sk), &intr_wait); |
588 | remove_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait); | 588 | remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait); |
589 | 589 | ||
590 | down_write(&hidp_session_sem); | 590 | down_write(&hidp_session_sem); |
591 | 591 | ||
@@ -609,7 +609,7 @@ static int hidp_session(void *arg) | |||
609 | 609 | ||
610 | fput(session->intr_sock->file); | 610 | fput(session->intr_sock->file); |
611 | 611 | ||
612 | wait_event_timeout(*(ctrl_sk->sk_sleep), | 612 | wait_event_timeout(*(sk_sleep(ctrl_sk)), |
613 | (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500)); | 613 | (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500)); |
614 | 614 | ||
615 | fput(session->ctrl_sock->file); | 615 | fput(session->ctrl_sock->file); |
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index a4e215d50c10..8d934a19da0a 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h | |||
@@ -164,8 +164,8 @@ static inline void hidp_schedule(struct hidp_session *session) | |||
164 | struct sock *ctrl_sk = session->ctrl_sock->sk; | 164 | struct sock *ctrl_sk = session->ctrl_sock->sk; |
165 | struct sock *intr_sk = session->intr_sock->sk; | 165 | struct sock *intr_sk = session->intr_sock->sk; |
166 | 166 | ||
167 | wake_up_interruptible(ctrl_sk->sk_sleep); | 167 | wake_up_interruptible(sk_sleep(ctrl_sk)); |
168 | wake_up_interruptible(intr_sk->sk_sleep); | 168 | wake_up_interruptible(sk_sleep(intr_sk)); |
169 | } | 169 | } |
170 | 170 | ||
171 | /* HIDP init defines */ | 171 | /* HIDP init defines */ |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 9753b690a8b3..1b682a5aa061 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -55,18 +55,27 @@ | |||
55 | 55 | ||
56 | #define VERSION "2.14" | 56 | #define VERSION "2.14" |
57 | 57 | ||
58 | #ifdef CONFIG_BT_L2CAP_EXT_FEATURES | ||
59 | static int enable_ertm = 1; | ||
60 | #else | ||
58 | static int enable_ertm = 0; | 61 | static int enable_ertm = 0; |
62 | #endif | ||
59 | static int max_transmit = L2CAP_DEFAULT_MAX_TX; | 63 | static int max_transmit = L2CAP_DEFAULT_MAX_TX; |
64 | static int tx_window = L2CAP_DEFAULT_TX_WINDOW; | ||
60 | 65 | ||
61 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; | 66 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; |
62 | static u8 l2cap_fixed_chan[8] = { 0x02, }; | 67 | static u8 l2cap_fixed_chan[8] = { 0x02, }; |
63 | 68 | ||
64 | static const struct proto_ops l2cap_sock_ops; | 69 | static const struct proto_ops l2cap_sock_ops; |
65 | 70 | ||
71 | static struct workqueue_struct *_busy_wq; | ||
72 | |||
66 | static struct bt_sock_list l2cap_sk_list = { | 73 | static struct bt_sock_list l2cap_sk_list = { |
67 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) | 74 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) |
68 | }; | 75 | }; |
69 | 76 | ||
77 | static void l2cap_busy_work(struct work_struct *work); | ||
78 | |||
70 | static void __l2cap_sock_close(struct sock *sk, int reason); | 79 | static void __l2cap_sock_close(struct sock *sk, int reason); |
71 | static void l2cap_sock_close(struct sock *sk); | 80 | static void l2cap_sock_close(struct sock *sk); |
72 | static void l2cap_sock_kill(struct sock *sk); | 81 | static void l2cap_sock_kill(struct sock *sk); |
@@ -219,7 +228,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so | |||
219 | 228 | ||
220 | l2cap_pi(sk)->conn = conn; | 229 | l2cap_pi(sk)->conn = conn; |
221 | 230 | ||
222 | if (sk->sk_type == SOCK_SEQPACKET) { | 231 | if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) { |
223 | /* Alloc CID for connection-oriented socket */ | 232 | /* Alloc CID for connection-oriented socket */ |
224 | l2cap_pi(sk)->scid = l2cap_alloc_cid(l); | 233 | l2cap_pi(sk)->scid = l2cap_alloc_cid(l); |
225 | } else if (sk->sk_type == SOCK_DGRAM) { | 234 | } else if (sk->sk_type == SOCK_DGRAM) { |
@@ -325,19 +334,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn) | |||
325 | return id; | 334 | return id; |
326 | } | 335 | } |
327 | 336 | ||
328 | static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) | 337 | static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) |
329 | { | 338 | { |
330 | struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); | 339 | struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); |
331 | 340 | ||
332 | BT_DBG("code 0x%2.2x", code); | 341 | BT_DBG("code 0x%2.2x", code); |
333 | 342 | ||
334 | if (!skb) | 343 | if (!skb) |
335 | return -ENOMEM; | 344 | return; |
336 | 345 | ||
337 | return hci_send_acl(conn->hcon, skb, 0); | 346 | hci_send_acl(conn->hcon, skb, 0); |
338 | } | 347 | } |
339 | 348 | ||
340 | static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) | 349 | static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) |
341 | { | 350 | { |
342 | struct sk_buff *skb; | 351 | struct sk_buff *skb; |
343 | struct l2cap_hdr *lh; | 352 | struct l2cap_hdr *lh; |
@@ -352,9 +361,19 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) | |||
352 | count = min_t(unsigned int, conn->mtu, hlen); | 361 | count = min_t(unsigned int, conn->mtu, hlen); |
353 | control |= L2CAP_CTRL_FRAME_TYPE; | 362 | control |= L2CAP_CTRL_FRAME_TYPE; |
354 | 363 | ||
364 | if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { | ||
365 | control |= L2CAP_CTRL_FINAL; | ||
366 | pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; | ||
367 | } | ||
368 | |||
369 | if (pi->conn_state & L2CAP_CONN_SEND_PBIT) { | ||
370 | control |= L2CAP_CTRL_POLL; | ||
371 | pi->conn_state &= ~L2CAP_CONN_SEND_PBIT; | ||
372 | } | ||
373 | |||
355 | skb = bt_skb_alloc(count, GFP_ATOMIC); | 374 | skb = bt_skb_alloc(count, GFP_ATOMIC); |
356 | if (!skb) | 375 | if (!skb) |
357 | return -ENOMEM; | 376 | return; |
358 | 377 | ||
359 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); | 378 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); |
360 | lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); | 379 | lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); |
@@ -366,19 +385,20 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) | |||
366 | put_unaligned_le16(fcs, skb_put(skb, 2)); | 385 | put_unaligned_le16(fcs, skb_put(skb, 2)); |
367 | } | 386 | } |
368 | 387 | ||
369 | return hci_send_acl(pi->conn->hcon, skb, 0); | 388 | hci_send_acl(pi->conn->hcon, skb, 0); |
370 | } | 389 | } |
371 | 390 | ||
372 | static inline int l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) | 391 | static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) |
373 | { | 392 | { |
374 | if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) | 393 | if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { |
375 | control |= L2CAP_SUPER_RCV_NOT_READY; | 394 | control |= L2CAP_SUPER_RCV_NOT_READY; |
376 | else | 395 | pi->conn_state |= L2CAP_CONN_RNR_SENT; |
396 | } else | ||
377 | control |= L2CAP_SUPER_RCV_READY; | 397 | control |= L2CAP_SUPER_RCV_READY; |
378 | 398 | ||
379 | control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 399 | control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
380 | 400 | ||
381 | return l2cap_send_sframe(pi, control); | 401 | l2cap_send_sframe(pi, control); |
382 | } | 402 | } |
383 | 403 | ||
384 | static void l2cap_do_start(struct sock *sk) | 404 | static void l2cap_do_start(struct sock *sk) |
@@ -437,7 +457,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
437 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 457 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { |
438 | bh_lock_sock(sk); | 458 | bh_lock_sock(sk); |
439 | 459 | ||
440 | if (sk->sk_type != SOCK_SEQPACKET) { | 460 | if (sk->sk_type != SOCK_SEQPACKET && |
461 | sk->sk_type != SOCK_STREAM) { | ||
441 | bh_unlock_sock(sk); | 462 | bh_unlock_sock(sk); |
442 | continue; | 463 | continue; |
443 | } | 464 | } |
@@ -497,7 +518,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
497 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 518 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { |
498 | bh_lock_sock(sk); | 519 | bh_lock_sock(sk); |
499 | 520 | ||
500 | if (sk->sk_type != SOCK_SEQPACKET) { | 521 | if (sk->sk_type != SOCK_SEQPACKET && |
522 | sk->sk_type != SOCK_STREAM) { | ||
501 | l2cap_sock_clear_timer(sk); | 523 | l2cap_sock_clear_timer(sk); |
502 | sk->sk_state = BT_CONNECTED; | 524 | sk->sk_state = BT_CONNECTED; |
503 | sk->sk_state_change(sk); | 525 | sk->sk_state_change(sk); |
@@ -706,7 +728,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason) | |||
706 | 728 | ||
707 | case BT_CONNECTED: | 729 | case BT_CONNECTED: |
708 | case BT_CONFIG: | 730 | case BT_CONFIG: |
709 | if (sk->sk_type == SOCK_SEQPACKET) { | 731 | if (sk->sk_type == SOCK_SEQPACKET || |
732 | sk->sk_type == SOCK_STREAM) { | ||
710 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | 733 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; |
711 | 734 | ||
712 | sk->sk_state = BT_DISCONN; | 735 | sk->sk_state = BT_DISCONN; |
@@ -717,7 +740,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason) | |||
717 | break; | 740 | break; |
718 | 741 | ||
719 | case BT_CONNECT2: | 742 | case BT_CONNECT2: |
720 | if (sk->sk_type == SOCK_SEQPACKET) { | 743 | if (sk->sk_type == SOCK_SEQPACKET || |
744 | sk->sk_type == SOCK_STREAM) { | ||
721 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | 745 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; |
722 | struct l2cap_conn_rsp rsp; | 746 | struct l2cap_conn_rsp rsp; |
723 | __u16 result; | 747 | __u16 result; |
@@ -772,14 +796,21 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
772 | pi->omtu = l2cap_pi(parent)->omtu; | 796 | pi->omtu = l2cap_pi(parent)->omtu; |
773 | pi->mode = l2cap_pi(parent)->mode; | 797 | pi->mode = l2cap_pi(parent)->mode; |
774 | pi->fcs = l2cap_pi(parent)->fcs; | 798 | pi->fcs = l2cap_pi(parent)->fcs; |
799 | pi->max_tx = l2cap_pi(parent)->max_tx; | ||
800 | pi->tx_win = l2cap_pi(parent)->tx_win; | ||
775 | pi->sec_level = l2cap_pi(parent)->sec_level; | 801 | pi->sec_level = l2cap_pi(parent)->sec_level; |
776 | pi->role_switch = l2cap_pi(parent)->role_switch; | 802 | pi->role_switch = l2cap_pi(parent)->role_switch; |
777 | pi->force_reliable = l2cap_pi(parent)->force_reliable; | 803 | pi->force_reliable = l2cap_pi(parent)->force_reliable; |
778 | } else { | 804 | } else { |
779 | pi->imtu = L2CAP_DEFAULT_MTU; | 805 | pi->imtu = L2CAP_DEFAULT_MTU; |
780 | pi->omtu = 0; | 806 | pi->omtu = 0; |
781 | pi->mode = L2CAP_MODE_BASIC; | 807 | if (enable_ertm && sk->sk_type == SOCK_STREAM) |
808 | pi->mode = L2CAP_MODE_ERTM; | ||
809 | else | ||
810 | pi->mode = L2CAP_MODE_BASIC; | ||
811 | pi->max_tx = max_transmit; | ||
782 | pi->fcs = L2CAP_FCS_CRC16; | 812 | pi->fcs = L2CAP_FCS_CRC16; |
813 | pi->tx_win = tx_window; | ||
783 | pi->sec_level = BT_SECURITY_LOW; | 814 | pi->sec_level = BT_SECURITY_LOW; |
784 | pi->role_switch = 0; | 815 | pi->role_switch = 0; |
785 | pi->force_reliable = 0; | 816 | pi->force_reliable = 0; |
@@ -790,6 +821,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
790 | pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; | 821 | pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; |
791 | skb_queue_head_init(TX_QUEUE(sk)); | 822 | skb_queue_head_init(TX_QUEUE(sk)); |
792 | skb_queue_head_init(SREJ_QUEUE(sk)); | 823 | skb_queue_head_init(SREJ_QUEUE(sk)); |
824 | skb_queue_head_init(BUSY_QUEUE(sk)); | ||
793 | INIT_LIST_HEAD(SREJ_LIST(sk)); | 825 | INIT_LIST_HEAD(SREJ_LIST(sk)); |
794 | } | 826 | } |
795 | 827 | ||
@@ -833,7 +865,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, | |||
833 | 865 | ||
834 | sock->state = SS_UNCONNECTED; | 866 | sock->state = SS_UNCONNECTED; |
835 | 867 | ||
836 | if (sock->type != SOCK_SEQPACKET && | 868 | if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM && |
837 | sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) | 869 | sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) |
838 | return -ESOCKTNOSUPPORT; | 870 | return -ESOCKTNOSUPPORT; |
839 | 871 | ||
@@ -981,7 +1013,8 @@ static int l2cap_do_connect(struct sock *sk) | |||
981 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 1013 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
982 | 1014 | ||
983 | if (hcon->state == BT_CONNECTED) { | 1015 | if (hcon->state == BT_CONNECTED) { |
984 | if (sk->sk_type != SOCK_SEQPACKET) { | 1016 | if (sk->sk_type != SOCK_SEQPACKET && |
1017 | sk->sk_type != SOCK_STREAM) { | ||
985 | l2cap_sock_clear_timer(sk); | 1018 | l2cap_sock_clear_timer(sk); |
986 | sk->sk_state = BT_CONNECTED; | 1019 | sk->sk_state = BT_CONNECTED; |
987 | } else | 1020 | } else |
@@ -1015,7 +1048,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
1015 | 1048 | ||
1016 | lock_sock(sk); | 1049 | lock_sock(sk); |
1017 | 1050 | ||
1018 | if (sk->sk_type == SOCK_SEQPACKET && !la.l2_psm) { | 1051 | if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) |
1052 | && !la.l2_psm) { | ||
1019 | err = -EINVAL; | 1053 | err = -EINVAL; |
1020 | goto done; | 1054 | goto done; |
1021 | } | 1055 | } |
@@ -1079,7 +1113,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) | |||
1079 | 1113 | ||
1080 | lock_sock(sk); | 1114 | lock_sock(sk); |
1081 | 1115 | ||
1082 | if (sk->sk_state != BT_BOUND || sock->type != SOCK_SEQPACKET) { | 1116 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) |
1117 | || sk->sk_state != BT_BOUND) { | ||
1083 | err = -EBADFD; | 1118 | err = -EBADFD; |
1084 | goto done; | 1119 | goto done; |
1085 | } | 1120 | } |
@@ -1147,7 +1182,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl | |||
1147 | BT_DBG("sk %p timeo %ld", sk, timeo); | 1182 | BT_DBG("sk %p timeo %ld", sk, timeo); |
1148 | 1183 | ||
1149 | /* Wait for an incoming connection. (wake-one). */ | 1184 | /* Wait for an incoming connection. (wake-one). */ |
1150 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 1185 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
1151 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { | 1186 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { |
1152 | set_current_state(TASK_INTERRUPTIBLE); | 1187 | set_current_state(TASK_INTERRUPTIBLE); |
1153 | if (!timeo) { | 1188 | if (!timeo) { |
@@ -1170,7 +1205,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl | |||
1170 | } | 1205 | } |
1171 | } | 1206 | } |
1172 | set_current_state(TASK_RUNNING); | 1207 | set_current_state(TASK_RUNNING); |
1173 | remove_wait_queue(sk->sk_sleep, &wait); | 1208 | remove_wait_queue(sk_sleep(sk), &wait); |
1174 | 1209 | ||
1175 | if (err) | 1210 | if (err) |
1176 | goto done; | 1211 | goto done; |
@@ -1207,10 +1242,40 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l | |||
1207 | return 0; | 1242 | return 0; |
1208 | } | 1243 | } |
1209 | 1244 | ||
1245 | static int __l2cap_wait_ack(struct sock *sk) | ||
1246 | { | ||
1247 | DECLARE_WAITQUEUE(wait, current); | ||
1248 | int err = 0; | ||
1249 | int timeo = HZ/5; | ||
1250 | |||
1251 | add_wait_queue(sk_sleep(sk), &wait); | ||
1252 | while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) { | ||
1253 | set_current_state(TASK_INTERRUPTIBLE); | ||
1254 | |||
1255 | if (!timeo) | ||
1256 | timeo = HZ/5; | ||
1257 | |||
1258 | if (signal_pending(current)) { | ||
1259 | err = sock_intr_errno(timeo); | ||
1260 | break; | ||
1261 | } | ||
1262 | |||
1263 | release_sock(sk); | ||
1264 | timeo = schedule_timeout(timeo); | ||
1265 | lock_sock(sk); | ||
1266 | |||
1267 | err = sock_error(sk); | ||
1268 | if (err) | ||
1269 | break; | ||
1270 | } | ||
1271 | set_current_state(TASK_RUNNING); | ||
1272 | remove_wait_queue(sk_sleep(sk), &wait); | ||
1273 | return err; | ||
1274 | } | ||
1275 | |||
1210 | static void l2cap_monitor_timeout(unsigned long arg) | 1276 | static void l2cap_monitor_timeout(unsigned long arg) |
1211 | { | 1277 | { |
1212 | struct sock *sk = (void *) arg; | 1278 | struct sock *sk = (void *) arg; |
1213 | u16 control; | ||
1214 | 1279 | ||
1215 | bh_lock_sock(sk); | 1280 | bh_lock_sock(sk); |
1216 | if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) { | 1281 | if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) { |
@@ -1222,15 +1287,13 @@ static void l2cap_monitor_timeout(unsigned long arg) | |||
1222 | l2cap_pi(sk)->retry_count++; | 1287 | l2cap_pi(sk)->retry_count++; |
1223 | __mod_monitor_timer(); | 1288 | __mod_monitor_timer(); |
1224 | 1289 | ||
1225 | control = L2CAP_CTRL_POLL; | 1290 | l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); |
1226 | l2cap_send_rr_or_rnr(l2cap_pi(sk), control); | ||
1227 | bh_unlock_sock(sk); | 1291 | bh_unlock_sock(sk); |
1228 | } | 1292 | } |
1229 | 1293 | ||
1230 | static void l2cap_retrans_timeout(unsigned long arg) | 1294 | static void l2cap_retrans_timeout(unsigned long arg) |
1231 | { | 1295 | { |
1232 | struct sock *sk = (void *) arg; | 1296 | struct sock *sk = (void *) arg; |
1233 | u16 control; | ||
1234 | 1297 | ||
1235 | bh_lock_sock(sk); | 1298 | bh_lock_sock(sk); |
1236 | l2cap_pi(sk)->retry_count = 1; | 1299 | l2cap_pi(sk)->retry_count = 1; |
@@ -1238,8 +1301,7 @@ static void l2cap_retrans_timeout(unsigned long arg) | |||
1238 | 1301 | ||
1239 | l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; | 1302 | l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; |
1240 | 1303 | ||
1241 | control = L2CAP_CTRL_POLL; | 1304 | l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); |
1242 | l2cap_send_rr_or_rnr(l2cap_pi(sk), control); | ||
1243 | bh_unlock_sock(sk); | 1305 | bh_unlock_sock(sk); |
1244 | } | 1306 | } |
1245 | 1307 | ||
@@ -1247,7 +1309,8 @@ static void l2cap_drop_acked_frames(struct sock *sk) | |||
1247 | { | 1309 | { |
1248 | struct sk_buff *skb; | 1310 | struct sk_buff *skb; |
1249 | 1311 | ||
1250 | while ((skb = skb_peek(TX_QUEUE(sk)))) { | 1312 | while ((skb = skb_peek(TX_QUEUE(sk))) && |
1313 | l2cap_pi(sk)->unacked_frames) { | ||
1251 | if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq) | 1314 | if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq) |
1252 | break; | 1315 | break; |
1253 | 1316 | ||
@@ -1259,22 +1322,15 @@ static void l2cap_drop_acked_frames(struct sock *sk) | |||
1259 | 1322 | ||
1260 | if (!l2cap_pi(sk)->unacked_frames) | 1323 | if (!l2cap_pi(sk)->unacked_frames) |
1261 | del_timer(&l2cap_pi(sk)->retrans_timer); | 1324 | del_timer(&l2cap_pi(sk)->retrans_timer); |
1262 | |||
1263 | return; | ||
1264 | } | 1325 | } |
1265 | 1326 | ||
1266 | static inline int l2cap_do_send(struct sock *sk, struct sk_buff *skb) | 1327 | static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb) |
1267 | { | 1328 | { |
1268 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 1329 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
1269 | int err; | ||
1270 | 1330 | ||
1271 | BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); | 1331 | BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); |
1272 | 1332 | ||
1273 | err = hci_send_acl(pi->conn->hcon, skb, 0); | 1333 | hci_send_acl(pi->conn->hcon, skb, 0); |
1274 | if (err < 0) | ||
1275 | kfree_skb(skb); | ||
1276 | |||
1277 | return err; | ||
1278 | } | 1334 | } |
1279 | 1335 | ||
1280 | static int l2cap_streaming_send(struct sock *sk) | 1336 | static int l2cap_streaming_send(struct sock *sk) |
@@ -1282,7 +1338,6 @@ static int l2cap_streaming_send(struct sock *sk) | |||
1282 | struct sk_buff *skb, *tx_skb; | 1338 | struct sk_buff *skb, *tx_skb; |
1283 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 1339 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
1284 | u16 control, fcs; | 1340 | u16 control, fcs; |
1285 | int err; | ||
1286 | 1341 | ||
1287 | while ((skb = sk->sk_send_head)) { | 1342 | while ((skb = sk->sk_send_head)) { |
1288 | tx_skb = skb_clone(skb, GFP_ATOMIC); | 1343 | tx_skb = skb_clone(skb, GFP_ATOMIC); |
@@ -1291,16 +1346,12 @@ static int l2cap_streaming_send(struct sock *sk) | |||
1291 | control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; | 1346 | control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; |
1292 | put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); | 1347 | put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); |
1293 | 1348 | ||
1294 | if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) { | 1349 | if (pi->fcs == L2CAP_FCS_CRC16) { |
1295 | fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); | 1350 | fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); |
1296 | put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); | 1351 | put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); |
1297 | } | 1352 | } |
1298 | 1353 | ||
1299 | err = l2cap_do_send(sk, tx_skb); | 1354 | l2cap_do_send(sk, tx_skb); |
1300 | if (err < 0) { | ||
1301 | l2cap_send_disconn_req(pi->conn, sk); | ||
1302 | return err; | ||
1303 | } | ||
1304 | 1355 | ||
1305 | pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; | 1356 | pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; |
1306 | 1357 | ||
@@ -1315,48 +1366,44 @@ static int l2cap_streaming_send(struct sock *sk) | |||
1315 | return 0; | 1366 | return 0; |
1316 | } | 1367 | } |
1317 | 1368 | ||
1318 | static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq) | 1369 | static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) |
1319 | { | 1370 | { |
1320 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 1371 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
1321 | struct sk_buff *skb, *tx_skb; | 1372 | struct sk_buff *skb, *tx_skb; |
1322 | u16 control, fcs; | 1373 | u16 control, fcs; |
1323 | int err; | ||
1324 | 1374 | ||
1325 | skb = skb_peek(TX_QUEUE(sk)); | 1375 | skb = skb_peek(TX_QUEUE(sk)); |
1326 | do { | 1376 | if (!skb) |
1327 | if (bt_cb(skb)->tx_seq != tx_seq) { | 1377 | return; |
1328 | if (skb_queue_is_last(TX_QUEUE(sk), skb)) | ||
1329 | break; | ||
1330 | skb = skb_queue_next(TX_QUEUE(sk), skb); | ||
1331 | continue; | ||
1332 | } | ||
1333 | 1378 | ||
1334 | if (pi->remote_max_tx && | 1379 | do { |
1335 | bt_cb(skb)->retries == pi->remote_max_tx) { | 1380 | if (bt_cb(skb)->tx_seq == tx_seq) |
1336 | l2cap_send_disconn_req(pi->conn, sk); | ||
1337 | break; | 1381 | break; |
1338 | } | ||
1339 | 1382 | ||
1340 | tx_skb = skb_clone(skb, GFP_ATOMIC); | 1383 | if (skb_queue_is_last(TX_QUEUE(sk), skb)) |
1341 | bt_cb(skb)->retries++; | 1384 | return; |
1342 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); | ||
1343 | control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) | ||
1344 | | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); | ||
1345 | put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); | ||
1346 | 1385 | ||
1347 | if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) { | 1386 | } while ((skb = skb_queue_next(TX_QUEUE(sk), skb))); |
1348 | fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); | ||
1349 | put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); | ||
1350 | } | ||
1351 | 1387 | ||
1352 | err = l2cap_do_send(sk, tx_skb); | 1388 | if (pi->remote_max_tx && |
1353 | if (err < 0) { | 1389 | bt_cb(skb)->retries == pi->remote_max_tx) { |
1354 | l2cap_send_disconn_req(pi->conn, sk); | 1390 | l2cap_send_disconn_req(pi->conn, sk); |
1355 | return err; | 1391 | return; |
1356 | } | 1392 | } |
1357 | break; | 1393 | |
1358 | } while(1); | 1394 | tx_skb = skb_clone(skb, GFP_ATOMIC); |
1359 | return 0; | 1395 | bt_cb(skb)->retries++; |
1396 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); | ||
1397 | control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) | ||
1398 | | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); | ||
1399 | put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); | ||
1400 | |||
1401 | if (pi->fcs == L2CAP_FCS_CRC16) { | ||
1402 | fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); | ||
1403 | put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); | ||
1404 | } | ||
1405 | |||
1406 | l2cap_do_send(sk, tx_skb); | ||
1360 | } | 1407 | } |
1361 | 1408 | ||
1362 | static int l2cap_ertm_send(struct sock *sk) | 1409 | static int l2cap_ertm_send(struct sock *sk) |
@@ -1364,13 +1411,13 @@ static int l2cap_ertm_send(struct sock *sk) | |||
1364 | struct sk_buff *skb, *tx_skb; | 1411 | struct sk_buff *skb, *tx_skb; |
1365 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 1412 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
1366 | u16 control, fcs; | 1413 | u16 control, fcs; |
1367 | int err; | 1414 | int nsent = 0; |
1368 | 1415 | ||
1369 | if (pi->conn_state & L2CAP_CONN_WAIT_F) | 1416 | if (pi->conn_state & L2CAP_CONN_WAIT_F) |
1370 | return 0; | 1417 | return 0; |
1371 | 1418 | ||
1372 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) && | 1419 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) && |
1373 | !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { | 1420 | !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { |
1374 | 1421 | ||
1375 | if (pi->remote_max_tx && | 1422 | if (pi->remote_max_tx && |
1376 | bt_cb(skb)->retries == pi->remote_max_tx) { | 1423 | bt_cb(skb)->retries == pi->remote_max_tx) { |
@@ -1383,35 +1430,97 @@ static int l2cap_ertm_send(struct sock *sk) | |||
1383 | bt_cb(skb)->retries++; | 1430 | bt_cb(skb)->retries++; |
1384 | 1431 | ||
1385 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); | 1432 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); |
1433 | if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { | ||
1434 | control |= L2CAP_CTRL_FINAL; | ||
1435 | pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; | ||
1436 | } | ||
1386 | control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) | 1437 | control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) |
1387 | | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); | 1438 | | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); |
1388 | put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); | 1439 | put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); |
1389 | 1440 | ||
1390 | 1441 | ||
1391 | if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) { | 1442 | if (pi->fcs == L2CAP_FCS_CRC16) { |
1392 | fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2); | 1443 | fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2); |
1393 | put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); | 1444 | put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); |
1394 | } | 1445 | } |
1395 | 1446 | ||
1396 | err = l2cap_do_send(sk, tx_skb); | 1447 | l2cap_do_send(sk, tx_skb); |
1397 | if (err < 0) { | 1448 | |
1398 | l2cap_send_disconn_req(pi->conn, sk); | ||
1399 | return err; | ||
1400 | } | ||
1401 | __mod_retrans_timer(); | 1449 | __mod_retrans_timer(); |
1402 | 1450 | ||
1403 | bt_cb(skb)->tx_seq = pi->next_tx_seq; | 1451 | bt_cb(skb)->tx_seq = pi->next_tx_seq; |
1404 | pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; | 1452 | pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; |
1405 | 1453 | ||
1406 | pi->unacked_frames++; | 1454 | pi->unacked_frames++; |
1455 | pi->frames_sent++; | ||
1407 | 1456 | ||
1408 | if (skb_queue_is_last(TX_QUEUE(sk), skb)) | 1457 | if (skb_queue_is_last(TX_QUEUE(sk), skb)) |
1409 | sk->sk_send_head = NULL; | 1458 | sk->sk_send_head = NULL; |
1410 | else | 1459 | else |
1411 | sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); | 1460 | sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); |
1461 | |||
1462 | nsent++; | ||
1412 | } | 1463 | } |
1413 | 1464 | ||
1414 | return 0; | 1465 | return nsent; |
1466 | } | ||
1467 | |||
1468 | static int l2cap_retransmit_frames(struct sock *sk) | ||
1469 | { | ||
1470 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
1471 | int ret; | ||
1472 | |||
1473 | spin_lock_bh(&pi->send_lock); | ||
1474 | |||
1475 | if (!skb_queue_empty(TX_QUEUE(sk))) | ||
1476 | sk->sk_send_head = TX_QUEUE(sk)->next; | ||
1477 | |||
1478 | pi->next_tx_seq = pi->expected_ack_seq; | ||
1479 | ret = l2cap_ertm_send(sk); | ||
1480 | |||
1481 | spin_unlock_bh(&pi->send_lock); | ||
1482 | |||
1483 | return ret; | ||
1484 | } | ||
1485 | |||
1486 | static void l2cap_send_ack(struct l2cap_pinfo *pi) | ||
1487 | { | ||
1488 | struct sock *sk = (struct sock *)pi; | ||
1489 | u16 control = 0; | ||
1490 | int nframes; | ||
1491 | |||
1492 | control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | ||
1493 | |||
1494 | if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { | ||
1495 | control |= L2CAP_SUPER_RCV_NOT_READY; | ||
1496 | pi->conn_state |= L2CAP_CONN_RNR_SENT; | ||
1497 | l2cap_send_sframe(pi, control); | ||
1498 | return; | ||
1499 | } | ||
1500 | |||
1501 | spin_lock_bh(&pi->send_lock); | ||
1502 | nframes = l2cap_ertm_send(sk); | ||
1503 | spin_unlock_bh(&pi->send_lock); | ||
1504 | |||
1505 | if (nframes > 0) | ||
1506 | return; | ||
1507 | |||
1508 | control |= L2CAP_SUPER_RCV_READY; | ||
1509 | l2cap_send_sframe(pi, control); | ||
1510 | } | ||
1511 | |||
1512 | static void l2cap_send_srejtail(struct sock *sk) | ||
1513 | { | ||
1514 | struct srej_list *tail; | ||
1515 | u16 control; | ||
1516 | |||
1517 | control = L2CAP_SUPER_SELECT_REJECT; | ||
1518 | control |= L2CAP_CTRL_FINAL; | ||
1519 | |||
1520 | tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list); | ||
1521 | control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; | ||
1522 | |||
1523 | l2cap_send_sframe(l2cap_pi(sk), control); | ||
1415 | } | 1524 | } |
1416 | 1525 | ||
1417 | static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) | 1526 | static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) |
@@ -1420,9 +1529,8 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in | |||
1420 | struct sk_buff **frag; | 1529 | struct sk_buff **frag; |
1421 | int err, sent = 0; | 1530 | int err, sent = 0; |
1422 | 1531 | ||
1423 | if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { | 1532 | if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) |
1424 | return -EFAULT; | 1533 | return -EFAULT; |
1425 | } | ||
1426 | 1534 | ||
1427 | sent += count; | 1535 | sent += count; |
1428 | len -= count; | 1536 | len -= count; |
@@ -1513,6 +1621,9 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *m | |||
1513 | 1621 | ||
1514 | BT_DBG("sk %p len %d", sk, (int)len); | 1622 | BT_DBG("sk %p len %d", sk, (int)len); |
1515 | 1623 | ||
1624 | if (!conn) | ||
1625 | return ERR_PTR(-ENOTCONN); | ||
1626 | |||
1516 | if (sdulen) | 1627 | if (sdulen) |
1517 | hlen += 2; | 1628 | hlen += 2; |
1518 | 1629 | ||
@@ -1554,25 +1665,24 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz | |||
1554 | u16 control; | 1665 | u16 control; |
1555 | size_t size = 0; | 1666 | size_t size = 0; |
1556 | 1667 | ||
1557 | __skb_queue_head_init(&sar_queue); | 1668 | skb_queue_head_init(&sar_queue); |
1558 | control = L2CAP_SDU_START; | 1669 | control = L2CAP_SDU_START; |
1559 | skb = l2cap_create_iframe_pdu(sk, msg, pi->max_pdu_size, control, len); | 1670 | skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len); |
1560 | if (IS_ERR(skb)) | 1671 | if (IS_ERR(skb)) |
1561 | return PTR_ERR(skb); | 1672 | return PTR_ERR(skb); |
1562 | 1673 | ||
1563 | __skb_queue_tail(&sar_queue, skb); | 1674 | __skb_queue_tail(&sar_queue, skb); |
1564 | len -= pi->max_pdu_size; | 1675 | len -= pi->remote_mps; |
1565 | size +=pi->max_pdu_size; | 1676 | size += pi->remote_mps; |
1566 | control = 0; | ||
1567 | 1677 | ||
1568 | while (len > 0) { | 1678 | while (len > 0) { |
1569 | size_t buflen; | 1679 | size_t buflen; |
1570 | 1680 | ||
1571 | if (len > pi->max_pdu_size) { | 1681 | if (len > pi->remote_mps) { |
1572 | control |= L2CAP_SDU_CONTINUE; | 1682 | control = L2CAP_SDU_CONTINUE; |
1573 | buflen = pi->max_pdu_size; | 1683 | buflen = pi->remote_mps; |
1574 | } else { | 1684 | } else { |
1575 | control |= L2CAP_SDU_END; | 1685 | control = L2CAP_SDU_END; |
1576 | buflen = len; | 1686 | buflen = len; |
1577 | } | 1687 | } |
1578 | 1688 | ||
@@ -1585,11 +1695,12 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz | |||
1585 | __skb_queue_tail(&sar_queue, skb); | 1695 | __skb_queue_tail(&sar_queue, skb); |
1586 | len -= buflen; | 1696 | len -= buflen; |
1587 | size += buflen; | 1697 | size += buflen; |
1588 | control = 0; | ||
1589 | } | 1698 | } |
1590 | skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk)); | 1699 | skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk)); |
1700 | spin_lock_bh(&pi->send_lock); | ||
1591 | if (sk->sk_send_head == NULL) | 1701 | if (sk->sk_send_head == NULL) |
1592 | sk->sk_send_head = sar_queue.next; | 1702 | sk->sk_send_head = sar_queue.next; |
1703 | spin_unlock_bh(&pi->send_lock); | ||
1593 | 1704 | ||
1594 | return size; | 1705 | return size; |
1595 | } | 1706 | } |
@@ -1611,11 +1722,6 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1611 | if (msg->msg_flags & MSG_OOB) | 1722 | if (msg->msg_flags & MSG_OOB) |
1612 | return -EOPNOTSUPP; | 1723 | return -EOPNOTSUPP; |
1613 | 1724 | ||
1614 | /* Check outgoing MTU */ | ||
1615 | if (sk->sk_type == SOCK_SEQPACKET && pi->mode == L2CAP_MODE_BASIC && | ||
1616 | len > pi->omtu) | ||
1617 | return -EINVAL; | ||
1618 | |||
1619 | lock_sock(sk); | 1725 | lock_sock(sk); |
1620 | 1726 | ||
1621 | if (sk->sk_state != BT_CONNECTED) { | 1727 | if (sk->sk_state != BT_CONNECTED) { |
@@ -1626,15 +1732,23 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1626 | /* Connectionless channel */ | 1732 | /* Connectionless channel */ |
1627 | if (sk->sk_type == SOCK_DGRAM) { | 1733 | if (sk->sk_type == SOCK_DGRAM) { |
1628 | skb = l2cap_create_connless_pdu(sk, msg, len); | 1734 | skb = l2cap_create_connless_pdu(sk, msg, len); |
1629 | if (IS_ERR(skb)) | 1735 | if (IS_ERR(skb)) { |
1630 | err = PTR_ERR(skb); | 1736 | err = PTR_ERR(skb); |
1631 | else | 1737 | } else { |
1632 | err = l2cap_do_send(sk, skb); | 1738 | l2cap_do_send(sk, skb); |
1739 | err = len; | ||
1740 | } | ||
1633 | goto done; | 1741 | goto done; |
1634 | } | 1742 | } |
1635 | 1743 | ||
1636 | switch (pi->mode) { | 1744 | switch (pi->mode) { |
1637 | case L2CAP_MODE_BASIC: | 1745 | case L2CAP_MODE_BASIC: |
1746 | /* Check outgoing MTU */ | ||
1747 | if (len > pi->omtu) { | ||
1748 | err = -EINVAL; | ||
1749 | goto done; | ||
1750 | } | ||
1751 | |||
1638 | /* Create a basic PDU */ | 1752 | /* Create a basic PDU */ |
1639 | skb = l2cap_create_basic_pdu(sk, msg, len); | 1753 | skb = l2cap_create_basic_pdu(sk, msg, len); |
1640 | if (IS_ERR(skb)) { | 1754 | if (IS_ERR(skb)) { |
@@ -1642,15 +1756,14 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1642 | goto done; | 1756 | goto done; |
1643 | } | 1757 | } |
1644 | 1758 | ||
1645 | err = l2cap_do_send(sk, skb); | 1759 | l2cap_do_send(sk, skb); |
1646 | if (!err) | 1760 | err = len; |
1647 | err = len; | ||
1648 | break; | 1761 | break; |
1649 | 1762 | ||
1650 | case L2CAP_MODE_ERTM: | 1763 | case L2CAP_MODE_ERTM: |
1651 | case L2CAP_MODE_STREAMING: | 1764 | case L2CAP_MODE_STREAMING: |
1652 | /* Entire SDU fits into one PDU */ | 1765 | /* Entire SDU fits into one PDU */ |
1653 | if (len <= pi->max_pdu_size) { | 1766 | if (len <= pi->remote_mps) { |
1654 | control = L2CAP_SDU_UNSEGMENTED; | 1767 | control = L2CAP_SDU_UNSEGMENTED; |
1655 | skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); | 1768 | skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); |
1656 | if (IS_ERR(skb)) { | 1769 | if (IS_ERR(skb)) { |
@@ -1658,8 +1771,15 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1658 | goto done; | 1771 | goto done; |
1659 | } | 1772 | } |
1660 | __skb_queue_tail(TX_QUEUE(sk), skb); | 1773 | __skb_queue_tail(TX_QUEUE(sk), skb); |
1774 | |||
1775 | if (pi->mode == L2CAP_MODE_ERTM) | ||
1776 | spin_lock_bh(&pi->send_lock); | ||
1777 | |||
1661 | if (sk->sk_send_head == NULL) | 1778 | if (sk->sk_send_head == NULL) |
1662 | sk->sk_send_head = skb; | 1779 | sk->sk_send_head = skb; |
1780 | |||
1781 | if (pi->mode == L2CAP_MODE_ERTM) | ||
1782 | spin_unlock_bh(&pi->send_lock); | ||
1663 | } else { | 1783 | } else { |
1664 | /* Segment SDU into multiples PDUs */ | 1784 | /* Segment SDU into multiples PDUs */ |
1665 | err = l2cap_sar_segment_sdu(sk, msg, len); | 1785 | err = l2cap_sar_segment_sdu(sk, msg, len); |
@@ -1667,12 +1787,15 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1667 | goto done; | 1787 | goto done; |
1668 | } | 1788 | } |
1669 | 1789 | ||
1670 | if (pi->mode == L2CAP_MODE_STREAMING) | 1790 | if (pi->mode == L2CAP_MODE_STREAMING) { |
1671 | err = l2cap_streaming_send(sk); | 1791 | err = l2cap_streaming_send(sk); |
1672 | else | 1792 | } else { |
1793 | spin_lock_bh(&pi->send_lock); | ||
1673 | err = l2cap_ertm_send(sk); | 1794 | err = l2cap_ertm_send(sk); |
1795 | spin_unlock_bh(&pi->send_lock); | ||
1796 | } | ||
1674 | 1797 | ||
1675 | if (!err) | 1798 | if (err >= 0) |
1676 | err = len; | 1799 | err = len; |
1677 | break; | 1800 | break; |
1678 | 1801 | ||
@@ -1731,6 +1854,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
1731 | opts.flush_to = l2cap_pi(sk)->flush_to; | 1854 | opts.flush_to = l2cap_pi(sk)->flush_to; |
1732 | opts.mode = l2cap_pi(sk)->mode; | 1855 | opts.mode = l2cap_pi(sk)->mode; |
1733 | opts.fcs = l2cap_pi(sk)->fcs; | 1856 | opts.fcs = l2cap_pi(sk)->fcs; |
1857 | opts.max_tx = l2cap_pi(sk)->max_tx; | ||
1858 | opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; | ||
1734 | 1859 | ||
1735 | len = min_t(unsigned int, sizeof(opts), optlen); | 1860 | len = min_t(unsigned int, sizeof(opts), optlen); |
1736 | if (copy_from_user((char *) &opts, optval, len)) { | 1861 | if (copy_from_user((char *) &opts, optval, len)) { |
@@ -1738,10 +1863,25 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
1738 | break; | 1863 | break; |
1739 | } | 1864 | } |
1740 | 1865 | ||
1866 | l2cap_pi(sk)->mode = opts.mode; | ||
1867 | switch (l2cap_pi(sk)->mode) { | ||
1868 | case L2CAP_MODE_BASIC: | ||
1869 | break; | ||
1870 | case L2CAP_MODE_ERTM: | ||
1871 | case L2CAP_MODE_STREAMING: | ||
1872 | if (enable_ertm) | ||
1873 | break; | ||
1874 | /* fall through */ | ||
1875 | default: | ||
1876 | err = -EINVAL; | ||
1877 | break; | ||
1878 | } | ||
1879 | |||
1741 | l2cap_pi(sk)->imtu = opts.imtu; | 1880 | l2cap_pi(sk)->imtu = opts.imtu; |
1742 | l2cap_pi(sk)->omtu = opts.omtu; | 1881 | l2cap_pi(sk)->omtu = opts.omtu; |
1743 | l2cap_pi(sk)->mode = opts.mode; | ||
1744 | l2cap_pi(sk)->fcs = opts.fcs; | 1882 | l2cap_pi(sk)->fcs = opts.fcs; |
1883 | l2cap_pi(sk)->max_tx = opts.max_tx; | ||
1884 | l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size; | ||
1745 | break; | 1885 | break; |
1746 | 1886 | ||
1747 | case L2CAP_LM: | 1887 | case L2CAP_LM: |
@@ -1789,7 +1929,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
1789 | 1929 | ||
1790 | switch (optname) { | 1930 | switch (optname) { |
1791 | case BT_SECURITY: | 1931 | case BT_SECURITY: |
1792 | if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_RAW) { | 1932 | if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM |
1933 | && sk->sk_type != SOCK_RAW) { | ||
1793 | err = -EINVAL; | 1934 | err = -EINVAL; |
1794 | break; | 1935 | break; |
1795 | } | 1936 | } |
@@ -1856,6 +1997,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us | |||
1856 | opts.flush_to = l2cap_pi(sk)->flush_to; | 1997 | opts.flush_to = l2cap_pi(sk)->flush_to; |
1857 | opts.mode = l2cap_pi(sk)->mode; | 1998 | opts.mode = l2cap_pi(sk)->mode; |
1858 | opts.fcs = l2cap_pi(sk)->fcs; | 1999 | opts.fcs = l2cap_pi(sk)->fcs; |
2000 | opts.max_tx = l2cap_pi(sk)->max_tx; | ||
2001 | opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; | ||
1859 | 2002 | ||
1860 | len = min_t(unsigned int, len, sizeof(opts)); | 2003 | len = min_t(unsigned int, len, sizeof(opts)); |
1861 | if (copy_to_user(optval, (char *) &opts, len)) | 2004 | if (copy_to_user(optval, (char *) &opts, len)) |
@@ -1937,7 +2080,8 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
1937 | 2080 | ||
1938 | switch (optname) { | 2081 | switch (optname) { |
1939 | case BT_SECURITY: | 2082 | case BT_SECURITY: |
1940 | if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_RAW) { | 2083 | if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM |
2084 | && sk->sk_type != SOCK_RAW) { | ||
1941 | err = -EINVAL; | 2085 | err = -EINVAL; |
1942 | break; | 2086 | break; |
1943 | } | 2087 | } |
@@ -1982,6 +2126,9 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
1982 | 2126 | ||
1983 | lock_sock(sk); | 2127 | lock_sock(sk); |
1984 | if (!sk->sk_shutdown) { | 2128 | if (!sk->sk_shutdown) { |
2129 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) | ||
2130 | err = __l2cap_wait_ack(sk); | ||
2131 | |||
1985 | sk->sk_shutdown = SHUTDOWN_MASK; | 2132 | sk->sk_shutdown = SHUTDOWN_MASK; |
1986 | l2cap_sock_clear_timer(sk); | 2133 | l2cap_sock_clear_timer(sk); |
1987 | __l2cap_sock_close(sk, 0); | 2134 | __l2cap_sock_close(sk, 0); |
@@ -2184,19 +2331,35 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) | |||
2184 | *ptr += L2CAP_CONF_OPT_SIZE + len; | 2331 | *ptr += L2CAP_CONF_OPT_SIZE + len; |
2185 | } | 2332 | } |
2186 | 2333 | ||
2334 | static void l2cap_ack_timeout(unsigned long arg) | ||
2335 | { | ||
2336 | struct sock *sk = (void *) arg; | ||
2337 | |||
2338 | bh_lock_sock(sk); | ||
2339 | l2cap_send_ack(l2cap_pi(sk)); | ||
2340 | bh_unlock_sock(sk); | ||
2341 | } | ||
2342 | |||
2187 | static inline void l2cap_ertm_init(struct sock *sk) | 2343 | static inline void l2cap_ertm_init(struct sock *sk) |
2188 | { | 2344 | { |
2189 | l2cap_pi(sk)->expected_ack_seq = 0; | 2345 | l2cap_pi(sk)->expected_ack_seq = 0; |
2190 | l2cap_pi(sk)->unacked_frames = 0; | 2346 | l2cap_pi(sk)->unacked_frames = 0; |
2191 | l2cap_pi(sk)->buffer_seq = 0; | 2347 | l2cap_pi(sk)->buffer_seq = 0; |
2192 | l2cap_pi(sk)->num_to_ack = 0; | 2348 | l2cap_pi(sk)->num_acked = 0; |
2349 | l2cap_pi(sk)->frames_sent = 0; | ||
2193 | 2350 | ||
2194 | setup_timer(&l2cap_pi(sk)->retrans_timer, | 2351 | setup_timer(&l2cap_pi(sk)->retrans_timer, |
2195 | l2cap_retrans_timeout, (unsigned long) sk); | 2352 | l2cap_retrans_timeout, (unsigned long) sk); |
2196 | setup_timer(&l2cap_pi(sk)->monitor_timer, | 2353 | setup_timer(&l2cap_pi(sk)->monitor_timer, |
2197 | l2cap_monitor_timeout, (unsigned long) sk); | 2354 | l2cap_monitor_timeout, (unsigned long) sk); |
2355 | setup_timer(&l2cap_pi(sk)->ack_timer, | ||
2356 | l2cap_ack_timeout, (unsigned long) sk); | ||
2198 | 2357 | ||
2199 | __skb_queue_head_init(SREJ_QUEUE(sk)); | 2358 | __skb_queue_head_init(SREJ_QUEUE(sk)); |
2359 | __skb_queue_head_init(BUSY_QUEUE(sk)); | ||
2360 | spin_lock_init(&l2cap_pi(sk)->send_lock); | ||
2361 | |||
2362 | INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work); | ||
2200 | } | 2363 | } |
2201 | 2364 | ||
2202 | static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) | 2365 | static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) |
@@ -2232,7 +2395,7 @@ static int l2cap_build_conf_req(struct sock *sk, void *data) | |||
2232 | { | 2395 | { |
2233 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 2396 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
2234 | struct l2cap_conf_req *req = data; | 2397 | struct l2cap_conf_req *req = data; |
2235 | struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; | 2398 | struct l2cap_conf_rfc rfc = { .mode = pi->mode }; |
2236 | void *ptr = req->data; | 2399 | void *ptr = req->data; |
2237 | 2400 | ||
2238 | BT_DBG("sk %p", sk); | 2401 | BT_DBG("sk %p", sk); |
@@ -2261,11 +2424,13 @@ done: | |||
2261 | 2424 | ||
2262 | case L2CAP_MODE_ERTM: | 2425 | case L2CAP_MODE_ERTM: |
2263 | rfc.mode = L2CAP_MODE_ERTM; | 2426 | rfc.mode = L2CAP_MODE_ERTM; |
2264 | rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; | 2427 | rfc.txwin_size = pi->tx_win; |
2265 | rfc.max_transmit = max_transmit; | 2428 | rfc.max_transmit = pi->max_tx; |
2266 | rfc.retrans_timeout = 0; | 2429 | rfc.retrans_timeout = 0; |
2267 | rfc.monitor_timeout = 0; | 2430 | rfc.monitor_timeout = 0; |
2268 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); | 2431 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); |
2432 | if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) | ||
2433 | rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); | ||
2269 | 2434 | ||
2270 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 2435 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
2271 | sizeof(rfc), (unsigned long) &rfc); | 2436 | sizeof(rfc), (unsigned long) &rfc); |
@@ -2287,6 +2452,8 @@ done: | |||
2287 | rfc.retrans_timeout = 0; | 2452 | rfc.retrans_timeout = 0; |
2288 | rfc.monitor_timeout = 0; | 2453 | rfc.monitor_timeout = 0; |
2289 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); | 2454 | rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); |
2455 | if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) | ||
2456 | rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); | ||
2290 | 2457 | ||
2291 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 2458 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
2292 | sizeof(rfc), (unsigned long) &rfc); | 2459 | sizeof(rfc), (unsigned long) &rfc); |
@@ -2415,10 +2582,15 @@ done: | |||
2415 | case L2CAP_MODE_ERTM: | 2582 | case L2CAP_MODE_ERTM: |
2416 | pi->remote_tx_win = rfc.txwin_size; | 2583 | pi->remote_tx_win = rfc.txwin_size; |
2417 | pi->remote_max_tx = rfc.max_transmit; | 2584 | pi->remote_max_tx = rfc.max_transmit; |
2418 | pi->max_pdu_size = rfc.max_pdu_size; | 2585 | if (rfc.max_pdu_size > pi->conn->mtu - 10) |
2586 | rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10); | ||
2419 | 2587 | ||
2420 | rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; | 2588 | pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); |
2421 | rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; | 2589 | |
2590 | rfc.retrans_timeout = | ||
2591 | le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO); | ||
2592 | rfc.monitor_timeout = | ||
2593 | le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO); | ||
2422 | 2594 | ||
2423 | pi->conf_state |= L2CAP_CONF_MODE_DONE; | 2595 | pi->conf_state |= L2CAP_CONF_MODE_DONE; |
2424 | 2596 | ||
@@ -2428,8 +2600,10 @@ done: | |||
2428 | break; | 2600 | break; |
2429 | 2601 | ||
2430 | case L2CAP_MODE_STREAMING: | 2602 | case L2CAP_MODE_STREAMING: |
2431 | pi->remote_tx_win = rfc.txwin_size; | 2603 | if (rfc.max_pdu_size > pi->conn->mtu - 10) |
2432 | pi->max_pdu_size = rfc.max_pdu_size; | 2604 | rfc.max_pdu_size = le16_to_cpu(pi->conn->mtu - 10); |
2605 | |||
2606 | pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); | ||
2433 | 2607 | ||
2434 | pi->conf_state |= L2CAP_CONF_MODE_DONE; | 2608 | pi->conf_state |= L2CAP_CONF_MODE_DONE; |
2435 | 2609 | ||
@@ -2506,13 +2680,12 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, | |||
2506 | switch (rfc.mode) { | 2680 | switch (rfc.mode) { |
2507 | case L2CAP_MODE_ERTM: | 2681 | case L2CAP_MODE_ERTM: |
2508 | pi->remote_tx_win = rfc.txwin_size; | 2682 | pi->remote_tx_win = rfc.txwin_size; |
2509 | pi->retrans_timeout = rfc.retrans_timeout; | 2683 | pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); |
2510 | pi->monitor_timeout = rfc.monitor_timeout; | 2684 | pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); |
2511 | pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); | 2685 | pi->mps = le16_to_cpu(rfc.max_pdu_size); |
2512 | break; | 2686 | break; |
2513 | case L2CAP_MODE_STREAMING: | 2687 | case L2CAP_MODE_STREAMING: |
2514 | pi->max_pdu_size = le16_to_cpu(rfc.max_pdu_size); | 2688 | pi->mps = le16_to_cpu(rfc.max_pdu_size); |
2515 | break; | ||
2516 | } | 2689 | } |
2517 | } | 2690 | } |
2518 | 2691 | ||
@@ -2536,6 +2709,42 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla | |||
2536 | return ptr - data; | 2709 | return ptr - data; |
2537 | } | 2710 | } |
2538 | 2711 | ||
2712 | static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) | ||
2713 | { | ||
2714 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
2715 | int type, olen; | ||
2716 | unsigned long val; | ||
2717 | struct l2cap_conf_rfc rfc; | ||
2718 | |||
2719 | BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len); | ||
2720 | |||
2721 | if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) | ||
2722 | return; | ||
2723 | |||
2724 | while (len >= L2CAP_CONF_OPT_SIZE) { | ||
2725 | len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); | ||
2726 | |||
2727 | switch (type) { | ||
2728 | case L2CAP_CONF_RFC: | ||
2729 | if (olen == sizeof(rfc)) | ||
2730 | memcpy(&rfc, (void *)val, olen); | ||
2731 | goto done; | ||
2732 | } | ||
2733 | } | ||
2734 | |||
2735 | done: | ||
2736 | switch (rfc.mode) { | ||
2737 | case L2CAP_MODE_ERTM: | ||
2738 | pi->remote_tx_win = rfc.txwin_size; | ||
2739 | pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); | ||
2740 | pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); | ||
2741 | pi->mps = le16_to_cpu(rfc.max_pdu_size); | ||
2742 | break; | ||
2743 | case L2CAP_MODE_STREAMING: | ||
2744 | pi->mps = le16_to_cpu(rfc.max_pdu_size); | ||
2745 | } | ||
2746 | } | ||
2747 | |||
2539 | static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 2748 | static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) |
2540 | { | 2749 | { |
2541 | struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data; | 2750 | struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data; |
@@ -2815,6 +3024,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2815 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; | 3024 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; |
2816 | u16 scid, flags, result; | 3025 | u16 scid, flags, result; |
2817 | struct sock *sk; | 3026 | struct sock *sk; |
3027 | int len = cmd->len - sizeof(*rsp); | ||
2818 | 3028 | ||
2819 | scid = __le16_to_cpu(rsp->scid); | 3029 | scid = __le16_to_cpu(rsp->scid); |
2820 | flags = __le16_to_cpu(rsp->flags); | 3030 | flags = __le16_to_cpu(rsp->flags); |
@@ -2829,11 +3039,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2829 | 3039 | ||
2830 | switch (result) { | 3040 | switch (result) { |
2831 | case L2CAP_CONF_SUCCESS: | 3041 | case L2CAP_CONF_SUCCESS: |
3042 | l2cap_conf_rfc_get(sk, rsp->data, len); | ||
2832 | break; | 3043 | break; |
2833 | 3044 | ||
2834 | case L2CAP_CONF_UNACCEPT: | 3045 | case L2CAP_CONF_UNACCEPT: |
2835 | if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { | 3046 | if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { |
2836 | int len = cmd->len - sizeof(*rsp); | ||
2837 | char req[64]; | 3047 | char req[64]; |
2838 | 3048 | ||
2839 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { | 3049 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { |
@@ -2917,8 +3127,10 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
2917 | 3127 | ||
2918 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { | 3128 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { |
2919 | skb_queue_purge(SREJ_QUEUE(sk)); | 3129 | skb_queue_purge(SREJ_QUEUE(sk)); |
3130 | skb_queue_purge(BUSY_QUEUE(sk)); | ||
2920 | del_timer(&l2cap_pi(sk)->retrans_timer); | 3131 | del_timer(&l2cap_pi(sk)->retrans_timer); |
2921 | del_timer(&l2cap_pi(sk)->monitor_timer); | 3132 | del_timer(&l2cap_pi(sk)->monitor_timer); |
3133 | del_timer(&l2cap_pi(sk)->ack_timer); | ||
2922 | } | 3134 | } |
2923 | 3135 | ||
2924 | l2cap_chan_del(sk, ECONNRESET); | 3136 | l2cap_chan_del(sk, ECONNRESET); |
@@ -2947,8 +3159,10 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
2947 | 3159 | ||
2948 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { | 3160 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { |
2949 | skb_queue_purge(SREJ_QUEUE(sk)); | 3161 | skb_queue_purge(SREJ_QUEUE(sk)); |
3162 | skb_queue_purge(BUSY_QUEUE(sk)); | ||
2950 | del_timer(&l2cap_pi(sk)->retrans_timer); | 3163 | del_timer(&l2cap_pi(sk)->retrans_timer); |
2951 | del_timer(&l2cap_pi(sk)->monitor_timer); | 3164 | del_timer(&l2cap_pi(sk)->monitor_timer); |
3165 | del_timer(&l2cap_pi(sk)->ack_timer); | ||
2952 | } | 3166 | } |
2953 | 3167 | ||
2954 | l2cap_chan_del(sk, 0); | 3168 | l2cap_chan_del(sk, 0); |
@@ -3143,7 +3357,40 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb) | |||
3143 | return 0; | 3357 | return 0; |
3144 | } | 3358 | } |
3145 | 3359 | ||
3146 | static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) | 3360 | static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) |
3361 | { | ||
3362 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
3363 | u16 control = 0; | ||
3364 | |||
3365 | pi->frames_sent = 0; | ||
3366 | pi->conn_state |= L2CAP_CONN_SEND_FBIT; | ||
3367 | |||
3368 | control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | ||
3369 | |||
3370 | if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { | ||
3371 | control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL; | ||
3372 | l2cap_send_sframe(pi, control); | ||
3373 | pi->conn_state |= L2CAP_CONN_RNR_SENT; | ||
3374 | pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; | ||
3375 | } | ||
3376 | |||
3377 | if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0) | ||
3378 | __mod_retrans_timer(); | ||
3379 | |||
3380 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | ||
3381 | |||
3382 | spin_lock_bh(&pi->send_lock); | ||
3383 | l2cap_ertm_send(sk); | ||
3384 | spin_unlock_bh(&pi->send_lock); | ||
3385 | |||
3386 | if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) && | ||
3387 | pi->frames_sent == 0) { | ||
3388 | control |= L2CAP_SUPER_RCV_READY; | ||
3389 | l2cap_send_sframe(pi, control); | ||
3390 | } | ||
3391 | } | ||
3392 | |||
3393 | static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) | ||
3147 | { | 3394 | { |
3148 | struct sk_buff *next_skb; | 3395 | struct sk_buff *next_skb; |
3149 | 3396 | ||
@@ -3153,29 +3400,256 @@ static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_ | |||
3153 | next_skb = skb_peek(SREJ_QUEUE(sk)); | 3400 | next_skb = skb_peek(SREJ_QUEUE(sk)); |
3154 | if (!next_skb) { | 3401 | if (!next_skb) { |
3155 | __skb_queue_tail(SREJ_QUEUE(sk), skb); | 3402 | __skb_queue_tail(SREJ_QUEUE(sk), skb); |
3156 | return; | 3403 | return 0; |
3157 | } | 3404 | } |
3158 | 3405 | ||
3159 | do { | 3406 | do { |
3407 | if (bt_cb(next_skb)->tx_seq == tx_seq) | ||
3408 | return -EINVAL; | ||
3409 | |||
3160 | if (bt_cb(next_skb)->tx_seq > tx_seq) { | 3410 | if (bt_cb(next_skb)->tx_seq > tx_seq) { |
3161 | __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb); | 3411 | __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb); |
3162 | return; | 3412 | return 0; |
3163 | } | 3413 | } |
3164 | 3414 | ||
3165 | if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb)) | 3415 | if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb)) |
3166 | break; | 3416 | break; |
3167 | 3417 | ||
3168 | } while((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); | 3418 | } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); |
3169 | 3419 | ||
3170 | __skb_queue_tail(SREJ_QUEUE(sk), skb); | 3420 | __skb_queue_tail(SREJ_QUEUE(sk), skb); |
3421 | |||
3422 | return 0; | ||
3171 | } | 3423 | } |
3172 | 3424 | ||
3173 | static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) | 3425 | static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) |
3426 | { | ||
3427 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
3428 | struct sk_buff *_skb; | ||
3429 | int err; | ||
3430 | |||
3431 | switch (control & L2CAP_CTRL_SAR) { | ||
3432 | case L2CAP_SDU_UNSEGMENTED: | ||
3433 | if (pi->conn_state & L2CAP_CONN_SAR_SDU) | ||
3434 | goto drop; | ||
3435 | |||
3436 | err = sock_queue_rcv_skb(sk, skb); | ||
3437 | if (!err) | ||
3438 | return err; | ||
3439 | |||
3440 | break; | ||
3441 | |||
3442 | case L2CAP_SDU_START: | ||
3443 | if (pi->conn_state & L2CAP_CONN_SAR_SDU) | ||
3444 | goto drop; | ||
3445 | |||
3446 | pi->sdu_len = get_unaligned_le16(skb->data); | ||
3447 | |||
3448 | if (pi->sdu_len > pi->imtu) | ||
3449 | goto disconnect; | ||
3450 | |||
3451 | pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); | ||
3452 | if (!pi->sdu) | ||
3453 | return -ENOMEM; | ||
3454 | |||
3455 | /* pull sdu_len bytes only after alloc, because of Local Busy | ||
3456 | * condition we have to be sure that this will be executed | ||
3457 | * only once, i.e., when alloc does not fail */ | ||
3458 | skb_pull(skb, 2); | ||
3459 | |||
3460 | memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); | ||
3461 | |||
3462 | pi->conn_state |= L2CAP_CONN_SAR_SDU; | ||
3463 | pi->partial_sdu_len = skb->len; | ||
3464 | break; | ||
3465 | |||
3466 | case L2CAP_SDU_CONTINUE: | ||
3467 | if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) | ||
3468 | goto disconnect; | ||
3469 | |||
3470 | if (!pi->sdu) | ||
3471 | goto disconnect; | ||
3472 | |||
3473 | pi->partial_sdu_len += skb->len; | ||
3474 | if (pi->partial_sdu_len > pi->sdu_len) | ||
3475 | goto drop; | ||
3476 | |||
3477 | memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); | ||
3478 | |||
3479 | break; | ||
3480 | |||
3481 | case L2CAP_SDU_END: | ||
3482 | if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) | ||
3483 | goto disconnect; | ||
3484 | |||
3485 | if (!pi->sdu) | ||
3486 | goto disconnect; | ||
3487 | |||
3488 | if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) { | ||
3489 | pi->partial_sdu_len += skb->len; | ||
3490 | |||
3491 | if (pi->partial_sdu_len > pi->imtu) | ||
3492 | goto drop; | ||
3493 | |||
3494 | if (pi->partial_sdu_len != pi->sdu_len) | ||
3495 | goto drop; | ||
3496 | |||
3497 | memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); | ||
3498 | } | ||
3499 | |||
3500 | _skb = skb_clone(pi->sdu, GFP_ATOMIC); | ||
3501 | if (!_skb) { | ||
3502 | pi->conn_state |= L2CAP_CONN_SAR_RETRY; | ||
3503 | return -ENOMEM; | ||
3504 | } | ||
3505 | |||
3506 | err = sock_queue_rcv_skb(sk, _skb); | ||
3507 | if (err < 0) { | ||
3508 | kfree_skb(_skb); | ||
3509 | pi->conn_state |= L2CAP_CONN_SAR_RETRY; | ||
3510 | return err; | ||
3511 | } | ||
3512 | |||
3513 | pi->conn_state &= ~L2CAP_CONN_SAR_RETRY; | ||
3514 | pi->conn_state &= ~L2CAP_CONN_SAR_SDU; | ||
3515 | |||
3516 | kfree_skb(pi->sdu); | ||
3517 | break; | ||
3518 | } | ||
3519 | |||
3520 | kfree_skb(skb); | ||
3521 | return 0; | ||
3522 | |||
3523 | drop: | ||
3524 | kfree_skb(pi->sdu); | ||
3525 | pi->sdu = NULL; | ||
3526 | |||
3527 | disconnect: | ||
3528 | l2cap_send_disconn_req(pi->conn, sk); | ||
3529 | kfree_skb(skb); | ||
3530 | return 0; | ||
3531 | } | ||
3532 | |||
3533 | static void l2cap_busy_work(struct work_struct *work) | ||
3534 | { | ||
3535 | DECLARE_WAITQUEUE(wait, current); | ||
3536 | struct l2cap_pinfo *pi = | ||
3537 | container_of(work, struct l2cap_pinfo, busy_work); | ||
3538 | struct sock *sk = (struct sock *)pi; | ||
3539 | int n_tries = 0, timeo = HZ/5, err; | ||
3540 | struct sk_buff *skb; | ||
3541 | u16 control; | ||
3542 | |||
3543 | lock_sock(sk); | ||
3544 | |||
3545 | add_wait_queue(sk_sleep(sk), &wait); | ||
3546 | while ((skb = skb_peek(BUSY_QUEUE(sk)))) { | ||
3547 | set_current_state(TASK_INTERRUPTIBLE); | ||
3548 | |||
3549 | if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) { | ||
3550 | err = -EBUSY; | ||
3551 | l2cap_send_disconn_req(pi->conn, sk); | ||
3552 | goto done; | ||
3553 | } | ||
3554 | |||
3555 | if (!timeo) | ||
3556 | timeo = HZ/5; | ||
3557 | |||
3558 | if (signal_pending(current)) { | ||
3559 | err = sock_intr_errno(timeo); | ||
3560 | goto done; | ||
3561 | } | ||
3562 | |||
3563 | release_sock(sk); | ||
3564 | timeo = schedule_timeout(timeo); | ||
3565 | lock_sock(sk); | ||
3566 | |||
3567 | err = sock_error(sk); | ||
3568 | if (err) | ||
3569 | goto done; | ||
3570 | |||
3571 | while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) { | ||
3572 | control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; | ||
3573 | err = l2cap_ertm_reassembly_sdu(sk, skb, control); | ||
3574 | if (err < 0) { | ||
3575 | skb_queue_head(BUSY_QUEUE(sk), skb); | ||
3576 | break; | ||
3577 | } | ||
3578 | |||
3579 | pi->buffer_seq = (pi->buffer_seq + 1) % 64; | ||
3580 | } | ||
3581 | |||
3582 | if (!skb) | ||
3583 | break; | ||
3584 | } | ||
3585 | |||
3586 | if (!(pi->conn_state & L2CAP_CONN_RNR_SENT)) | ||
3587 | goto done; | ||
3588 | |||
3589 | control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | ||
3590 | control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; | ||
3591 | l2cap_send_sframe(pi, control); | ||
3592 | l2cap_pi(sk)->retry_count = 1; | ||
3593 | |||
3594 | del_timer(&pi->retrans_timer); | ||
3595 | __mod_monitor_timer(); | ||
3596 | |||
3597 | l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; | ||
3598 | |||
3599 | done: | ||
3600 | pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; | ||
3601 | pi->conn_state &= ~L2CAP_CONN_RNR_SENT; | ||
3602 | |||
3603 | set_current_state(TASK_RUNNING); | ||
3604 | remove_wait_queue(sk_sleep(sk), &wait); | ||
3605 | |||
3606 | release_sock(sk); | ||
3607 | } | ||
3608 | |||
3609 | static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) | ||
3610 | { | ||
3611 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
3612 | int sctrl, err; | ||
3613 | |||
3614 | if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { | ||
3615 | bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; | ||
3616 | __skb_queue_tail(BUSY_QUEUE(sk), skb); | ||
3617 | return -EBUSY; | ||
3618 | } | ||
3619 | |||
3620 | err = l2cap_ertm_reassembly_sdu(sk, skb, control); | ||
3621 | if (err >= 0) { | ||
3622 | pi->buffer_seq = (pi->buffer_seq + 1) % 64; | ||
3623 | return err; | ||
3624 | } | ||
3625 | |||
3626 | /* Busy Condition */ | ||
3627 | pi->conn_state |= L2CAP_CONN_LOCAL_BUSY; | ||
3628 | bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; | ||
3629 | __skb_queue_tail(BUSY_QUEUE(sk), skb); | ||
3630 | |||
3631 | sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | ||
3632 | sctrl |= L2CAP_SUPER_RCV_NOT_READY; | ||
3633 | l2cap_send_sframe(pi, sctrl); | ||
3634 | |||
3635 | pi->conn_state |= L2CAP_CONN_RNR_SENT; | ||
3636 | |||
3637 | queue_work(_busy_wq, &pi->busy_work); | ||
3638 | |||
3639 | return err; | ||
3640 | } | ||
3641 | |||
3642 | static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) | ||
3174 | { | 3643 | { |
3175 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 3644 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
3176 | struct sk_buff *_skb; | 3645 | struct sk_buff *_skb; |
3177 | int err = -EINVAL; | 3646 | int err = -EINVAL; |
3178 | 3647 | ||
3648 | /* | ||
3649 | * TODO: We have to notify the userland if some data is lost with the | ||
3650 | * Streaming Mode. | ||
3651 | */ | ||
3652 | |||
3179 | switch (control & L2CAP_CTRL_SAR) { | 3653 | switch (control & L2CAP_CTRL_SAR) { |
3180 | case L2CAP_SDU_UNSEGMENTED: | 3654 | case L2CAP_SDU_UNSEGMENTED: |
3181 | if (pi->conn_state & L2CAP_CONN_SAR_SDU) { | 3655 | if (pi->conn_state & L2CAP_CONN_SAR_SDU) { |
@@ -3198,6 +3672,11 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co | |||
3198 | pi->sdu_len = get_unaligned_le16(skb->data); | 3672 | pi->sdu_len = get_unaligned_le16(skb->data); |
3199 | skb_pull(skb, 2); | 3673 | skb_pull(skb, 2); |
3200 | 3674 | ||
3675 | if (pi->sdu_len > pi->imtu) { | ||
3676 | err = -EMSGSIZE; | ||
3677 | break; | ||
3678 | } | ||
3679 | |||
3201 | pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); | 3680 | pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); |
3202 | if (!pi->sdu) { | 3681 | if (!pi->sdu) { |
3203 | err = -ENOMEM; | 3682 | err = -ENOMEM; |
@@ -3234,15 +3713,19 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co | |||
3234 | pi->conn_state &= ~L2CAP_CONN_SAR_SDU; | 3713 | pi->conn_state &= ~L2CAP_CONN_SAR_SDU; |
3235 | pi->partial_sdu_len += skb->len; | 3714 | pi->partial_sdu_len += skb->len; |
3236 | 3715 | ||
3716 | if (pi->partial_sdu_len > pi->imtu) | ||
3717 | goto drop; | ||
3718 | |||
3237 | if (pi->partial_sdu_len == pi->sdu_len) { | 3719 | if (pi->partial_sdu_len == pi->sdu_len) { |
3238 | _skb = skb_clone(pi->sdu, GFP_ATOMIC); | 3720 | _skb = skb_clone(pi->sdu, GFP_ATOMIC); |
3239 | err = sock_queue_rcv_skb(sk, _skb); | 3721 | err = sock_queue_rcv_skb(sk, _skb); |
3240 | if (err < 0) | 3722 | if (err < 0) |
3241 | kfree_skb(_skb); | 3723 | kfree_skb(_skb); |
3242 | } | 3724 | } |
3243 | kfree_skb(pi->sdu); | ||
3244 | err = 0; | 3725 | err = 0; |
3245 | 3726 | ||
3727 | drop: | ||
3728 | kfree_skb(pi->sdu); | ||
3246 | break; | 3729 | break; |
3247 | } | 3730 | } |
3248 | 3731 | ||
@@ -3253,15 +3736,15 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co | |||
3253 | static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) | 3736 | static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) |
3254 | { | 3737 | { |
3255 | struct sk_buff *skb; | 3738 | struct sk_buff *skb; |
3256 | u16 control = 0; | 3739 | u16 control; |
3257 | 3740 | ||
3258 | while((skb = skb_peek(SREJ_QUEUE(sk)))) { | 3741 | while ((skb = skb_peek(SREJ_QUEUE(sk)))) { |
3259 | if (bt_cb(skb)->tx_seq != tx_seq) | 3742 | if (bt_cb(skb)->tx_seq != tx_seq) |
3260 | break; | 3743 | break; |
3261 | 3744 | ||
3262 | skb = skb_dequeue(SREJ_QUEUE(sk)); | 3745 | skb = skb_dequeue(SREJ_QUEUE(sk)); |
3263 | control |= bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; | 3746 | control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; |
3264 | l2cap_sar_reassembly_sdu(sk, skb, control); | 3747 | l2cap_ertm_reassembly_sdu(sk, skb, control); |
3265 | l2cap_pi(sk)->buffer_seq_srej = | 3748 | l2cap_pi(sk)->buffer_seq_srej = |
3266 | (l2cap_pi(sk)->buffer_seq_srej + 1) % 64; | 3749 | (l2cap_pi(sk)->buffer_seq_srej + 1) % 64; |
3267 | tx_seq++; | 3750 | tx_seq++; |
@@ -3274,7 +3757,7 @@ static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq) | |||
3274 | struct srej_list *l, *tmp; | 3757 | struct srej_list *l, *tmp; |
3275 | u16 control; | 3758 | u16 control; |
3276 | 3759 | ||
3277 | list_for_each_entry_safe(l,tmp, SREJ_LIST(sk), list) { | 3760 | list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { |
3278 | if (l->tx_seq == tx_seq) { | 3761 | if (l->tx_seq == tx_seq) { |
3279 | list_del(&l->list); | 3762 | list_del(&l->list); |
3280 | kfree(l); | 3763 | kfree(l); |
@@ -3297,10 +3780,6 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) | |||
3297 | while (tx_seq != pi->expected_tx_seq) { | 3780 | while (tx_seq != pi->expected_tx_seq) { |
3298 | control = L2CAP_SUPER_SELECT_REJECT; | 3781 | control = L2CAP_SUPER_SELECT_REJECT; |
3299 | control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 3782 | control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
3300 | if (pi->conn_state & L2CAP_CONN_SEND_PBIT) { | ||
3301 | control |= L2CAP_CTRL_POLL; | ||
3302 | pi->conn_state &= ~L2CAP_CONN_SEND_PBIT; | ||
3303 | } | ||
3304 | l2cap_send_sframe(pi, control); | 3783 | l2cap_send_sframe(pi, control); |
3305 | 3784 | ||
3306 | new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); | 3785 | new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); |
@@ -3315,18 +3794,40 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str | |||
3315 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 3794 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
3316 | u8 tx_seq = __get_txseq(rx_control); | 3795 | u8 tx_seq = __get_txseq(rx_control); |
3317 | u8 req_seq = __get_reqseq(rx_control); | 3796 | u8 req_seq = __get_reqseq(rx_control); |
3318 | u16 tx_control = 0; | ||
3319 | u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; | 3797 | u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; |
3798 | u8 tx_seq_offset, expected_tx_seq_offset; | ||
3799 | int num_to_ack = (pi->tx_win/6) + 1; | ||
3320 | int err = 0; | 3800 | int err = 0; |
3321 | 3801 | ||
3322 | BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); | 3802 | BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); |
3323 | 3803 | ||
3804 | if (L2CAP_CTRL_FINAL & rx_control && | ||
3805 | l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { | ||
3806 | del_timer(&pi->monitor_timer); | ||
3807 | if (pi->unacked_frames > 0) | ||
3808 | __mod_retrans_timer(); | ||
3809 | pi->conn_state &= ~L2CAP_CONN_WAIT_F; | ||
3810 | } | ||
3811 | |||
3324 | pi->expected_ack_seq = req_seq; | 3812 | pi->expected_ack_seq = req_seq; |
3325 | l2cap_drop_acked_frames(sk); | 3813 | l2cap_drop_acked_frames(sk); |
3326 | 3814 | ||
3327 | if (tx_seq == pi->expected_tx_seq) | 3815 | if (tx_seq == pi->expected_tx_seq) |
3328 | goto expected; | 3816 | goto expected; |
3329 | 3817 | ||
3818 | tx_seq_offset = (tx_seq - pi->buffer_seq) % 64; | ||
3819 | if (tx_seq_offset < 0) | ||
3820 | tx_seq_offset += 64; | ||
3821 | |||
3822 | /* invalid tx_seq */ | ||
3823 | if (tx_seq_offset >= pi->tx_win) { | ||
3824 | l2cap_send_disconn_req(pi->conn, sk); | ||
3825 | goto drop; | ||
3826 | } | ||
3827 | |||
3828 | if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY) | ||
3829 | goto drop; | ||
3830 | |||
3330 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { | 3831 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { |
3331 | struct srej_list *first; | 3832 | struct srej_list *first; |
3332 | 3833 | ||
@@ -3342,10 +3843,14 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str | |||
3342 | if (list_empty(SREJ_LIST(sk))) { | 3843 | if (list_empty(SREJ_LIST(sk))) { |
3343 | pi->buffer_seq = pi->buffer_seq_srej; | 3844 | pi->buffer_seq = pi->buffer_seq_srej; |
3344 | pi->conn_state &= ~L2CAP_CONN_SREJ_SENT; | 3845 | pi->conn_state &= ~L2CAP_CONN_SREJ_SENT; |
3846 | l2cap_send_ack(pi); | ||
3345 | } | 3847 | } |
3346 | } else { | 3848 | } else { |
3347 | struct srej_list *l; | 3849 | struct srej_list *l; |
3348 | l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); | 3850 | |
3851 | /* duplicated tx_seq */ | ||
3852 | if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0) | ||
3853 | goto drop; | ||
3349 | 3854 | ||
3350 | list_for_each_entry(l, SREJ_LIST(sk), list) { | 3855 | list_for_each_entry(l, SREJ_LIST(sk), list) { |
3351 | if (l->tx_seq == tx_seq) { | 3856 | if (l->tx_seq == tx_seq) { |
@@ -3356,12 +3861,22 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str | |||
3356 | l2cap_send_srejframe(sk, tx_seq); | 3861 | l2cap_send_srejframe(sk, tx_seq); |
3357 | } | 3862 | } |
3358 | } else { | 3863 | } else { |
3864 | expected_tx_seq_offset = | ||
3865 | (pi->expected_tx_seq - pi->buffer_seq) % 64; | ||
3866 | if (expected_tx_seq_offset < 0) | ||
3867 | expected_tx_seq_offset += 64; | ||
3868 | |||
3869 | /* duplicated tx_seq */ | ||
3870 | if (tx_seq_offset < expected_tx_seq_offset) | ||
3871 | goto drop; | ||
3872 | |||
3359 | pi->conn_state |= L2CAP_CONN_SREJ_SENT; | 3873 | pi->conn_state |= L2CAP_CONN_SREJ_SENT; |
3360 | 3874 | ||
3361 | INIT_LIST_HEAD(SREJ_LIST(sk)); | 3875 | INIT_LIST_HEAD(SREJ_LIST(sk)); |
3362 | pi->buffer_seq_srej = pi->buffer_seq; | 3876 | pi->buffer_seq_srej = pi->buffer_seq; |
3363 | 3877 | ||
3364 | __skb_queue_head_init(SREJ_QUEUE(sk)); | 3878 | __skb_queue_head_init(SREJ_QUEUE(sk)); |
3879 | __skb_queue_head_init(BUSY_QUEUE(sk)); | ||
3365 | l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); | 3880 | l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); |
3366 | 3881 | ||
3367 | pi->conn_state |= L2CAP_CONN_SEND_PBIT; | 3882 | pi->conn_state |= L2CAP_CONN_SEND_PBIT; |
@@ -3374,153 +3889,189 @@ expected: | |||
3374 | pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; | 3889 | pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; |
3375 | 3890 | ||
3376 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { | 3891 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { |
3377 | l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); | 3892 | bt_cb(skb)->tx_seq = tx_seq; |
3893 | bt_cb(skb)->sar = sar; | ||
3894 | __skb_queue_tail(SREJ_QUEUE(sk), skb); | ||
3378 | return 0; | 3895 | return 0; |
3379 | } | 3896 | } |
3380 | 3897 | ||
3381 | if (rx_control & L2CAP_CTRL_FINAL) { | 3898 | if (rx_control & L2CAP_CTRL_FINAL) { |
3382 | if (pi->conn_state & L2CAP_CONN_REJ_ACT) | 3899 | if (pi->conn_state & L2CAP_CONN_REJ_ACT) |
3383 | pi->conn_state &= ~L2CAP_CONN_REJ_ACT; | 3900 | pi->conn_state &= ~L2CAP_CONN_REJ_ACT; |
3384 | else { | 3901 | else |
3385 | sk->sk_send_head = TX_QUEUE(sk)->next; | 3902 | l2cap_retransmit_frames(sk); |
3386 | pi->next_tx_seq = pi->expected_ack_seq; | ||
3387 | l2cap_ertm_send(sk); | ||
3388 | } | ||
3389 | } | 3903 | } |
3390 | 3904 | ||
3391 | pi->buffer_seq = (pi->buffer_seq + 1) % 64; | 3905 | err = l2cap_push_rx_skb(sk, skb, rx_control); |
3392 | |||
3393 | err = l2cap_sar_reassembly_sdu(sk, skb, rx_control); | ||
3394 | if (err < 0) | 3906 | if (err < 0) |
3395 | return err; | 3907 | return 0; |
3908 | |||
3909 | __mod_ack_timer(); | ||
3910 | |||
3911 | pi->num_acked = (pi->num_acked + 1) % num_to_ack; | ||
3912 | if (pi->num_acked == num_to_ack - 1) | ||
3913 | l2cap_send_ack(pi); | ||
3396 | 3914 | ||
3397 | pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK; | 3915 | return 0; |
3398 | if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) { | 3916 | |
3399 | tx_control |= L2CAP_SUPER_RCV_READY; | 3917 | drop: |
3400 | tx_control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 3918 | kfree_skb(skb); |
3401 | l2cap_send_sframe(pi, tx_control); | ||
3402 | } | ||
3403 | return 0; | 3919 | return 0; |
3404 | } | 3920 | } |
3405 | 3921 | ||
3406 | static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) | 3922 | static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) |
3407 | { | 3923 | { |
3408 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 3924 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
3409 | u8 tx_seq = __get_reqseq(rx_control); | ||
3410 | 3925 | ||
3411 | BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); | 3926 | pi->expected_ack_seq = __get_reqseq(rx_control); |
3927 | l2cap_drop_acked_frames(sk); | ||
3412 | 3928 | ||
3413 | switch (rx_control & L2CAP_CTRL_SUPERVISE) { | 3929 | if (rx_control & L2CAP_CTRL_POLL) { |
3414 | case L2CAP_SUPER_RCV_READY: | 3930 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { |
3415 | if (rx_control & L2CAP_CTRL_POLL) { | 3931 | if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && |
3416 | u16 control = L2CAP_CTRL_FINAL; | 3932 | (pi->unacked_frames > 0)) |
3417 | control |= L2CAP_SUPER_RCV_READY | | 3933 | __mod_retrans_timer(); |
3418 | (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT); | ||
3419 | l2cap_send_sframe(l2cap_pi(sk), control); | ||
3420 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | ||
3421 | 3934 | ||
3422 | } else if (rx_control & L2CAP_CTRL_FINAL) { | ||
3423 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | 3935 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; |
3424 | pi->expected_ack_seq = tx_seq; | 3936 | l2cap_send_srejtail(sk); |
3425 | l2cap_drop_acked_frames(sk); | 3937 | } else { |
3426 | 3938 | l2cap_send_i_or_rr_or_rnr(sk); | |
3427 | if (pi->conn_state & L2CAP_CONN_REJ_ACT) | 3939 | } |
3428 | pi->conn_state &= ~L2CAP_CONN_REJ_ACT; | ||
3429 | else { | ||
3430 | sk->sk_send_head = TX_QUEUE(sk)->next; | ||
3431 | pi->next_tx_seq = pi->expected_ack_seq; | ||
3432 | l2cap_ertm_send(sk); | ||
3433 | } | ||
3434 | |||
3435 | if (!(pi->conn_state & L2CAP_CONN_WAIT_F)) | ||
3436 | break; | ||
3437 | 3940 | ||
3438 | pi->conn_state &= ~L2CAP_CONN_WAIT_F; | 3941 | } else if (rx_control & L2CAP_CTRL_FINAL) { |
3439 | del_timer(&pi->monitor_timer); | 3942 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; |
3440 | 3943 | ||
3441 | if (pi->unacked_frames > 0) | 3944 | if (pi->conn_state & L2CAP_CONN_REJ_ACT) |
3442 | __mod_retrans_timer(); | 3945 | pi->conn_state &= ~L2CAP_CONN_REJ_ACT; |
3443 | } else { | 3946 | else |
3444 | pi->expected_ack_seq = tx_seq; | 3947 | l2cap_retransmit_frames(sk); |
3445 | l2cap_drop_acked_frames(sk); | ||
3446 | 3948 | ||
3447 | if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && | 3949 | } else { |
3448 | (pi->unacked_frames > 0)) | 3950 | if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && |
3449 | __mod_retrans_timer(); | 3951 | (pi->unacked_frames > 0)) |
3952 | __mod_retrans_timer(); | ||
3450 | 3953 | ||
3451 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | 3954 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; |
3955 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { | ||
3956 | l2cap_send_ack(pi); | ||
3957 | } else { | ||
3958 | spin_lock_bh(&pi->send_lock); | ||
3452 | l2cap_ertm_send(sk); | 3959 | l2cap_ertm_send(sk); |
3960 | spin_unlock_bh(&pi->send_lock); | ||
3453 | } | 3961 | } |
3454 | break; | 3962 | } |
3963 | } | ||
3455 | 3964 | ||
3456 | case L2CAP_SUPER_REJECT: | 3965 | static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) |
3457 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | 3966 | { |
3967 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
3968 | u8 tx_seq = __get_reqseq(rx_control); | ||
3969 | |||
3970 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | ||
3971 | |||
3972 | pi->expected_ack_seq = tx_seq; | ||
3973 | l2cap_drop_acked_frames(sk); | ||
3458 | 3974 | ||
3459 | pi->expected_ack_seq = __get_reqseq(rx_control); | 3975 | if (rx_control & L2CAP_CTRL_FINAL) { |
3976 | if (pi->conn_state & L2CAP_CONN_REJ_ACT) | ||
3977 | pi->conn_state &= ~L2CAP_CONN_REJ_ACT; | ||
3978 | else | ||
3979 | l2cap_retransmit_frames(sk); | ||
3980 | } else { | ||
3981 | l2cap_retransmit_frames(sk); | ||
3982 | |||
3983 | if (pi->conn_state & L2CAP_CONN_WAIT_F) | ||
3984 | pi->conn_state |= L2CAP_CONN_REJ_ACT; | ||
3985 | } | ||
3986 | } | ||
3987 | static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control) | ||
3988 | { | ||
3989 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
3990 | u8 tx_seq = __get_reqseq(rx_control); | ||
3991 | |||
3992 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | ||
3993 | |||
3994 | if (rx_control & L2CAP_CTRL_POLL) { | ||
3995 | pi->expected_ack_seq = tx_seq; | ||
3460 | l2cap_drop_acked_frames(sk); | 3996 | l2cap_drop_acked_frames(sk); |
3997 | l2cap_retransmit_one_frame(sk, tx_seq); | ||
3461 | 3998 | ||
3462 | if (rx_control & L2CAP_CTRL_FINAL) { | 3999 | spin_lock_bh(&pi->send_lock); |
3463 | if (pi->conn_state & L2CAP_CONN_REJ_ACT) | 4000 | l2cap_ertm_send(sk); |
3464 | pi->conn_state &= ~L2CAP_CONN_REJ_ACT; | 4001 | spin_unlock_bh(&pi->send_lock); |
3465 | else { | ||
3466 | sk->sk_send_head = TX_QUEUE(sk)->next; | ||
3467 | pi->next_tx_seq = pi->expected_ack_seq; | ||
3468 | l2cap_ertm_send(sk); | ||
3469 | } | ||
3470 | } else { | ||
3471 | sk->sk_send_head = TX_QUEUE(sk)->next; | ||
3472 | pi->next_tx_seq = pi->expected_ack_seq; | ||
3473 | l2cap_ertm_send(sk); | ||
3474 | 4002 | ||
3475 | if (pi->conn_state & L2CAP_CONN_WAIT_F) { | 4003 | if (pi->conn_state & L2CAP_CONN_WAIT_F) { |
3476 | pi->srej_save_reqseq = tx_seq; | 4004 | pi->srej_save_reqseq = tx_seq; |
3477 | pi->conn_state |= L2CAP_CONN_REJ_ACT; | 4005 | pi->conn_state |= L2CAP_CONN_SREJ_ACT; |
3478 | } | 4006 | } |
4007 | } else if (rx_control & L2CAP_CTRL_FINAL) { | ||
4008 | if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) && | ||
4009 | pi->srej_save_reqseq == tx_seq) | ||
4010 | pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; | ||
4011 | else | ||
4012 | l2cap_retransmit_one_frame(sk, tx_seq); | ||
4013 | } else { | ||
4014 | l2cap_retransmit_one_frame(sk, tx_seq); | ||
4015 | if (pi->conn_state & L2CAP_CONN_WAIT_F) { | ||
4016 | pi->srej_save_reqseq = tx_seq; | ||
4017 | pi->conn_state |= L2CAP_CONN_SREJ_ACT; | ||
3479 | } | 4018 | } |
4019 | } | ||
4020 | } | ||
3480 | 4021 | ||
4022 | static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control) | ||
4023 | { | ||
4024 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
4025 | u8 tx_seq = __get_reqseq(rx_control); | ||
4026 | |||
4027 | pi->conn_state |= L2CAP_CONN_REMOTE_BUSY; | ||
4028 | pi->expected_ack_seq = tx_seq; | ||
4029 | l2cap_drop_acked_frames(sk); | ||
4030 | |||
4031 | if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) { | ||
4032 | del_timer(&pi->retrans_timer); | ||
4033 | if (rx_control & L2CAP_CTRL_POLL) | ||
4034 | l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL); | ||
4035 | return; | ||
4036 | } | ||
4037 | |||
4038 | if (rx_control & L2CAP_CTRL_POLL) | ||
4039 | l2cap_send_srejtail(sk); | ||
4040 | else | ||
4041 | l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY); | ||
4042 | } | ||
4043 | |||
4044 | static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) | ||
4045 | { | ||
4046 | BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); | ||
4047 | |||
4048 | if (L2CAP_CTRL_FINAL & rx_control && | ||
4049 | l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { | ||
4050 | del_timer(&l2cap_pi(sk)->monitor_timer); | ||
4051 | if (l2cap_pi(sk)->unacked_frames > 0) | ||
4052 | __mod_retrans_timer(); | ||
4053 | l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F; | ||
4054 | } | ||
4055 | |||
4056 | switch (rx_control & L2CAP_CTRL_SUPERVISE) { | ||
4057 | case L2CAP_SUPER_RCV_READY: | ||
4058 | l2cap_data_channel_rrframe(sk, rx_control); | ||
3481 | break; | 4059 | break; |
3482 | 4060 | ||
3483 | case L2CAP_SUPER_SELECT_REJECT: | 4061 | case L2CAP_SUPER_REJECT: |
3484 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | 4062 | l2cap_data_channel_rejframe(sk, rx_control); |
4063 | break; | ||
3485 | 4064 | ||
3486 | if (rx_control & L2CAP_CTRL_POLL) { | 4065 | case L2CAP_SUPER_SELECT_REJECT: |
3487 | pi->expected_ack_seq = tx_seq; | 4066 | l2cap_data_channel_srejframe(sk, rx_control); |
3488 | l2cap_drop_acked_frames(sk); | ||
3489 | l2cap_retransmit_frame(sk, tx_seq); | ||
3490 | l2cap_ertm_send(sk); | ||
3491 | if (pi->conn_state & L2CAP_CONN_WAIT_F) { | ||
3492 | pi->srej_save_reqseq = tx_seq; | ||
3493 | pi->conn_state |= L2CAP_CONN_SREJ_ACT; | ||
3494 | } | ||
3495 | } else if (rx_control & L2CAP_CTRL_FINAL) { | ||
3496 | if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) && | ||
3497 | pi->srej_save_reqseq == tx_seq) | ||
3498 | pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; | ||
3499 | else | ||
3500 | l2cap_retransmit_frame(sk, tx_seq); | ||
3501 | } | ||
3502 | else { | ||
3503 | l2cap_retransmit_frame(sk, tx_seq); | ||
3504 | if (pi->conn_state & L2CAP_CONN_WAIT_F) { | ||
3505 | pi->srej_save_reqseq = tx_seq; | ||
3506 | pi->conn_state |= L2CAP_CONN_SREJ_ACT; | ||
3507 | } | ||
3508 | } | ||
3509 | break; | 4067 | break; |
3510 | 4068 | ||
3511 | case L2CAP_SUPER_RCV_NOT_READY: | 4069 | case L2CAP_SUPER_RCV_NOT_READY: |
3512 | pi->conn_state |= L2CAP_CONN_REMOTE_BUSY; | 4070 | l2cap_data_channel_rnrframe(sk, rx_control); |
3513 | pi->expected_ack_seq = tx_seq; | ||
3514 | l2cap_drop_acked_frames(sk); | ||
3515 | |||
3516 | del_timer(&l2cap_pi(sk)->retrans_timer); | ||
3517 | if (rx_control & L2CAP_CTRL_POLL) { | ||
3518 | u16 control = L2CAP_CTRL_FINAL; | ||
3519 | l2cap_send_rr_or_rnr(l2cap_pi(sk), control); | ||
3520 | } | ||
3521 | break; | 4071 | break; |
3522 | } | 4072 | } |
3523 | 4073 | ||
4074 | kfree_skb(skb); | ||
3524 | return 0; | 4075 | return 0; |
3525 | } | 4076 | } |
3526 | 4077 | ||
@@ -3529,7 +4080,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3529 | struct sock *sk; | 4080 | struct sock *sk; |
3530 | struct l2cap_pinfo *pi; | 4081 | struct l2cap_pinfo *pi; |
3531 | u16 control, len; | 4082 | u16 control, len; |
3532 | u8 tx_seq; | 4083 | u8 tx_seq, req_seq, next_tx_seq_offset, req_seq_offset; |
3533 | 4084 | ||
3534 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); | 4085 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); |
3535 | if (!sk) { | 4086 | if (!sk) { |
@@ -3574,16 +4125,45 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3574 | * Receiver will miss it and start proper recovery | 4125 | * Receiver will miss it and start proper recovery |
3575 | * procedures and ask retransmission. | 4126 | * procedures and ask retransmission. |
3576 | */ | 4127 | */ |
3577 | if (len > L2CAP_DEFAULT_MAX_PDU_SIZE) | 4128 | if (len > pi->mps) { |
4129 | l2cap_send_disconn_req(pi->conn, sk); | ||
3578 | goto drop; | 4130 | goto drop; |
4131 | } | ||
3579 | 4132 | ||
3580 | if (l2cap_check_fcs(pi, skb)) | 4133 | if (l2cap_check_fcs(pi, skb)) |
3581 | goto drop; | 4134 | goto drop; |
3582 | 4135 | ||
3583 | if (__is_iframe(control)) | 4136 | req_seq = __get_reqseq(control); |
4137 | req_seq_offset = (req_seq - pi->expected_ack_seq) % 64; | ||
4138 | if (req_seq_offset < 0) | ||
4139 | req_seq_offset += 64; | ||
4140 | |||
4141 | next_tx_seq_offset = | ||
4142 | (pi->next_tx_seq - pi->expected_ack_seq) % 64; | ||
4143 | if (next_tx_seq_offset < 0) | ||
4144 | next_tx_seq_offset += 64; | ||
4145 | |||
4146 | /* check for invalid req-seq */ | ||
4147 | if (req_seq_offset > next_tx_seq_offset) { | ||
4148 | l2cap_send_disconn_req(pi->conn, sk); | ||
4149 | goto drop; | ||
4150 | } | ||
4151 | |||
4152 | if (__is_iframe(control)) { | ||
4153 | if (len < 4) { | ||
4154 | l2cap_send_disconn_req(pi->conn, sk); | ||
4155 | goto drop; | ||
4156 | } | ||
4157 | |||
3584 | l2cap_data_channel_iframe(sk, control, skb); | 4158 | l2cap_data_channel_iframe(sk, control, skb); |
3585 | else | 4159 | } else { |
4160 | if (len != 0) { | ||
4161 | l2cap_send_disconn_req(pi->conn, sk); | ||
4162 | goto drop; | ||
4163 | } | ||
4164 | |||
3586 | l2cap_data_channel_sframe(sk, control, skb); | 4165 | l2cap_data_channel_sframe(sk, control, skb); |
4166 | } | ||
3587 | 4167 | ||
3588 | goto done; | 4168 | goto done; |
3589 | 4169 | ||
@@ -3598,7 +4178,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3598 | if (pi->fcs == L2CAP_FCS_CRC16) | 4178 | if (pi->fcs == L2CAP_FCS_CRC16) |
3599 | len -= 2; | 4179 | len -= 2; |
3600 | 4180 | ||
3601 | if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || __is_sframe(control)) | 4181 | if (len > pi->mps || len < 4 || __is_sframe(control)) |
3602 | goto drop; | 4182 | goto drop; |
3603 | 4183 | ||
3604 | if (l2cap_check_fcs(pi, skb)) | 4184 | if (l2cap_check_fcs(pi, skb)) |
@@ -3609,14 +4189,14 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3609 | if (pi->expected_tx_seq == tx_seq) | 4189 | if (pi->expected_tx_seq == tx_seq) |
3610 | pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; | 4190 | pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; |
3611 | else | 4191 | else |
3612 | pi->expected_tx_seq = tx_seq + 1; | 4192 | pi->expected_tx_seq = (tx_seq + 1) % 64; |
3613 | 4193 | ||
3614 | l2cap_sar_reassembly_sdu(sk, skb, control); | 4194 | l2cap_streaming_reassembly_sdu(sk, skb, control); |
3615 | 4195 | ||
3616 | goto done; | 4196 | goto done; |
3617 | 4197 | ||
3618 | default: | 4198 | default: |
3619 | BT_DBG("sk %p: bad mode 0x%2.2x", sk, l2cap_pi(sk)->mode); | 4199 | BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode); |
3620 | break; | 4200 | break; |
3621 | } | 4201 | } |
3622 | 4202 | ||
@@ -3772,7 +4352,7 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) | |||
3772 | 4352 | ||
3773 | static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt) | 4353 | static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt) |
3774 | { | 4354 | { |
3775 | if (sk->sk_type != SOCK_SEQPACKET) | 4355 | if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) |
3776 | return; | 4356 | return; |
3777 | 4357 | ||
3778 | if (encrypt == 0x00) { | 4358 | if (encrypt == 0x00) { |
@@ -4030,6 +4610,10 @@ static int __init l2cap_init(void) | |||
4030 | if (err < 0) | 4610 | if (err < 0) |
4031 | return err; | 4611 | return err; |
4032 | 4612 | ||
4613 | _busy_wq = create_singlethread_workqueue("l2cap"); | ||
4614 | if (!_busy_wq) | ||
4615 | goto error; | ||
4616 | |||
4033 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); | 4617 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); |
4034 | if (err < 0) { | 4618 | if (err < 0) { |
4035 | BT_ERR("L2CAP socket registration failed"); | 4619 | BT_ERR("L2CAP socket registration failed"); |
@@ -4064,6 +4648,9 @@ static void __exit l2cap_exit(void) | |||
4064 | { | 4648 | { |
4065 | debugfs_remove(l2cap_debugfs); | 4649 | debugfs_remove(l2cap_debugfs); |
4066 | 4650 | ||
4651 | flush_workqueue(_busy_wq); | ||
4652 | destroy_workqueue(_busy_wq); | ||
4653 | |||
4067 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) | 4654 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) |
4068 | BT_ERR("L2CAP socket unregistration failed"); | 4655 | BT_ERR("L2CAP socket unregistration failed"); |
4069 | 4656 | ||
@@ -4078,7 +4665,6 @@ void l2cap_load(void) | |||
4078 | /* Dummy function to trigger automatic L2CAP module loading by | 4665 | /* Dummy function to trigger automatic L2CAP module loading by |
4079 | * other modules that use L2CAP sockets but don't use any other | 4666 | * other modules that use L2CAP sockets but don't use any other |
4080 | * symbols from it. */ | 4667 | * symbols from it. */ |
4081 | return; | ||
4082 | } | 4668 | } |
4083 | EXPORT_SYMBOL(l2cap_load); | 4669 | EXPORT_SYMBOL(l2cap_load); |
4084 | 4670 | ||
@@ -4091,6 +4677,9 @@ MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode"); | |||
4091 | module_param(max_transmit, uint, 0644); | 4677 | module_param(max_transmit, uint, 0644); |
4092 | MODULE_PARM_DESC(max_transmit, "Max transmit value (default = 3)"); | 4678 | MODULE_PARM_DESC(max_transmit, "Max transmit value (default = 3)"); |
4093 | 4679 | ||
4680 | module_param(tx_window, uint, 0644); | ||
4681 | MODULE_PARM_DESC(tx_window, "Transmission window size value (default = 63)"); | ||
4682 | |||
4094 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | 4683 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); |
4095 | MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION); | 4684 | MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION); |
4096 | MODULE_VERSION(VERSION); | 4685 | MODULE_VERSION(VERSION); |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 8ed3c37684fa..43fbf6b4b4bf 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -503,7 +503,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f | |||
503 | BT_DBG("sk %p timeo %ld", sk, timeo); | 503 | BT_DBG("sk %p timeo %ld", sk, timeo); |
504 | 504 | ||
505 | /* Wait for an incoming connection. (wake-one). */ | 505 | /* Wait for an incoming connection. (wake-one). */ |
506 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 506 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
507 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { | 507 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { |
508 | set_current_state(TASK_INTERRUPTIBLE); | 508 | set_current_state(TASK_INTERRUPTIBLE); |
509 | if (!timeo) { | 509 | if (!timeo) { |
@@ -526,7 +526,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f | |||
526 | } | 526 | } |
527 | } | 527 | } |
528 | set_current_state(TASK_RUNNING); | 528 | set_current_state(TASK_RUNNING); |
529 | remove_wait_queue(sk->sk_sleep, &wait); | 529 | remove_wait_queue(sk_sleep(sk), &wait); |
530 | 530 | ||
531 | if (err) | 531 | if (err) |
532 | goto done; | 532 | goto done; |
@@ -621,7 +621,7 @@ static long rfcomm_sock_data_wait(struct sock *sk, long timeo) | |||
621 | { | 621 | { |
622 | DECLARE_WAITQUEUE(wait, current); | 622 | DECLARE_WAITQUEUE(wait, current); |
623 | 623 | ||
624 | add_wait_queue(sk->sk_sleep, &wait); | 624 | add_wait_queue(sk_sleep(sk), &wait); |
625 | for (;;) { | 625 | for (;;) { |
626 | set_current_state(TASK_INTERRUPTIBLE); | 626 | set_current_state(TASK_INTERRUPTIBLE); |
627 | 627 | ||
@@ -640,7 +640,7 @@ static long rfcomm_sock_data_wait(struct sock *sk, long timeo) | |||
640 | } | 640 | } |
641 | 641 | ||
642 | __set_current_state(TASK_RUNNING); | 642 | __set_current_state(TASK_RUNNING); |
643 | remove_wait_queue(sk->sk_sleep, &wait); | 643 | remove_wait_queue(sk_sleep(sk), &wait); |
644 | return timeo; | 644 | return timeo; |
645 | } | 645 | } |
646 | 646 | ||
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index cab71ea2796d..309b6c261b25 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -1014,8 +1014,6 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
1014 | rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud, | 1014 | rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud, |
1015 | data_bits, stop_bits, parity, | 1015 | data_bits, stop_bits, parity, |
1016 | RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes); | 1016 | RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes); |
1017 | |||
1018 | return; | ||
1019 | } | 1017 | } |
1020 | 1018 | ||
1021 | static void rfcomm_tty_throttle(struct tty_struct *tty) | 1019 | static void rfcomm_tty_throttle(struct tty_struct *tty) |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index ca6b2ad1c3fc..d0927d1fdada 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -165,11 +165,11 @@ static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct so | |||
165 | int err = 0; | 165 | int err = 0; |
166 | 166 | ||
167 | sco_conn_lock(conn); | 167 | sco_conn_lock(conn); |
168 | if (conn->sk) { | 168 | if (conn->sk) |
169 | err = -EBUSY; | 169 | err = -EBUSY; |
170 | } else { | 170 | else |
171 | __sco_chan_add(conn, sk, parent); | 171 | __sco_chan_add(conn, sk, parent); |
172 | } | 172 | |
173 | sco_conn_unlock(conn); | 173 | sco_conn_unlock(conn); |
174 | return err; | 174 | return err; |
175 | } | 175 | } |
@@ -241,22 +241,19 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) | |||
241 | BT_DBG("sk %p len %d", sk, len); | 241 | BT_DBG("sk %p len %d", sk, len); |
242 | 242 | ||
243 | count = min_t(unsigned int, conn->mtu, len); | 243 | count = min_t(unsigned int, conn->mtu, len); |
244 | if (!(skb = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err))) | 244 | skb = bt_skb_send_alloc(sk, count, |
245 | msg->msg_flags & MSG_DONTWAIT, &err); | ||
246 | if (!skb) | ||
245 | return err; | 247 | return err; |
246 | 248 | ||
247 | if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { | 249 | if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { |
248 | err = -EFAULT; | 250 | kfree_skb(skb); |
249 | goto fail; | 251 | return -EFAULT; |
250 | } | 252 | } |
251 | 253 | ||
252 | if ((err = hci_send_sco(conn->hcon, skb)) < 0) | 254 | hci_send_sco(conn->hcon, skb); |
253 | return err; | ||
254 | 255 | ||
255 | return count; | 256 | return count; |
256 | |||
257 | fail: | ||
258 | kfree_skb(skb); | ||
259 | return err; | ||
260 | } | 257 | } |
261 | 258 | ||
262 | static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) | 259 | static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) |
@@ -276,7 +273,6 @@ static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) | |||
276 | 273 | ||
277 | drop: | 274 | drop: |
278 | kfree_skb(skb); | 275 | kfree_skb(skb); |
279 | return; | ||
280 | } | 276 | } |
281 | 277 | ||
282 | /* -------- Socket interface ---------- */ | 278 | /* -------- Socket interface ---------- */ |
@@ -567,7 +563,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag | |||
567 | BT_DBG("sk %p timeo %ld", sk, timeo); | 563 | BT_DBG("sk %p timeo %ld", sk, timeo); |
568 | 564 | ||
569 | /* Wait for an incoming connection. (wake-one). */ | 565 | /* Wait for an incoming connection. (wake-one). */ |
570 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 566 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
571 | while (!(ch = bt_accept_dequeue(sk, newsock))) { | 567 | while (!(ch = bt_accept_dequeue(sk, newsock))) { |
572 | set_current_state(TASK_INTERRUPTIBLE); | 568 | set_current_state(TASK_INTERRUPTIBLE); |
573 | if (!timeo) { | 569 | if (!timeo) { |
@@ -590,7 +586,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag | |||
590 | } | 586 | } |
591 | } | 587 | } |
592 | set_current_state(TASK_RUNNING); | 588 | set_current_state(TASK_RUNNING); |
593 | remove_wait_queue(sk->sk_sleep, &wait); | 589 | remove_wait_queue(sk_sleep(sk), &wait); |
594 | 590 | ||
595 | if (err) | 591 | if (err) |
596 | goto done; | 592 | goto done; |
@@ -626,7 +622,7 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
626 | struct msghdr *msg, size_t len) | 622 | struct msghdr *msg, size_t len) |
627 | { | 623 | { |
628 | struct sock *sk = sock->sk; | 624 | struct sock *sk = sock->sk; |
629 | int err = 0; | 625 | int err; |
630 | 626 | ||
631 | BT_DBG("sock %p, sk %p", sock, sk); | 627 | BT_DBG("sock %p, sk %p", sock, sk); |
632 | 628 | ||
@@ -851,7 +847,8 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
851 | 847 | ||
852 | bh_lock_sock(parent); | 848 | bh_lock_sock(parent); |
853 | 849 | ||
854 | sk = sco_sock_alloc(sock_net(parent), NULL, BTPROTO_SCO, GFP_ATOMIC); | 850 | sk = sco_sock_alloc(sock_net(parent), NULL, |
851 | BTPROTO_SCO, GFP_ATOMIC); | ||
855 | if (!sk) { | 852 | if (!sk) { |
856 | bh_unlock_sock(parent); | 853 | bh_unlock_sock(parent); |
857 | goto done; | 854 | goto done; |
diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig index d115d5cea5b6..9190ae462cb4 100644 --- a/net/bridge/Kconfig +++ b/net/bridge/Kconfig | |||
@@ -33,14 +33,14 @@ config BRIDGE | |||
33 | If unsure, say N. | 33 | If unsure, say N. |
34 | 34 | ||
35 | config BRIDGE_IGMP_SNOOPING | 35 | config BRIDGE_IGMP_SNOOPING |
36 | bool "IGMP snooping" | 36 | bool "IGMP/MLD snooping" |
37 | depends on BRIDGE | 37 | depends on BRIDGE |
38 | depends on INET | 38 | depends on INET |
39 | default y | 39 | default y |
40 | ---help--- | 40 | ---help--- |
41 | If you say Y here, then the Ethernet bridge will be able selectively | 41 | If you say Y here, then the Ethernet bridge will be able selectively |
42 | forward multicast traffic based on IGMP traffic received from each | 42 | forward multicast traffic based on IGMP/MLD traffic received from |
43 | port. | 43 | each port. |
44 | 44 | ||
45 | Say N to exclude this support and reduce the binary size. | 45 | Say N to exclude this support and reduce the binary size. |
46 | 46 | ||
diff --git a/net/bridge/br.c b/net/bridge/br.c index e1241c76239a..76357b547752 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
@@ -38,7 +38,7 @@ static int __init br_init(void) | |||
38 | 38 | ||
39 | err = stp_proto_register(&br_stp_proto); | 39 | err = stp_proto_register(&br_stp_proto); |
40 | if (err < 0) { | 40 | if (err < 0) { |
41 | printk(KERN_ERR "bridge: can't register sap for STP\n"); | 41 | pr_err("bridge: can't register sap for STP\n"); |
42 | return err; | 42 | return err; |
43 | } | 43 | } |
44 | 44 | ||
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 90a9024e5c1e..eedf2c94820e 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -13,8 +13,11 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/netpoll.h> | ||
16 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
17 | #include <linux/ethtool.h> | 18 | #include <linux/ethtool.h> |
19 | #include <linux/list.h> | ||
20 | #include <linux/netfilter_bridge.h> | ||
18 | 21 | ||
19 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
20 | #include "br_private.h" | 23 | #include "br_private.h" |
@@ -26,16 +29,24 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
26 | const unsigned char *dest = skb->data; | 29 | const unsigned char *dest = skb->data; |
27 | struct net_bridge_fdb_entry *dst; | 30 | struct net_bridge_fdb_entry *dst; |
28 | struct net_bridge_mdb_entry *mdst; | 31 | struct net_bridge_mdb_entry *mdst; |
32 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); | ||
29 | 33 | ||
30 | BR_INPUT_SKB_CB(skb)->brdev = dev; | 34 | #ifdef CONFIG_BRIDGE_NETFILTER |
35 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { | ||
36 | br_nf_pre_routing_finish_bridge_slow(skb); | ||
37 | return NETDEV_TX_OK; | ||
38 | } | ||
39 | #endif | ||
31 | 40 | ||
32 | dev->stats.tx_packets++; | 41 | brstats->tx_packets++; |
33 | dev->stats.tx_bytes += skb->len; | 42 | brstats->tx_bytes += skb->len; |
43 | |||
44 | BR_INPUT_SKB_CB(skb)->brdev = dev; | ||
34 | 45 | ||
35 | skb_reset_mac_header(skb); | 46 | skb_reset_mac_header(skb); |
36 | skb_pull(skb, ETH_HLEN); | 47 | skb_pull(skb, ETH_HLEN); |
37 | 48 | ||
38 | if (dest[0] & 1) { | 49 | if (is_multicast_ether_addr(dest)) { |
39 | if (br_multicast_rcv(br, NULL, skb)) | 50 | if (br_multicast_rcv(br, NULL, skb)) |
40 | goto out; | 51 | goto out; |
41 | 52 | ||
@@ -81,6 +92,31 @@ static int br_dev_stop(struct net_device *dev) | |||
81 | return 0; | 92 | return 0; |
82 | } | 93 | } |
83 | 94 | ||
95 | static struct net_device_stats *br_get_stats(struct net_device *dev) | ||
96 | { | ||
97 | struct net_bridge *br = netdev_priv(dev); | ||
98 | struct net_device_stats *stats = &dev->stats; | ||
99 | struct br_cpu_netstats sum = { 0 }; | ||
100 | unsigned int cpu; | ||
101 | |||
102 | for_each_possible_cpu(cpu) { | ||
103 | const struct br_cpu_netstats *bstats | ||
104 | = per_cpu_ptr(br->stats, cpu); | ||
105 | |||
106 | sum.tx_bytes += bstats->tx_bytes; | ||
107 | sum.tx_packets += bstats->tx_packets; | ||
108 | sum.rx_bytes += bstats->rx_bytes; | ||
109 | sum.rx_packets += bstats->rx_packets; | ||
110 | } | ||
111 | |||
112 | stats->tx_bytes = sum.tx_bytes; | ||
113 | stats->tx_packets = sum.tx_packets; | ||
114 | stats->rx_bytes = sum.rx_bytes; | ||
115 | stats->rx_packets = sum.rx_packets; | ||
116 | |||
117 | return stats; | ||
118 | } | ||
119 | |||
84 | static int br_change_mtu(struct net_device *dev, int new_mtu) | 120 | static int br_change_mtu(struct net_device *dev, int new_mtu) |
85 | { | 121 | { |
86 | struct net_bridge *br = netdev_priv(dev); | 122 | struct net_bridge *br = netdev_priv(dev); |
@@ -162,6 +198,78 @@ static int br_set_tx_csum(struct net_device *dev, u32 data) | |||
162 | return 0; | 198 | return 0; |
163 | } | 199 | } |
164 | 200 | ||
201 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
202 | static bool br_devices_support_netpoll(struct net_bridge *br) | ||
203 | { | ||
204 | struct net_bridge_port *p; | ||
205 | bool ret = true; | ||
206 | int count = 0; | ||
207 | unsigned long flags; | ||
208 | |||
209 | spin_lock_irqsave(&br->lock, flags); | ||
210 | list_for_each_entry(p, &br->port_list, list) { | ||
211 | count++; | ||
212 | if ((p->dev->priv_flags & IFF_DISABLE_NETPOLL) || | ||
213 | !p->dev->netdev_ops->ndo_poll_controller) | ||
214 | ret = false; | ||
215 | } | ||
216 | spin_unlock_irqrestore(&br->lock, flags); | ||
217 | return count != 0 && ret; | ||
218 | } | ||
219 | |||
220 | static void br_poll_controller(struct net_device *br_dev) | ||
221 | { | ||
222 | struct netpoll *np = br_dev->npinfo->netpoll; | ||
223 | |||
224 | if (np->real_dev != br_dev) | ||
225 | netpoll_poll_dev(np->real_dev); | ||
226 | } | ||
227 | |||
228 | void br_netpoll_cleanup(struct net_device *dev) | ||
229 | { | ||
230 | struct net_bridge *br = netdev_priv(dev); | ||
231 | struct net_bridge_port *p, *n; | ||
232 | const struct net_device_ops *ops; | ||
233 | |||
234 | br->dev->npinfo = NULL; | ||
235 | list_for_each_entry_safe(p, n, &br->port_list, list) { | ||
236 | if (p->dev) { | ||
237 | ops = p->dev->netdev_ops; | ||
238 | if (ops->ndo_netpoll_cleanup) | ||
239 | ops->ndo_netpoll_cleanup(p->dev); | ||
240 | else | ||
241 | p->dev->npinfo = NULL; | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | |||
246 | void br_netpoll_disable(struct net_bridge *br, | ||
247 | struct net_device *dev) | ||
248 | { | ||
249 | if (br_devices_support_netpoll(br)) | ||
250 | br->dev->priv_flags &= ~IFF_DISABLE_NETPOLL; | ||
251 | if (dev->netdev_ops->ndo_netpoll_cleanup) | ||
252 | dev->netdev_ops->ndo_netpoll_cleanup(dev); | ||
253 | else | ||
254 | dev->npinfo = NULL; | ||
255 | } | ||
256 | |||
257 | void br_netpoll_enable(struct net_bridge *br, | ||
258 | struct net_device *dev) | ||
259 | { | ||
260 | if (br_devices_support_netpoll(br)) { | ||
261 | br->dev->priv_flags &= ~IFF_DISABLE_NETPOLL; | ||
262 | if (br->dev->npinfo) | ||
263 | dev->npinfo = br->dev->npinfo; | ||
264 | } else if (!(br->dev->priv_flags & IFF_DISABLE_NETPOLL)) { | ||
265 | br->dev->priv_flags |= IFF_DISABLE_NETPOLL; | ||
266 | br_info(br,"new device %s does not support netpoll (disabling)", | ||
267 | dev->name); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | #endif | ||
272 | |||
165 | static const struct ethtool_ops br_ethtool_ops = { | 273 | static const struct ethtool_ops br_ethtool_ops = { |
166 | .get_drvinfo = br_getinfo, | 274 | .get_drvinfo = br_getinfo, |
167 | .get_link = ethtool_op_get_link, | 275 | .get_link = ethtool_op_get_link, |
@@ -180,19 +288,32 @@ static const struct net_device_ops br_netdev_ops = { | |||
180 | .ndo_open = br_dev_open, | 288 | .ndo_open = br_dev_open, |
181 | .ndo_stop = br_dev_stop, | 289 | .ndo_stop = br_dev_stop, |
182 | .ndo_start_xmit = br_dev_xmit, | 290 | .ndo_start_xmit = br_dev_xmit, |
291 | .ndo_get_stats = br_get_stats, | ||
183 | .ndo_set_mac_address = br_set_mac_address, | 292 | .ndo_set_mac_address = br_set_mac_address, |
184 | .ndo_set_multicast_list = br_dev_set_multicast_list, | 293 | .ndo_set_multicast_list = br_dev_set_multicast_list, |
185 | .ndo_change_mtu = br_change_mtu, | 294 | .ndo_change_mtu = br_change_mtu, |
186 | .ndo_do_ioctl = br_dev_ioctl, | 295 | .ndo_do_ioctl = br_dev_ioctl, |
296 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
297 | .ndo_netpoll_cleanup = br_netpoll_cleanup, | ||
298 | .ndo_poll_controller = br_poll_controller, | ||
299 | #endif | ||
187 | }; | 300 | }; |
188 | 301 | ||
302 | static void br_dev_free(struct net_device *dev) | ||
303 | { | ||
304 | struct net_bridge *br = netdev_priv(dev); | ||
305 | |||
306 | free_percpu(br->stats); | ||
307 | free_netdev(dev); | ||
308 | } | ||
309 | |||
189 | void br_dev_setup(struct net_device *dev) | 310 | void br_dev_setup(struct net_device *dev) |
190 | { | 311 | { |
191 | random_ether_addr(dev->dev_addr); | 312 | random_ether_addr(dev->dev_addr); |
192 | ether_setup(dev); | 313 | ether_setup(dev); |
193 | 314 | ||
194 | dev->netdev_ops = &br_netdev_ops; | 315 | dev->netdev_ops = &br_netdev_ops; |
195 | dev->destructor = free_netdev; | 316 | dev->destructor = br_dev_free; |
196 | SET_ETHTOOL_OPS(dev, &br_ethtool_ops); | 317 | SET_ETHTOOL_OPS(dev, &br_ethtool_ops); |
197 | dev->tx_queue_len = 0; | 318 | dev->tx_queue_len = 0; |
198 | dev->priv_flags = IFF_EBRIDGE; | 319 | dev->priv_flags = IFF_EBRIDGE; |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 9101a4e56201..26637439965b 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -353,8 +353,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | |||
353 | */ | 353 | */ |
354 | if (fdb->is_local) | 354 | if (fdb->is_local) |
355 | return 0; | 355 | return 0; |
356 | 356 | br_warn(br, "adding interface %s with same address " | |
357 | printk(KERN_WARNING "%s adding interface with same address " | ||
358 | "as a received packet\n", | 357 | "as a received packet\n", |
359 | source->dev->name); | 358 | source->dev->name); |
360 | fdb_delete(fdb); | 359 | fdb_delete(fdb); |
@@ -397,9 +396,9 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
397 | /* attempt to update an entry for a local interface */ | 396 | /* attempt to update an entry for a local interface */ |
398 | if (unlikely(fdb->is_local)) { | 397 | if (unlikely(fdb->is_local)) { |
399 | if (net_ratelimit()) | 398 | if (net_ratelimit()) |
400 | printk(KERN_WARNING "%s: received packet with " | 399 | br_warn(br, "received packet on %s with " |
401 | "own address as source address\n", | 400 | "own address as source address\n", |
402 | source->dev->name); | 401 | source->dev->name); |
403 | } else { | 402 | } else { |
404 | /* fastpath: update of existing entry */ | 403 | /* fastpath: update of existing entry */ |
405 | fdb->dst = source; | 404 | fdb->dst = source; |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 7a241c396981..a98ef1393097 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/netpoll.h> | ||
18 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
19 | #include <linux/if_vlan.h> | 20 | #include <linux/if_vlan.h> |
20 | #include <linux/netfilter_bridge.h> | 21 | #include <linux/netfilter_bridge.h> |
@@ -44,13 +45,19 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) | |||
44 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) | 45 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) |
45 | kfree_skb(skb); | 46 | kfree_skb(skb); |
46 | else { | 47 | else { |
47 | /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ | 48 | /* ip_fragment doesn't copy the MAC header */ |
48 | if (nf_bridge_maybe_copy_header(skb)) | 49 | if (nf_bridge_maybe_copy_header(skb)) |
49 | kfree_skb(skb); | 50 | kfree_skb(skb); |
50 | else { | 51 | else { |
51 | skb_push(skb, ETH_HLEN); | 52 | skb_push(skb, ETH_HLEN); |
52 | 53 | ||
53 | dev_queue_xmit(skb); | 54 | #ifdef CONFIG_NET_POLL_CONTROLLER |
55 | if (unlikely(skb->dev->priv_flags & IFF_IN_NETPOLL)) { | ||
56 | netpoll_send_skb(skb->dev->npinfo->netpoll, skb); | ||
57 | skb->dev->priv_flags &= ~IFF_IN_NETPOLL; | ||
58 | } else | ||
59 | #endif | ||
60 | dev_queue_xmit(skb); | ||
54 | } | 61 | } |
55 | } | 62 | } |
56 | 63 | ||
@@ -59,16 +66,30 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) | |||
59 | 66 | ||
60 | int br_forward_finish(struct sk_buff *skb) | 67 | int br_forward_finish(struct sk_buff *skb) |
61 | { | 68 | { |
62 | return NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev, | 69 | return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev, |
63 | br_dev_queue_push_xmit); | 70 | br_dev_queue_push_xmit); |
64 | 71 | ||
65 | } | 72 | } |
66 | 73 | ||
67 | static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | 74 | static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) |
68 | { | 75 | { |
76 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
77 | struct net_bridge *br = to->br; | ||
78 | if (unlikely(br->dev->priv_flags & IFF_IN_NETPOLL)) { | ||
79 | struct netpoll *np; | ||
80 | to->dev->npinfo = skb->dev->npinfo; | ||
81 | np = skb->dev->npinfo->netpoll; | ||
82 | np->real_dev = np->dev = to->dev; | ||
83 | to->dev->priv_flags |= IFF_IN_NETPOLL; | ||
84 | } | ||
85 | #endif | ||
69 | skb->dev = to->dev; | 86 | skb->dev = to->dev; |
70 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, | 87 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, |
71 | br_forward_finish); | 88 | br_forward_finish); |
89 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
90 | if (skb->dev->npinfo) | ||
91 | skb->dev->npinfo->netpoll->dev = br->dev; | ||
92 | #endif | ||
72 | } | 93 | } |
73 | 94 | ||
74 | static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | 95 | static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) |
@@ -84,8 +105,8 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | |||
84 | skb->dev = to->dev; | 105 | skb->dev = to->dev; |
85 | skb_forward_csum(skb); | 106 | skb_forward_csum(skb); |
86 | 107 | ||
87 | NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev, | 108 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev, |
88 | br_forward_finish); | 109 | br_forward_finish); |
89 | } | 110 | } |
90 | 111 | ||
91 | /* called with rcu_read_lock */ | 112 | /* called with rcu_read_lock */ |
@@ -208,17 +229,15 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst, | |||
208 | { | 229 | { |
209 | struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; | 230 | struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; |
210 | struct net_bridge *br = netdev_priv(dev); | 231 | struct net_bridge *br = netdev_priv(dev); |
211 | struct net_bridge_port *port; | 232 | struct net_bridge_port *prev = NULL; |
212 | struct net_bridge_port *lport, *rport; | ||
213 | struct net_bridge_port *prev; | ||
214 | struct net_bridge_port_group *p; | 233 | struct net_bridge_port_group *p; |
215 | struct hlist_node *rp; | 234 | struct hlist_node *rp; |
216 | 235 | ||
217 | prev = NULL; | 236 | rp = rcu_dereference(br->router_list.first); |
218 | 237 | p = mdst ? rcu_dereference(mdst->ports) : NULL; | |
219 | rp = br->router_list.first; | ||
220 | p = mdst ? mdst->ports : NULL; | ||
221 | while (p || rp) { | 238 | while (p || rp) { |
239 | struct net_bridge_port *port, *lport, *rport; | ||
240 | |||
222 | lport = p ? p->port : NULL; | 241 | lport = p ? p->port : NULL; |
223 | rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : | 242 | rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : |
224 | NULL; | 243 | NULL; |
@@ -231,9 +250,9 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst, | |||
231 | goto out; | 250 | goto out; |
232 | 251 | ||
233 | if ((unsigned long)lport >= (unsigned long)port) | 252 | if ((unsigned long)lport >= (unsigned long)port) |
234 | p = p->next; | 253 | p = rcu_dereference(p->next); |
235 | if ((unsigned long)rport >= (unsigned long)port) | 254 | if ((unsigned long)rport >= (unsigned long)port) |
236 | rp = rp->next; | 255 | rp = rcu_dereference(rp->next); |
237 | } | 256 | } |
238 | 257 | ||
239 | if (!prev) | 258 | if (!prev) |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 0b6b1f2ff7ac..18b245e2c00e 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/netpoll.h> | ||
16 | #include <linux/ethtool.h> | 17 | #include <linux/ethtool.h> |
17 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
@@ -132,7 +133,7 @@ static void del_nbp(struct net_bridge_port *p) | |||
132 | struct net_bridge *br = p->br; | 133 | struct net_bridge *br = p->br; |
133 | struct net_device *dev = p->dev; | 134 | struct net_device *dev = p->dev; |
134 | 135 | ||
135 | sysfs_remove_link(br->ifobj, dev->name); | 136 | sysfs_remove_link(br->ifobj, p->dev->name); |
136 | 137 | ||
137 | dev_set_promiscuity(dev, -1); | 138 | dev_set_promiscuity(dev, -1); |
138 | 139 | ||
@@ -153,6 +154,7 @@ static void del_nbp(struct net_bridge_port *p) | |||
153 | kobject_uevent(&p->kobj, KOBJ_REMOVE); | 154 | kobject_uevent(&p->kobj, KOBJ_REMOVE); |
154 | kobject_del(&p->kobj); | 155 | kobject_del(&p->kobj); |
155 | 156 | ||
157 | br_netpoll_disable(br, dev); | ||
156 | call_rcu(&p->rcu, destroy_nbp_rcu); | 158 | call_rcu(&p->rcu, destroy_nbp_rcu); |
157 | } | 159 | } |
158 | 160 | ||
@@ -165,6 +167,8 @@ static void del_br(struct net_bridge *br, struct list_head *head) | |||
165 | del_nbp(p); | 167 | del_nbp(p); |
166 | } | 168 | } |
167 | 169 | ||
170 | br_netpoll_cleanup(br->dev); | ||
171 | |||
168 | del_timer_sync(&br->gc_timer); | 172 | del_timer_sync(&br->gc_timer); |
169 | 173 | ||
170 | br_sysfs_delbr(br->dev); | 174 | br_sysfs_delbr(br->dev); |
@@ -186,6 +190,12 @@ static struct net_device *new_bridge_dev(struct net *net, const char *name) | |||
186 | br = netdev_priv(dev); | 190 | br = netdev_priv(dev); |
187 | br->dev = dev; | 191 | br->dev = dev; |
188 | 192 | ||
193 | br->stats = alloc_percpu(struct br_cpu_netstats); | ||
194 | if (!br->stats) { | ||
195 | free_netdev(dev); | ||
196 | return NULL; | ||
197 | } | ||
198 | |||
189 | spin_lock_init(&br->lock); | 199 | spin_lock_init(&br->lock); |
190 | INIT_LIST_HEAD(&br->port_list); | 200 | INIT_LIST_HEAD(&br->port_list); |
191 | spin_lock_init(&br->hash_lock); | 201 | spin_lock_init(&br->hash_lock); |
@@ -438,6 +448,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
438 | 448 | ||
439 | kobject_uevent(&p->kobj, KOBJ_ADD); | 449 | kobject_uevent(&p->kobj, KOBJ_ADD); |
440 | 450 | ||
451 | br_netpoll_enable(br, dev); | ||
452 | |||
441 | return 0; | 453 | return 0; |
442 | err2: | 454 | err2: |
443 | br_fdb_delete_by_port(br, p, 1); | 455 | br_fdb_delete_by_port(br, p, 1); |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index a82dde2d2ead..d36e700f7a26 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -24,14 +24,16 @@ const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; | |||
24 | static int br_pass_frame_up(struct sk_buff *skb) | 24 | static int br_pass_frame_up(struct sk_buff *skb) |
25 | { | 25 | { |
26 | struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; | 26 | struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; |
27 | struct net_bridge *br = netdev_priv(brdev); | ||
28 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); | ||
27 | 29 | ||
28 | brdev->stats.rx_packets++; | 30 | brstats->rx_packets++; |
29 | brdev->stats.rx_bytes += skb->len; | 31 | brstats->rx_bytes += skb->len; |
30 | 32 | ||
31 | indev = skb->dev; | 33 | indev = skb->dev; |
32 | skb->dev = brdev; | 34 | skb->dev = brdev; |
33 | 35 | ||
34 | return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, | 36 | return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, |
35 | netif_receive_skb); | 37 | netif_receive_skb); |
36 | } | 38 | } |
37 | 39 | ||
@@ -154,7 +156,7 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) | |||
154 | if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) | 156 | if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) |
155 | goto forward; | 157 | goto forward; |
156 | 158 | ||
157 | if (NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | 159 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
158 | NULL, br_handle_local_finish)) | 160 | NULL, br_handle_local_finish)) |
159 | return NULL; /* frame consumed by filter */ | 161 | return NULL; /* frame consumed by filter */ |
160 | else | 162 | else |
@@ -175,7 +177,7 @@ forward: | |||
175 | if (!compare_ether_addr(p->br->dev->dev_addr, dest)) | 177 | if (!compare_ether_addr(p->br->dev->dev_addr, dest)) |
176 | skb->pkt_type = PACKET_HOST; | 178 | skb->pkt_type = PACKET_HOST; |
177 | 179 | ||
178 | NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, | 180 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, |
179 | br_handle_frame_finish); | 181 | br_handle_frame_finish); |
180 | break; | 182 | break; |
181 | default: | 183 | default: |
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 995afc4b04dc..cb43312b846e 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c | |||
@@ -412,6 +412,6 @@ int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
412 | 412 | ||
413 | } | 413 | } |
414 | 414 | ||
415 | pr_debug("Bridge does not support ioctl 0x%x\n", cmd); | 415 | br_debug(br, "Bridge does not support ioctl 0x%x\n", cmd); |
416 | return -EOPNOTSUPP; | 416 | return -EOPNOTSUPP; |
417 | } | 417 | } |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index eaa0e1bae49b..9d21d98ae5fa 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -24,51 +24,139 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/timer.h> | 25 | #include <linux/timer.h> |
26 | #include <net/ip.h> | 26 | #include <net/ip.h> |
27 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
28 | #include <net/ipv6.h> | ||
29 | #include <net/mld.h> | ||
30 | #include <net/addrconf.h> | ||
31 | #include <net/ip6_checksum.h> | ||
32 | #endif | ||
27 | 33 | ||
28 | #include "br_private.h" | 34 | #include "br_private.h" |
29 | 35 | ||
30 | static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb, __be32 ip) | 36 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
37 | static inline int ipv6_is_local_multicast(const struct in6_addr *addr) | ||
31 | { | 38 | { |
32 | return jhash_1word(mdb->secret, (u32)ip) & (mdb->max - 1); | 39 | if (ipv6_addr_is_multicast(addr) && |
40 | IPV6_ADDR_MC_SCOPE(addr) <= IPV6_ADDR_SCOPE_LINKLOCAL) | ||
41 | return 1; | ||
42 | return 0; | ||
43 | } | ||
44 | #endif | ||
45 | |||
46 | static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) | ||
47 | { | ||
48 | if (a->proto != b->proto) | ||
49 | return 0; | ||
50 | switch (a->proto) { | ||
51 | case htons(ETH_P_IP): | ||
52 | return a->u.ip4 == b->u.ip4; | ||
53 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
54 | case htons(ETH_P_IPV6): | ||
55 | return ipv6_addr_equal(&a->u.ip6, &b->u.ip6); | ||
56 | #endif | ||
57 | } | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static inline int __br_ip4_hash(struct net_bridge_mdb_htable *mdb, __be32 ip) | ||
62 | { | ||
63 | return jhash_1word(mdb->secret, (__force u32)ip) & (mdb->max - 1); | ||
64 | } | ||
65 | |||
66 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
67 | static inline int __br_ip6_hash(struct net_bridge_mdb_htable *mdb, | ||
68 | const struct in6_addr *ip) | ||
69 | { | ||
70 | return jhash2((__force u32 *)ip->s6_addr32, 4, mdb->secret) & (mdb->max - 1); | ||
71 | } | ||
72 | #endif | ||
73 | |||
74 | static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb, | ||
75 | struct br_ip *ip) | ||
76 | { | ||
77 | switch (ip->proto) { | ||
78 | case htons(ETH_P_IP): | ||
79 | return __br_ip4_hash(mdb, ip->u.ip4); | ||
80 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
81 | case htons(ETH_P_IPV6): | ||
82 | return __br_ip6_hash(mdb, &ip->u.ip6); | ||
83 | #endif | ||
84 | } | ||
85 | return 0; | ||
33 | } | 86 | } |
34 | 87 | ||
35 | static struct net_bridge_mdb_entry *__br_mdb_ip_get( | 88 | static struct net_bridge_mdb_entry *__br_mdb_ip_get( |
36 | struct net_bridge_mdb_htable *mdb, __be32 dst, int hash) | 89 | struct net_bridge_mdb_htable *mdb, struct br_ip *dst, int hash) |
37 | { | 90 | { |
38 | struct net_bridge_mdb_entry *mp; | 91 | struct net_bridge_mdb_entry *mp; |
39 | struct hlist_node *p; | 92 | struct hlist_node *p; |
40 | 93 | ||
41 | hlist_for_each_entry_rcu(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { | 94 | hlist_for_each_entry_rcu(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { |
42 | if (dst == mp->addr) | 95 | if (br_ip_equal(&mp->addr, dst)) |
43 | return mp; | 96 | return mp; |
44 | } | 97 | } |
45 | 98 | ||
46 | return NULL; | 99 | return NULL; |
47 | } | 100 | } |
48 | 101 | ||
49 | static struct net_bridge_mdb_entry *br_mdb_ip_get( | 102 | static struct net_bridge_mdb_entry *br_mdb_ip4_get( |
50 | struct net_bridge_mdb_htable *mdb, __be32 dst) | 103 | struct net_bridge_mdb_htable *mdb, __be32 dst) |
51 | { | 104 | { |
52 | if (!mdb) | 105 | struct br_ip br_dst; |
53 | return NULL; | 106 | |
107 | br_dst.u.ip4 = dst; | ||
108 | br_dst.proto = htons(ETH_P_IP); | ||
109 | |||
110 | return __br_mdb_ip_get(mdb, &br_dst, __br_ip4_hash(mdb, dst)); | ||
111 | } | ||
112 | |||
113 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
114 | static struct net_bridge_mdb_entry *br_mdb_ip6_get( | ||
115 | struct net_bridge_mdb_htable *mdb, const struct in6_addr *dst) | ||
116 | { | ||
117 | struct br_ip br_dst; | ||
118 | |||
119 | ipv6_addr_copy(&br_dst.u.ip6, dst); | ||
120 | br_dst.proto = htons(ETH_P_IPV6); | ||
54 | 121 | ||
122 | return __br_mdb_ip_get(mdb, &br_dst, __br_ip6_hash(mdb, dst)); | ||
123 | } | ||
124 | #endif | ||
125 | |||
126 | static struct net_bridge_mdb_entry *br_mdb_ip_get( | ||
127 | struct net_bridge_mdb_htable *mdb, struct br_ip *dst) | ||
128 | { | ||
55 | return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); | 129 | return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); |
56 | } | 130 | } |
57 | 131 | ||
58 | struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, | 132 | struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, |
59 | struct sk_buff *skb) | 133 | struct sk_buff *skb) |
60 | { | 134 | { |
61 | if (br->multicast_disabled) | 135 | struct net_bridge_mdb_htable *mdb = br->mdb; |
136 | struct br_ip ip; | ||
137 | |||
138 | if (!mdb || br->multicast_disabled) | ||
62 | return NULL; | 139 | return NULL; |
63 | 140 | ||
141 | if (BR_INPUT_SKB_CB(skb)->igmp) | ||
142 | return NULL; | ||
143 | |||
144 | ip.proto = skb->protocol; | ||
145 | |||
64 | switch (skb->protocol) { | 146 | switch (skb->protocol) { |
65 | case htons(ETH_P_IP): | 147 | case htons(ETH_P_IP): |
66 | if (BR_INPUT_SKB_CB(skb)->igmp) | 148 | ip.u.ip4 = ip_hdr(skb)->daddr; |
67 | break; | 149 | break; |
68 | return br_mdb_ip_get(br->mdb, ip_hdr(skb)->daddr); | 150 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
151 | case htons(ETH_P_IPV6): | ||
152 | ipv6_addr_copy(&ip.u.ip6, &ipv6_hdr(skb)->daddr); | ||
153 | break; | ||
154 | #endif | ||
155 | default: | ||
156 | return NULL; | ||
69 | } | 157 | } |
70 | 158 | ||
71 | return NULL; | 159 | return br_mdb_ip_get(mdb, &ip); |
72 | } | 160 | } |
73 | 161 | ||
74 | static void br_mdb_free(struct rcu_head *head) | 162 | static void br_mdb_free(struct rcu_head *head) |
@@ -95,7 +183,7 @@ static int br_mdb_copy(struct net_bridge_mdb_htable *new, | |||
95 | for (i = 0; i < old->max; i++) | 183 | for (i = 0; i < old->max; i++) |
96 | hlist_for_each_entry(mp, p, &old->mhash[i], hlist[old->ver]) | 184 | hlist_for_each_entry(mp, p, &old->mhash[i], hlist[old->ver]) |
97 | hlist_add_head(&mp->hlist[new->ver], | 185 | hlist_add_head(&mp->hlist[new->ver], |
98 | &new->mhash[br_ip_hash(new, mp->addr)]); | 186 | &new->mhash[br_ip_hash(new, &mp->addr)]); |
99 | 187 | ||
100 | if (!elasticity) | 188 | if (!elasticity) |
101 | return 0; | 189 | return 0; |
@@ -163,7 +251,7 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
163 | struct net_bridge_port_group *p; | 251 | struct net_bridge_port_group *p; |
164 | struct net_bridge_port_group **pp; | 252 | struct net_bridge_port_group **pp; |
165 | 253 | ||
166 | mp = br_mdb_ip_get(mdb, pg->addr); | 254 | mp = br_mdb_ip_get(mdb, &pg->addr); |
167 | if (WARN_ON(!mp)) | 255 | if (WARN_ON(!mp)) |
168 | return; | 256 | return; |
169 | 257 | ||
@@ -171,7 +259,7 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
171 | if (p != pg) | 259 | if (p != pg) |
172 | continue; | 260 | continue; |
173 | 261 | ||
174 | *pp = p->next; | 262 | rcu_assign_pointer(*pp, p->next); |
175 | hlist_del_init(&p->mglist); | 263 | hlist_del_init(&p->mglist); |
176 | del_timer(&p->timer); | 264 | del_timer(&p->timer); |
177 | del_timer(&p->query_timer); | 265 | del_timer(&p->query_timer); |
@@ -249,8 +337,8 @@ out: | |||
249 | return 0; | 337 | return 0; |
250 | } | 338 | } |
251 | 339 | ||
252 | static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, | 340 | static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, |
253 | __be32 group) | 341 | __be32 group) |
254 | { | 342 | { |
255 | struct sk_buff *skb; | 343 | struct sk_buff *skb; |
256 | struct igmphdr *ih; | 344 | struct igmphdr *ih; |
@@ -314,12 +402,104 @@ out: | |||
314 | return skb; | 402 | return skb; |
315 | } | 403 | } |
316 | 404 | ||
405 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
406 | static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | ||
407 | struct in6_addr *group) | ||
408 | { | ||
409 | struct sk_buff *skb; | ||
410 | struct ipv6hdr *ip6h; | ||
411 | struct mld_msg *mldq; | ||
412 | struct ethhdr *eth; | ||
413 | u8 *hopopt; | ||
414 | unsigned long interval; | ||
415 | |||
416 | skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*ip6h) + | ||
417 | 8 + sizeof(*mldq)); | ||
418 | if (!skb) | ||
419 | goto out; | ||
420 | |||
421 | skb->protocol = htons(ETH_P_IPV6); | ||
422 | |||
423 | /* Ethernet header */ | ||
424 | skb_reset_mac_header(skb); | ||
425 | eth = eth_hdr(skb); | ||
426 | |||
427 | memcpy(eth->h_source, br->dev->dev_addr, 6); | ||
428 | ipv6_eth_mc_map(group, eth->h_dest); | ||
429 | eth->h_proto = htons(ETH_P_IPV6); | ||
430 | skb_put(skb, sizeof(*eth)); | ||
431 | |||
432 | /* IPv6 header + HbH option */ | ||
433 | skb_set_network_header(skb, skb->len); | ||
434 | ip6h = ipv6_hdr(skb); | ||
435 | |||
436 | *(__force __be32 *)ip6h = htonl(0x60000000); | ||
437 | ip6h->payload_len = 8 + sizeof(*mldq); | ||
438 | ip6h->nexthdr = IPPROTO_HOPOPTS; | ||
439 | ip6h->hop_limit = 1; | ||
440 | ipv6_addr_set(&ip6h->saddr, 0, 0, 0, 0); | ||
441 | ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1)); | ||
442 | |||
443 | hopopt = (u8 *)(ip6h + 1); | ||
444 | hopopt[0] = IPPROTO_ICMPV6; /* next hdr */ | ||
445 | hopopt[1] = 0; /* length of HbH */ | ||
446 | hopopt[2] = IPV6_TLV_ROUTERALERT; /* Router Alert */ | ||
447 | hopopt[3] = 2; /* Length of RA Option */ | ||
448 | hopopt[4] = 0; /* Type = 0x0000 (MLD) */ | ||
449 | hopopt[5] = 0; | ||
450 | hopopt[6] = IPV6_TLV_PAD0; /* Pad0 */ | ||
451 | hopopt[7] = IPV6_TLV_PAD0; /* Pad0 */ | ||
452 | |||
453 | skb_put(skb, sizeof(*ip6h) + 8); | ||
454 | |||
455 | /* ICMPv6 */ | ||
456 | skb_set_transport_header(skb, skb->len); | ||
457 | mldq = (struct mld_msg *) icmp6_hdr(skb); | ||
458 | |||
459 | interval = ipv6_addr_any(group) ? br->multicast_last_member_interval : | ||
460 | br->multicast_query_response_interval; | ||
461 | |||
462 | mldq->mld_type = ICMPV6_MGM_QUERY; | ||
463 | mldq->mld_code = 0; | ||
464 | mldq->mld_cksum = 0; | ||
465 | mldq->mld_maxdelay = htons((u16)jiffies_to_msecs(interval)); | ||
466 | mldq->mld_reserved = 0; | ||
467 | ipv6_addr_copy(&mldq->mld_mca, group); | ||
468 | |||
469 | /* checksum */ | ||
470 | mldq->mld_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, | ||
471 | sizeof(*mldq), IPPROTO_ICMPV6, | ||
472 | csum_partial(mldq, | ||
473 | sizeof(*mldq), 0)); | ||
474 | skb_put(skb, sizeof(*mldq)); | ||
475 | |||
476 | __skb_pull(skb, sizeof(*eth)); | ||
477 | |||
478 | out: | ||
479 | return skb; | ||
480 | } | ||
481 | #endif | ||
482 | |||
483 | static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, | ||
484 | struct br_ip *addr) | ||
485 | { | ||
486 | switch (addr->proto) { | ||
487 | case htons(ETH_P_IP): | ||
488 | return br_ip4_multicast_alloc_query(br, addr->u.ip4); | ||
489 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
490 | case htons(ETH_P_IPV6): | ||
491 | return br_ip6_multicast_alloc_query(br, &addr->u.ip6); | ||
492 | #endif | ||
493 | } | ||
494 | return NULL; | ||
495 | } | ||
496 | |||
317 | static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) | 497 | static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) |
318 | { | 498 | { |
319 | struct net_bridge *br = mp->br; | 499 | struct net_bridge *br = mp->br; |
320 | struct sk_buff *skb; | 500 | struct sk_buff *skb; |
321 | 501 | ||
322 | skb = br_multicast_alloc_query(br, mp->addr); | 502 | skb = br_multicast_alloc_query(br, &mp->addr); |
323 | if (!skb) | 503 | if (!skb) |
324 | goto timer; | 504 | goto timer; |
325 | 505 | ||
@@ -353,7 +533,7 @@ static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg) | |||
353 | struct net_bridge *br = port->br; | 533 | struct net_bridge *br = port->br; |
354 | struct sk_buff *skb; | 534 | struct sk_buff *skb; |
355 | 535 | ||
356 | skb = br_multicast_alloc_query(br, pg->addr); | 536 | skb = br_multicast_alloc_query(br, &pg->addr); |
357 | if (!skb) | 537 | if (!skb) |
358 | goto timer; | 538 | goto timer; |
359 | 539 | ||
@@ -383,8 +563,8 @@ out: | |||
383 | } | 563 | } |
384 | 564 | ||
385 | static struct net_bridge_mdb_entry *br_multicast_get_group( | 565 | static struct net_bridge_mdb_entry *br_multicast_get_group( |
386 | struct net_bridge *br, struct net_bridge_port *port, __be32 group, | 566 | struct net_bridge *br, struct net_bridge_port *port, |
387 | int hash) | 567 | struct br_ip *group, int hash) |
388 | { | 568 | { |
389 | struct net_bridge_mdb_htable *mdb = br->mdb; | 569 | struct net_bridge_mdb_htable *mdb = br->mdb; |
390 | struct net_bridge_mdb_entry *mp; | 570 | struct net_bridge_mdb_entry *mp; |
@@ -396,9 +576,8 @@ static struct net_bridge_mdb_entry *br_multicast_get_group( | |||
396 | 576 | ||
397 | hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { | 577 | hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { |
398 | count++; | 578 | count++; |
399 | if (unlikely(group == mp->addr)) { | 579 | if (unlikely(br_ip_equal(group, &mp->addr))) |
400 | return mp; | 580 | return mp; |
401 | } | ||
402 | } | 581 | } |
403 | 582 | ||
404 | elasticity = 0; | 583 | elasticity = 0; |
@@ -406,10 +585,9 @@ static struct net_bridge_mdb_entry *br_multicast_get_group( | |||
406 | 585 | ||
407 | if (unlikely(count > br->hash_elasticity && count)) { | 586 | if (unlikely(count > br->hash_elasticity && count)) { |
408 | if (net_ratelimit()) | 587 | if (net_ratelimit()) |
409 | printk(KERN_INFO "%s: Multicast hash table " | 588 | br_info(br, "Multicast hash table " |
410 | "chain limit reached: %s\n", | 589 | "chain limit reached: %s\n", |
411 | br->dev->name, port ? port->dev->name : | 590 | port ? port->dev->name : br->dev->name); |
412 | br->dev->name); | ||
413 | 591 | ||
414 | elasticity = br->hash_elasticity; | 592 | elasticity = br->hash_elasticity; |
415 | } | 593 | } |
@@ -417,11 +595,9 @@ static struct net_bridge_mdb_entry *br_multicast_get_group( | |||
417 | if (mdb->size >= max) { | 595 | if (mdb->size >= max) { |
418 | max *= 2; | 596 | max *= 2; |
419 | if (unlikely(max >= br->hash_max)) { | 597 | if (unlikely(max >= br->hash_max)) { |
420 | printk(KERN_WARNING "%s: Multicast hash table maximum " | 598 | br_warn(br, "Multicast hash table maximum " |
421 | "reached, disabling snooping: %s, %d\n", | 599 | "reached, disabling snooping: %s, %d\n", |
422 | br->dev->name, port ? port->dev->name : | 600 | port ? port->dev->name : br->dev->name, max); |
423 | br->dev->name, | ||
424 | max); | ||
425 | err = -E2BIG; | 601 | err = -E2BIG; |
426 | disable: | 602 | disable: |
427 | br->multicast_disabled = 1; | 603 | br->multicast_disabled = 1; |
@@ -432,22 +608,19 @@ disable: | |||
432 | if (max > mdb->max || elasticity) { | 608 | if (max > mdb->max || elasticity) { |
433 | if (mdb->old) { | 609 | if (mdb->old) { |
434 | if (net_ratelimit()) | 610 | if (net_ratelimit()) |
435 | printk(KERN_INFO "%s: Multicast hash table " | 611 | br_info(br, "Multicast hash table " |
436 | "on fire: %s\n", | 612 | "on fire: %s\n", |
437 | br->dev->name, port ? port->dev->name : | 613 | port ? port->dev->name : br->dev->name); |
438 | br->dev->name); | ||
439 | err = -EEXIST; | 614 | err = -EEXIST; |
440 | goto err; | 615 | goto err; |
441 | } | 616 | } |
442 | 617 | ||
443 | err = br_mdb_rehash(&br->mdb, max, elasticity); | 618 | err = br_mdb_rehash(&br->mdb, max, elasticity); |
444 | if (err) { | 619 | if (err) { |
445 | printk(KERN_WARNING "%s: Cannot rehash multicast " | 620 | br_warn(br, "Cannot rehash multicast " |
446 | "hash table, disabling snooping: " | 621 | "hash table, disabling snooping: %s, %d, %d\n", |
447 | "%s, %d, %d\n", | 622 | port ? port->dev->name : br->dev->name, |
448 | br->dev->name, port ? port->dev->name : | 623 | mdb->size, err); |
449 | br->dev->name, | ||
450 | mdb->size, err); | ||
451 | goto disable; | 624 | goto disable; |
452 | } | 625 | } |
453 | 626 | ||
@@ -463,7 +636,8 @@ err: | |||
463 | } | 636 | } |
464 | 637 | ||
465 | static struct net_bridge_mdb_entry *br_multicast_new_group( | 638 | static struct net_bridge_mdb_entry *br_multicast_new_group( |
466 | struct net_bridge *br, struct net_bridge_port *port, __be32 group) | 639 | struct net_bridge *br, struct net_bridge_port *port, |
640 | struct br_ip *group) | ||
467 | { | 641 | { |
468 | struct net_bridge_mdb_htable *mdb = br->mdb; | 642 | struct net_bridge_mdb_htable *mdb = br->mdb; |
469 | struct net_bridge_mdb_entry *mp; | 643 | struct net_bridge_mdb_entry *mp; |
@@ -496,7 +670,7 @@ rehash: | |||
496 | goto out; | 670 | goto out; |
497 | 671 | ||
498 | mp->br = br; | 672 | mp->br = br; |
499 | mp->addr = group; | 673 | mp->addr = *group; |
500 | setup_timer(&mp->timer, br_multicast_group_expired, | 674 | setup_timer(&mp->timer, br_multicast_group_expired, |
501 | (unsigned long)mp); | 675 | (unsigned long)mp); |
502 | setup_timer(&mp->query_timer, br_multicast_group_query_expired, | 676 | setup_timer(&mp->query_timer, br_multicast_group_query_expired, |
@@ -510,7 +684,8 @@ out: | |||
510 | } | 684 | } |
511 | 685 | ||
512 | static int br_multicast_add_group(struct net_bridge *br, | 686 | static int br_multicast_add_group(struct net_bridge *br, |
513 | struct net_bridge_port *port, __be32 group) | 687 | struct net_bridge_port *port, |
688 | struct br_ip *group) | ||
514 | { | 689 | { |
515 | struct net_bridge_mdb_entry *mp; | 690 | struct net_bridge_mdb_entry *mp; |
516 | struct net_bridge_port_group *p; | 691 | struct net_bridge_port_group *p; |
@@ -518,9 +693,6 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
518 | unsigned long now = jiffies; | 693 | unsigned long now = jiffies; |
519 | int err; | 694 | int err; |
520 | 695 | ||
521 | if (ipv4_is_local_multicast(group)) | ||
522 | return 0; | ||
523 | |||
524 | spin_lock(&br->multicast_lock); | 696 | spin_lock(&br->multicast_lock); |
525 | if (!netif_running(br->dev) || | 697 | if (!netif_running(br->dev) || |
526 | (port && port->state == BR_STATE_DISABLED)) | 698 | (port && port->state == BR_STATE_DISABLED)) |
@@ -549,7 +721,7 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
549 | if (unlikely(!p)) | 721 | if (unlikely(!p)) |
550 | goto err; | 722 | goto err; |
551 | 723 | ||
552 | p->addr = group; | 724 | p->addr = *group; |
553 | p->port = port; | 725 | p->port = port; |
554 | p->next = *pp; | 726 | p->next = *pp; |
555 | hlist_add_head(&p->mglist, &port->mglist); | 727 | hlist_add_head(&p->mglist, &port->mglist); |
@@ -570,6 +742,38 @@ err: | |||
570 | return err; | 742 | return err; |
571 | } | 743 | } |
572 | 744 | ||
745 | static int br_ip4_multicast_add_group(struct net_bridge *br, | ||
746 | struct net_bridge_port *port, | ||
747 | __be32 group) | ||
748 | { | ||
749 | struct br_ip br_group; | ||
750 | |||
751 | if (ipv4_is_local_multicast(group)) | ||
752 | return 0; | ||
753 | |||
754 | br_group.u.ip4 = group; | ||
755 | br_group.proto = htons(ETH_P_IP); | ||
756 | |||
757 | return br_multicast_add_group(br, port, &br_group); | ||
758 | } | ||
759 | |||
760 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
761 | static int br_ip6_multicast_add_group(struct net_bridge *br, | ||
762 | struct net_bridge_port *port, | ||
763 | const struct in6_addr *group) | ||
764 | { | ||
765 | struct br_ip br_group; | ||
766 | |||
767 | if (ipv6_is_local_multicast(group)) | ||
768 | return 0; | ||
769 | |||
770 | ipv6_addr_copy(&br_group.u.ip6, group); | ||
771 | br_group.proto = htons(ETH_P_IP); | ||
772 | |||
773 | return br_multicast_add_group(br, port, &br_group); | ||
774 | } | ||
775 | #endif | ||
776 | |||
573 | static void br_multicast_router_expired(unsigned long data) | 777 | static void br_multicast_router_expired(unsigned long data) |
574 | { | 778 | { |
575 | struct net_bridge_port *port = (void *)data; | 779 | struct net_bridge_port *port = (void *)data; |
@@ -591,29 +795,45 @@ static void br_multicast_local_router_expired(unsigned long data) | |||
591 | { | 795 | { |
592 | } | 796 | } |
593 | 797 | ||
594 | static void br_multicast_send_query(struct net_bridge *br, | 798 | static void __br_multicast_send_query(struct net_bridge *br, |
595 | struct net_bridge_port *port, u32 sent) | 799 | struct net_bridge_port *port, |
800 | struct br_ip *ip) | ||
596 | { | 801 | { |
597 | unsigned long time; | ||
598 | struct sk_buff *skb; | 802 | struct sk_buff *skb; |
599 | 803 | ||
600 | if (!netif_running(br->dev) || br->multicast_disabled || | 804 | skb = br_multicast_alloc_query(br, ip); |
601 | timer_pending(&br->multicast_querier_timer)) | ||
602 | return; | ||
603 | |||
604 | skb = br_multicast_alloc_query(br, 0); | ||
605 | if (!skb) | 805 | if (!skb) |
606 | goto timer; | 806 | return; |
607 | 807 | ||
608 | if (port) { | 808 | if (port) { |
609 | __skb_push(skb, sizeof(struct ethhdr)); | 809 | __skb_push(skb, sizeof(struct ethhdr)); |
610 | skb->dev = port->dev; | 810 | skb->dev = port->dev; |
611 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, | 811 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, |
612 | dev_queue_xmit); | 812 | dev_queue_xmit); |
613 | } else | 813 | } else |
614 | netif_rx(skb); | 814 | netif_rx(skb); |
815 | } | ||
816 | |||
817 | static void br_multicast_send_query(struct net_bridge *br, | ||
818 | struct net_bridge_port *port, u32 sent) | ||
819 | { | ||
820 | unsigned long time; | ||
821 | struct br_ip br_group; | ||
822 | |||
823 | if (!netif_running(br->dev) || br->multicast_disabled || | ||
824 | timer_pending(&br->multicast_querier_timer)) | ||
825 | return; | ||
826 | |||
827 | memset(&br_group.u, 0, sizeof(br_group.u)); | ||
828 | |||
829 | br_group.proto = htons(ETH_P_IP); | ||
830 | __br_multicast_send_query(br, port, &br_group); | ||
831 | |||
832 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
833 | br_group.proto = htons(ETH_P_IPV6); | ||
834 | __br_multicast_send_query(br, port, &br_group); | ||
835 | #endif | ||
615 | 836 | ||
616 | timer: | ||
617 | time = jiffies; | 837 | time = jiffies; |
618 | time += sent < br->multicast_startup_query_count ? | 838 | time += sent < br->multicast_startup_query_count ? |
619 | br->multicast_startup_query_interval : | 839 | br->multicast_startup_query_interval : |
@@ -698,9 +918,9 @@ void br_multicast_disable_port(struct net_bridge_port *port) | |||
698 | spin_unlock(&br->multicast_lock); | 918 | spin_unlock(&br->multicast_lock); |
699 | } | 919 | } |
700 | 920 | ||
701 | static int br_multicast_igmp3_report(struct net_bridge *br, | 921 | static int br_ip4_multicast_igmp3_report(struct net_bridge *br, |
702 | struct net_bridge_port *port, | 922 | struct net_bridge_port *port, |
703 | struct sk_buff *skb) | 923 | struct sk_buff *skb) |
704 | { | 924 | { |
705 | struct igmpv3_report *ih; | 925 | struct igmpv3_report *ih; |
706 | struct igmpv3_grec *grec; | 926 | struct igmpv3_grec *grec; |
@@ -745,7 +965,7 @@ static int br_multicast_igmp3_report(struct net_bridge *br, | |||
745 | continue; | 965 | continue; |
746 | } | 966 | } |
747 | 967 | ||
748 | err = br_multicast_add_group(br, port, group); | 968 | err = br_ip4_multicast_add_group(br, port, group); |
749 | if (err) | 969 | if (err) |
750 | break; | 970 | break; |
751 | } | 971 | } |
@@ -753,24 +973,87 @@ static int br_multicast_igmp3_report(struct net_bridge *br, | |||
753 | return err; | 973 | return err; |
754 | } | 974 | } |
755 | 975 | ||
976 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
977 | static int br_ip6_multicast_mld2_report(struct net_bridge *br, | ||
978 | struct net_bridge_port *port, | ||
979 | struct sk_buff *skb) | ||
980 | { | ||
981 | struct icmp6hdr *icmp6h; | ||
982 | struct mld2_grec *grec; | ||
983 | int i; | ||
984 | int len; | ||
985 | int num; | ||
986 | int err = 0; | ||
987 | |||
988 | if (!pskb_may_pull(skb, sizeof(*icmp6h))) | ||
989 | return -EINVAL; | ||
990 | |||
991 | icmp6h = icmp6_hdr(skb); | ||
992 | num = ntohs(icmp6h->icmp6_dataun.un_data16[1]); | ||
993 | len = sizeof(*icmp6h); | ||
994 | |||
995 | for (i = 0; i < num; i++) { | ||
996 | __be16 *nsrcs, _nsrcs; | ||
997 | |||
998 | nsrcs = skb_header_pointer(skb, | ||
999 | len + offsetof(struct mld2_grec, | ||
1000 | grec_mca), | ||
1001 | sizeof(_nsrcs), &_nsrcs); | ||
1002 | if (!nsrcs) | ||
1003 | return -EINVAL; | ||
1004 | |||
1005 | if (!pskb_may_pull(skb, | ||
1006 | len + sizeof(*grec) + | ||
1007 | sizeof(struct in6_addr) * (*nsrcs))) | ||
1008 | return -EINVAL; | ||
1009 | |||
1010 | grec = (struct mld2_grec *)(skb->data + len); | ||
1011 | len += sizeof(*grec) + sizeof(struct in6_addr) * (*nsrcs); | ||
1012 | |||
1013 | /* We treat these as MLDv1 reports for now. */ | ||
1014 | switch (grec->grec_type) { | ||
1015 | case MLD2_MODE_IS_INCLUDE: | ||
1016 | case MLD2_MODE_IS_EXCLUDE: | ||
1017 | case MLD2_CHANGE_TO_INCLUDE: | ||
1018 | case MLD2_CHANGE_TO_EXCLUDE: | ||
1019 | case MLD2_ALLOW_NEW_SOURCES: | ||
1020 | case MLD2_BLOCK_OLD_SOURCES: | ||
1021 | break; | ||
1022 | |||
1023 | default: | ||
1024 | continue; | ||
1025 | } | ||
1026 | |||
1027 | err = br_ip6_multicast_add_group(br, port, &grec->grec_mca); | ||
1028 | if (!err) | ||
1029 | break; | ||
1030 | } | ||
1031 | |||
1032 | return err; | ||
1033 | } | ||
1034 | #endif | ||
1035 | |||
1036 | /* | ||
1037 | * Add port to rotuer_list | ||
1038 | * list is maintained ordered by pointer value | ||
1039 | * and locked by br->multicast_lock and RCU | ||
1040 | */ | ||
756 | static void br_multicast_add_router(struct net_bridge *br, | 1041 | static void br_multicast_add_router(struct net_bridge *br, |
757 | struct net_bridge_port *port) | 1042 | struct net_bridge_port *port) |
758 | { | 1043 | { |
759 | struct hlist_node *p; | 1044 | struct net_bridge_port *p; |
760 | struct hlist_node **h; | 1045 | struct hlist_node *n, *slot = NULL; |
761 | 1046 | ||
762 | for (h = &br->router_list.first; | 1047 | hlist_for_each_entry(p, n, &br->router_list, rlist) { |
763 | (p = *h) && | 1048 | if ((unsigned long) port >= (unsigned long) p) |
764 | (unsigned long)container_of(p, struct net_bridge_port, rlist) > | 1049 | break; |
765 | (unsigned long)port; | 1050 | slot = n; |
766 | h = &p->next) | 1051 | } |
767 | ; | 1052 | |
768 | 1053 | if (slot) | |
769 | port->rlist.pprev = h; | 1054 | hlist_add_after_rcu(slot, &port->rlist); |
770 | port->rlist.next = p; | 1055 | else |
771 | rcu_assign_pointer(*h, &port->rlist); | 1056 | hlist_add_head_rcu(&port->rlist, &br->router_list); |
772 | if (p) | ||
773 | p->pprev = &port->rlist.next; | ||
774 | } | 1057 | } |
775 | 1058 | ||
776 | static void br_multicast_mark_router(struct net_bridge *br, | 1059 | static void br_multicast_mark_router(struct net_bridge *br, |
@@ -800,7 +1083,7 @@ timer: | |||
800 | 1083 | ||
801 | static void br_multicast_query_received(struct net_bridge *br, | 1084 | static void br_multicast_query_received(struct net_bridge *br, |
802 | struct net_bridge_port *port, | 1085 | struct net_bridge_port *port, |
803 | __be32 saddr) | 1086 | int saddr) |
804 | { | 1087 | { |
805 | if (saddr) | 1088 | if (saddr) |
806 | mod_timer(&br->multicast_querier_timer, | 1089 | mod_timer(&br->multicast_querier_timer, |
@@ -811,9 +1094,9 @@ static void br_multicast_query_received(struct net_bridge *br, | |||
811 | br_multicast_mark_router(br, port); | 1094 | br_multicast_mark_router(br, port); |
812 | } | 1095 | } |
813 | 1096 | ||
814 | static int br_multicast_query(struct net_bridge *br, | 1097 | static int br_ip4_multicast_query(struct net_bridge *br, |
815 | struct net_bridge_port *port, | 1098 | struct net_bridge_port *port, |
816 | struct sk_buff *skb) | 1099 | struct sk_buff *skb) |
817 | { | 1100 | { |
818 | struct iphdr *iph = ip_hdr(skb); | 1101 | struct iphdr *iph = ip_hdr(skb); |
819 | struct igmphdr *ih = igmp_hdr(skb); | 1102 | struct igmphdr *ih = igmp_hdr(skb); |
@@ -831,7 +1114,7 @@ static int br_multicast_query(struct net_bridge *br, | |||
831 | (port && port->state == BR_STATE_DISABLED)) | 1114 | (port && port->state == BR_STATE_DISABLED)) |
832 | goto out; | 1115 | goto out; |
833 | 1116 | ||
834 | br_multicast_query_received(br, port, iph->saddr); | 1117 | br_multicast_query_received(br, port, !!iph->saddr); |
835 | 1118 | ||
836 | group = ih->group; | 1119 | group = ih->group; |
837 | 1120 | ||
@@ -859,7 +1142,7 @@ static int br_multicast_query(struct net_bridge *br, | |||
859 | if (!group) | 1142 | if (!group) |
860 | goto out; | 1143 | goto out; |
861 | 1144 | ||
862 | mp = br_mdb_ip_get(br->mdb, group); | 1145 | mp = br_mdb_ip4_get(br->mdb, group); |
863 | if (!mp) | 1146 | if (!mp) |
864 | goto out; | 1147 | goto out; |
865 | 1148 | ||
@@ -883,9 +1166,78 @@ out: | |||
883 | return err; | 1166 | return err; |
884 | } | 1167 | } |
885 | 1168 | ||
1169 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1170 | static int br_ip6_multicast_query(struct net_bridge *br, | ||
1171 | struct net_bridge_port *port, | ||
1172 | struct sk_buff *skb) | ||
1173 | { | ||
1174 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | ||
1175 | struct mld_msg *mld = (struct mld_msg *) icmp6_hdr(skb); | ||
1176 | struct net_bridge_mdb_entry *mp; | ||
1177 | struct mld2_query *mld2q; | ||
1178 | struct net_bridge_port_group *p, **pp; | ||
1179 | unsigned long max_delay; | ||
1180 | unsigned long now = jiffies; | ||
1181 | struct in6_addr *group = NULL; | ||
1182 | int err = 0; | ||
1183 | |||
1184 | spin_lock(&br->multicast_lock); | ||
1185 | if (!netif_running(br->dev) || | ||
1186 | (port && port->state == BR_STATE_DISABLED)) | ||
1187 | goto out; | ||
1188 | |||
1189 | br_multicast_query_received(br, port, !ipv6_addr_any(&ip6h->saddr)); | ||
1190 | |||
1191 | if (skb->len == sizeof(*mld)) { | ||
1192 | if (!pskb_may_pull(skb, sizeof(*mld))) { | ||
1193 | err = -EINVAL; | ||
1194 | goto out; | ||
1195 | } | ||
1196 | mld = (struct mld_msg *) icmp6_hdr(skb); | ||
1197 | max_delay = msecs_to_jiffies(htons(mld->mld_maxdelay)); | ||
1198 | if (max_delay) | ||
1199 | group = &mld->mld_mca; | ||
1200 | } else if (skb->len >= sizeof(*mld2q)) { | ||
1201 | if (!pskb_may_pull(skb, sizeof(*mld2q))) { | ||
1202 | err = -EINVAL; | ||
1203 | goto out; | ||
1204 | } | ||
1205 | mld2q = (struct mld2_query *)icmp6_hdr(skb); | ||
1206 | if (!mld2q->mld2q_nsrcs) | ||
1207 | group = &mld2q->mld2q_mca; | ||
1208 | max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(mld2q->mld2q_mrc) : 1; | ||
1209 | } | ||
1210 | |||
1211 | if (!group) | ||
1212 | goto out; | ||
1213 | |||
1214 | mp = br_mdb_ip6_get(br->mdb, group); | ||
1215 | if (!mp) | ||
1216 | goto out; | ||
1217 | |||
1218 | max_delay *= br->multicast_last_member_count; | ||
1219 | if (!hlist_unhashed(&mp->mglist) && | ||
1220 | (timer_pending(&mp->timer) ? | ||
1221 | time_after(mp->timer.expires, now + max_delay) : | ||
1222 | try_to_del_timer_sync(&mp->timer) >= 0)) | ||
1223 | mod_timer(&mp->timer, now + max_delay); | ||
1224 | |||
1225 | for (pp = &mp->ports; (p = *pp); pp = &p->next) { | ||
1226 | if (timer_pending(&p->timer) ? | ||
1227 | time_after(p->timer.expires, now + max_delay) : | ||
1228 | try_to_del_timer_sync(&p->timer) >= 0) | ||
1229 | mod_timer(&mp->timer, now + max_delay); | ||
1230 | } | ||
1231 | |||
1232 | out: | ||
1233 | spin_unlock(&br->multicast_lock); | ||
1234 | return err; | ||
1235 | } | ||
1236 | #endif | ||
1237 | |||
886 | static void br_multicast_leave_group(struct net_bridge *br, | 1238 | static void br_multicast_leave_group(struct net_bridge *br, |
887 | struct net_bridge_port *port, | 1239 | struct net_bridge_port *port, |
888 | __be32 group) | 1240 | struct br_ip *group) |
889 | { | 1241 | { |
890 | struct net_bridge_mdb_htable *mdb; | 1242 | struct net_bridge_mdb_htable *mdb; |
891 | struct net_bridge_mdb_entry *mp; | 1243 | struct net_bridge_mdb_entry *mp; |
@@ -893,9 +1245,6 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
893 | unsigned long now; | 1245 | unsigned long now; |
894 | unsigned long time; | 1246 | unsigned long time; |
895 | 1247 | ||
896 | if (ipv4_is_local_multicast(group)) | ||
897 | return; | ||
898 | |||
899 | spin_lock(&br->multicast_lock); | 1248 | spin_lock(&br->multicast_lock); |
900 | if (!netif_running(br->dev) || | 1249 | if (!netif_running(br->dev) || |
901 | (port && port->state == BR_STATE_DISABLED) || | 1250 | (port && port->state == BR_STATE_DISABLED) || |
@@ -946,6 +1295,38 @@ out: | |||
946 | spin_unlock(&br->multicast_lock); | 1295 | spin_unlock(&br->multicast_lock); |
947 | } | 1296 | } |
948 | 1297 | ||
1298 | static void br_ip4_multicast_leave_group(struct net_bridge *br, | ||
1299 | struct net_bridge_port *port, | ||
1300 | __be32 group) | ||
1301 | { | ||
1302 | struct br_ip br_group; | ||
1303 | |||
1304 | if (ipv4_is_local_multicast(group)) | ||
1305 | return; | ||
1306 | |||
1307 | br_group.u.ip4 = group; | ||
1308 | br_group.proto = htons(ETH_P_IP); | ||
1309 | |||
1310 | br_multicast_leave_group(br, port, &br_group); | ||
1311 | } | ||
1312 | |||
1313 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1314 | static void br_ip6_multicast_leave_group(struct net_bridge *br, | ||
1315 | struct net_bridge_port *port, | ||
1316 | const struct in6_addr *group) | ||
1317 | { | ||
1318 | struct br_ip br_group; | ||
1319 | |||
1320 | if (ipv6_is_local_multicast(group)) | ||
1321 | return; | ||
1322 | |||
1323 | ipv6_addr_copy(&br_group.u.ip6, group); | ||
1324 | br_group.proto = htons(ETH_P_IPV6); | ||
1325 | |||
1326 | br_multicast_leave_group(br, port, &br_group); | ||
1327 | } | ||
1328 | #endif | ||
1329 | |||
949 | static int br_multicast_ipv4_rcv(struct net_bridge *br, | 1330 | static int br_multicast_ipv4_rcv(struct net_bridge *br, |
950 | struct net_bridge_port *port, | 1331 | struct net_bridge_port *port, |
951 | struct sk_buff *skb) | 1332 | struct sk_buff *skb) |
@@ -1000,8 +1381,6 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1000 | if (!pskb_may_pull(skb2, sizeof(*ih))) | 1381 | if (!pskb_may_pull(skb2, sizeof(*ih))) |
1001 | goto out; | 1382 | goto out; |
1002 | 1383 | ||
1003 | iph = ip_hdr(skb2); | ||
1004 | |||
1005 | switch (skb2->ip_summed) { | 1384 | switch (skb2->ip_summed) { |
1006 | case CHECKSUM_COMPLETE: | 1385 | case CHECKSUM_COMPLETE: |
1007 | if (!csum_fold(skb2->csum)) | 1386 | if (!csum_fold(skb2->csum)) |
@@ -1022,16 +1401,16 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1022 | case IGMP_HOST_MEMBERSHIP_REPORT: | 1401 | case IGMP_HOST_MEMBERSHIP_REPORT: |
1023 | case IGMPV2_HOST_MEMBERSHIP_REPORT: | 1402 | case IGMPV2_HOST_MEMBERSHIP_REPORT: |
1024 | BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; | 1403 | BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; |
1025 | err = br_multicast_add_group(br, port, ih->group); | 1404 | err = br_ip4_multicast_add_group(br, port, ih->group); |
1026 | break; | 1405 | break; |
1027 | case IGMPV3_HOST_MEMBERSHIP_REPORT: | 1406 | case IGMPV3_HOST_MEMBERSHIP_REPORT: |
1028 | err = br_multicast_igmp3_report(br, port, skb2); | 1407 | err = br_ip4_multicast_igmp3_report(br, port, skb2); |
1029 | break; | 1408 | break; |
1030 | case IGMP_HOST_MEMBERSHIP_QUERY: | 1409 | case IGMP_HOST_MEMBERSHIP_QUERY: |
1031 | err = br_multicast_query(br, port, skb2); | 1410 | err = br_ip4_multicast_query(br, port, skb2); |
1032 | break; | 1411 | break; |
1033 | case IGMP_HOST_LEAVE_MESSAGE: | 1412 | case IGMP_HOST_LEAVE_MESSAGE: |
1034 | br_multicast_leave_group(br, port, ih->group); | 1413 | br_ip4_multicast_leave_group(br, port, ih->group); |
1035 | break; | 1414 | break; |
1036 | } | 1415 | } |
1037 | 1416 | ||
@@ -1043,6 +1422,123 @@ err_out: | |||
1043 | return err; | 1422 | return err; |
1044 | } | 1423 | } |
1045 | 1424 | ||
1425 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1426 | static int br_multicast_ipv6_rcv(struct net_bridge *br, | ||
1427 | struct net_bridge_port *port, | ||
1428 | struct sk_buff *skb) | ||
1429 | { | ||
1430 | struct sk_buff *skb2 = skb; | ||
1431 | struct ipv6hdr *ip6h; | ||
1432 | struct icmp6hdr *icmp6h; | ||
1433 | u8 nexthdr; | ||
1434 | unsigned len; | ||
1435 | unsigned offset; | ||
1436 | int err; | ||
1437 | |||
1438 | if (!pskb_may_pull(skb, sizeof(*ip6h))) | ||
1439 | return -EINVAL; | ||
1440 | |||
1441 | ip6h = ipv6_hdr(skb); | ||
1442 | |||
1443 | /* | ||
1444 | * We're interested in MLD messages only. | ||
1445 | * - Version is 6 | ||
1446 | * - MLD has always Router Alert hop-by-hop option | ||
1447 | * - But we do not support jumbrograms. | ||
1448 | */ | ||
1449 | if (ip6h->version != 6 || | ||
1450 | ip6h->nexthdr != IPPROTO_HOPOPTS || | ||
1451 | ip6h->payload_len == 0) | ||
1452 | return 0; | ||
1453 | |||
1454 | len = ntohs(ip6h->payload_len); | ||
1455 | if (skb->len < len) | ||
1456 | return -EINVAL; | ||
1457 | |||
1458 | nexthdr = ip6h->nexthdr; | ||
1459 | offset = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr); | ||
1460 | |||
1461 | if (offset < 0 || nexthdr != IPPROTO_ICMPV6) | ||
1462 | return 0; | ||
1463 | |||
1464 | /* Okay, we found ICMPv6 header */ | ||
1465 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
1466 | if (!skb2) | ||
1467 | return -ENOMEM; | ||
1468 | |||
1469 | len -= offset - skb_network_offset(skb2); | ||
1470 | |||
1471 | __skb_pull(skb2, offset); | ||
1472 | skb_reset_transport_header(skb2); | ||
1473 | |||
1474 | err = -EINVAL; | ||
1475 | if (!pskb_may_pull(skb2, sizeof(*icmp6h))) | ||
1476 | goto out; | ||
1477 | |||
1478 | icmp6h = icmp6_hdr(skb2); | ||
1479 | |||
1480 | switch (icmp6h->icmp6_type) { | ||
1481 | case ICMPV6_MGM_QUERY: | ||
1482 | case ICMPV6_MGM_REPORT: | ||
1483 | case ICMPV6_MGM_REDUCTION: | ||
1484 | case ICMPV6_MLD2_REPORT: | ||
1485 | break; | ||
1486 | default: | ||
1487 | err = 0; | ||
1488 | goto out; | ||
1489 | } | ||
1490 | |||
1491 | /* Okay, we found MLD message. Check further. */ | ||
1492 | if (skb2->len > len) { | ||
1493 | err = pskb_trim_rcsum(skb2, len); | ||
1494 | if (err) | ||
1495 | goto out; | ||
1496 | } | ||
1497 | |||
1498 | switch (skb2->ip_summed) { | ||
1499 | case CHECKSUM_COMPLETE: | ||
1500 | if (!csum_fold(skb2->csum)) | ||
1501 | break; | ||
1502 | /*FALLTHROUGH*/ | ||
1503 | case CHECKSUM_NONE: | ||
1504 | skb2->csum = 0; | ||
1505 | if (skb_checksum_complete(skb2)) | ||
1506 | goto out; | ||
1507 | } | ||
1508 | |||
1509 | err = 0; | ||
1510 | |||
1511 | BR_INPUT_SKB_CB(skb)->igmp = 1; | ||
1512 | |||
1513 | switch (icmp6h->icmp6_type) { | ||
1514 | case ICMPV6_MGM_REPORT: | ||
1515 | { | ||
1516 | struct mld_msg *mld = (struct mld_msg *)icmp6h; | ||
1517 | BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; | ||
1518 | err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); | ||
1519 | break; | ||
1520 | } | ||
1521 | case ICMPV6_MLD2_REPORT: | ||
1522 | err = br_ip6_multicast_mld2_report(br, port, skb2); | ||
1523 | break; | ||
1524 | case ICMPV6_MGM_QUERY: | ||
1525 | err = br_ip6_multicast_query(br, port, skb2); | ||
1526 | break; | ||
1527 | case ICMPV6_MGM_REDUCTION: | ||
1528 | { | ||
1529 | struct mld_msg *mld = (struct mld_msg *)icmp6h; | ||
1530 | br_ip6_multicast_leave_group(br, port, &mld->mld_mca); | ||
1531 | } | ||
1532 | } | ||
1533 | |||
1534 | out: | ||
1535 | __skb_push(skb2, offset); | ||
1536 | if (skb2 != skb) | ||
1537 | kfree_skb(skb2); | ||
1538 | return err; | ||
1539 | } | ||
1540 | #endif | ||
1541 | |||
1046 | int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, | 1542 | int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, |
1047 | struct sk_buff *skb) | 1543 | struct sk_buff *skb) |
1048 | { | 1544 | { |
@@ -1055,6 +1551,10 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, | |||
1055 | switch (skb->protocol) { | 1551 | switch (skb->protocol) { |
1056 | case htons(ETH_P_IP): | 1552 | case htons(ETH_P_IP): |
1057 | return br_multicast_ipv4_rcv(br, port, skb); | 1553 | return br_multicast_ipv4_rcv(br, port, skb); |
1554 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1555 | case htons(ETH_P_IPV6): | ||
1556 | return br_multicast_ipv6_rcv(br, port, skb); | ||
1557 | #endif | ||
1058 | } | 1558 | } |
1059 | 1559 | ||
1060 | return 0; | 1560 | return 0; |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 4c4977d12fd6..44420992f72f 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -3,15 +3,8 @@ | |||
3 | * Linux ethernet bridge | 3 | * Linux ethernet bridge |
4 | * | 4 | * |
5 | * Authors: | 5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> | 6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * Bart De Schuymer (maintainer) <bdschuym@pandora.be> | 7 | * Bart De Schuymer <bdschuym@pandora.be> |
8 | * | ||
9 | * Changes: | ||
10 | * Apr 29 2003: physdev module support (bdschuym) | ||
11 | * Jun 19 2003: let arptables see bridged ARP traffic (bdschuym) | ||
12 | * Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge | ||
13 | * (bdschuym) | ||
14 | * Sep 01 2004: add IPv6 filtering (bdschuym) | ||
15 | * | 8 | * |
16 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
17 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
@@ -204,15 +197,24 @@ static inline void nf_bridge_save_header(struct sk_buff *skb) | |||
204 | skb->nf_bridge->data, header_size); | 197 | skb->nf_bridge->data, header_size); |
205 | } | 198 | } |
206 | 199 | ||
207 | /* | 200 | static inline void nf_bridge_update_protocol(struct sk_buff *skb) |
208 | * When forwarding bridge frames, we save a copy of the original | 201 | { |
209 | * header before processing. | 202 | if (skb->nf_bridge->mask & BRNF_8021Q) |
203 | skb->protocol = htons(ETH_P_8021Q); | ||
204 | else if (skb->nf_bridge->mask & BRNF_PPPoE) | ||
205 | skb->protocol = htons(ETH_P_PPP_SES); | ||
206 | } | ||
207 | |||
208 | /* Fill in the header for fragmented IP packets handled by | ||
209 | * the IPv4 connection tracking code. | ||
210 | */ | 210 | */ |
211 | int nf_bridge_copy_header(struct sk_buff *skb) | 211 | int nf_bridge_copy_header(struct sk_buff *skb) |
212 | { | 212 | { |
213 | int err; | 213 | int err; |
214 | int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); | 214 | unsigned int header_size; |
215 | 215 | ||
216 | nf_bridge_update_protocol(skb); | ||
217 | header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); | ||
216 | err = skb_cow_head(skb, header_size); | 218 | err = skb_cow_head(skb, header_size); |
217 | if (err) | 219 | if (err) |
218 | return err; | 220 | return err; |
@@ -246,27 +248,48 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) | |||
246 | skb_dst_set(skb, &rt->u.dst); | 248 | skb_dst_set(skb, &rt->u.dst); |
247 | 249 | ||
248 | skb->dev = nf_bridge->physindev; | 250 | skb->dev = nf_bridge->physindev; |
251 | nf_bridge_update_protocol(skb); | ||
249 | nf_bridge_push_encap_header(skb); | 252 | nf_bridge_push_encap_header(skb); |
250 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, | 253 | NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, |
251 | br_handle_frame_finish, 1); | 254 | br_handle_frame_finish, 1); |
252 | 255 | ||
253 | return 0; | 256 | return 0; |
254 | } | 257 | } |
255 | 258 | ||
256 | static void __br_dnat_complain(void) | 259 | /* Obtain the correct destination MAC address, while preserving the original |
260 | * source MAC address. If we already know this address, we just copy it. If we | ||
261 | * don't, we use the neighbour framework to find out. In both cases, we make | ||
262 | * sure that br_handle_frame_finish() is called afterwards. | ||
263 | */ | ||
264 | static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) | ||
257 | { | 265 | { |
258 | static unsigned long last_complaint; | 266 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
267 | struct dst_entry *dst; | ||
259 | 268 | ||
260 | if (jiffies - last_complaint >= 5 * HZ) { | 269 | skb->dev = bridge_parent(skb->dev); |
261 | printk(KERN_WARNING "Performing cross-bridge DNAT requires IP " | 270 | if (!skb->dev) |
262 | "forwarding to be enabled\n"); | 271 | goto free_skb; |
263 | last_complaint = jiffies; | 272 | dst = skb_dst(skb); |
273 | if (dst->hh) { | ||
274 | neigh_hh_bridge(dst->hh, skb); | ||
275 | skb->dev = nf_bridge->physindev; | ||
276 | return br_handle_frame_finish(skb); | ||
277 | } else if (dst->neighbour) { | ||
278 | /* the neighbour function below overwrites the complete | ||
279 | * MAC header, so we save the Ethernet source address and | ||
280 | * protocol number. */ | ||
281 | skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); | ||
282 | /* tell br_dev_xmit to continue with forwarding */ | ||
283 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; | ||
284 | return dst->neighbour->output(skb); | ||
264 | } | 285 | } |
286 | free_skb: | ||
287 | kfree_skb(skb); | ||
288 | return 0; | ||
265 | } | 289 | } |
266 | 290 | ||
267 | /* This requires some explaining. If DNAT has taken place, | 291 | /* This requires some explaining. If DNAT has taken place, |
268 | * we will need to fix up the destination Ethernet address, | 292 | * we will need to fix up the destination Ethernet address. |
269 | * and this is a tricky process. | ||
270 | * | 293 | * |
271 | * There are two cases to consider: | 294 | * There are two cases to consider: |
272 | * 1. The packet was DNAT'ed to a device in the same bridge | 295 | * 1. The packet was DNAT'ed to a device in the same bridge |
@@ -280,62 +303,29 @@ static void __br_dnat_complain(void) | |||
280 | * call ip_route_input() and to look at skb->dst->dev, which is | 303 | * call ip_route_input() and to look at skb->dst->dev, which is |
281 | * changed to the destination device if ip_route_input() succeeds. | 304 | * changed to the destination device if ip_route_input() succeeds. |
282 | * | 305 | * |
283 | * Let us first consider the case that ip_route_input() succeeds: | 306 | * Let's first consider the case that ip_route_input() succeeds: |
284 | * | ||
285 | * If skb->dst->dev equals the logical bridge device the packet | ||
286 | * came in on, we can consider this bridging. The packet is passed | ||
287 | * through the neighbour output function to build a new destination | ||
288 | * MAC address, which will make the packet enter br_nf_local_out() | ||
289 | * not much later. In that function it is assured that the iptables | ||
290 | * FORWARD chain is traversed for the packet. | ||
291 | * | 307 | * |
308 | * If the output device equals the logical bridge device the packet | ||
309 | * came in on, we can consider this bridging. The corresponding MAC | ||
310 | * address will be obtained in br_nf_pre_routing_finish_bridge. | ||
292 | * Otherwise, the packet is considered to be routed and we just | 311 | * Otherwise, the packet is considered to be routed and we just |
293 | * change the destination MAC address so that the packet will | 312 | * change the destination MAC address so that the packet will |
294 | * later be passed up to the IP stack to be routed. For a redirected | 313 | * later be passed up to the IP stack to be routed. For a redirected |
295 | * packet, ip_route_input() will give back the localhost as output device, | 314 | * packet, ip_route_input() will give back the localhost as output device, |
296 | * which differs from the bridge device. | 315 | * which differs from the bridge device. |
297 | * | 316 | * |
298 | * Let us now consider the case that ip_route_input() fails: | 317 | * Let's now consider the case that ip_route_input() fails: |
299 | * | 318 | * |
300 | * This can be because the destination address is martian, in which case | 319 | * This can be because the destination address is martian, in which case |
301 | * the packet will be dropped. | 320 | * the packet will be dropped. |
302 | * After a "echo '0' > /proc/sys/net/ipv4/ip_forward" ip_route_input() | 321 | * If IP forwarding is disabled, ip_route_input() will fail, while |
303 | * will fail, while __ip_route_output_key() will return success. The source | 322 | * ip_route_output_key() can return success. The source |
304 | * address for __ip_route_output_key() is set to zero, so __ip_route_output_key | 323 | * address for ip_route_output_key() is set to zero, so ip_route_output_key() |
305 | * thinks we're handling a locally generated packet and won't care | 324 | * thinks we're handling a locally generated packet and won't care |
306 | * if IP forwarding is allowed. We send a warning message to the users's | 325 | * if IP forwarding is enabled. If the output device equals the logical bridge |
307 | * log telling her to put IP forwarding on. | 326 | * device, we proceed as if ip_route_input() succeeded. If it differs from the |
308 | * | 327 | * logical bridge port or if ip_route_output_key() fails we drop the packet. |
309 | * ip_route_input() will also fail if there is no route available. | 328 | */ |
310 | * In that case we just drop the packet. | ||
311 | * | ||
312 | * --Lennert, 20020411 | ||
313 | * --Bart, 20020416 (updated) | ||
314 | * --Bart, 20021007 (updated) | ||
315 | * --Bart, 20062711 (updated) */ | ||
316 | static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) | ||
317 | { | ||
318 | if (skb->pkt_type == PACKET_OTHERHOST) { | ||
319 | skb->pkt_type = PACKET_HOST; | ||
320 | skb->nf_bridge->mask |= BRNF_PKT_TYPE; | ||
321 | } | ||
322 | skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; | ||
323 | |||
324 | skb->dev = bridge_parent(skb->dev); | ||
325 | if (skb->dev) { | ||
326 | struct dst_entry *dst = skb_dst(skb); | ||
327 | |||
328 | nf_bridge_pull_encap_header(skb); | ||
329 | |||
330 | if (dst->hh) | ||
331 | return neigh_hh_output(dst->hh, skb); | ||
332 | else if (dst->neighbour) | ||
333 | return dst->neighbour->output(skb); | ||
334 | } | ||
335 | kfree_skb(skb); | ||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static int br_nf_pre_routing_finish(struct sk_buff *skb) | 329 | static int br_nf_pre_routing_finish(struct sk_buff *skb) |
340 | { | 330 | { |
341 | struct net_device *dev = skb->dev; | 331 | struct net_device *dev = skb->dev; |
@@ -379,11 +369,6 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) | |||
379 | skb_dst_set(skb, (struct dst_entry *)rt); | 369 | skb_dst_set(skb, (struct dst_entry *)rt); |
380 | goto bridged_dnat; | 370 | goto bridged_dnat; |
381 | } | 371 | } |
382 | /* we are sure that forwarding is disabled, so printing | ||
383 | * this message is no problem. Note that the packet could | ||
384 | * still have a martian destination address, in which case | ||
385 | * the packet could be dropped even if forwarding were enabled */ | ||
386 | __br_dnat_complain(); | ||
387 | dst_release((struct dst_entry *)rt); | 372 | dst_release((struct dst_entry *)rt); |
388 | } | 373 | } |
389 | free_skb: | 374 | free_skb: |
@@ -392,12 +377,11 @@ free_skb: | |||
392 | } else { | 377 | } else { |
393 | if (skb_dst(skb)->dev == dev) { | 378 | if (skb_dst(skb)->dev == dev) { |
394 | bridged_dnat: | 379 | bridged_dnat: |
395 | /* Tell br_nf_local_out this is a | ||
396 | * bridged frame */ | ||
397 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; | ||
398 | skb->dev = nf_bridge->physindev; | 380 | skb->dev = nf_bridge->physindev; |
381 | nf_bridge_update_protocol(skb); | ||
399 | nf_bridge_push_encap_header(skb); | 382 | nf_bridge_push_encap_header(skb); |
400 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, | 383 | NF_HOOK_THRESH(NFPROTO_BRIDGE, |
384 | NF_BR_PRE_ROUTING, | ||
401 | skb, skb->dev, NULL, | 385 | skb, skb->dev, NULL, |
402 | br_nf_pre_routing_finish_bridge, | 386 | br_nf_pre_routing_finish_bridge, |
403 | 1); | 387 | 1); |
@@ -417,8 +401,9 @@ bridged_dnat: | |||
417 | } | 401 | } |
418 | 402 | ||
419 | skb->dev = nf_bridge->physindev; | 403 | skb->dev = nf_bridge->physindev; |
404 | nf_bridge_update_protocol(skb); | ||
420 | nf_bridge_push_encap_header(skb); | 405 | nf_bridge_push_encap_header(skb); |
421 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, | 406 | NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, |
422 | br_handle_frame_finish, 1); | 407 | br_handle_frame_finish, 1); |
423 | 408 | ||
424 | return 0; | 409 | return 0; |
@@ -437,6 +422,10 @@ static struct net_device *setup_pre_routing(struct sk_buff *skb) | |||
437 | nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; | 422 | nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; |
438 | nf_bridge->physindev = skb->dev; | 423 | nf_bridge->physindev = skb->dev; |
439 | skb->dev = bridge_parent(skb->dev); | 424 | skb->dev = bridge_parent(skb->dev); |
425 | if (skb->protocol == htons(ETH_P_8021Q)) | ||
426 | nf_bridge->mask |= BRNF_8021Q; | ||
427 | else if (skb->protocol == htons(ETH_P_PPP_SES)) | ||
428 | nf_bridge->mask |= BRNF_PPPoE; | ||
440 | 429 | ||
441 | return skb->dev; | 430 | return skb->dev; |
442 | } | 431 | } |
@@ -535,7 +524,8 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, | |||
535 | if (!setup_pre_routing(skb)) | 524 | if (!setup_pre_routing(skb)) |
536 | return NF_DROP; | 525 | return NF_DROP; |
537 | 526 | ||
538 | NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, | 527 | skb->protocol = htons(ETH_P_IPV6); |
528 | NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, | ||
539 | br_nf_pre_routing_finish_ipv6); | 529 | br_nf_pre_routing_finish_ipv6); |
540 | 530 | ||
541 | return NF_STOLEN; | 531 | return NF_STOLEN; |
@@ -607,8 +597,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb, | |||
607 | if (!setup_pre_routing(skb)) | 597 | if (!setup_pre_routing(skb)) |
608 | return NF_DROP; | 598 | return NF_DROP; |
609 | store_orig_dstaddr(skb); | 599 | store_orig_dstaddr(skb); |
600 | skb->protocol = htons(ETH_P_IP); | ||
610 | 601 | ||
611 | NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, | 602 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, |
612 | br_nf_pre_routing_finish); | 603 | br_nf_pre_routing_finish); |
613 | 604 | ||
614 | return NF_STOLEN; | 605 | return NF_STOLEN; |
@@ -652,11 +643,13 @@ static int br_nf_forward_finish(struct sk_buff *skb) | |||
652 | skb->pkt_type = PACKET_OTHERHOST; | 643 | skb->pkt_type = PACKET_OTHERHOST; |
653 | nf_bridge->mask ^= BRNF_PKT_TYPE; | 644 | nf_bridge->mask ^= BRNF_PKT_TYPE; |
654 | } | 645 | } |
646 | nf_bridge_update_protocol(skb); | ||
655 | } else { | 647 | } else { |
656 | in = *((struct net_device **)(skb->cb)); | 648 | in = *((struct net_device **)(skb->cb)); |
657 | } | 649 | } |
658 | nf_bridge_push_encap_header(skb); | 650 | nf_bridge_push_encap_header(skb); |
659 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, | 651 | |
652 | NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, in, | ||
660 | skb->dev, br_forward_finish, 1); | 653 | skb->dev, br_forward_finish, 1); |
661 | return 0; | 654 | return 0; |
662 | } | 655 | } |
@@ -707,6 +700,10 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, | |||
707 | /* The physdev module checks on this */ | 700 | /* The physdev module checks on this */ |
708 | nf_bridge->mask |= BRNF_BRIDGED; | 701 | nf_bridge->mask |= BRNF_BRIDGED; |
709 | nf_bridge->physoutdev = skb->dev; | 702 | nf_bridge->physoutdev = skb->dev; |
703 | if (pf == PF_INET) | ||
704 | skb->protocol = htons(ETH_P_IP); | ||
705 | else | ||
706 | skb->protocol = htons(ETH_P_IPV6); | ||
710 | 707 | ||
711 | NF_HOOK(pf, NF_INET_FORWARD, skb, bridge_parent(in), parent, | 708 | NF_HOOK(pf, NF_INET_FORWARD, skb, bridge_parent(in), parent, |
712 | br_nf_forward_finish); | 709 | br_nf_forward_finish); |
@@ -744,60 +741,11 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb, | |||
744 | return NF_STOLEN; | 741 | return NF_STOLEN; |
745 | } | 742 | } |
746 | 743 | ||
747 | /* PF_BRIDGE/LOCAL_OUT *********************************************** | ||
748 | * | ||
749 | * This function sees both locally originated IP packets and forwarded | ||
750 | * IP packets (in both cases the destination device is a bridge | ||
751 | * device). It also sees bridged-and-DNAT'ed packets. | ||
752 | * | ||
753 | * If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged | ||
754 | * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward() | ||
755 | * will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority | ||
756 | * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor | ||
757 | * will be executed. | ||
758 | */ | ||
759 | static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff *skb, | ||
760 | const struct net_device *in, | ||
761 | const struct net_device *out, | ||
762 | int (*okfn)(struct sk_buff *)) | ||
763 | { | ||
764 | struct net_device *realindev; | ||
765 | struct nf_bridge_info *nf_bridge; | ||
766 | |||
767 | if (!skb->nf_bridge) | ||
768 | return NF_ACCEPT; | ||
769 | |||
770 | /* Need exclusive nf_bridge_info since we might have multiple | ||
771 | * different physoutdevs. */ | ||
772 | if (!nf_bridge_unshare(skb)) | ||
773 | return NF_DROP; | ||
774 | |||
775 | nf_bridge = skb->nf_bridge; | ||
776 | if (!(nf_bridge->mask & BRNF_BRIDGED_DNAT)) | ||
777 | return NF_ACCEPT; | ||
778 | |||
779 | /* Bridged, take PF_BRIDGE/FORWARD. | ||
780 | * (see big note in front of br_nf_pre_routing_finish) */ | ||
781 | nf_bridge->physoutdev = skb->dev; | ||
782 | realindev = nf_bridge->physindev; | ||
783 | |||
784 | if (nf_bridge->mask & BRNF_PKT_TYPE) { | ||
785 | skb->pkt_type = PACKET_OTHERHOST; | ||
786 | nf_bridge->mask ^= BRNF_PKT_TYPE; | ||
787 | } | ||
788 | nf_bridge_push_encap_header(skb); | ||
789 | |||
790 | NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev, | ||
791 | br_forward_finish); | ||
792 | return NF_STOLEN; | ||
793 | } | ||
794 | |||
795 | #if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE) | 744 | #if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE) |
796 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) | 745 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) |
797 | { | 746 | { |
798 | if (skb->nfct != NULL && | 747 | if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) && |
799 | (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) && | 748 | skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu && |
800 | skb->len > skb->dev->mtu && | ||
801 | !skb_is_gso(skb)) | 749 | !skb_is_gso(skb)) |
802 | return ip_fragment(skb, br_dev_queue_push_xmit); | 750 | return ip_fragment(skb, br_dev_queue_push_xmit); |
803 | else | 751 | else |
@@ -820,21 +768,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, | |||
820 | struct net_device *realoutdev = bridge_parent(skb->dev); | 768 | struct net_device *realoutdev = bridge_parent(skb->dev); |
821 | u_int8_t pf; | 769 | u_int8_t pf; |
822 | 770 | ||
823 | #ifdef CONFIG_NETFILTER_DEBUG | 771 | if (!nf_bridge || !(nf_bridge->mask & BRNF_BRIDGED)) |
824 | /* Be very paranoid. This probably won't happen anymore, but let's | ||
825 | * keep the check just to be sure... */ | ||
826 | if (skb_mac_header(skb) < skb->head || | ||
827 | skb_mac_header(skb) + ETH_HLEN > skb->data) { | ||
828 | printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: " | ||
829 | "bad mac.raw pointer.\n"); | ||
830 | goto print_error; | ||
831 | } | ||
832 | #endif | ||
833 | |||
834 | if (!nf_bridge) | ||
835 | return NF_ACCEPT; | ||
836 | |||
837 | if (!(nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT))) | ||
838 | return NF_ACCEPT; | 772 | return NF_ACCEPT; |
839 | 773 | ||
840 | if (!realoutdev) | 774 | if (!realoutdev) |
@@ -849,13 +783,6 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, | |||
849 | else | 783 | else |
850 | return NF_ACCEPT; | 784 | return NF_ACCEPT; |
851 | 785 | ||
852 | #ifdef CONFIG_NETFILTER_DEBUG | ||
853 | if (skb_dst(skb) == NULL) { | ||
854 | printk(KERN_INFO "br_netfilter post_routing: skb->dst == NULL\n"); | ||
855 | goto print_error; | ||
856 | } | ||
857 | #endif | ||
858 | |||
859 | /* We assume any code from br_dev_queue_push_xmit onwards doesn't care | 786 | /* We assume any code from br_dev_queue_push_xmit onwards doesn't care |
860 | * about the value of skb->pkt_type. */ | 787 | * about the value of skb->pkt_type. */ |
861 | if (skb->pkt_type == PACKET_OTHERHOST) { | 788 | if (skb->pkt_type == PACKET_OTHERHOST) { |
@@ -865,24 +792,15 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, | |||
865 | 792 | ||
866 | nf_bridge_pull_encap_header(skb); | 793 | nf_bridge_pull_encap_header(skb); |
867 | nf_bridge_save_header(skb); | 794 | nf_bridge_save_header(skb); |
795 | if (pf == PF_INET) | ||
796 | skb->protocol = htons(ETH_P_IP); | ||
797 | else | ||
798 | skb->protocol = htons(ETH_P_IPV6); | ||
868 | 799 | ||
869 | NF_HOOK(pf, NF_INET_POST_ROUTING, skb, NULL, realoutdev, | 800 | NF_HOOK(pf, NF_INET_POST_ROUTING, skb, NULL, realoutdev, |
870 | br_nf_dev_queue_xmit); | 801 | br_nf_dev_queue_xmit); |
871 | 802 | ||
872 | return NF_STOLEN; | 803 | return NF_STOLEN; |
873 | |||
874 | #ifdef CONFIG_NETFILTER_DEBUG | ||
875 | print_error: | ||
876 | if (skb->dev != NULL) { | ||
877 | printk("[%s]", skb->dev->name); | ||
878 | if (realoutdev) | ||
879 | printk("[%s]", realoutdev->name); | ||
880 | } | ||
881 | printk(" head:%p, raw:%p, data:%p\n", skb->head, skb_mac_header(skb), | ||
882 | skb->data); | ||
883 | dump_stack(); | ||
884 | return NF_ACCEPT; | ||
885 | #endif | ||
886 | } | 804 | } |
887 | 805 | ||
888 | /* IP/SABOTAGE *****************************************************/ | 806 | /* IP/SABOTAGE *****************************************************/ |
@@ -901,10 +819,8 @@ static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb, | |||
901 | return NF_ACCEPT; | 819 | return NF_ACCEPT; |
902 | } | 820 | } |
903 | 821 | ||
904 | /* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent | 822 | /* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because |
905 | * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input. | 823 | * br_dev_queue_push_xmit is called afterwards */ |
906 | * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because | ||
907 | * ip_refrag() can return NF_STOLEN. */ | ||
908 | static struct nf_hook_ops br_nf_ops[] __read_mostly = { | 824 | static struct nf_hook_ops br_nf_ops[] __read_mostly = { |
909 | { | 825 | { |
910 | .hook = br_nf_pre_routing, | 826 | .hook = br_nf_pre_routing, |
@@ -935,13 +851,6 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = { | |||
935 | .priority = NF_BR_PRI_BRNF, | 851 | .priority = NF_BR_PRI_BRNF, |
936 | }, | 852 | }, |
937 | { | 853 | { |
938 | .hook = br_nf_local_out, | ||
939 | .owner = THIS_MODULE, | ||
940 | .pf = PF_BRIDGE, | ||
941 | .hooknum = NF_BR_LOCAL_OUT, | ||
942 | .priority = NF_BR_PRI_FIRST, | ||
943 | }, | ||
944 | { | ||
945 | .hook = br_nf_post_routing, | 854 | .hook = br_nf_post_routing, |
946 | .owner = THIS_MODULE, | 855 | .owner = THIS_MODULE, |
947 | .pf = PF_BRIDGE, | 856 | .pf = PF_BRIDGE, |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index aa56ac2c8829..fe0a79018ab2 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -42,8 +42,8 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por | |||
42 | struct nlmsghdr *nlh; | 42 | struct nlmsghdr *nlh; |
43 | u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; | 43 | u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; |
44 | 44 | ||
45 | pr_debug("br_fill_info event %d port %s master %s\n", | 45 | br_debug(br, "br_fill_info event %d port %s master %s\n", |
46 | event, dev->name, br->dev->name); | 46 | event, dev->name, br->dev->name); |
47 | 47 | ||
48 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); | 48 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); |
49 | if (nlh == NULL) | 49 | if (nlh == NULL) |
@@ -87,7 +87,9 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port) | |||
87 | struct sk_buff *skb; | 87 | struct sk_buff *skb; |
88 | int err = -ENOBUFS; | 88 | int err = -ENOBUFS; |
89 | 89 | ||
90 | pr_debug("bridge notify event=%d\n", event); | 90 | br_debug(port->br, "port %u(%s) event %d\n", |
91 | (unsigned)port->port_no, port->dev->name, event); | ||
92 | |||
91 | skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC); | 93 | skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC); |
92 | if (skb == NULL) | 94 | if (skb == NULL) |
93 | goto errout; | 95 | goto errout; |
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 763a3ec292e5..717e1fd6133c 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c | |||
@@ -34,6 +34,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v | |||
34 | struct net_device *dev = ptr; | 34 | struct net_device *dev = ptr; |
35 | struct net_bridge_port *p = dev->br_port; | 35 | struct net_bridge_port *p = dev->br_port; |
36 | struct net_bridge *br; | 36 | struct net_bridge *br; |
37 | int err; | ||
37 | 38 | ||
38 | /* not a port of a bridge */ | 39 | /* not a port of a bridge */ |
39 | if (p == NULL) | 40 | if (p == NULL) |
@@ -82,6 +83,16 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v | |||
82 | case NETDEV_UNREGISTER: | 83 | case NETDEV_UNREGISTER: |
83 | br_del_if(br, dev); | 84 | br_del_if(br, dev); |
84 | break; | 85 | break; |
86 | |||
87 | case NETDEV_CHANGENAME: | ||
88 | err = br_sysfs_renameif(p); | ||
89 | if (err) | ||
90 | return notifier_from_errno(err); | ||
91 | break; | ||
92 | |||
93 | case NETDEV_PRE_TYPE_CHANGE: | ||
94 | /* Forbid underlaying device to change its type. */ | ||
95 | return NOTIFY_BAD; | ||
85 | } | 96 | } |
86 | 97 | ||
87 | /* Events that may cause spanning tree to refresh */ | 98 | /* Events that may cause spanning tree to refresh */ |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 846d7d1e2075..0f4a74bc6a9b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -45,6 +45,17 @@ struct mac_addr | |||
45 | unsigned char addr[6]; | 45 | unsigned char addr[6]; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | struct br_ip | ||
49 | { | ||
50 | union { | ||
51 | __be32 ip4; | ||
52 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
53 | struct in6_addr ip6; | ||
54 | #endif | ||
55 | } u; | ||
56 | __be16 proto; | ||
57 | }; | ||
58 | |||
48 | struct net_bridge_fdb_entry | 59 | struct net_bridge_fdb_entry |
49 | { | 60 | { |
50 | struct hlist_node hlist; | 61 | struct hlist_node hlist; |
@@ -64,7 +75,7 @@ struct net_bridge_port_group { | |||
64 | struct rcu_head rcu; | 75 | struct rcu_head rcu; |
65 | struct timer_list timer; | 76 | struct timer_list timer; |
66 | struct timer_list query_timer; | 77 | struct timer_list query_timer; |
67 | __be32 addr; | 78 | struct br_ip addr; |
68 | u32 queries_sent; | 79 | u32 queries_sent; |
69 | }; | 80 | }; |
70 | 81 | ||
@@ -77,7 +88,7 @@ struct net_bridge_mdb_entry | |||
77 | struct rcu_head rcu; | 88 | struct rcu_head rcu; |
78 | struct timer_list timer; | 89 | struct timer_list timer; |
79 | struct timer_list query_timer; | 90 | struct timer_list query_timer; |
80 | __be32 addr; | 91 | struct br_ip addr; |
81 | u32 queries_sent; | 92 | u32 queries_sent; |
82 | }; | 93 | }; |
83 | 94 | ||
@@ -128,6 +139,17 @@ struct net_bridge_port | |||
128 | struct hlist_head mglist; | 139 | struct hlist_head mglist; |
129 | struct hlist_node rlist; | 140 | struct hlist_node rlist; |
130 | #endif | 141 | #endif |
142 | |||
143 | #ifdef CONFIG_SYSFS | ||
144 | char sysfs_name[IFNAMSIZ]; | ||
145 | #endif | ||
146 | }; | ||
147 | |||
148 | struct br_cpu_netstats { | ||
149 | unsigned long rx_packets; | ||
150 | unsigned long rx_bytes; | ||
151 | unsigned long tx_packets; | ||
152 | unsigned long tx_bytes; | ||
131 | }; | 153 | }; |
132 | 154 | ||
133 | struct net_bridge | 155 | struct net_bridge |
@@ -135,6 +157,8 @@ struct net_bridge | |||
135 | spinlock_t lock; | 157 | spinlock_t lock; |
136 | struct list_head port_list; | 158 | struct list_head port_list; |
137 | struct net_device *dev; | 159 | struct net_device *dev; |
160 | |||
161 | struct br_cpu_netstats __percpu *stats; | ||
138 | spinlock_t hash_lock; | 162 | spinlock_t hash_lock; |
139 | struct hlist_head hash[BR_HASH_SIZE]; | 163 | struct hlist_head hash[BR_HASH_SIZE]; |
140 | unsigned long feature_mask; | 164 | unsigned long feature_mask; |
@@ -220,6 +244,21 @@ struct br_input_skb_cb { | |||
220 | # define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb) (0) | 244 | # define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb) (0) |
221 | #endif | 245 | #endif |
222 | 246 | ||
247 | #define br_printk(level, br, format, args...) \ | ||
248 | printk(level "%s: " format, (br)->dev->name, ##args) | ||
249 | |||
250 | #define br_err(__br, format, args...) \ | ||
251 | br_printk(KERN_ERR, __br, format, ##args) | ||
252 | #define br_warn(__br, format, args...) \ | ||
253 | br_printk(KERN_WARNING, __br, format, ##args) | ||
254 | #define br_notice(__br, format, args...) \ | ||
255 | br_printk(KERN_NOTICE, __br, format, ##args) | ||
256 | #define br_info(__br, format, args...) \ | ||
257 | br_printk(KERN_INFO, __br, format, ##args) | ||
258 | |||
259 | #define br_debug(br, format, args...) \ | ||
260 | pr_debug("%s: " format, (br)->dev->name, ##args) | ||
261 | |||
223 | extern struct notifier_block br_device_notifier; | 262 | extern struct notifier_block br_device_notifier; |
224 | extern const u8 br_group_address[ETH_ALEN]; | 263 | extern const u8 br_group_address[ETH_ALEN]; |
225 | 264 | ||
@@ -233,6 +272,18 @@ static inline int br_is_root_bridge(const struct net_bridge *br) | |||
233 | extern void br_dev_setup(struct net_device *dev); | 272 | extern void br_dev_setup(struct net_device *dev); |
234 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, | 273 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, |
235 | struct net_device *dev); | 274 | struct net_device *dev); |
275 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
276 | extern void br_netpoll_cleanup(struct net_device *dev); | ||
277 | extern void br_netpoll_enable(struct net_bridge *br, | ||
278 | struct net_device *dev); | ||
279 | extern void br_netpoll_disable(struct net_bridge *br, | ||
280 | struct net_device *dev); | ||
281 | #else | ||
282 | #define br_netpoll_cleanup(br) | ||
283 | #define br_netpoll_enable(br, dev) | ||
284 | #define br_netpoll_disable(br, dev) | ||
285 | |||
286 | #endif | ||
236 | 287 | ||
237 | /* br_fdb.c */ | 288 | /* br_fdb.c */ |
238 | extern int br_fdb_init(void); | 289 | extern int br_fdb_init(void); |
@@ -433,6 +484,7 @@ extern void br_ifinfo_notify(int event, struct net_bridge_port *port); | |||
433 | /* br_sysfs_if.c */ | 484 | /* br_sysfs_if.c */ |
434 | extern const struct sysfs_ops brport_sysfs_ops; | 485 | extern const struct sysfs_ops brport_sysfs_ops; |
435 | extern int br_sysfs_addif(struct net_bridge_port *p); | 486 | extern int br_sysfs_addif(struct net_bridge_port *p); |
487 | extern int br_sysfs_renameif(struct net_bridge_port *p); | ||
436 | 488 | ||
437 | /* br_sysfs_br.c */ | 489 | /* br_sysfs_br.c */ |
438 | extern int br_sysfs_addbr(struct net_device *dev); | 490 | extern int br_sysfs_addbr(struct net_device *dev); |
@@ -441,6 +493,7 @@ extern void br_sysfs_delbr(struct net_device *dev); | |||
441 | #else | 493 | #else |
442 | 494 | ||
443 | #define br_sysfs_addif(p) (0) | 495 | #define br_sysfs_addif(p) (0) |
496 | #define br_sysfs_renameif(p) (0) | ||
444 | #define br_sysfs_addbr(dev) (0) | 497 | #define br_sysfs_addbr(dev) (0) |
445 | #define br_sysfs_delbr(dev) do { } while(0) | 498 | #define br_sysfs_delbr(dev) do { } while(0) |
446 | #endif /* CONFIG_SYSFS */ | 499 | #endif /* CONFIG_SYSFS */ |
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index edcf14b560f6..57186d84d2bd 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c | |||
@@ -31,10 +31,9 @@ static const char *const br_port_state_names[] = { | |||
31 | 31 | ||
32 | void br_log_state(const struct net_bridge_port *p) | 32 | void br_log_state(const struct net_bridge_port *p) |
33 | { | 33 | { |
34 | pr_info("%s: port %d(%s) entering %s state\n", | 34 | br_info(p->br, "port %u(%s) entering %s state\n", |
35 | p->br->dev->name, p->port_no, p->dev->name, | 35 | (unsigned) p->port_no, p->dev->name, |
36 | br_port_state_names[p->state]); | 36 | br_port_state_names[p->state]); |
37 | |||
38 | } | 37 | } |
39 | 38 | ||
40 | /* called under bridge lock */ | 39 | /* called under bridge lock */ |
@@ -300,7 +299,7 @@ void br_topology_change_detection(struct net_bridge *br) | |||
300 | if (br->stp_enabled != BR_KERNEL_STP) | 299 | if (br->stp_enabled != BR_KERNEL_STP) |
301 | return; | 300 | return; |
302 | 301 | ||
303 | pr_info("%s: topology change detected, %s\n", br->dev->name, | 302 | br_info(br, "topology change detected, %s\n", |
304 | isroot ? "propagating" : "sending tcn bpdu"); | 303 | isroot ? "propagating" : "sending tcn bpdu"); |
305 | 304 | ||
306 | if (isroot) { | 305 | if (isroot) { |
@@ -469,8 +468,8 @@ void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *b | |||
469 | void br_received_tcn_bpdu(struct net_bridge_port *p) | 468 | void br_received_tcn_bpdu(struct net_bridge_port *p) |
470 | { | 469 | { |
471 | if (br_is_designated_port(p)) { | 470 | if (br_is_designated_port(p)) { |
472 | pr_info("%s: received tcn bpdu on port %i(%s)\n", | 471 | br_info(p->br, "port %u(%s) received tcn bpdu\n", |
473 | p->br->dev->name, p->port_no, p->dev->name); | 472 | (unsigned) p->port_no, p->dev->name); |
474 | 473 | ||
475 | br_topology_change_detection(p->br); | 474 | br_topology_change_detection(p->br); |
476 | br_topology_change_acknowledge(p); | 475 | br_topology_change_acknowledge(p); |
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index d66cce11f3bf..217bd225a42f 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c | |||
@@ -50,7 +50,7 @@ static void br_send_bpdu(struct net_bridge_port *p, | |||
50 | 50 | ||
51 | llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr); | 51 | llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr); |
52 | 52 | ||
53 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, | 53 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, |
54 | dev_queue_xmit); | 54 | dev_queue_xmit); |
55 | } | 55 | } |
56 | 56 | ||
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index d527119e9f54..1d8826914cbf 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -85,17 +85,16 @@ void br_stp_enable_port(struct net_bridge_port *p) | |||
85 | { | 85 | { |
86 | br_init_port(p); | 86 | br_init_port(p); |
87 | br_port_state_selection(p->br); | 87 | br_port_state_selection(p->br); |
88 | br_log_state(p); | ||
88 | } | 89 | } |
89 | 90 | ||
90 | /* called under bridge lock */ | 91 | /* called under bridge lock */ |
91 | void br_stp_disable_port(struct net_bridge_port *p) | 92 | void br_stp_disable_port(struct net_bridge_port *p) |
92 | { | 93 | { |
93 | struct net_bridge *br; | 94 | struct net_bridge *br = p->br; |
94 | int wasroot; | 95 | int wasroot; |
95 | 96 | ||
96 | br = p->br; | 97 | br_log_state(p); |
97 | printk(KERN_INFO "%s: port %i(%s) entering %s state\n", | ||
98 | br->dev->name, p->port_no, p->dev->name, "disabled"); | ||
99 | 98 | ||
100 | wasroot = br_is_root_bridge(br); | 99 | wasroot = br_is_root_bridge(br); |
101 | br_become_designated_port(p); | 100 | br_become_designated_port(p); |
@@ -127,11 +126,10 @@ static void br_stp_start(struct net_bridge *br) | |||
127 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); | 126 | r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); |
128 | if (r == 0) { | 127 | if (r == 0) { |
129 | br->stp_enabled = BR_USER_STP; | 128 | br->stp_enabled = BR_USER_STP; |
130 | printk(KERN_INFO "%s: userspace STP started\n", br->dev->name); | 129 | br_debug(br, "userspace STP started\n"); |
131 | } else { | 130 | } else { |
132 | br->stp_enabled = BR_KERNEL_STP; | 131 | br->stp_enabled = BR_KERNEL_STP; |
133 | printk(KERN_INFO "%s: starting userspace STP failed, " | 132 | br_debug(br, "using kernel STP\n"); |
134 | "starting kernel STP\n", br->dev->name); | ||
135 | 133 | ||
136 | /* To start timers on any ports left in blocking */ | 134 | /* To start timers on any ports left in blocking */ |
137 | spin_lock_bh(&br->lock); | 135 | spin_lock_bh(&br->lock); |
@@ -148,9 +146,7 @@ static void br_stp_stop(struct net_bridge *br) | |||
148 | 146 | ||
149 | if (br->stp_enabled == BR_USER_STP) { | 147 | if (br->stp_enabled == BR_USER_STP) { |
150 | r = call_usermodehelper(BR_STP_PROG, argv, envp, 1); | 148 | r = call_usermodehelper(BR_STP_PROG, argv, envp, 1); |
151 | printk(KERN_INFO "%s: userspace STP stopped, return code %d\n", | 149 | br_info(br, "userspace STP stopped, return code %d\n", r); |
152 | br->dev->name, r); | ||
153 | |||
154 | 150 | ||
155 | /* To start timers on any ports left in blocking */ | 151 | /* To start timers on any ports left in blocking */ |
156 | spin_lock_bh(&br->lock); | 152 | spin_lock_bh(&br->lock); |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 772a140bfdf0..7b22456023c5 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
@@ -35,7 +35,7 @@ static void br_hello_timer_expired(unsigned long arg) | |||
35 | { | 35 | { |
36 | struct net_bridge *br = (struct net_bridge *)arg; | 36 | struct net_bridge *br = (struct net_bridge *)arg; |
37 | 37 | ||
38 | pr_debug("%s: hello timer expired\n", br->dev->name); | 38 | br_debug(br, "hello timer expired\n"); |
39 | spin_lock(&br->lock); | 39 | spin_lock(&br->lock); |
40 | if (br->dev->flags & IFF_UP) { | 40 | if (br->dev->flags & IFF_UP) { |
41 | br_config_bpdu_generation(br); | 41 | br_config_bpdu_generation(br); |
@@ -55,13 +55,9 @@ static void br_message_age_timer_expired(unsigned long arg) | |||
55 | if (p->state == BR_STATE_DISABLED) | 55 | if (p->state == BR_STATE_DISABLED) |
56 | return; | 56 | return; |
57 | 57 | ||
58 | 58 | br_info(br, "port %u(%s) neighbor %.2x%.2x.%pM lost\n", | |
59 | pr_info("%s: neighbor %.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x lost on port %d(%s)\n", | 59 | (unsigned) p->port_no, p->dev->name, |
60 | br->dev->name, | 60 | id->prio[0], id->prio[1], &id->addr); |
61 | id->prio[0], id->prio[1], | ||
62 | id->addr[0], id->addr[1], id->addr[2], | ||
63 | id->addr[3], id->addr[4], id->addr[5], | ||
64 | p->port_no, p->dev->name); | ||
65 | 61 | ||
66 | /* | 62 | /* |
67 | * According to the spec, the message age timer cannot be | 63 | * According to the spec, the message age timer cannot be |
@@ -87,8 +83,8 @@ static void br_forward_delay_timer_expired(unsigned long arg) | |||
87 | struct net_bridge_port *p = (struct net_bridge_port *) arg; | 83 | struct net_bridge_port *p = (struct net_bridge_port *) arg; |
88 | struct net_bridge *br = p->br; | 84 | struct net_bridge *br = p->br; |
89 | 85 | ||
90 | pr_debug("%s: %d(%s) forward delay timer\n", | 86 | br_debug(br, "port %u(%s) forward delay timer\n", |
91 | br->dev->name, p->port_no, p->dev->name); | 87 | (unsigned) p->port_no, p->dev->name); |
92 | spin_lock(&br->lock); | 88 | spin_lock(&br->lock); |
93 | if (p->state == BR_STATE_LISTENING) { | 89 | if (p->state == BR_STATE_LISTENING) { |
94 | p->state = BR_STATE_LEARNING; | 90 | p->state = BR_STATE_LEARNING; |
@@ -107,7 +103,7 @@ static void br_tcn_timer_expired(unsigned long arg) | |||
107 | { | 103 | { |
108 | struct net_bridge *br = (struct net_bridge *) arg; | 104 | struct net_bridge *br = (struct net_bridge *) arg; |
109 | 105 | ||
110 | pr_debug("%s: tcn timer expired\n", br->dev->name); | 106 | br_debug(br, "tcn timer expired\n"); |
111 | spin_lock(&br->lock); | 107 | spin_lock(&br->lock); |
112 | if (br->dev->flags & IFF_UP) { | 108 | if (br->dev->flags & IFF_UP) { |
113 | br_transmit_tcn(br); | 109 | br_transmit_tcn(br); |
@@ -121,7 +117,7 @@ static void br_topology_change_timer_expired(unsigned long arg) | |||
121 | { | 117 | { |
122 | struct net_bridge *br = (struct net_bridge *) arg; | 118 | struct net_bridge *br = (struct net_bridge *) arg; |
123 | 119 | ||
124 | pr_debug("%s: topo change timer expired\n", br->dev->name); | 120 | br_debug(br, "topo change timer expired\n"); |
125 | spin_lock(&br->lock); | 121 | spin_lock(&br->lock); |
126 | br->topology_change_detected = 0; | 122 | br->topology_change_detected = 0; |
127 | br->topology_change = 0; | 123 | br->topology_change = 0; |
@@ -132,8 +128,8 @@ static void br_hold_timer_expired(unsigned long arg) | |||
132 | { | 128 | { |
133 | struct net_bridge_port *p = (struct net_bridge_port *) arg; | 129 | struct net_bridge_port *p = (struct net_bridge_port *) arg; |
134 | 130 | ||
135 | pr_debug("%s: %d(%s) hold timer expired\n", | 131 | br_debug(p->br, "port %u(%s) hold timer expired\n", |
136 | p->br->dev->name, p->port_no, p->dev->name); | 132 | (unsigned) p->port_no, p->dev->name); |
137 | 133 | ||
138 | spin_lock(&p->br->lock); | 134 | spin_lock(&p->br->lock); |
139 | if (p->config_pending) | 135 | if (p->config_pending) |
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 0b9916489d6b..fd5799c9bc8d 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
@@ -246,7 +246,7 @@ const struct sysfs_ops brport_sysfs_ops = { | |||
246 | /* | 246 | /* |
247 | * Add sysfs entries to ethernet device added to a bridge. | 247 | * Add sysfs entries to ethernet device added to a bridge. |
248 | * Creates a brport subdirectory with bridge attributes. | 248 | * Creates a brport subdirectory with bridge attributes. |
249 | * Puts symlink in bridge's brport subdirectory | 249 | * Puts symlink in bridge's brif subdirectory |
250 | */ | 250 | */ |
251 | int br_sysfs_addif(struct net_bridge_port *p) | 251 | int br_sysfs_addif(struct net_bridge_port *p) |
252 | { | 252 | { |
@@ -257,15 +257,37 @@ int br_sysfs_addif(struct net_bridge_port *p) | |||
257 | err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj, | 257 | err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj, |
258 | SYSFS_BRIDGE_PORT_LINK); | 258 | SYSFS_BRIDGE_PORT_LINK); |
259 | if (err) | 259 | if (err) |
260 | goto out2; | 260 | return err; |
261 | 261 | ||
262 | for (a = brport_attrs; *a; ++a) { | 262 | for (a = brport_attrs; *a; ++a) { |
263 | err = sysfs_create_file(&p->kobj, &((*a)->attr)); | 263 | err = sysfs_create_file(&p->kobj, &((*a)->attr)); |
264 | if (err) | 264 | if (err) |
265 | goto out2; | 265 | return err; |
266 | } | 266 | } |
267 | 267 | ||
268 | err = sysfs_create_link(br->ifobj, &p->kobj, p->dev->name); | 268 | strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ); |
269 | out2: | 269 | return sysfs_create_link(br->ifobj, &p->kobj, p->sysfs_name); |
270 | } | ||
271 | |||
272 | /* Rename bridge's brif symlink */ | ||
273 | int br_sysfs_renameif(struct net_bridge_port *p) | ||
274 | { | ||
275 | struct net_bridge *br = p->br; | ||
276 | int err; | ||
277 | |||
278 | /* If a rename fails, the rollback will cause another | ||
279 | * rename call with the existing name. | ||
280 | */ | ||
281 | if (!strncmp(p->sysfs_name, p->dev->name, IFNAMSIZ)) | ||
282 | return 0; | ||
283 | |||
284 | err = sysfs_rename_link(br->ifobj, &p->kobj, | ||
285 | p->sysfs_name, p->dev->name); | ||
286 | if (err) | ||
287 | netdev_notice(br->dev, "unable to rename link %s to %s", | ||
288 | p->sysfs_name, p->dev->name); | ||
289 | else | ||
290 | strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ); | ||
291 | |||
270 | return err; | 292 | return err; |
271 | } | 293 | } |
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c index 5d1176758ca5..2a449b7ab8fa 100644 --- a/net/bridge/netfilter/ebt_802_3.c +++ b/net/bridge/netfilter/ebt_802_3.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/netfilter_bridge/ebt_802_3.h> | 13 | #include <linux/netfilter_bridge/ebt_802_3.h> |
14 | 14 | ||
15 | static bool | 15 | static bool |
16 | ebt_802_3_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 16 | ebt_802_3_mt(const struct sk_buff *skb, struct xt_action_param *par) |
17 | { | 17 | { |
18 | const struct ebt_802_3_info *info = par->matchinfo; | 18 | const struct ebt_802_3_info *info = par->matchinfo; |
19 | const struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb); | 19 | const struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb); |
@@ -36,14 +36,14 @@ ebt_802_3_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
36 | return true; | 36 | return true; |
37 | } | 37 | } |
38 | 38 | ||
39 | static bool ebt_802_3_mt_check(const struct xt_mtchk_param *par) | 39 | static int ebt_802_3_mt_check(const struct xt_mtchk_param *par) |
40 | { | 40 | { |
41 | const struct ebt_802_3_info *info = par->matchinfo; | 41 | const struct ebt_802_3_info *info = par->matchinfo; |
42 | 42 | ||
43 | if (info->bitmask & ~EBT_802_3_MASK || info->invflags & ~EBT_802_3_MASK) | 43 | if (info->bitmask & ~EBT_802_3_MASK || info->invflags & ~EBT_802_3_MASK) |
44 | return false; | 44 | return -EINVAL; |
45 | 45 | ||
46 | return true; | 46 | return 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | static struct xt_match ebt_802_3_mt_reg __read_mostly = { | 49 | static struct xt_match ebt_802_3_mt_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c index b595f091f35b..8b84c581be30 100644 --- a/net/bridge/netfilter/ebt_among.c +++ b/net/bridge/netfilter/ebt_among.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * August, 2003 | 7 | * August, 2003 |
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
10 | #include <linux/ip.h> | 11 | #include <linux/ip.h> |
11 | #include <linux/if_arp.h> | 12 | #include <linux/if_arp.h> |
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
@@ -128,7 +129,7 @@ static int get_ip_src(const struct sk_buff *skb, __be32 *addr) | |||
128 | } | 129 | } |
129 | 130 | ||
130 | static bool | 131 | static bool |
131 | ebt_among_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 132 | ebt_among_mt(const struct sk_buff *skb, struct xt_action_param *par) |
132 | { | 133 | { |
133 | const struct ebt_among_info *info = par->matchinfo; | 134 | const struct ebt_among_info *info = par->matchinfo; |
134 | const char *dmac, *smac; | 135 | const char *dmac, *smac; |
@@ -171,7 +172,7 @@ ebt_among_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
171 | return true; | 172 | return true; |
172 | } | 173 | } |
173 | 174 | ||
174 | static bool ebt_among_mt_check(const struct xt_mtchk_param *par) | 175 | static int ebt_among_mt_check(const struct xt_mtchk_param *par) |
175 | { | 176 | { |
176 | const struct ebt_among_info *info = par->matchinfo; | 177 | const struct ebt_among_info *info = par->matchinfo; |
177 | const struct ebt_entry_match *em = | 178 | const struct ebt_entry_match *em = |
@@ -186,24 +187,20 @@ static bool ebt_among_mt_check(const struct xt_mtchk_param *par) | |||
186 | expected_length += ebt_mac_wormhash_size(wh_src); | 187 | expected_length += ebt_mac_wormhash_size(wh_src); |
187 | 188 | ||
188 | if (em->match_size != EBT_ALIGN(expected_length)) { | 189 | if (em->match_size != EBT_ALIGN(expected_length)) { |
189 | printk(KERN_WARNING | 190 | pr_info("wrong size: %d against expected %d, rounded to %Zd\n", |
190 | "ebtables: among: wrong size: %d " | 191 | em->match_size, expected_length, |
191 | "against expected %d, rounded to %Zd\n", | 192 | EBT_ALIGN(expected_length)); |
192 | em->match_size, expected_length, | 193 | return -EINVAL; |
193 | EBT_ALIGN(expected_length)); | ||
194 | return false; | ||
195 | } | 194 | } |
196 | if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) { | 195 | if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) { |
197 | printk(KERN_WARNING | 196 | pr_info("dst integrity fail: %x\n", -err); |
198 | "ebtables: among: dst integrity fail: %x\n", -err); | 197 | return -EINVAL; |
199 | return false; | ||
200 | } | 198 | } |
201 | if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) { | 199 | if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) { |
202 | printk(KERN_WARNING | 200 | pr_info("src integrity fail: %x\n", -err); |
203 | "ebtables: among: src integrity fail: %x\n", -err); | 201 | return -EINVAL; |
204 | return false; | ||
205 | } | 202 | } |
206 | return true; | 203 | return 0; |
207 | } | 204 | } |
208 | 205 | ||
209 | static struct xt_match ebt_among_mt_reg __read_mostly = { | 206 | static struct xt_match ebt_among_mt_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c index e727697c5847..cd457b891b27 100644 --- a/net/bridge/netfilter/ebt_arp.c +++ b/net/bridge/netfilter/ebt_arp.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/netfilter_bridge/ebt_arp.h> | 16 | #include <linux/netfilter_bridge/ebt_arp.h> |
17 | 17 | ||
18 | static bool | 18 | static bool |
19 | ebt_arp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 19 | ebt_arp_mt(const struct sk_buff *skb, struct xt_action_param *par) |
20 | { | 20 | { |
21 | const struct ebt_arp_info *info = par->matchinfo; | 21 | const struct ebt_arp_info *info = par->matchinfo; |
22 | const struct arphdr *ah; | 22 | const struct arphdr *ah; |
@@ -100,7 +100,7 @@ ebt_arp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
100 | return true; | 100 | return true; |
101 | } | 101 | } |
102 | 102 | ||
103 | static bool ebt_arp_mt_check(const struct xt_mtchk_param *par) | 103 | static int ebt_arp_mt_check(const struct xt_mtchk_param *par) |
104 | { | 104 | { |
105 | const struct ebt_arp_info *info = par->matchinfo; | 105 | const struct ebt_arp_info *info = par->matchinfo; |
106 | const struct ebt_entry *e = par->entryinfo; | 106 | const struct ebt_entry *e = par->entryinfo; |
@@ -108,10 +108,10 @@ static bool ebt_arp_mt_check(const struct xt_mtchk_param *par) | |||
108 | if ((e->ethproto != htons(ETH_P_ARP) && | 108 | if ((e->ethproto != htons(ETH_P_ARP) && |
109 | e->ethproto != htons(ETH_P_RARP)) || | 109 | e->ethproto != htons(ETH_P_RARP)) || |
110 | e->invflags & EBT_IPROTO) | 110 | e->invflags & EBT_IPROTO) |
111 | return false; | 111 | return -EINVAL; |
112 | if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK) | 112 | if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK) |
113 | return false; | 113 | return -EINVAL; |
114 | return true; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | static struct xt_match ebt_arp_mt_reg __read_mostly = { | 117 | static struct xt_match ebt_arp_mt_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c index f392e9d93f53..070cf134a22f 100644 --- a/net/bridge/netfilter/ebt_arpreply.c +++ b/net/bridge/netfilter/ebt_arpreply.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/netfilter_bridge/ebt_arpreply.h> | 16 | #include <linux/netfilter_bridge/ebt_arpreply.h> |
17 | 17 | ||
18 | static unsigned int | 18 | static unsigned int |
19 | ebt_arpreply_tg(struct sk_buff *skb, const struct xt_target_param *par) | 19 | ebt_arpreply_tg(struct sk_buff *skb, const struct xt_action_param *par) |
20 | { | 20 | { |
21 | const struct ebt_arpreply_info *info = par->targinfo; | 21 | const struct ebt_arpreply_info *info = par->targinfo; |
22 | const __be32 *siptr, *diptr; | 22 | const __be32 *siptr, *diptr; |
@@ -57,17 +57,17 @@ ebt_arpreply_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
57 | return info->target; | 57 | return info->target; |
58 | } | 58 | } |
59 | 59 | ||
60 | static bool ebt_arpreply_tg_check(const struct xt_tgchk_param *par) | 60 | static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par) |
61 | { | 61 | { |
62 | const struct ebt_arpreply_info *info = par->targinfo; | 62 | const struct ebt_arpreply_info *info = par->targinfo; |
63 | const struct ebt_entry *e = par->entryinfo; | 63 | const struct ebt_entry *e = par->entryinfo; |
64 | 64 | ||
65 | if (BASE_CHAIN && info->target == EBT_RETURN) | 65 | if (BASE_CHAIN && info->target == EBT_RETURN) |
66 | return false; | 66 | return -EINVAL; |
67 | if (e->ethproto != htons(ETH_P_ARP) || | 67 | if (e->ethproto != htons(ETH_P_ARP) || |
68 | e->invflags & EBT_IPROTO) | 68 | e->invflags & EBT_IPROTO) |
69 | return false; | 69 | return -EINVAL; |
70 | return true; | 70 | return 0; |
71 | } | 71 | } |
72 | 72 | ||
73 | static struct xt_target ebt_arpreply_tg_reg __read_mostly = { | 73 | static struct xt_target ebt_arpreply_tg_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c index 2bb40d728a35..c59f7bfae6e2 100644 --- a/net/bridge/netfilter/ebt_dnat.c +++ b/net/bridge/netfilter/ebt_dnat.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/netfilter_bridge/ebt_nat.h> | 15 | #include <linux/netfilter_bridge/ebt_nat.h> |
16 | 16 | ||
17 | static unsigned int | 17 | static unsigned int |
18 | ebt_dnat_tg(struct sk_buff *skb, const struct xt_target_param *par) | 18 | ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par) |
19 | { | 19 | { |
20 | const struct ebt_nat_info *info = par->targinfo; | 20 | const struct ebt_nat_info *info = par->targinfo; |
21 | 21 | ||
@@ -26,13 +26,13 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
26 | return info->target; | 26 | return info->target; |
27 | } | 27 | } |
28 | 28 | ||
29 | static bool ebt_dnat_tg_check(const struct xt_tgchk_param *par) | 29 | static int ebt_dnat_tg_check(const struct xt_tgchk_param *par) |
30 | { | 30 | { |
31 | const struct ebt_nat_info *info = par->targinfo; | 31 | const struct ebt_nat_info *info = par->targinfo; |
32 | unsigned int hook_mask; | 32 | unsigned int hook_mask; |
33 | 33 | ||
34 | if (BASE_CHAIN && info->target == EBT_RETURN) | 34 | if (BASE_CHAIN && info->target == EBT_RETURN) |
35 | return false; | 35 | return -EINVAL; |
36 | 36 | ||
37 | hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS); | 37 | hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS); |
38 | if ((strcmp(par->table, "nat") != 0 || | 38 | if ((strcmp(par->table, "nat") != 0 || |
@@ -40,10 +40,10 @@ static bool ebt_dnat_tg_check(const struct xt_tgchk_param *par) | |||
40 | (1 << NF_BR_LOCAL_OUT)))) && | 40 | (1 << NF_BR_LOCAL_OUT)))) && |
41 | (strcmp(par->table, "broute") != 0 || | 41 | (strcmp(par->table, "broute") != 0 || |
42 | hook_mask & ~(1 << NF_BR_BROUTING))) | 42 | hook_mask & ~(1 << NF_BR_BROUTING))) |
43 | return false; | 43 | return -EINVAL; |
44 | if (INVALID_TARGET) | 44 | if (INVALID_TARGET) |
45 | return false; | 45 | return -EINVAL; |
46 | return true; | 46 | return 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | static struct xt_target ebt_dnat_tg_reg __read_mostly = { | 49 | static struct xt_target ebt_dnat_tg_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c index 5de6df6f86b8..23bca62d58d2 100644 --- a/net/bridge/netfilter/ebt_ip.c +++ b/net/bridge/netfilter/ebt_ip.c | |||
@@ -25,7 +25,7 @@ struct tcpudphdr { | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | static bool | 27 | static bool |
28 | ebt_ip_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 28 | ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) |
29 | { | 29 | { |
30 | const struct ebt_ip_info *info = par->matchinfo; | 30 | const struct ebt_ip_info *info = par->matchinfo; |
31 | const struct iphdr *ih; | 31 | const struct iphdr *ih; |
@@ -77,31 +77,31 @@ ebt_ip_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
77 | return true; | 77 | return true; |
78 | } | 78 | } |
79 | 79 | ||
80 | static bool ebt_ip_mt_check(const struct xt_mtchk_param *par) | 80 | static int ebt_ip_mt_check(const struct xt_mtchk_param *par) |
81 | { | 81 | { |
82 | const struct ebt_ip_info *info = par->matchinfo; | 82 | const struct ebt_ip_info *info = par->matchinfo; |
83 | const struct ebt_entry *e = par->entryinfo; | 83 | const struct ebt_entry *e = par->entryinfo; |
84 | 84 | ||
85 | if (e->ethproto != htons(ETH_P_IP) || | 85 | if (e->ethproto != htons(ETH_P_IP) || |
86 | e->invflags & EBT_IPROTO) | 86 | e->invflags & EBT_IPROTO) |
87 | return false; | 87 | return -EINVAL; |
88 | if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) | 88 | if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) |
89 | return false; | 89 | return -EINVAL; |
90 | if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) { | 90 | if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) { |
91 | if (info->invflags & EBT_IP_PROTO) | 91 | if (info->invflags & EBT_IP_PROTO) |
92 | return false; | 92 | return -EINVAL; |
93 | if (info->protocol != IPPROTO_TCP && | 93 | if (info->protocol != IPPROTO_TCP && |
94 | info->protocol != IPPROTO_UDP && | 94 | info->protocol != IPPROTO_UDP && |
95 | info->protocol != IPPROTO_UDPLITE && | 95 | info->protocol != IPPROTO_UDPLITE && |
96 | info->protocol != IPPROTO_SCTP && | 96 | info->protocol != IPPROTO_SCTP && |
97 | info->protocol != IPPROTO_DCCP) | 97 | info->protocol != IPPROTO_DCCP) |
98 | return false; | 98 | return -EINVAL; |
99 | } | 99 | } |
100 | if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) | 100 | if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) |
101 | return false; | 101 | return -EINVAL; |
102 | if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) | 102 | if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) |
103 | return false; | 103 | return -EINVAL; |
104 | return true; | 104 | return 0; |
105 | } | 105 | } |
106 | 106 | ||
107 | static struct xt_match ebt_ip_mt_reg __read_mostly = { | 107 | static struct xt_match ebt_ip_mt_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c index bbf2534ef026..50a46afc2bcc 100644 --- a/net/bridge/netfilter/ebt_ip6.c +++ b/net/bridge/netfilter/ebt_ip6.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Authors: | 4 | * Authors: |
5 | * Manohar Castelino <manohar.r.castelino@intel.com> | 5 | * Manohar Castelino <manohar.r.castelino@intel.com> |
6 | * Kuo-Lang Tseng <kuo-lang.tseng@intel.com> | 6 | * Kuo-Lang Tseng <kuo-lang.tseng@intel.com> |
7 | * Jan Engelhardt <jengelh@computergmbh.de> | 7 | * Jan Engelhardt <jengelh@medozas.de> |
8 | * | 8 | * |
9 | * Summary: | 9 | * Summary: |
10 | * This is just a modification of the IPv4 code written by | 10 | * This is just a modification of the IPv4 code written by |
@@ -28,15 +28,13 @@ struct tcpudphdr { | |||
28 | }; | 28 | }; |
29 | 29 | ||
30 | static bool | 30 | static bool |
31 | ebt_ip6_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 31 | ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) |
32 | { | 32 | { |
33 | const struct ebt_ip6_info *info = par->matchinfo; | 33 | const struct ebt_ip6_info *info = par->matchinfo; |
34 | const struct ipv6hdr *ih6; | 34 | const struct ipv6hdr *ih6; |
35 | struct ipv6hdr _ip6h; | 35 | struct ipv6hdr _ip6h; |
36 | const struct tcpudphdr *pptr; | 36 | const struct tcpudphdr *pptr; |
37 | struct tcpudphdr _ports; | 37 | struct tcpudphdr _ports; |
38 | struct in6_addr tmp_addr; | ||
39 | int i; | ||
40 | 38 | ||
41 | ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); | 39 | ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); |
42 | if (ih6 == NULL) | 40 | if (ih6 == NULL) |
@@ -44,18 +42,10 @@ ebt_ip6_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
44 | if (info->bitmask & EBT_IP6_TCLASS && | 42 | if (info->bitmask & EBT_IP6_TCLASS && |
45 | FWINV(info->tclass != ipv6_get_dsfield(ih6), EBT_IP6_TCLASS)) | 43 | FWINV(info->tclass != ipv6_get_dsfield(ih6), EBT_IP6_TCLASS)) |
46 | return false; | 44 | return false; |
47 | for (i = 0; i < 4; i++) | 45 | if (FWINV(ipv6_masked_addr_cmp(&ih6->saddr, &info->smsk, |
48 | tmp_addr.in6_u.u6_addr32[i] = ih6->saddr.in6_u.u6_addr32[i] & | 46 | &info->saddr), EBT_IP6_SOURCE) || |
49 | info->smsk.in6_u.u6_addr32[i]; | 47 | FWINV(ipv6_masked_addr_cmp(&ih6->daddr, &info->dmsk, |
50 | if (info->bitmask & EBT_IP6_SOURCE && | 48 | &info->daddr), EBT_IP6_DEST)) |
51 | FWINV((ipv6_addr_cmp(&tmp_addr, &info->saddr) != 0), | ||
52 | EBT_IP6_SOURCE)) | ||
53 | return false; | ||
54 | for (i = 0; i < 4; i++) | ||
55 | tmp_addr.in6_u.u6_addr32[i] = ih6->daddr.in6_u.u6_addr32[i] & | ||
56 | info->dmsk.in6_u.u6_addr32[i]; | ||
57 | if (info->bitmask & EBT_IP6_DEST && | ||
58 | FWINV((ipv6_addr_cmp(&tmp_addr, &info->daddr) != 0), EBT_IP6_DEST)) | ||
59 | return false; | 49 | return false; |
60 | if (info->bitmask & EBT_IP6_PROTO) { | 50 | if (info->bitmask & EBT_IP6_PROTO) { |
61 | uint8_t nexthdr = ih6->nexthdr; | 51 | uint8_t nexthdr = ih6->nexthdr; |
@@ -90,30 +80,30 @@ ebt_ip6_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
90 | return true; | 80 | return true; |
91 | } | 81 | } |
92 | 82 | ||
93 | static bool ebt_ip6_mt_check(const struct xt_mtchk_param *par) | 83 | static int ebt_ip6_mt_check(const struct xt_mtchk_param *par) |
94 | { | 84 | { |
95 | const struct ebt_entry *e = par->entryinfo; | 85 | const struct ebt_entry *e = par->entryinfo; |
96 | struct ebt_ip6_info *info = par->matchinfo; | 86 | struct ebt_ip6_info *info = par->matchinfo; |
97 | 87 | ||
98 | if (e->ethproto != htons(ETH_P_IPV6) || e->invflags & EBT_IPROTO) | 88 | if (e->ethproto != htons(ETH_P_IPV6) || e->invflags & EBT_IPROTO) |
99 | return false; | 89 | return -EINVAL; |
100 | if (info->bitmask & ~EBT_IP6_MASK || info->invflags & ~EBT_IP6_MASK) | 90 | if (info->bitmask & ~EBT_IP6_MASK || info->invflags & ~EBT_IP6_MASK) |
101 | return false; | 91 | return -EINVAL; |
102 | if (info->bitmask & (EBT_IP6_DPORT | EBT_IP6_SPORT)) { | 92 | if (info->bitmask & (EBT_IP6_DPORT | EBT_IP6_SPORT)) { |
103 | if (info->invflags & EBT_IP6_PROTO) | 93 | if (info->invflags & EBT_IP6_PROTO) |
104 | return false; | 94 | return -EINVAL; |
105 | if (info->protocol != IPPROTO_TCP && | 95 | if (info->protocol != IPPROTO_TCP && |
106 | info->protocol != IPPROTO_UDP && | 96 | info->protocol != IPPROTO_UDP && |
107 | info->protocol != IPPROTO_UDPLITE && | 97 | info->protocol != IPPROTO_UDPLITE && |
108 | info->protocol != IPPROTO_SCTP && | 98 | info->protocol != IPPROTO_SCTP && |
109 | info->protocol != IPPROTO_DCCP) | 99 | info->protocol != IPPROTO_DCCP) |
110 | return false; | 100 | return -EINVAL; |
111 | } | 101 | } |
112 | if (info->bitmask & EBT_IP6_DPORT && info->dport[0] > info->dport[1]) | 102 | if (info->bitmask & EBT_IP6_DPORT && info->dport[0] > info->dport[1]) |
113 | return false; | 103 | return -EINVAL; |
114 | if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1]) | 104 | if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1]) |
115 | return false; | 105 | return -EINVAL; |
116 | return true; | 106 | return 0; |
117 | } | 107 | } |
118 | 108 | ||
119 | static struct xt_match ebt_ip6_mt_reg __read_mostly = { | 109 | static struct xt_match ebt_ip6_mt_reg __read_mostly = { |
@@ -139,4 +129,5 @@ static void __exit ebt_ip6_fini(void) | |||
139 | module_init(ebt_ip6_init); | 129 | module_init(ebt_ip6_init); |
140 | module_exit(ebt_ip6_fini); | 130 | module_exit(ebt_ip6_fini); |
141 | MODULE_DESCRIPTION("Ebtables: IPv6 protocol packet match"); | 131 | MODULE_DESCRIPTION("Ebtables: IPv6 protocol packet match"); |
132 | MODULE_AUTHOR("Kuo-Lang Tseng <kuo-lang.tseng@intel.com>"); | ||
142 | MODULE_LICENSE("GPL"); | 133 | MODULE_LICENSE("GPL"); |
diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c index 7a8182710eb3..517e78befcb2 100644 --- a/net/bridge/netfilter/ebt_limit.c +++ b/net/bridge/netfilter/ebt_limit.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * September, 2003 | 10 | * September, 2003 |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
15 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
@@ -31,7 +32,7 @@ static DEFINE_SPINLOCK(limit_lock); | |||
31 | #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) | 32 | #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) |
32 | 33 | ||
33 | static bool | 34 | static bool |
34 | ebt_limit_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 35 | ebt_limit_mt(const struct sk_buff *skb, struct xt_action_param *par) |
35 | { | 36 | { |
36 | struct ebt_limit_info *info = (void *)par->matchinfo; | 37 | struct ebt_limit_info *info = (void *)par->matchinfo; |
37 | unsigned long now = jiffies; | 38 | unsigned long now = jiffies; |
@@ -64,16 +65,16 @@ user2credits(u_int32_t user) | |||
64 | return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE; | 65 | return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE; |
65 | } | 66 | } |
66 | 67 | ||
67 | static bool ebt_limit_mt_check(const struct xt_mtchk_param *par) | 68 | static int ebt_limit_mt_check(const struct xt_mtchk_param *par) |
68 | { | 69 | { |
69 | struct ebt_limit_info *info = par->matchinfo; | 70 | struct ebt_limit_info *info = par->matchinfo; |
70 | 71 | ||
71 | /* Check for overflow. */ | 72 | /* Check for overflow. */ |
72 | if (info->burst == 0 || | 73 | if (info->burst == 0 || |
73 | user2credits(info->avg * info->burst) < user2credits(info->avg)) { | 74 | user2credits(info->avg * info->burst) < user2credits(info->avg)) { |
74 | printk("Overflow in ebt_limit, try lower: %u/%u\n", | 75 | pr_info("overflow, try lower: %u/%u\n", |
75 | info->avg, info->burst); | 76 | info->avg, info->burst); |
76 | return false; | 77 | return -EINVAL; |
77 | } | 78 | } |
78 | 79 | ||
79 | /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */ | 80 | /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */ |
@@ -81,7 +82,7 @@ static bool ebt_limit_mt_check(const struct xt_mtchk_param *par) | |||
81 | info->credit = user2credits(info->avg * info->burst); | 82 | info->credit = user2credits(info->avg * info->burst); |
82 | info->credit_cap = user2credits(info->avg * info->burst); | 83 | info->credit_cap = user2credits(info->avg * info->burst); |
83 | info->cost = user2credits(info->avg); | 84 | info->cost = user2credits(info->avg); |
84 | return true; | 85 | return 0; |
85 | } | 86 | } |
86 | 87 | ||
87 | 88 | ||
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index e873924ddb5d..6e5a8bb9b940 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c | |||
@@ -24,16 +24,16 @@ | |||
24 | 24 | ||
25 | static DEFINE_SPINLOCK(ebt_log_lock); | 25 | static DEFINE_SPINLOCK(ebt_log_lock); |
26 | 26 | ||
27 | static bool ebt_log_tg_check(const struct xt_tgchk_param *par) | 27 | static int ebt_log_tg_check(const struct xt_tgchk_param *par) |
28 | { | 28 | { |
29 | struct ebt_log_info *info = par->targinfo; | 29 | struct ebt_log_info *info = par->targinfo; |
30 | 30 | ||
31 | if (info->bitmask & ~EBT_LOG_MASK) | 31 | if (info->bitmask & ~EBT_LOG_MASK) |
32 | return false; | 32 | return -EINVAL; |
33 | if (info->loglevel >= 8) | 33 | if (info->loglevel >= 8) |
34 | return false; | 34 | return -EINVAL; |
35 | info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0'; | 35 | info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0'; |
36 | return true; | 36 | return 0; |
37 | } | 37 | } |
38 | 38 | ||
39 | struct tcpudphdr | 39 | struct tcpudphdr |
@@ -171,7 +171,7 @@ out: | |||
171 | } | 171 | } |
172 | 172 | ||
173 | static unsigned int | 173 | static unsigned int |
174 | ebt_log_tg(struct sk_buff *skb, const struct xt_target_param *par) | 174 | ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par) |
175 | { | 175 | { |
176 | const struct ebt_log_info *info = par->targinfo; | 176 | const struct ebt_log_info *info = par->targinfo; |
177 | struct nf_loginfo li; | 177 | struct nf_loginfo li; |
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index 2b5ce533d6b9..66697cbd0a8b 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/netfilter_bridge/ebt_mark_t.h> | 19 | #include <linux/netfilter_bridge/ebt_mark_t.h> |
20 | 20 | ||
21 | static unsigned int | 21 | static unsigned int |
22 | ebt_mark_tg(struct sk_buff *skb, const struct xt_target_param *par) | 22 | ebt_mark_tg(struct sk_buff *skb, const struct xt_action_param *par) |
23 | { | 23 | { |
24 | const struct ebt_mark_t_info *info = par->targinfo; | 24 | const struct ebt_mark_t_info *info = par->targinfo; |
25 | int action = info->target & -16; | 25 | int action = info->target & -16; |
@@ -36,21 +36,21 @@ ebt_mark_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
36 | return info->target | ~EBT_VERDICT_BITS; | 36 | return info->target | ~EBT_VERDICT_BITS; |
37 | } | 37 | } |
38 | 38 | ||
39 | static bool ebt_mark_tg_check(const struct xt_tgchk_param *par) | 39 | static int ebt_mark_tg_check(const struct xt_tgchk_param *par) |
40 | { | 40 | { |
41 | const struct ebt_mark_t_info *info = par->targinfo; | 41 | const struct ebt_mark_t_info *info = par->targinfo; |
42 | int tmp; | 42 | int tmp; |
43 | 43 | ||
44 | tmp = info->target | ~EBT_VERDICT_BITS; | 44 | tmp = info->target | ~EBT_VERDICT_BITS; |
45 | if (BASE_CHAIN && tmp == EBT_RETURN) | 45 | if (BASE_CHAIN && tmp == EBT_RETURN) |
46 | return false; | 46 | return -EINVAL; |
47 | if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) | 47 | if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) |
48 | return false; | 48 | return -EINVAL; |
49 | tmp = info->target & ~EBT_VERDICT_BITS; | 49 | tmp = info->target & ~EBT_VERDICT_BITS; |
50 | if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE && | 50 | if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE && |
51 | tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE) | 51 | tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE) |
52 | return false; | 52 | return -EINVAL; |
53 | return true; | 53 | return 0; |
54 | } | 54 | } |
55 | #ifdef CONFIG_COMPAT | 55 | #ifdef CONFIG_COMPAT |
56 | struct compat_ebt_mark_t_info { | 56 | struct compat_ebt_mark_t_info { |
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c index 8de8c396d913..d98baefc4c7e 100644 --- a/net/bridge/netfilter/ebt_mark_m.c +++ b/net/bridge/netfilter/ebt_mark_m.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/netfilter_bridge/ebt_mark_m.h> | 13 | #include <linux/netfilter_bridge/ebt_mark_m.h> |
14 | 14 | ||
15 | static bool | 15 | static bool |
16 | ebt_mark_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 16 | ebt_mark_mt(const struct sk_buff *skb, struct xt_action_param *par) |
17 | { | 17 | { |
18 | const struct ebt_mark_m_info *info = par->matchinfo; | 18 | const struct ebt_mark_m_info *info = par->matchinfo; |
19 | 19 | ||
@@ -22,17 +22,17 @@ ebt_mark_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
22 | return ((skb->mark & info->mask) == info->mark) ^ info->invert; | 22 | return ((skb->mark & info->mask) == info->mark) ^ info->invert; |
23 | } | 23 | } |
24 | 24 | ||
25 | static bool ebt_mark_mt_check(const struct xt_mtchk_param *par) | 25 | static int ebt_mark_mt_check(const struct xt_mtchk_param *par) |
26 | { | 26 | { |
27 | const struct ebt_mark_m_info *info = par->matchinfo; | 27 | const struct ebt_mark_m_info *info = par->matchinfo; |
28 | 28 | ||
29 | if (info->bitmask & ~EBT_MARK_MASK) | 29 | if (info->bitmask & ~EBT_MARK_MASK) |
30 | return false; | 30 | return -EINVAL; |
31 | if ((info->bitmask & EBT_MARK_OR) && (info->bitmask & EBT_MARK_AND)) | 31 | if ((info->bitmask & EBT_MARK_OR) && (info->bitmask & EBT_MARK_AND)) |
32 | return false; | 32 | return -EINVAL; |
33 | if (!info->bitmask) | 33 | if (!info->bitmask) |
34 | return false; | 34 | return -EINVAL; |
35 | return true; | 35 | return 0; |
36 | } | 36 | } |
37 | 37 | ||
38 | 38 | ||
diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c index 40dbd248b9ae..5be68bbcc341 100644 --- a/net/bridge/netfilter/ebt_nflog.c +++ b/net/bridge/netfilter/ebt_nflog.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <net/netfilter/nf_log.h> | 20 | #include <net/netfilter/nf_log.h> |
21 | 21 | ||
22 | static unsigned int | 22 | static unsigned int |
23 | ebt_nflog_tg(struct sk_buff *skb, const struct xt_target_param *par) | 23 | ebt_nflog_tg(struct sk_buff *skb, const struct xt_action_param *par) |
24 | { | 24 | { |
25 | const struct ebt_nflog_info *info = par->targinfo; | 25 | const struct ebt_nflog_info *info = par->targinfo; |
26 | struct nf_loginfo li; | 26 | struct nf_loginfo li; |
@@ -35,14 +35,14 @@ ebt_nflog_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
35 | return EBT_CONTINUE; | 35 | return EBT_CONTINUE; |
36 | } | 36 | } |
37 | 37 | ||
38 | static bool ebt_nflog_tg_check(const struct xt_tgchk_param *par) | 38 | static int ebt_nflog_tg_check(const struct xt_tgchk_param *par) |
39 | { | 39 | { |
40 | struct ebt_nflog_info *info = par->targinfo; | 40 | struct ebt_nflog_info *info = par->targinfo; |
41 | 41 | ||
42 | if (info->flags & ~EBT_NFLOG_MASK) | 42 | if (info->flags & ~EBT_NFLOG_MASK) |
43 | return false; | 43 | return -EINVAL; |
44 | info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0'; | 44 | info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0'; |
45 | return true; | 45 | return 0; |
46 | } | 46 | } |
47 | 47 | ||
48 | static struct xt_target ebt_nflog_tg_reg __read_mostly = { | 48 | static struct xt_target ebt_nflog_tg_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_pkttype.c b/net/bridge/netfilter/ebt_pkttype.c index e2a07e6cbef3..496a56515307 100644 --- a/net/bridge/netfilter/ebt_pkttype.c +++ b/net/bridge/netfilter/ebt_pkttype.c | |||
@@ -13,21 +13,21 @@ | |||
13 | #include <linux/netfilter_bridge/ebt_pkttype.h> | 13 | #include <linux/netfilter_bridge/ebt_pkttype.h> |
14 | 14 | ||
15 | static bool | 15 | static bool |
16 | ebt_pkttype_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 16 | ebt_pkttype_mt(const struct sk_buff *skb, struct xt_action_param *par) |
17 | { | 17 | { |
18 | const struct ebt_pkttype_info *info = par->matchinfo; | 18 | const struct ebt_pkttype_info *info = par->matchinfo; |
19 | 19 | ||
20 | return (skb->pkt_type == info->pkt_type) ^ info->invert; | 20 | return (skb->pkt_type == info->pkt_type) ^ info->invert; |
21 | } | 21 | } |
22 | 22 | ||
23 | static bool ebt_pkttype_mt_check(const struct xt_mtchk_param *par) | 23 | static int ebt_pkttype_mt_check(const struct xt_mtchk_param *par) |
24 | { | 24 | { |
25 | const struct ebt_pkttype_info *info = par->matchinfo; | 25 | const struct ebt_pkttype_info *info = par->matchinfo; |
26 | 26 | ||
27 | if (info->invert != 0 && info->invert != 1) | 27 | if (info->invert != 0 && info->invert != 1) |
28 | return false; | 28 | return -EINVAL; |
29 | /* Allow any pkt_type value */ | 29 | /* Allow any pkt_type value */ |
30 | return true; | 30 | return 0; |
31 | } | 31 | } |
32 | 32 | ||
33 | static struct xt_match ebt_pkttype_mt_reg __read_mostly = { | 33 | static struct xt_match ebt_pkttype_mt_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c index 9be8fbcd370b..9e19166ba453 100644 --- a/net/bridge/netfilter/ebt_redirect.c +++ b/net/bridge/netfilter/ebt_redirect.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/netfilter_bridge/ebt_redirect.h> | 16 | #include <linux/netfilter_bridge/ebt_redirect.h> |
17 | 17 | ||
18 | static unsigned int | 18 | static unsigned int |
19 | ebt_redirect_tg(struct sk_buff *skb, const struct xt_target_param *par) | 19 | ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par) |
20 | { | 20 | { |
21 | const struct ebt_redirect_info *info = par->targinfo; | 21 | const struct ebt_redirect_info *info = par->targinfo; |
22 | 22 | ||
@@ -32,23 +32,23 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
32 | return info->target; | 32 | return info->target; |
33 | } | 33 | } |
34 | 34 | ||
35 | static bool ebt_redirect_tg_check(const struct xt_tgchk_param *par) | 35 | static int ebt_redirect_tg_check(const struct xt_tgchk_param *par) |
36 | { | 36 | { |
37 | const struct ebt_redirect_info *info = par->targinfo; | 37 | const struct ebt_redirect_info *info = par->targinfo; |
38 | unsigned int hook_mask; | 38 | unsigned int hook_mask; |
39 | 39 | ||
40 | if (BASE_CHAIN && info->target == EBT_RETURN) | 40 | if (BASE_CHAIN && info->target == EBT_RETURN) |
41 | return false; | 41 | return -EINVAL; |
42 | 42 | ||
43 | hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS); | 43 | hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS); |
44 | if ((strcmp(par->table, "nat") != 0 || | 44 | if ((strcmp(par->table, "nat") != 0 || |
45 | hook_mask & ~(1 << NF_BR_PRE_ROUTING)) && | 45 | hook_mask & ~(1 << NF_BR_PRE_ROUTING)) && |
46 | (strcmp(par->table, "broute") != 0 || | 46 | (strcmp(par->table, "broute") != 0 || |
47 | hook_mask & ~(1 << NF_BR_BROUTING))) | 47 | hook_mask & ~(1 << NF_BR_BROUTING))) |
48 | return false; | 48 | return -EINVAL; |
49 | if (INVALID_TARGET) | 49 | if (INVALID_TARGET) |
50 | return false; | 50 | return -EINVAL; |
51 | return true; | 51 | return 0; |
52 | } | 52 | } |
53 | 53 | ||
54 | static struct xt_target ebt_redirect_tg_reg __read_mostly = { | 54 | static struct xt_target ebt_redirect_tg_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c index 9c7b520765a2..f8f0bd1a1d51 100644 --- a/net/bridge/netfilter/ebt_snat.c +++ b/net/bridge/netfilter/ebt_snat.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/netfilter_bridge/ebt_nat.h> | 17 | #include <linux/netfilter_bridge/ebt_nat.h> |
18 | 18 | ||
19 | static unsigned int | 19 | static unsigned int |
20 | ebt_snat_tg(struct sk_buff *skb, const struct xt_target_param *par) | 20 | ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par) |
21 | { | 21 | { |
22 | const struct ebt_nat_info *info = par->targinfo; | 22 | const struct ebt_nat_info *info = par->targinfo; |
23 | 23 | ||
@@ -42,21 +42,21 @@ out: | |||
42 | return info->target | ~EBT_VERDICT_BITS; | 42 | return info->target | ~EBT_VERDICT_BITS; |
43 | } | 43 | } |
44 | 44 | ||
45 | static bool ebt_snat_tg_check(const struct xt_tgchk_param *par) | 45 | static int ebt_snat_tg_check(const struct xt_tgchk_param *par) |
46 | { | 46 | { |
47 | const struct ebt_nat_info *info = par->targinfo; | 47 | const struct ebt_nat_info *info = par->targinfo; |
48 | int tmp; | 48 | int tmp; |
49 | 49 | ||
50 | tmp = info->target | ~EBT_VERDICT_BITS; | 50 | tmp = info->target | ~EBT_VERDICT_BITS; |
51 | if (BASE_CHAIN && tmp == EBT_RETURN) | 51 | if (BASE_CHAIN && tmp == EBT_RETURN) |
52 | return false; | 52 | return -EINVAL; |
53 | 53 | ||
54 | if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) | 54 | if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) |
55 | return false; | 55 | return -EINVAL; |
56 | tmp = info->target | EBT_VERDICT_BITS; | 56 | tmp = info->target | EBT_VERDICT_BITS; |
57 | if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT) | 57 | if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT) |
58 | return false; | 58 | return -EINVAL; |
59 | return true; | 59 | return 0; |
60 | } | 60 | } |
61 | 61 | ||
62 | static struct xt_target ebt_snat_tg_reg __read_mostly = { | 62 | static struct xt_target ebt_snat_tg_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c index 92a93d363765..5b33a2e634a6 100644 --- a/net/bridge/netfilter/ebt_stp.c +++ b/net/bridge/netfilter/ebt_stp.c | |||
@@ -120,7 +120,7 @@ static bool ebt_filter_config(const struct ebt_stp_info *info, | |||
120 | } | 120 | } |
121 | 121 | ||
122 | static bool | 122 | static bool |
123 | ebt_stp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 123 | ebt_stp_mt(const struct sk_buff *skb, struct xt_action_param *par) |
124 | { | 124 | { |
125 | const struct ebt_stp_info *info = par->matchinfo; | 125 | const struct ebt_stp_info *info = par->matchinfo; |
126 | const struct stp_header *sp; | 126 | const struct stp_header *sp; |
@@ -153,7 +153,7 @@ ebt_stp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
153 | return true; | 153 | return true; |
154 | } | 154 | } |
155 | 155 | ||
156 | static bool ebt_stp_mt_check(const struct xt_mtchk_param *par) | 156 | static int ebt_stp_mt_check(const struct xt_mtchk_param *par) |
157 | { | 157 | { |
158 | const struct ebt_stp_info *info = par->matchinfo; | 158 | const struct ebt_stp_info *info = par->matchinfo; |
159 | const uint8_t bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; | 159 | const uint8_t bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; |
@@ -162,13 +162,13 @@ static bool ebt_stp_mt_check(const struct xt_mtchk_param *par) | |||
162 | 162 | ||
163 | if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK || | 163 | if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK || |
164 | !(info->bitmask & EBT_STP_MASK)) | 164 | !(info->bitmask & EBT_STP_MASK)) |
165 | return false; | 165 | return -EINVAL; |
166 | /* Make sure the match only receives stp frames */ | 166 | /* Make sure the match only receives stp frames */ |
167 | if (compare_ether_addr(e->destmac, bridge_ula) || | 167 | if (compare_ether_addr(e->destmac, bridge_ula) || |
168 | compare_ether_addr(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC)) | 168 | compare_ether_addr(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC)) |
169 | return false; | 169 | return -EINVAL; |
170 | 170 | ||
171 | return true; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | static struct xt_match ebt_stp_mt_reg __read_mostly = { | 174 | static struct xt_match ebt_stp_mt_reg __read_mostly = { |
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index f9560f3dbdc7..ae3c7cef1484 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c | |||
@@ -27,7 +27,7 @@ | |||
27 | * flushed even if it is not full yet. | 27 | * flushed even if it is not full yet. |
28 | * | 28 | * |
29 | */ | 29 | */ |
30 | 30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/spinlock.h> | 33 | #include <linux/spinlock.h> |
@@ -44,9 +44,6 @@ | |||
44 | #include <net/sock.h> | 44 | #include <net/sock.h> |
45 | #include "../br_private.h" | 45 | #include "../br_private.h" |
46 | 46 | ||
47 | #define PRINTR(format, args...) do { if (net_ratelimit()) \ | ||
48 | printk(format , ## args); } while (0) | ||
49 | |||
50 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; | 47 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; |
51 | module_param(nlbufsiz, uint, 0600); | 48 | module_param(nlbufsiz, uint, 0600); |
52 | MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " | 49 | MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " |
@@ -107,15 +104,14 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size) | |||
107 | n = max(size, nlbufsiz); | 104 | n = max(size, nlbufsiz); |
108 | skb = alloc_skb(n, GFP_ATOMIC); | 105 | skb = alloc_skb(n, GFP_ATOMIC); |
109 | if (!skb) { | 106 | if (!skb) { |
110 | PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer " | 107 | pr_debug("cannot alloc whole buffer of size %ub!\n", n); |
111 | "of size %ub!\n", n); | ||
112 | if (n > size) { | 108 | if (n > size) { |
113 | /* try to allocate only as much as we need for | 109 | /* try to allocate only as much as we need for |
114 | * current packet */ | 110 | * current packet */ |
115 | skb = alloc_skb(size, GFP_ATOMIC); | 111 | skb = alloc_skb(size, GFP_ATOMIC); |
116 | if (!skb) | 112 | if (!skb) |
117 | PRINTR(KERN_ERR "ebt_ulog: can't even allocate " | 113 | pr_debug("cannot even allocate " |
118 | "buffer of size %ub\n", size); | 114 | "buffer of size %ub\n", size); |
119 | } | 115 | } |
120 | } | 116 | } |
121 | 117 | ||
@@ -142,8 +138,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, | |||
142 | 138 | ||
143 | size = NLMSG_SPACE(sizeof(*pm) + copy_len); | 139 | size = NLMSG_SPACE(sizeof(*pm) + copy_len); |
144 | if (size > nlbufsiz) { | 140 | if (size > nlbufsiz) { |
145 | PRINTR("ebt_ulog: Size %Zd needed, but nlbufsiz=%d\n", | 141 | pr_debug("Size %Zd needed, but nlbufsiz=%d\n", size, nlbufsiz); |
146 | size, nlbufsiz); | ||
147 | return; | 142 | return; |
148 | } | 143 | } |
149 | 144 | ||
@@ -217,8 +212,8 @@ unlock: | |||
217 | return; | 212 | return; |
218 | 213 | ||
219 | nlmsg_failure: | 214 | nlmsg_failure: |
220 | printk(KERN_CRIT "ebt_ulog: error during NLMSG_PUT. This should " | 215 | pr_debug("error during NLMSG_PUT. This should " |
221 | "not happen, please report to author.\n"); | 216 | "not happen, please report to author.\n"); |
222 | goto unlock; | 217 | goto unlock; |
223 | alloc_failure: | 218 | alloc_failure: |
224 | goto unlock; | 219 | goto unlock; |
@@ -248,26 +243,26 @@ static void ebt_log_packet(u_int8_t pf, unsigned int hooknum, | |||
248 | } | 243 | } |
249 | 244 | ||
250 | static unsigned int | 245 | static unsigned int |
251 | ebt_ulog_tg(struct sk_buff *skb, const struct xt_target_param *par) | 246 | ebt_ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) |
252 | { | 247 | { |
253 | ebt_ulog_packet(par->hooknum, skb, par->in, par->out, | 248 | ebt_ulog_packet(par->hooknum, skb, par->in, par->out, |
254 | par->targinfo, NULL); | 249 | par->targinfo, NULL); |
255 | return EBT_CONTINUE; | 250 | return EBT_CONTINUE; |
256 | } | 251 | } |
257 | 252 | ||
258 | static bool ebt_ulog_tg_check(const struct xt_tgchk_param *par) | 253 | static int ebt_ulog_tg_check(const struct xt_tgchk_param *par) |
259 | { | 254 | { |
260 | struct ebt_ulog_info *uloginfo = par->targinfo; | 255 | struct ebt_ulog_info *uloginfo = par->targinfo; |
261 | 256 | ||
262 | if (uloginfo->nlgroup > 31) | 257 | if (uloginfo->nlgroup > 31) |
263 | return false; | 258 | return -EINVAL; |
264 | 259 | ||
265 | uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0'; | 260 | uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0'; |
266 | 261 | ||
267 | if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN) | 262 | if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN) |
268 | uloginfo->qthreshold = EBT_ULOG_MAX_QLEN; | 263 | uloginfo->qthreshold = EBT_ULOG_MAX_QLEN; |
269 | 264 | ||
270 | return true; | 265 | return 0; |
271 | } | 266 | } |
272 | 267 | ||
273 | static struct xt_target ebt_ulog_tg_reg __read_mostly = { | 268 | static struct xt_target ebt_ulog_tg_reg __read_mostly = { |
@@ -292,8 +287,8 @@ static int __init ebt_ulog_init(void) | |||
292 | int i; | 287 | int i; |
293 | 288 | ||
294 | if (nlbufsiz >= 128*1024) { | 289 | if (nlbufsiz >= 128*1024) { |
295 | printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB," | 290 | pr_warning("Netlink buffer has to be <= 128kB," |
296 | " please try a smaller nlbufsiz parameter.\n"); | 291 | " please try a smaller nlbufsiz parameter.\n"); |
297 | return -EINVAL; | 292 | return -EINVAL; |
298 | } | 293 | } |
299 | 294 | ||
@@ -306,13 +301,10 @@ static int __init ebt_ulog_init(void) | |||
306 | ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG, | 301 | ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG, |
307 | EBT_ULOG_MAXNLGROUPS, NULL, NULL, | 302 | EBT_ULOG_MAXNLGROUPS, NULL, NULL, |
308 | THIS_MODULE); | 303 | THIS_MODULE); |
309 | if (!ebtulognl) { | 304 | if (!ebtulognl) |
310 | printk(KERN_WARNING KBUILD_MODNAME ": out of memory trying to " | ||
311 | "call netlink_kernel_create\n"); | ||
312 | ret = -ENOMEM; | 305 | ret = -ENOMEM; |
313 | } else if ((ret = xt_register_target(&ebt_ulog_tg_reg)) != 0) { | 306 | else if ((ret = xt_register_target(&ebt_ulog_tg_reg)) != 0) |
314 | netlink_kernel_release(ebtulognl); | 307 | netlink_kernel_release(ebtulognl); |
315 | } | ||
316 | 308 | ||
317 | if (ret == 0) | 309 | if (ret == 0) |
318 | nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger); | 310 | nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger); |
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c index be1dd2e1f615..87b53b3a921d 100644 --- a/net/bridge/netfilter/ebt_vlan.c +++ b/net/bridge/netfilter/ebt_vlan.c | |||
@@ -26,22 +26,17 @@ | |||
26 | #include <linux/netfilter_bridge/ebtables.h> | 26 | #include <linux/netfilter_bridge/ebtables.h> |
27 | #include <linux/netfilter_bridge/ebt_vlan.h> | 27 | #include <linux/netfilter_bridge/ebt_vlan.h> |
28 | 28 | ||
29 | static int debug; | ||
30 | #define MODULE_VERS "0.6" | 29 | #define MODULE_VERS "0.6" |
31 | 30 | ||
32 | module_param(debug, int, 0); | ||
33 | MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages"); | ||
34 | MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>"); | 31 | MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>"); |
35 | MODULE_DESCRIPTION("Ebtables: 802.1Q VLAN tag match"); | 32 | MODULE_DESCRIPTION("Ebtables: 802.1Q VLAN tag match"); |
36 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
37 | 34 | ||
38 | |||
39 | #define DEBUG_MSG(args...) if (debug) printk (KERN_DEBUG "ebt_vlan: " args) | ||
40 | #define GET_BITMASK(_BIT_MASK_) info->bitmask & _BIT_MASK_ | 35 | #define GET_BITMASK(_BIT_MASK_) info->bitmask & _BIT_MASK_ |
41 | #define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return false; } | 36 | #define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return false; } |
42 | 37 | ||
43 | static bool | 38 | static bool |
44 | ebt_vlan_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 39 | ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par) |
45 | { | 40 | { |
46 | const struct ebt_vlan_info *info = par->matchinfo; | 41 | const struct ebt_vlan_info *info = par->matchinfo; |
47 | const struct vlan_hdr *fp; | 42 | const struct vlan_hdr *fp; |
@@ -84,32 +79,31 @@ ebt_vlan_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
84 | return true; | 79 | return true; |
85 | } | 80 | } |
86 | 81 | ||
87 | static bool ebt_vlan_mt_check(const struct xt_mtchk_param *par) | 82 | static int ebt_vlan_mt_check(const struct xt_mtchk_param *par) |
88 | { | 83 | { |
89 | struct ebt_vlan_info *info = par->matchinfo; | 84 | struct ebt_vlan_info *info = par->matchinfo; |
90 | const struct ebt_entry *e = par->entryinfo; | 85 | const struct ebt_entry *e = par->entryinfo; |
91 | 86 | ||
92 | /* Is it 802.1Q frame checked? */ | 87 | /* Is it 802.1Q frame checked? */ |
93 | if (e->ethproto != htons(ETH_P_8021Q)) { | 88 | if (e->ethproto != htons(ETH_P_8021Q)) { |
94 | DEBUG_MSG | 89 | pr_debug("passed entry proto %2.4X is not 802.1Q (8100)\n", |
95 | ("passed entry proto %2.4X is not 802.1Q (8100)\n", | 90 | ntohs(e->ethproto)); |
96 | (unsigned short) ntohs(e->ethproto)); | 91 | return -EINVAL; |
97 | return false; | ||
98 | } | 92 | } |
99 | 93 | ||
100 | /* Check for bitmask range | 94 | /* Check for bitmask range |
101 | * True if even one bit is out of mask */ | 95 | * True if even one bit is out of mask */ |
102 | if (info->bitmask & ~EBT_VLAN_MASK) { | 96 | if (info->bitmask & ~EBT_VLAN_MASK) { |
103 | DEBUG_MSG("bitmask %2X is out of mask (%2X)\n", | 97 | pr_debug("bitmask %2X is out of mask (%2X)\n", |
104 | info->bitmask, EBT_VLAN_MASK); | 98 | info->bitmask, EBT_VLAN_MASK); |
105 | return false; | 99 | return -EINVAL; |
106 | } | 100 | } |
107 | 101 | ||
108 | /* Check for inversion flags range */ | 102 | /* Check for inversion flags range */ |
109 | if (info->invflags & ~EBT_VLAN_MASK) { | 103 | if (info->invflags & ~EBT_VLAN_MASK) { |
110 | DEBUG_MSG("inversion flags %2X is out of mask (%2X)\n", | 104 | pr_debug("inversion flags %2X is out of mask (%2X)\n", |
111 | info->invflags, EBT_VLAN_MASK); | 105 | info->invflags, EBT_VLAN_MASK); |
112 | return false; | 106 | return -EINVAL; |
113 | } | 107 | } |
114 | 108 | ||
115 | /* Reserved VLAN ID (VID) values | 109 | /* Reserved VLAN ID (VID) values |
@@ -121,10 +115,9 @@ static bool ebt_vlan_mt_check(const struct xt_mtchk_param *par) | |||
121 | if (GET_BITMASK(EBT_VLAN_ID)) { | 115 | if (GET_BITMASK(EBT_VLAN_ID)) { |
122 | if (!!info->id) { /* if id!=0 => check vid range */ | 116 | if (!!info->id) { /* if id!=0 => check vid range */ |
123 | if (info->id > VLAN_GROUP_ARRAY_LEN) { | 117 | if (info->id > VLAN_GROUP_ARRAY_LEN) { |
124 | DEBUG_MSG | 118 | pr_debug("id %d is out of range (1-4096)\n", |
125 | ("id %d is out of range (1-4096)\n", | 119 | info->id); |
126 | info->id); | 120 | return -EINVAL; |
127 | return false; | ||
128 | } | 121 | } |
129 | /* Note: This is valid VLAN-tagged frame point. | 122 | /* Note: This is valid VLAN-tagged frame point. |
130 | * Any value of user_priority are acceptable, | 123 | * Any value of user_priority are acceptable, |
@@ -137,9 +130,9 @@ static bool ebt_vlan_mt_check(const struct xt_mtchk_param *par) | |||
137 | 130 | ||
138 | if (GET_BITMASK(EBT_VLAN_PRIO)) { | 131 | if (GET_BITMASK(EBT_VLAN_PRIO)) { |
139 | if ((unsigned char) info->prio > 7) { | 132 | if ((unsigned char) info->prio > 7) { |
140 | DEBUG_MSG("prio %d is out of range (0-7)\n", | 133 | pr_debug("prio %d is out of range (0-7)\n", |
141 | info->prio); | 134 | info->prio); |
142 | return false; | 135 | return -EINVAL; |
143 | } | 136 | } |
144 | } | 137 | } |
145 | /* Check for encapsulated proto range - it is possible to be | 138 | /* Check for encapsulated proto range - it is possible to be |
@@ -147,14 +140,13 @@ static bool ebt_vlan_mt_check(const struct xt_mtchk_param *par) | |||
147 | * if_ether.h: ETH_ZLEN 60 - Min. octets in frame sans FCS */ | 140 | * if_ether.h: ETH_ZLEN 60 - Min. octets in frame sans FCS */ |
148 | if (GET_BITMASK(EBT_VLAN_ENCAP)) { | 141 | if (GET_BITMASK(EBT_VLAN_ENCAP)) { |
149 | if ((unsigned short) ntohs(info->encap) < ETH_ZLEN) { | 142 | if ((unsigned short) ntohs(info->encap) < ETH_ZLEN) { |
150 | DEBUG_MSG | 143 | pr_debug("encap frame length %d is less than " |
151 | ("encap frame length %d is less than minimal\n", | 144 | "minimal\n", ntohs(info->encap)); |
152 | ntohs(info->encap)); | 145 | return -EINVAL; |
153 | return false; | ||
154 | } | 146 | } |
155 | } | 147 | } |
156 | 148 | ||
157 | return true; | 149 | return 0; |
158 | } | 150 | } |
159 | 151 | ||
160 | static struct xt_match ebt_vlan_mt_reg __read_mostly = { | 152 | static struct xt_match ebt_vlan_mt_reg __read_mostly = { |
@@ -169,9 +161,7 @@ static struct xt_match ebt_vlan_mt_reg __read_mostly = { | |||
169 | 161 | ||
170 | static int __init ebt_vlan_init(void) | 162 | static int __init ebt_vlan_init(void) |
171 | { | 163 | { |
172 | DEBUG_MSG("ebtables 802.1Q extension module v" | 164 | pr_debug("ebtables 802.1Q extension module v" MODULE_VERS "\n"); |
173 | MODULE_VERS "\n"); | ||
174 | DEBUG_MSG("module debug=%d\n", !!debug); | ||
175 | return xt_register_match(&ebt_vlan_mt_reg); | 165 | return xt_register_match(&ebt_vlan_mt_reg); |
176 | } | 166 | } |
177 | 167 | ||
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index f0865fd1e3ec..59ca00e40dec 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -14,8 +14,7 @@ | |||
14 | * as published by the Free Software Foundation; either version | 14 | * as published by the Free Software Foundation; either version |
15 | * 2 of the License, or (at your option) any later version. | 15 | * 2 of the License, or (at your option) any later version. |
16 | */ | 16 | */ |
17 | 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
18 | |||
19 | #include <linux/kmod.h> | 18 | #include <linux/kmod.h> |
20 | #include <linux/module.h> | 19 | #include <linux/module.h> |
21 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
@@ -87,7 +86,7 @@ static struct xt_target ebt_standard_target = { | |||
87 | 86 | ||
88 | static inline int | 87 | static inline int |
89 | ebt_do_watcher(const struct ebt_entry_watcher *w, struct sk_buff *skb, | 88 | ebt_do_watcher(const struct ebt_entry_watcher *w, struct sk_buff *skb, |
90 | struct xt_target_param *par) | 89 | struct xt_action_param *par) |
91 | { | 90 | { |
92 | par->target = w->u.watcher; | 91 | par->target = w->u.watcher; |
93 | par->targinfo = w->data; | 92 | par->targinfo = w->data; |
@@ -96,8 +95,9 @@ ebt_do_watcher(const struct ebt_entry_watcher *w, struct sk_buff *skb, | |||
96 | return 0; | 95 | return 0; |
97 | } | 96 | } |
98 | 97 | ||
99 | static inline int ebt_do_match (struct ebt_entry_match *m, | 98 | static inline int |
100 | const struct sk_buff *skb, struct xt_match_param *par) | 99 | ebt_do_match(struct ebt_entry_match *m, const struct sk_buff *skb, |
100 | struct xt_action_param *par) | ||
101 | { | 101 | { |
102 | par->match = m->u.match; | 102 | par->match = m->u.match; |
103 | par->matchinfo = m->data; | 103 | par->matchinfo = m->data; |
@@ -186,15 +186,13 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, | |||
186 | struct ebt_entries *chaininfo; | 186 | struct ebt_entries *chaininfo; |
187 | const char *base; | 187 | const char *base; |
188 | const struct ebt_table_info *private; | 188 | const struct ebt_table_info *private; |
189 | bool hotdrop = false; | 189 | struct xt_action_param acpar; |
190 | struct xt_match_param mtpar; | ||
191 | struct xt_target_param tgpar; | ||
192 | 190 | ||
193 | mtpar.family = tgpar.family = NFPROTO_BRIDGE; | 191 | acpar.family = NFPROTO_BRIDGE; |
194 | mtpar.in = tgpar.in = in; | 192 | acpar.in = in; |
195 | mtpar.out = tgpar.out = out; | 193 | acpar.out = out; |
196 | mtpar.hotdrop = &hotdrop; | 194 | acpar.hotdrop = false; |
197 | mtpar.hooknum = tgpar.hooknum = hook; | 195 | acpar.hooknum = hook; |
198 | 196 | ||
199 | read_lock_bh(&table->lock); | 197 | read_lock_bh(&table->lock); |
200 | private = table->private; | 198 | private = table->private; |
@@ -215,9 +213,9 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, | |||
215 | if (ebt_basic_match(point, eth_hdr(skb), in, out)) | 213 | if (ebt_basic_match(point, eth_hdr(skb), in, out)) |
216 | goto letscontinue; | 214 | goto letscontinue; |
217 | 215 | ||
218 | if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &mtpar) != 0) | 216 | if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0) |
219 | goto letscontinue; | 217 | goto letscontinue; |
220 | if (hotdrop) { | 218 | if (acpar.hotdrop) { |
221 | read_unlock_bh(&table->lock); | 219 | read_unlock_bh(&table->lock); |
222 | return NF_DROP; | 220 | return NF_DROP; |
223 | } | 221 | } |
@@ -228,7 +226,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, | |||
228 | 226 | ||
229 | /* these should only watch: not modify, nor tell us | 227 | /* these should only watch: not modify, nor tell us |
230 | what to do with the packet */ | 228 | what to do with the packet */ |
231 | EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &tgpar); | 229 | EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &acpar); |
232 | 230 | ||
233 | t = (struct ebt_entry_target *) | 231 | t = (struct ebt_entry_target *) |
234 | (((char *)point) + point->target_offset); | 232 | (((char *)point) + point->target_offset); |
@@ -236,9 +234,9 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, | |||
236 | if (!t->u.target->target) | 234 | if (!t->u.target->target) |
237 | verdict = ((struct ebt_standard_target *)t)->verdict; | 235 | verdict = ((struct ebt_standard_target *)t)->verdict; |
238 | else { | 236 | else { |
239 | tgpar.target = t->u.target; | 237 | acpar.target = t->u.target; |
240 | tgpar.targinfo = t->data; | 238 | acpar.targinfo = t->data; |
241 | verdict = t->u.target->target(skb, &tgpar); | 239 | verdict = t->u.target->target(skb, &acpar); |
242 | } | 240 | } |
243 | if (verdict == EBT_ACCEPT) { | 241 | if (verdict == EBT_ACCEPT) { |
244 | read_unlock_bh(&table->lock); | 242 | read_unlock_bh(&table->lock); |
@@ -363,12 +361,9 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par, | |||
363 | left - sizeof(struct ebt_entry_match) < m->match_size) | 361 | left - sizeof(struct ebt_entry_match) < m->match_size) |
364 | return -EINVAL; | 362 | return -EINVAL; |
365 | 363 | ||
366 | match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE, | 364 | match = xt_request_find_match(NFPROTO_BRIDGE, m->u.name, 0); |
367 | m->u.name, 0), "ebt_%s", m->u.name); | ||
368 | if (IS_ERR(match)) | 365 | if (IS_ERR(match)) |
369 | return PTR_ERR(match); | 366 | return PTR_ERR(match); |
370 | if (match == NULL) | ||
371 | return -ENOENT; | ||
372 | m->u.match = match; | 367 | m->u.match = match; |
373 | 368 | ||
374 | par->match = match; | 369 | par->match = match; |
@@ -397,13 +392,9 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par, | |||
397 | left - sizeof(struct ebt_entry_watcher) < w->watcher_size) | 392 | left - sizeof(struct ebt_entry_watcher) < w->watcher_size) |
398 | return -EINVAL; | 393 | return -EINVAL; |
399 | 394 | ||
400 | watcher = try_then_request_module( | 395 | watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0); |
401 | xt_find_target(NFPROTO_BRIDGE, w->u.name, 0), | ||
402 | "ebt_%s", w->u.name); | ||
403 | if (IS_ERR(watcher)) | 396 | if (IS_ERR(watcher)) |
404 | return PTR_ERR(watcher); | 397 | return PTR_ERR(watcher); |
405 | if (watcher == NULL) | ||
406 | return -ENOENT; | ||
407 | w->u.watcher = watcher; | 398 | w->u.watcher = watcher; |
408 | 399 | ||
409 | par->target = watcher; | 400 | par->target = watcher; |
@@ -716,15 +707,10 @@ ebt_check_entry(struct ebt_entry *e, struct net *net, | |||
716 | t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); | 707 | t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); |
717 | gap = e->next_offset - e->target_offset; | 708 | gap = e->next_offset - e->target_offset; |
718 | 709 | ||
719 | target = try_then_request_module( | 710 | target = xt_request_find_target(NFPROTO_BRIDGE, t->u.name, 0); |
720 | xt_find_target(NFPROTO_BRIDGE, t->u.name, 0), | ||
721 | "ebt_%s", t->u.name); | ||
722 | if (IS_ERR(target)) { | 711 | if (IS_ERR(target)) { |
723 | ret = PTR_ERR(target); | 712 | ret = PTR_ERR(target); |
724 | goto cleanup_watchers; | 713 | goto cleanup_watchers; |
725 | } else if (target == NULL) { | ||
726 | ret = -ENOENT; | ||
727 | goto cleanup_watchers; | ||
728 | } | 714 | } |
729 | 715 | ||
730 | t->u.target = target; | 716 | t->u.target = target; |
@@ -2128,7 +2114,7 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, | |||
2128 | return ret; | 2114 | return ret; |
2129 | new_offset += ret; | 2115 | new_offset += ret; |
2130 | if (offsets_update && new_offset) { | 2116 | if (offsets_update && new_offset) { |
2131 | pr_debug("ebtables: change offset %d to %d\n", | 2117 | pr_debug("change offset %d to %d\n", |
2132 | offsets_update[i], offsets[j] + new_offset); | 2118 | offsets_update[i], offsets[j] + new_offset); |
2133 | offsets_update[i] = offsets[j] + new_offset; | 2119 | offsets_update[i] = offsets[j] + new_offset; |
2134 | } | 2120 | } |
diff --git a/net/caif/Kconfig b/net/caif/Kconfig new file mode 100644 index 000000000000..cd1daf6008bd --- /dev/null +++ b/net/caif/Kconfig | |||
@@ -0,0 +1,48 @@ | |||
1 | # | ||
2 | # CAIF net configurations | ||
3 | # | ||
4 | |||
5 | #menu "CAIF Support" | ||
6 | comment "CAIF Support" | ||
7 | menuconfig CAIF | ||
8 | tristate "Enable CAIF support" | ||
9 | select CRC_CCITT | ||
10 | default n | ||
11 | ---help--- | ||
12 | The "Communication CPU to Application CPU Interface" (CAIF) is a packet | ||
13 | based connection-oriented MUX protocol developed by ST-Ericsson for use | ||
14 | with its modems. It is accessed from user space as sockets (PF_CAIF). | ||
15 | |||
16 | Say Y (or M) here if you build for a phone product (e.g. Android or | ||
17 | MeeGo ) that uses CAIF as transport, if unsure say N. | ||
18 | |||
19 | If you select to build it as module then CAIF_NETDEV also needs to be | ||
20 | built as modules. You will also need to say yes to any CAIF physical | ||
21 | devices that your platform requires. | ||
22 | |||
23 | See Documentation/networking/caif for a further explanation on how to | ||
24 | use and configure CAIF. | ||
25 | |||
26 | if CAIF | ||
27 | |||
28 | config CAIF_DEBUG | ||
29 | bool "Enable Debug" | ||
30 | default n | ||
31 | --- help --- | ||
32 | Enable the inclusion of debug code in the CAIF stack. | ||
33 | Be aware that doing this will impact performance. | ||
34 | If unsure say N. | ||
35 | |||
36 | |||
37 | config CAIF_NETDEV | ||
38 | tristate "CAIF GPRS Network device" | ||
39 | default CAIF | ||
40 | ---help--- | ||
41 | Say Y if you will be using a CAIF based GPRS network device. | ||
42 | This can be either built-in or a loadable module, | ||
43 | If you select to build it as a built-in then the main CAIF device must | ||
44 | also be a built-in. | ||
45 | If unsure say Y. | ||
46 | |||
47 | endif | ||
48 | #endmenu | ||
diff --git a/net/caif/Makefile b/net/caif/Makefile new file mode 100644 index 000000000000..34852af2595e --- /dev/null +++ b/net/caif/Makefile | |||
@@ -0,0 +1,26 @@ | |||
1 | ifeq ($(CONFIG_CAIF_DEBUG),1) | ||
2 | CAIF_DBG_FLAGS := -DDEBUG | ||
3 | endif | ||
4 | |||
5 | ccflags-y := $(CAIF_FLAGS) $(CAIF_DBG_FLAGS) | ||
6 | |||
7 | caif-objs := caif_dev.o \ | ||
8 | cfcnfg.o cfmuxl.o cfctrl.o \ | ||
9 | cffrml.o cfveil.o cfdbgl.o\ | ||
10 | cfserl.o cfdgml.o \ | ||
11 | cfrfml.o cfvidl.o cfutill.o \ | ||
12 | cfsrvl.o cfpkt_skbuff.o caif_config_util.o | ||
13 | clean-dirs:= .tmp_versions | ||
14 | |||
15 | clean-files:= \ | ||
16 | Module.symvers \ | ||
17 | modules.order \ | ||
18 | *.cmd \ | ||
19 | *.o \ | ||
20 | *~ | ||
21 | |||
22 | obj-$(CONFIG_CAIF) += caif.o | ||
23 | obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o | ||
24 | obj-$(CONFIG_CAIF) += caif_socket.o | ||
25 | |||
26 | export-objs := caif.o | ||
diff --git a/net/caif/caif_config_util.c b/net/caif/caif_config_util.c new file mode 100644 index 000000000000..6f36580366f0 --- /dev/null +++ b/net/caif/caif_config_util.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/spinlock.h> | ||
9 | #include <net/caif/cfctrl.h> | ||
10 | #include <net/caif/cfcnfg.h> | ||
11 | #include <net/caif/caif_dev.h> | ||
12 | |||
13 | int connect_req_to_link_param(struct cfcnfg *cnfg, | ||
14 | struct caif_connect_request *s, | ||
15 | struct cfctrl_link_param *l) | ||
16 | { | ||
17 | struct dev_info *dev_info; | ||
18 | enum cfcnfg_phy_preference pref; | ||
19 | memset(l, 0, sizeof(*l)); | ||
20 | l->priority = s->priority; | ||
21 | |||
22 | if (s->link_name[0] != '\0') | ||
23 | l->phyid = cfcnfg_get_named(cnfg, s->link_name); | ||
24 | else { | ||
25 | switch (s->link_selector) { | ||
26 | case CAIF_LINK_HIGH_BANDW: | ||
27 | pref = CFPHYPREF_HIGH_BW; | ||
28 | break; | ||
29 | case CAIF_LINK_LOW_LATENCY: | ||
30 | pref = CFPHYPREF_LOW_LAT; | ||
31 | break; | ||
32 | default: | ||
33 | return -EINVAL; | ||
34 | } | ||
35 | dev_info = cfcnfg_get_phyid(cnfg, pref); | ||
36 | if (dev_info == NULL) | ||
37 | return -ENODEV; | ||
38 | l->phyid = dev_info->id; | ||
39 | } | ||
40 | switch (s->protocol) { | ||
41 | case CAIFPROTO_AT: | ||
42 | l->linktype = CFCTRL_SRV_VEI; | ||
43 | if (s->sockaddr.u.at.type == CAIF_ATTYPE_PLAIN) | ||
44 | l->chtype = 0x02; | ||
45 | else | ||
46 | l->chtype = s->sockaddr.u.at.type; | ||
47 | l->endpoint = 0x00; | ||
48 | break; | ||
49 | case CAIFPROTO_DATAGRAM: | ||
50 | l->linktype = CFCTRL_SRV_DATAGRAM; | ||
51 | l->chtype = 0x00; | ||
52 | l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; | ||
53 | break; | ||
54 | case CAIFPROTO_DATAGRAM_LOOP: | ||
55 | l->linktype = CFCTRL_SRV_DATAGRAM; | ||
56 | l->chtype = 0x03; | ||
57 | l->endpoint = 0x00; | ||
58 | l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; | ||
59 | break; | ||
60 | case CAIFPROTO_RFM: | ||
61 | l->linktype = CFCTRL_SRV_RFM; | ||
62 | l->u.datagram.connid = s->sockaddr.u.rfm.connection_id; | ||
63 | strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume, | ||
64 | sizeof(l->u.rfm.volume)-1); | ||
65 | l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0; | ||
66 | break; | ||
67 | case CAIFPROTO_UTIL: | ||
68 | l->linktype = CFCTRL_SRV_UTIL; | ||
69 | l->endpoint = 0x00; | ||
70 | l->chtype = 0x00; | ||
71 | strncpy(l->u.utility.name, s->sockaddr.u.util.service, | ||
72 | sizeof(l->u.utility.name)-1); | ||
73 | l->u.utility.name[sizeof(l->u.utility.name)-1] = 0; | ||
74 | caif_assert(sizeof(l->u.utility.name) > 10); | ||
75 | l->u.utility.paramlen = s->param.size; | ||
76 | if (l->u.utility.paramlen > sizeof(l->u.utility.params)) | ||
77 | l->u.utility.paramlen = sizeof(l->u.utility.params); | ||
78 | |||
79 | memcpy(l->u.utility.params, s->param.data, | ||
80 | l->u.utility.paramlen); | ||
81 | |||
82 | break; | ||
83 | default: | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | return 0; | ||
87 | } | ||
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c new file mode 100644 index 000000000000..e2b86f1f5a47 --- /dev/null +++ b/net/caif/caif_dev.c | |||
@@ -0,0 +1,417 @@ | |||
1 | /* | ||
2 | * CAIF Interface registration. | ||
3 | * Copyright (C) ST-Ericsson AB 2010 | ||
4 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | * | ||
7 | * Borrowed heavily from file: pn_dev.c. Thanks to | ||
8 | * Remi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
9 | * and Sakari Ailus <sakari.ailus@nokia.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/version.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/if_arp.h> | ||
16 | #include <linux/net.h> | ||
17 | #include <linux/netdevice.h> | ||
18 | #include <linux/skbuff.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/wait.h> | ||
21 | #include <net/netns/generic.h> | ||
22 | #include <net/net_namespace.h> | ||
23 | #include <net/pkt_sched.h> | ||
24 | #include <net/caif/caif_device.h> | ||
25 | #include <net/caif/caif_dev.h> | ||
26 | #include <net/caif/caif_layer.h> | ||
27 | #include <net/caif/cfpkt.h> | ||
28 | #include <net/caif/cfcnfg.h> | ||
29 | |||
30 | MODULE_LICENSE("GPL"); | ||
31 | #define TIMEOUT (HZ*5) | ||
32 | |||
33 | /* Used for local tracking of the CAIF net devices */ | ||
34 | struct caif_device_entry { | ||
35 | struct cflayer layer; | ||
36 | struct list_head list; | ||
37 | atomic_t in_use; | ||
38 | atomic_t state; | ||
39 | u16 phyid; | ||
40 | struct net_device *netdev; | ||
41 | wait_queue_head_t event; | ||
42 | }; | ||
43 | |||
44 | struct caif_device_entry_list { | ||
45 | struct list_head list; | ||
46 | /* Protects simulanous deletes in list */ | ||
47 | spinlock_t lock; | ||
48 | }; | ||
49 | |||
50 | struct caif_net { | ||
51 | struct caif_device_entry_list caifdevs; | ||
52 | }; | ||
53 | |||
54 | static int caif_net_id; | ||
55 | static struct cfcnfg *cfg; | ||
56 | |||
57 | static struct caif_device_entry_list *caif_device_list(struct net *net) | ||
58 | { | ||
59 | struct caif_net *caifn; | ||
60 | BUG_ON(!net); | ||
61 | caifn = net_generic(net, caif_net_id); | ||
62 | BUG_ON(!caifn); | ||
63 | return &caifn->caifdevs; | ||
64 | } | ||
65 | |||
66 | /* Allocate new CAIF device. */ | ||
67 | static struct caif_device_entry *caif_device_alloc(struct net_device *dev) | ||
68 | { | ||
69 | struct caif_device_entry_list *caifdevs; | ||
70 | struct caif_device_entry *caifd; | ||
71 | caifdevs = caif_device_list(dev_net(dev)); | ||
72 | BUG_ON(!caifdevs); | ||
73 | caifd = kzalloc(sizeof(*caifd), GFP_ATOMIC); | ||
74 | if (!caifd) | ||
75 | return NULL; | ||
76 | caifd->netdev = dev; | ||
77 | list_add(&caifd->list, &caifdevs->list); | ||
78 | init_waitqueue_head(&caifd->event); | ||
79 | return caifd; | ||
80 | } | ||
81 | |||
82 | static struct caif_device_entry *caif_get(struct net_device *dev) | ||
83 | { | ||
84 | struct caif_device_entry_list *caifdevs = | ||
85 | caif_device_list(dev_net(dev)); | ||
86 | struct caif_device_entry *caifd; | ||
87 | BUG_ON(!caifdevs); | ||
88 | list_for_each_entry(caifd, &caifdevs->list, list) { | ||
89 | if (caifd->netdev == dev) | ||
90 | return caifd; | ||
91 | } | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | static void caif_device_destroy(struct net_device *dev) | ||
96 | { | ||
97 | struct caif_device_entry_list *caifdevs = | ||
98 | caif_device_list(dev_net(dev)); | ||
99 | struct caif_device_entry *caifd; | ||
100 | ASSERT_RTNL(); | ||
101 | if (dev->type != ARPHRD_CAIF) | ||
102 | return; | ||
103 | |||
104 | spin_lock_bh(&caifdevs->lock); | ||
105 | caifd = caif_get(dev); | ||
106 | if (caifd == NULL) { | ||
107 | spin_unlock_bh(&caifdevs->lock); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | list_del(&caifd->list); | ||
112 | spin_unlock_bh(&caifdevs->lock); | ||
113 | |||
114 | kfree(caifd); | ||
115 | } | ||
116 | |||
117 | static int transmit(struct cflayer *layer, struct cfpkt *pkt) | ||
118 | { | ||
119 | struct caif_device_entry *caifd = | ||
120 | container_of(layer, struct caif_device_entry, layer); | ||
121 | struct sk_buff *skb, *skb2; | ||
122 | int ret = -EINVAL; | ||
123 | skb = cfpkt_tonative(pkt); | ||
124 | skb->dev = caifd->netdev; | ||
125 | /* | ||
126 | * Don't allow SKB to be destroyed upon error, but signal resend | ||
127 | * notification to clients. We can't rely on the return value as | ||
128 | * congestion (NET_XMIT_CN) sometimes drops the packet, sometimes don't. | ||
129 | */ | ||
130 | if (netif_queue_stopped(caifd->netdev)) | ||
131 | return -EAGAIN; | ||
132 | skb2 = skb_get(skb); | ||
133 | |||
134 | ret = dev_queue_xmit(skb2); | ||
135 | |||
136 | if (!ret) | ||
137 | kfree_skb(skb); | ||
138 | else | ||
139 | return -EAGAIN; | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) | ||
145 | { | ||
146 | struct caif_device_entry *caifd; | ||
147 | struct caif_dev_common *caifdev; | ||
148 | caifd = container_of(layr, struct caif_device_entry, layer); | ||
149 | caifdev = netdev_priv(caifd->netdev); | ||
150 | if (ctrl == _CAIF_MODEMCMD_PHYIF_USEFULL) { | ||
151 | atomic_set(&caifd->in_use, 1); | ||
152 | wake_up_interruptible(&caifd->event); | ||
153 | |||
154 | } else if (ctrl == _CAIF_MODEMCMD_PHYIF_USELESS) { | ||
155 | atomic_set(&caifd->in_use, 0); | ||
156 | wake_up_interruptible(&caifd->event); | ||
157 | } | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Stuff received packets to associated sockets. | ||
163 | * On error, returns non-zero and releases the skb. | ||
164 | */ | ||
165 | static int receive(struct sk_buff *skb, struct net_device *dev, | ||
166 | struct packet_type *pkttype, struct net_device *orig_dev) | ||
167 | { | ||
168 | struct net *net; | ||
169 | struct cfpkt *pkt; | ||
170 | struct caif_device_entry *caifd; | ||
171 | net = dev_net(dev); | ||
172 | pkt = cfpkt_fromnative(CAIF_DIR_IN, skb); | ||
173 | caifd = caif_get(dev); | ||
174 | if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) | ||
175 | return NET_RX_DROP; | ||
176 | |||
177 | if (caifd->layer.up->receive(caifd->layer.up, pkt)) | ||
178 | return NET_RX_DROP; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static struct packet_type caif_packet_type __read_mostly = { | ||
184 | .type = cpu_to_be16(ETH_P_CAIF), | ||
185 | .func = receive, | ||
186 | }; | ||
187 | |||
188 | static void dev_flowctrl(struct net_device *dev, int on) | ||
189 | { | ||
190 | struct caif_device_entry *caifd = caif_get(dev); | ||
191 | if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) | ||
192 | return; | ||
193 | |||
194 | caifd->layer.up->ctrlcmd(caifd->layer.up, | ||
195 | on ? | ||
196 | _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND : | ||
197 | _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND, | ||
198 | caifd->layer.id); | ||
199 | } | ||
200 | |||
201 | /* notify Caif of device events */ | ||
202 | static int caif_device_notify(struct notifier_block *me, unsigned long what, | ||
203 | void *arg) | ||
204 | { | ||
205 | struct net_device *dev = arg; | ||
206 | struct caif_device_entry *caifd = NULL; | ||
207 | struct caif_dev_common *caifdev; | ||
208 | enum cfcnfg_phy_preference pref; | ||
209 | int res = -EINVAL; | ||
210 | enum cfcnfg_phy_type phy_type; | ||
211 | |||
212 | if (dev->type != ARPHRD_CAIF) | ||
213 | return 0; | ||
214 | |||
215 | switch (what) { | ||
216 | case NETDEV_REGISTER: | ||
217 | pr_info("CAIF: %s():register %s\n", __func__, dev->name); | ||
218 | caifd = caif_device_alloc(dev); | ||
219 | if (caifd == NULL) | ||
220 | break; | ||
221 | caifdev = netdev_priv(dev); | ||
222 | caifdev->flowctrl = dev_flowctrl; | ||
223 | atomic_set(&caifd->state, what); | ||
224 | res = 0; | ||
225 | break; | ||
226 | |||
227 | case NETDEV_UP: | ||
228 | pr_info("CAIF: %s(): up %s\n", __func__, dev->name); | ||
229 | caifd = caif_get(dev); | ||
230 | if (caifd == NULL) | ||
231 | break; | ||
232 | caifdev = netdev_priv(dev); | ||
233 | if (atomic_read(&caifd->state) == NETDEV_UP) { | ||
234 | pr_info("CAIF: %s():%s already up\n", | ||
235 | __func__, dev->name); | ||
236 | break; | ||
237 | } | ||
238 | atomic_set(&caifd->state, what); | ||
239 | caifd->layer.transmit = transmit; | ||
240 | caifd->layer.modemcmd = modemcmd; | ||
241 | |||
242 | if (caifdev->use_frag) | ||
243 | phy_type = CFPHYTYPE_FRAG; | ||
244 | else | ||
245 | phy_type = CFPHYTYPE_CAIF; | ||
246 | |||
247 | switch (caifdev->link_select) { | ||
248 | case CAIF_LINK_HIGH_BANDW: | ||
249 | pref = CFPHYPREF_HIGH_BW; | ||
250 | break; | ||
251 | case CAIF_LINK_LOW_LATENCY: | ||
252 | pref = CFPHYPREF_LOW_LAT; | ||
253 | break; | ||
254 | default: | ||
255 | pref = CFPHYPREF_HIGH_BW; | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | cfcnfg_add_phy_layer(get_caif_conf(), | ||
260 | phy_type, | ||
261 | dev, | ||
262 | &caifd->layer, | ||
263 | &caifd->phyid, | ||
264 | pref, | ||
265 | caifdev->use_fcs, | ||
266 | caifdev->use_stx); | ||
267 | strncpy(caifd->layer.name, dev->name, | ||
268 | sizeof(caifd->layer.name) - 1); | ||
269 | caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0; | ||
270 | break; | ||
271 | |||
272 | case NETDEV_GOING_DOWN: | ||
273 | caifd = caif_get(dev); | ||
274 | if (caifd == NULL) | ||
275 | break; | ||
276 | pr_info("CAIF: %s():going down %s\n", __func__, dev->name); | ||
277 | |||
278 | if (atomic_read(&caifd->state) == NETDEV_GOING_DOWN || | ||
279 | atomic_read(&caifd->state) == NETDEV_DOWN) | ||
280 | break; | ||
281 | |||
282 | atomic_set(&caifd->state, what); | ||
283 | if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) | ||
284 | return -EINVAL; | ||
285 | caifd->layer.up->ctrlcmd(caifd->layer.up, | ||
286 | _CAIF_CTRLCMD_PHYIF_DOWN_IND, | ||
287 | caifd->layer.id); | ||
288 | res = wait_event_interruptible_timeout(caifd->event, | ||
289 | atomic_read(&caifd->in_use) == 0, | ||
290 | TIMEOUT); | ||
291 | break; | ||
292 | |||
293 | case NETDEV_DOWN: | ||
294 | caifd = caif_get(dev); | ||
295 | if (caifd == NULL) | ||
296 | break; | ||
297 | pr_info("CAIF: %s(): down %s\n", __func__, dev->name); | ||
298 | if (atomic_read(&caifd->in_use)) | ||
299 | pr_warning("CAIF: %s(): " | ||
300 | "Unregistering an active CAIF device: %s\n", | ||
301 | __func__, dev->name); | ||
302 | cfcnfg_del_phy_layer(get_caif_conf(), &caifd->layer); | ||
303 | atomic_set(&caifd->state, what); | ||
304 | break; | ||
305 | |||
306 | case NETDEV_UNREGISTER: | ||
307 | caifd = caif_get(dev); | ||
308 | pr_info("CAIF: %s(): unregister %s\n", __func__, dev->name); | ||
309 | atomic_set(&caifd->state, what); | ||
310 | caif_device_destroy(dev); | ||
311 | break; | ||
312 | } | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static struct notifier_block caif_device_notifier = { | ||
317 | .notifier_call = caif_device_notify, | ||
318 | .priority = 0, | ||
319 | }; | ||
320 | |||
321 | |||
322 | struct cfcnfg *get_caif_conf(void) | ||
323 | { | ||
324 | return cfg; | ||
325 | } | ||
326 | EXPORT_SYMBOL(get_caif_conf); | ||
327 | |||
328 | int caif_connect_client(struct caif_connect_request *conn_req, | ||
329 | struct cflayer *client_layer) | ||
330 | { | ||
331 | struct cfctrl_link_param param; | ||
332 | int ret; | ||
333 | ret = connect_req_to_link_param(get_caif_conf(), conn_req, ¶m); | ||
334 | if (ret) | ||
335 | return ret; | ||
336 | /* Hook up the adaptation layer. */ | ||
337 | return cfcnfg_add_adaptation_layer(get_caif_conf(), | ||
338 | ¶m, client_layer); | ||
339 | } | ||
340 | EXPORT_SYMBOL(caif_connect_client); | ||
341 | |||
342 | int caif_disconnect_client(struct cflayer *adap_layer) | ||
343 | { | ||
344 | return cfcnfg_disconn_adapt_layer(get_caif_conf(), adap_layer); | ||
345 | } | ||
346 | EXPORT_SYMBOL(caif_disconnect_client); | ||
347 | |||
348 | void caif_release_client(struct cflayer *adap_layer) | ||
349 | { | ||
350 | cfcnfg_release_adap_layer(adap_layer); | ||
351 | } | ||
352 | EXPORT_SYMBOL(caif_release_client); | ||
353 | |||
354 | /* Per-namespace Caif devices handling */ | ||
355 | static int caif_init_net(struct net *net) | ||
356 | { | ||
357 | struct caif_net *caifn = net_generic(net, caif_net_id); | ||
358 | INIT_LIST_HEAD(&caifn->caifdevs.list); | ||
359 | spin_lock_init(&caifn->caifdevs.lock); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static void caif_exit_net(struct net *net) | ||
364 | { | ||
365 | struct net_device *dev; | ||
366 | int res; | ||
367 | rtnl_lock(); | ||
368 | for_each_netdev(net, dev) { | ||
369 | if (dev->type != ARPHRD_CAIF) | ||
370 | continue; | ||
371 | res = dev_close(dev); | ||
372 | caif_device_destroy(dev); | ||
373 | } | ||
374 | rtnl_unlock(); | ||
375 | } | ||
376 | |||
377 | static struct pernet_operations caif_net_ops = { | ||
378 | .init = caif_init_net, | ||
379 | .exit = caif_exit_net, | ||
380 | .id = &caif_net_id, | ||
381 | .size = sizeof(struct caif_net), | ||
382 | }; | ||
383 | |||
384 | /* Initialize Caif devices list */ | ||
385 | static int __init caif_device_init(void) | ||
386 | { | ||
387 | int result; | ||
388 | cfg = cfcnfg_create(); | ||
389 | if (!cfg) { | ||
390 | pr_warning("CAIF: %s(): can't create cfcnfg.\n", __func__); | ||
391 | goto err_cfcnfg_create_failed; | ||
392 | } | ||
393 | result = register_pernet_device(&caif_net_ops); | ||
394 | |||
395 | if (result) { | ||
396 | kfree(cfg); | ||
397 | cfg = NULL; | ||
398 | return result; | ||
399 | } | ||
400 | dev_add_pack(&caif_packet_type); | ||
401 | register_netdevice_notifier(&caif_device_notifier); | ||
402 | |||
403 | return result; | ||
404 | err_cfcnfg_create_failed: | ||
405 | return -ENODEV; | ||
406 | } | ||
407 | |||
408 | static void __exit caif_device_exit(void) | ||
409 | { | ||
410 | dev_remove_pack(&caif_packet_type); | ||
411 | unregister_pernet_device(&caif_net_ops); | ||
412 | unregister_netdevice_notifier(&caif_device_notifier); | ||
413 | cfcnfg_remove(cfg); | ||
414 | } | ||
415 | |||
416 | module_init(caif_device_init); | ||
417 | module_exit(caif_device_exit); | ||
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c new file mode 100644 index 000000000000..c3a70c5c893a --- /dev/null +++ b/net/caif/caif_socket.c | |||
@@ -0,0 +1,1252 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/fs.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/spinlock.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/list.h> | ||
14 | #include <linux/wait.h> | ||
15 | #include <linux/poll.h> | ||
16 | #include <linux/tcp.h> | ||
17 | #include <linux/uaccess.h> | ||
18 | #include <linux/mutex.h> | ||
19 | #include <linux/debugfs.h> | ||
20 | #include <linux/caif/caif_socket.h> | ||
21 | #include <asm/atomic.h> | ||
22 | #include <net/sock.h> | ||
23 | #include <net/tcp_states.h> | ||
24 | #include <net/caif/caif_layer.h> | ||
25 | #include <net/caif/caif_dev.h> | ||
26 | #include <net/caif/cfpkt.h> | ||
27 | |||
28 | MODULE_LICENSE("GPL"); | ||
29 | MODULE_ALIAS_NETPROTO(AF_CAIF); | ||
30 | |||
31 | #define CAIF_DEF_SNDBUF (CAIF_MAX_PAYLOAD_SIZE*10) | ||
32 | #define CAIF_DEF_RCVBUF (CAIF_MAX_PAYLOAD_SIZE*100) | ||
33 | |||
34 | /* | ||
35 | * CAIF state is re-using the TCP socket states. | ||
36 | * caif_states stored in sk_state reflect the state as reported by | ||
37 | * the CAIF stack, while sk_socket->state is the state of the socket. | ||
38 | */ | ||
39 | enum caif_states { | ||
40 | CAIF_CONNECTED = TCP_ESTABLISHED, | ||
41 | CAIF_CONNECTING = TCP_SYN_SENT, | ||
42 | CAIF_DISCONNECTED = TCP_CLOSE | ||
43 | }; | ||
44 | |||
45 | #define TX_FLOW_ON_BIT 1 | ||
46 | #define RX_FLOW_ON_BIT 2 | ||
47 | |||
48 | static struct dentry *debugfsdir; | ||
49 | |||
50 | #ifdef CONFIG_DEBUG_FS | ||
51 | struct debug_fs_counter { | ||
52 | atomic_t caif_nr_socks; | ||
53 | atomic_t num_connect_req; | ||
54 | atomic_t num_connect_resp; | ||
55 | atomic_t num_connect_fail_resp; | ||
56 | atomic_t num_disconnect; | ||
57 | atomic_t num_remote_shutdown_ind; | ||
58 | atomic_t num_tx_flow_off_ind; | ||
59 | atomic_t num_tx_flow_on_ind; | ||
60 | atomic_t num_rx_flow_off; | ||
61 | atomic_t num_rx_flow_on; | ||
62 | }; | ||
63 | struct debug_fs_counter cnt; | ||
64 | #define dbfs_atomic_inc(v) atomic_inc(v) | ||
65 | #define dbfs_atomic_dec(v) atomic_dec(v) | ||
66 | #else | ||
67 | #define dbfs_atomic_inc(v) | ||
68 | #define dbfs_atomic_dec(v) | ||
69 | #endif | ||
70 | |||
71 | struct caifsock { | ||
72 | struct sock sk; /* must be first member */ | ||
73 | struct cflayer layer; | ||
74 | char name[CAIF_LAYER_NAME_SZ]; /* Used for debugging */ | ||
75 | u32 flow_state; | ||
76 | struct caif_connect_request conn_req; | ||
77 | struct mutex readlock; | ||
78 | struct dentry *debugfs_socket_dir; | ||
79 | }; | ||
80 | |||
81 | static int rx_flow_is_on(struct caifsock *cf_sk) | ||
82 | { | ||
83 | return test_bit(RX_FLOW_ON_BIT, | ||
84 | (void *) &cf_sk->flow_state); | ||
85 | } | ||
86 | |||
87 | static int tx_flow_is_on(struct caifsock *cf_sk) | ||
88 | { | ||
89 | return test_bit(TX_FLOW_ON_BIT, | ||
90 | (void *) &cf_sk->flow_state); | ||
91 | } | ||
92 | |||
93 | static void set_rx_flow_off(struct caifsock *cf_sk) | ||
94 | { | ||
95 | clear_bit(RX_FLOW_ON_BIT, | ||
96 | (void *) &cf_sk->flow_state); | ||
97 | } | ||
98 | |||
99 | static void set_rx_flow_on(struct caifsock *cf_sk) | ||
100 | { | ||
101 | set_bit(RX_FLOW_ON_BIT, | ||
102 | (void *) &cf_sk->flow_state); | ||
103 | } | ||
104 | |||
105 | static void set_tx_flow_off(struct caifsock *cf_sk) | ||
106 | { | ||
107 | clear_bit(TX_FLOW_ON_BIT, | ||
108 | (void *) &cf_sk->flow_state); | ||
109 | } | ||
110 | |||
111 | static void set_tx_flow_on(struct caifsock *cf_sk) | ||
112 | { | ||
113 | set_bit(TX_FLOW_ON_BIT, | ||
114 | (void *) &cf_sk->flow_state); | ||
115 | } | ||
116 | |||
117 | static void caif_read_lock(struct sock *sk) | ||
118 | { | ||
119 | struct caifsock *cf_sk; | ||
120 | cf_sk = container_of(sk, struct caifsock, sk); | ||
121 | mutex_lock(&cf_sk->readlock); | ||
122 | } | ||
123 | |||
124 | static void caif_read_unlock(struct sock *sk) | ||
125 | { | ||
126 | struct caifsock *cf_sk; | ||
127 | cf_sk = container_of(sk, struct caifsock, sk); | ||
128 | mutex_unlock(&cf_sk->readlock); | ||
129 | } | ||
130 | |||
131 | int sk_rcvbuf_lowwater(struct caifsock *cf_sk) | ||
132 | { | ||
133 | /* A quarter of full buffer is used a low water mark */ | ||
134 | return cf_sk->sk.sk_rcvbuf / 4; | ||
135 | } | ||
136 | |||
137 | void caif_flow_ctrl(struct sock *sk, int mode) | ||
138 | { | ||
139 | struct caifsock *cf_sk; | ||
140 | cf_sk = container_of(sk, struct caifsock, sk); | ||
141 | if (cf_sk->layer.dn) | ||
142 | cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, mode); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are | ||
147 | * not dropped, but CAIF is sending flow off instead. | ||
148 | */ | ||
149 | int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | ||
150 | { | ||
151 | int err; | ||
152 | int skb_len; | ||
153 | unsigned long flags; | ||
154 | struct sk_buff_head *list = &sk->sk_receive_queue; | ||
155 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
156 | |||
157 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= | ||
158 | (unsigned)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { | ||
159 | trace_printk("CAIF: %s():" | ||
160 | " sending flow OFF (queue len = %d %d)\n", | ||
161 | __func__, | ||
162 | atomic_read(&cf_sk->sk.sk_rmem_alloc), | ||
163 | sk_rcvbuf_lowwater(cf_sk)); | ||
164 | set_rx_flow_off(cf_sk); | ||
165 | if (cf_sk->layer.dn) | ||
166 | cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, | ||
167 | CAIF_MODEMCMD_FLOW_OFF_REQ); | ||
168 | } | ||
169 | |||
170 | err = sk_filter(sk, skb); | ||
171 | if (err) | ||
172 | return err; | ||
173 | if (!sk_rmem_schedule(sk, skb->truesize) && rx_flow_is_on(cf_sk)) { | ||
174 | set_rx_flow_off(cf_sk); | ||
175 | trace_printk("CAIF: %s():" | ||
176 | " sending flow OFF due to rmem_schedule\n", | ||
177 | __func__); | ||
178 | if (cf_sk->layer.dn) | ||
179 | cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, | ||
180 | CAIF_MODEMCMD_FLOW_OFF_REQ); | ||
181 | } | ||
182 | skb->dev = NULL; | ||
183 | skb_set_owner_r(skb, sk); | ||
184 | /* Cache the SKB length before we tack it onto the receive | ||
185 | * queue. Once it is added it no longer belongs to us and | ||
186 | * may be freed by other threads of control pulling packets | ||
187 | * from the queue. | ||
188 | */ | ||
189 | skb_len = skb->len; | ||
190 | spin_lock_irqsave(&list->lock, flags); | ||
191 | if (!sock_flag(sk, SOCK_DEAD)) | ||
192 | __skb_queue_tail(list, skb); | ||
193 | spin_unlock_irqrestore(&list->lock, flags); | ||
194 | |||
195 | if (!sock_flag(sk, SOCK_DEAD)) | ||
196 | sk->sk_data_ready(sk, skb_len); | ||
197 | else | ||
198 | kfree_skb(skb); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | /* Packet Receive Callback function called from CAIF Stack */ | ||
203 | static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt) | ||
204 | { | ||
205 | struct caifsock *cf_sk; | ||
206 | struct sk_buff *skb; | ||
207 | |||
208 | cf_sk = container_of(layr, struct caifsock, layer); | ||
209 | skb = cfpkt_tonative(pkt); | ||
210 | |||
211 | if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) { | ||
212 | cfpkt_destroy(pkt); | ||
213 | return 0; | ||
214 | } | ||
215 | caif_queue_rcv_skb(&cf_sk->sk, skb); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | /* Packet Control Callback function called from CAIF */ | ||
220 | static void caif_ctrl_cb(struct cflayer *layr, | ||
221 | enum caif_ctrlcmd flow, | ||
222 | int phyid) | ||
223 | { | ||
224 | struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); | ||
225 | switch (flow) { | ||
226 | case CAIF_CTRLCMD_FLOW_ON_IND: | ||
227 | /* OK from modem to start sending again */ | ||
228 | dbfs_atomic_inc(&cnt.num_tx_flow_on_ind); | ||
229 | set_tx_flow_on(cf_sk); | ||
230 | cf_sk->sk.sk_state_change(&cf_sk->sk); | ||
231 | break; | ||
232 | |||
233 | case CAIF_CTRLCMD_FLOW_OFF_IND: | ||
234 | /* Modem asks us to shut up */ | ||
235 | dbfs_atomic_inc(&cnt.num_tx_flow_off_ind); | ||
236 | set_tx_flow_off(cf_sk); | ||
237 | cf_sk->sk.sk_state_change(&cf_sk->sk); | ||
238 | break; | ||
239 | |||
240 | case CAIF_CTRLCMD_INIT_RSP: | ||
241 | /* We're now connected */ | ||
242 | dbfs_atomic_inc(&cnt.num_connect_resp); | ||
243 | cf_sk->sk.sk_state = CAIF_CONNECTED; | ||
244 | set_tx_flow_on(cf_sk); | ||
245 | cf_sk->sk.sk_state_change(&cf_sk->sk); | ||
246 | break; | ||
247 | |||
248 | case CAIF_CTRLCMD_DEINIT_RSP: | ||
249 | /* We're now disconnected */ | ||
250 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; | ||
251 | cf_sk->sk.sk_state_change(&cf_sk->sk); | ||
252 | cfcnfg_release_adap_layer(&cf_sk->layer); | ||
253 | break; | ||
254 | |||
255 | case CAIF_CTRLCMD_INIT_FAIL_RSP: | ||
256 | /* Connect request failed */ | ||
257 | dbfs_atomic_inc(&cnt.num_connect_fail_resp); | ||
258 | cf_sk->sk.sk_err = ECONNREFUSED; | ||
259 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; | ||
260 | cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; | ||
261 | /* | ||
262 | * Socket "standards" seems to require POLLOUT to | ||
263 | * be set at connect failure. | ||
264 | */ | ||
265 | set_tx_flow_on(cf_sk); | ||
266 | cf_sk->sk.sk_state_change(&cf_sk->sk); | ||
267 | break; | ||
268 | |||
269 | case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: | ||
270 | /* Modem has closed this connection, or device is down. */ | ||
271 | dbfs_atomic_inc(&cnt.num_remote_shutdown_ind); | ||
272 | cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; | ||
273 | cf_sk->sk.sk_err = ECONNRESET; | ||
274 | set_rx_flow_on(cf_sk); | ||
275 | cf_sk->sk.sk_error_report(&cf_sk->sk); | ||
276 | break; | ||
277 | |||
278 | default: | ||
279 | pr_debug("CAIF: %s(): Unexpected flow command %d\n", | ||
280 | __func__, flow); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static void caif_check_flow_release(struct sock *sk) | ||
285 | { | ||
286 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
287 | |||
288 | if (cf_sk->layer.dn == NULL || cf_sk->layer.dn->modemcmd == NULL) | ||
289 | return; | ||
290 | if (rx_flow_is_on(cf_sk)) | ||
291 | return; | ||
292 | |||
293 | if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) { | ||
294 | dbfs_atomic_inc(&cnt.num_rx_flow_on); | ||
295 | set_rx_flow_on(cf_sk); | ||
296 | cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, | ||
297 | CAIF_MODEMCMD_FLOW_ON_REQ); | ||
298 | } | ||
299 | } | ||
300 | /* | ||
301 | * Copied from sock.c:sock_queue_rcv_skb(), and added check that user buffer | ||
302 | * has sufficient size. | ||
303 | */ | ||
304 | |||
305 | static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
306 | struct msghdr *m, size_t buf_len, int flags) | ||
307 | |||
308 | { | ||
309 | struct sock *sk = sock->sk; | ||
310 | struct sk_buff *skb; | ||
311 | int ret = 0; | ||
312 | int len; | ||
313 | |||
314 | if (unlikely(!buf_len)) | ||
315 | return -EINVAL; | ||
316 | |||
317 | skb = skb_recv_datagram(sk, flags, 0 , &ret); | ||
318 | if (!skb) | ||
319 | goto read_error; | ||
320 | |||
321 | len = skb->len; | ||
322 | |||
323 | if (skb && skb->len > buf_len && !(flags & MSG_PEEK)) { | ||
324 | len = buf_len; | ||
325 | /* | ||
326 | * Push skb back on receive queue if buffer too small. | ||
327 | * This has a built-in race where multi-threaded receive | ||
328 | * may get packet in wrong order, but multiple read does | ||
329 | * not really guarantee ordered delivery anyway. | ||
330 | * Let's optimize for speed without taking locks. | ||
331 | */ | ||
332 | |||
333 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
334 | ret = -EMSGSIZE; | ||
335 | goto read_error; | ||
336 | } | ||
337 | |||
338 | ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, len); | ||
339 | if (ret) | ||
340 | goto read_error; | ||
341 | |||
342 | skb_free_datagram(sk, skb); | ||
343 | |||
344 | caif_check_flow_release(sk); | ||
345 | |||
346 | return len; | ||
347 | |||
348 | read_error: | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | |||
353 | /* Copied from unix_stream_wait_data, identical except for lock call. */ | ||
354 | static long caif_stream_data_wait(struct sock *sk, long timeo) | ||
355 | { | ||
356 | DEFINE_WAIT(wait); | ||
357 | lock_sock(sk); | ||
358 | |||
359 | for (;;) { | ||
360 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
361 | |||
362 | if (!skb_queue_empty(&sk->sk_receive_queue) || | ||
363 | sk->sk_err || | ||
364 | sk->sk_state != CAIF_CONNECTED || | ||
365 | sock_flag(sk, SOCK_DEAD) || | ||
366 | (sk->sk_shutdown & RCV_SHUTDOWN) || | ||
367 | signal_pending(current) || | ||
368 | !timeo) | ||
369 | break; | ||
370 | |||
371 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | ||
372 | release_sock(sk); | ||
373 | timeo = schedule_timeout(timeo); | ||
374 | lock_sock(sk); | ||
375 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | ||
376 | } | ||
377 | |||
378 | finish_wait(sk_sleep(sk), &wait); | ||
379 | release_sock(sk); | ||
380 | return timeo; | ||
381 | } | ||
382 | |||
383 | |||
384 | /* | ||
385 | * Copied from unix_stream_recvmsg, but removed credit checks, | ||
386 | * changed locking calls, changed address handling. | ||
387 | */ | ||
388 | static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
389 | struct msghdr *msg, size_t size, | ||
390 | int flags) | ||
391 | { | ||
392 | struct sock *sk = sock->sk; | ||
393 | int copied = 0; | ||
394 | int target; | ||
395 | int err = 0; | ||
396 | long timeo; | ||
397 | |||
398 | err = -EOPNOTSUPP; | ||
399 | if (flags&MSG_OOB) | ||
400 | goto out; | ||
401 | |||
402 | msg->msg_namelen = 0; | ||
403 | |||
404 | /* | ||
405 | * Lock the socket to prevent queue disordering | ||
406 | * while sleeps in memcpy_tomsg | ||
407 | */ | ||
408 | err = -EAGAIN; | ||
409 | if (sk->sk_state == CAIF_CONNECTING) | ||
410 | goto out; | ||
411 | |||
412 | caif_read_lock(sk); | ||
413 | target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); | ||
414 | timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); | ||
415 | |||
416 | do { | ||
417 | int chunk; | ||
418 | struct sk_buff *skb; | ||
419 | |||
420 | lock_sock(sk); | ||
421 | skb = skb_dequeue(&sk->sk_receive_queue); | ||
422 | caif_check_flow_release(sk); | ||
423 | |||
424 | if (skb == NULL) { | ||
425 | if (copied >= target) | ||
426 | goto unlock; | ||
427 | /* | ||
428 | * POSIX 1003.1g mandates this order. | ||
429 | */ | ||
430 | err = sock_error(sk); | ||
431 | if (err) | ||
432 | goto unlock; | ||
433 | err = -ECONNRESET; | ||
434 | if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
435 | goto unlock; | ||
436 | |||
437 | err = -EPIPE; | ||
438 | if (sk->sk_state != CAIF_CONNECTED) | ||
439 | goto unlock; | ||
440 | if (sock_flag(sk, SOCK_DEAD)) | ||
441 | goto unlock; | ||
442 | |||
443 | release_sock(sk); | ||
444 | |||
445 | err = -EAGAIN; | ||
446 | if (!timeo) | ||
447 | break; | ||
448 | |||
449 | caif_read_unlock(sk); | ||
450 | |||
451 | timeo = caif_stream_data_wait(sk, timeo); | ||
452 | |||
453 | if (signal_pending(current)) { | ||
454 | err = sock_intr_errno(timeo); | ||
455 | goto out; | ||
456 | } | ||
457 | caif_read_lock(sk); | ||
458 | continue; | ||
459 | unlock: | ||
460 | release_sock(sk); | ||
461 | break; | ||
462 | } | ||
463 | release_sock(sk); | ||
464 | chunk = min_t(unsigned int, skb->len, size); | ||
465 | if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { | ||
466 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
467 | if (copied == 0) | ||
468 | copied = -EFAULT; | ||
469 | break; | ||
470 | } | ||
471 | copied += chunk; | ||
472 | size -= chunk; | ||
473 | |||
474 | /* Mark read part of skb as used */ | ||
475 | if (!(flags & MSG_PEEK)) { | ||
476 | skb_pull(skb, chunk); | ||
477 | |||
478 | /* put the skb back if we didn't use it up. */ | ||
479 | if (skb->len) { | ||
480 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
481 | break; | ||
482 | } | ||
483 | kfree_skb(skb); | ||
484 | |||
485 | } else { | ||
486 | /* | ||
487 | * It is questionable, see note in unix_dgram_recvmsg. | ||
488 | */ | ||
489 | /* put message back and return */ | ||
490 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
491 | break; | ||
492 | } | ||
493 | } while (size); | ||
494 | caif_read_unlock(sk); | ||
495 | |||
496 | out: | ||
497 | return copied ? : err; | ||
498 | } | ||
499 | |||
500 | /* | ||
501 | * Copied from sock.c:sock_wait_for_wmem, but change to wait for | ||
502 | * CAIF flow-on and sock_writable. | ||
503 | */ | ||
504 | static long caif_wait_for_flow_on(struct caifsock *cf_sk, | ||
505 | int wait_writeable, long timeo, int *err) | ||
506 | { | ||
507 | struct sock *sk = &cf_sk->sk; | ||
508 | DEFINE_WAIT(wait); | ||
509 | for (;;) { | ||
510 | *err = 0; | ||
511 | if (tx_flow_is_on(cf_sk) && | ||
512 | (!wait_writeable || sock_writeable(&cf_sk->sk))) | ||
513 | break; | ||
514 | *err = -ETIMEDOUT; | ||
515 | if (!timeo) | ||
516 | break; | ||
517 | *err = -ERESTARTSYS; | ||
518 | if (signal_pending(current)) | ||
519 | break; | ||
520 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
521 | *err = -ECONNRESET; | ||
522 | if (sk->sk_shutdown & SHUTDOWN_MASK) | ||
523 | break; | ||
524 | *err = -sk->sk_err; | ||
525 | if (sk->sk_err) | ||
526 | break; | ||
527 | *err = -EPIPE; | ||
528 | if (cf_sk->sk.sk_state != CAIF_CONNECTED) | ||
529 | break; | ||
530 | timeo = schedule_timeout(timeo); | ||
531 | } | ||
532 | finish_wait(sk_sleep(sk), &wait); | ||
533 | return timeo; | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Transmit a SKB. The device may temporarily request re-transmission | ||
538 | * by returning EAGAIN. | ||
539 | */ | ||
540 | static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, | ||
541 | int noblock, long timeo) | ||
542 | { | ||
543 | struct cfpkt *pkt; | ||
544 | int ret, loopcnt = 0; | ||
545 | |||
546 | pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); | ||
547 | memset(cfpkt_info(pkt), 0, sizeof(struct caif_payload_info)); | ||
548 | do { | ||
549 | |||
550 | ret = -ETIMEDOUT; | ||
551 | |||
552 | /* Slight paranoia, probably not needed. */ | ||
553 | if (unlikely(loopcnt++ > 1000)) { | ||
554 | pr_warning("CAIF: %s(): transmit retries failed," | ||
555 | " error = %d\n", __func__, ret); | ||
556 | break; | ||
557 | } | ||
558 | |||
559 | if (cf_sk->layer.dn != NULL) | ||
560 | ret = cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); | ||
561 | if (likely(ret >= 0)) | ||
562 | break; | ||
563 | /* if transmit return -EAGAIN, then retry */ | ||
564 | if (noblock && ret == -EAGAIN) | ||
565 | break; | ||
566 | timeo = caif_wait_for_flow_on(cf_sk, 0, timeo, &ret); | ||
567 | if (signal_pending(current)) { | ||
568 | ret = sock_intr_errno(timeo); | ||
569 | break; | ||
570 | } | ||
571 | if (ret) | ||
572 | break; | ||
573 | if (cf_sk->sk.sk_state != CAIF_CONNECTED || | ||
574 | sock_flag(&cf_sk->sk, SOCK_DEAD) || | ||
575 | (cf_sk->sk.sk_shutdown & RCV_SHUTDOWN)) { | ||
576 | ret = -EPIPE; | ||
577 | cf_sk->sk.sk_err = EPIPE; | ||
578 | break; | ||
579 | } | ||
580 | } while (ret == -EAGAIN); | ||
581 | return ret; | ||
582 | } | ||
583 | |||
584 | /* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */ | ||
585 | static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, | ||
586 | struct msghdr *msg, size_t len) | ||
587 | { | ||
588 | struct sock *sk = sock->sk; | ||
589 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
590 | int buffer_size; | ||
591 | int ret = 0; | ||
592 | struct sk_buff *skb = NULL; | ||
593 | int noblock; | ||
594 | long timeo; | ||
595 | caif_assert(cf_sk); | ||
596 | ret = sock_error(sk); | ||
597 | if (ret) | ||
598 | goto err; | ||
599 | |||
600 | ret = -EOPNOTSUPP; | ||
601 | if (msg->msg_flags&MSG_OOB) | ||
602 | goto err; | ||
603 | |||
604 | ret = -EOPNOTSUPP; | ||
605 | if (msg->msg_namelen) | ||
606 | goto err; | ||
607 | |||
608 | ret = -EINVAL; | ||
609 | if (unlikely(msg->msg_iov->iov_base == NULL)) | ||
610 | goto err; | ||
611 | noblock = msg->msg_flags & MSG_DONTWAIT; | ||
612 | |||
613 | buffer_size = len + CAIF_NEEDED_HEADROOM + CAIF_NEEDED_TAILROOM; | ||
614 | |||
615 | ret = -EMSGSIZE; | ||
616 | if (buffer_size > CAIF_MAX_PAYLOAD_SIZE) | ||
617 | goto err; | ||
618 | |||
619 | timeo = sock_sndtimeo(sk, noblock); | ||
620 | timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), | ||
621 | 1, timeo, &ret); | ||
622 | |||
623 | ret = -EPIPE; | ||
624 | if (cf_sk->sk.sk_state != CAIF_CONNECTED || | ||
625 | sock_flag(sk, SOCK_DEAD) || | ||
626 | (sk->sk_shutdown & RCV_SHUTDOWN)) | ||
627 | goto err; | ||
628 | |||
629 | ret = -ENOMEM; | ||
630 | skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret); | ||
631 | if (!skb) | ||
632 | goto err; | ||
633 | skb_reserve(skb, CAIF_NEEDED_HEADROOM); | ||
634 | |||
635 | ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | ||
636 | |||
637 | if (ret) | ||
638 | goto err; | ||
639 | ret = transmit_skb(skb, cf_sk, noblock, timeo); | ||
640 | if (ret < 0) | ||
641 | goto err; | ||
642 | return len; | ||
643 | err: | ||
644 | kfree_skb(skb); | ||
645 | return ret; | ||
646 | } | ||
647 | |||
648 | /* | ||
649 | * Copied from unix_stream_sendmsg and adapted to CAIF: | ||
650 | * Changed removed permission handling and added waiting for flow on | ||
651 | * and other minor adaptations. | ||
652 | */ | ||
653 | static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | ||
654 | struct msghdr *msg, size_t len) | ||
655 | { | ||
656 | struct sock *sk = sock->sk; | ||
657 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
658 | int err, size; | ||
659 | struct sk_buff *skb; | ||
660 | int sent = 0; | ||
661 | long timeo; | ||
662 | |||
663 | err = -EOPNOTSUPP; | ||
664 | |||
665 | if (unlikely(msg->msg_flags&MSG_OOB)) | ||
666 | goto out_err; | ||
667 | |||
668 | if (unlikely(msg->msg_namelen)) | ||
669 | goto out_err; | ||
670 | |||
671 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); | ||
672 | timeo = caif_wait_for_flow_on(cf_sk, 1, timeo, &err); | ||
673 | |||
674 | if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN)) | ||
675 | goto pipe_err; | ||
676 | |||
677 | while (sent < len) { | ||
678 | |||
679 | size = len-sent; | ||
680 | |||
681 | if (size > CAIF_MAX_PAYLOAD_SIZE) | ||
682 | size = CAIF_MAX_PAYLOAD_SIZE; | ||
683 | |||
684 | /* If size is more than half of sndbuf, chop up message */ | ||
685 | if (size > ((sk->sk_sndbuf >> 1) - 64)) | ||
686 | size = (sk->sk_sndbuf >> 1) - 64; | ||
687 | |||
688 | if (size > SKB_MAX_ALLOC) | ||
689 | size = SKB_MAX_ALLOC; | ||
690 | |||
691 | skb = sock_alloc_send_skb(sk, | ||
692 | size + CAIF_NEEDED_HEADROOM | ||
693 | + CAIF_NEEDED_TAILROOM, | ||
694 | msg->msg_flags&MSG_DONTWAIT, | ||
695 | &err); | ||
696 | if (skb == NULL) | ||
697 | goto out_err; | ||
698 | |||
699 | skb_reserve(skb, CAIF_NEEDED_HEADROOM); | ||
700 | /* | ||
701 | * If you pass two values to the sock_alloc_send_skb | ||
702 | * it tries to grab the large buffer with GFP_NOFS | ||
703 | * (which can fail easily), and if it fails grab the | ||
704 | * fallback size buffer which is under a page and will | ||
705 | * succeed. [Alan] | ||
706 | */ | ||
707 | size = min_t(int, size, skb_tailroom(skb)); | ||
708 | |||
709 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); | ||
710 | if (err) { | ||
711 | kfree_skb(skb); | ||
712 | goto out_err; | ||
713 | } | ||
714 | err = transmit_skb(skb, cf_sk, | ||
715 | msg->msg_flags&MSG_DONTWAIT, timeo); | ||
716 | if (err < 0) { | ||
717 | kfree_skb(skb); | ||
718 | goto pipe_err; | ||
719 | } | ||
720 | sent += size; | ||
721 | } | ||
722 | |||
723 | return sent; | ||
724 | |||
725 | pipe_err: | ||
726 | if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL)) | ||
727 | send_sig(SIGPIPE, current, 0); | ||
728 | err = -EPIPE; | ||
729 | out_err: | ||
730 | return sent ? : err; | ||
731 | } | ||
732 | |||
733 | static int setsockopt(struct socket *sock, | ||
734 | int lvl, int opt, char __user *ov, unsigned int ol) | ||
735 | { | ||
736 | struct sock *sk = sock->sk; | ||
737 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
738 | int prio, linksel; | ||
739 | struct ifreq ifreq; | ||
740 | |||
741 | if (cf_sk->sk.sk_socket->state != SS_UNCONNECTED) | ||
742 | return -ENOPROTOOPT; | ||
743 | |||
744 | switch (opt) { | ||
745 | case CAIFSO_LINK_SELECT: | ||
746 | if (ol < sizeof(int)) | ||
747 | return -EINVAL; | ||
748 | if (lvl != SOL_CAIF) | ||
749 | goto bad_sol; | ||
750 | if (copy_from_user(&linksel, ov, sizeof(int))) | ||
751 | return -EINVAL; | ||
752 | lock_sock(&(cf_sk->sk)); | ||
753 | cf_sk->conn_req.link_selector = linksel; | ||
754 | release_sock(&cf_sk->sk); | ||
755 | return 0; | ||
756 | |||
757 | case SO_PRIORITY: | ||
758 | if (lvl != SOL_SOCKET) | ||
759 | goto bad_sol; | ||
760 | if (ol < sizeof(int)) | ||
761 | return -EINVAL; | ||
762 | if (copy_from_user(&prio, ov, sizeof(int))) | ||
763 | return -EINVAL; | ||
764 | lock_sock(&(cf_sk->sk)); | ||
765 | cf_sk->conn_req.priority = prio; | ||
766 | release_sock(&cf_sk->sk); | ||
767 | return 0; | ||
768 | |||
769 | case SO_BINDTODEVICE: | ||
770 | if (lvl != SOL_SOCKET) | ||
771 | goto bad_sol; | ||
772 | if (ol < sizeof(struct ifreq)) | ||
773 | return -EINVAL; | ||
774 | if (copy_from_user(&ifreq, ov, sizeof(ifreq))) | ||
775 | return -EFAULT; | ||
776 | lock_sock(&(cf_sk->sk)); | ||
777 | strncpy(cf_sk->conn_req.link_name, ifreq.ifr_name, | ||
778 | sizeof(cf_sk->conn_req.link_name)); | ||
779 | cf_sk->conn_req.link_name | ||
780 | [sizeof(cf_sk->conn_req.link_name)-1] = 0; | ||
781 | release_sock(&cf_sk->sk); | ||
782 | return 0; | ||
783 | |||
784 | case CAIFSO_REQ_PARAM: | ||
785 | if (lvl != SOL_CAIF) | ||
786 | goto bad_sol; | ||
787 | if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL) | ||
788 | return -ENOPROTOOPT; | ||
789 | lock_sock(&(cf_sk->sk)); | ||
790 | cf_sk->conn_req.param.size = ol; | ||
791 | if (ol > sizeof(cf_sk->conn_req.param.data) || | ||
792 | copy_from_user(&cf_sk->conn_req.param.data, ov, ol)) { | ||
793 | release_sock(&cf_sk->sk); | ||
794 | return -EINVAL; | ||
795 | } | ||
796 | release_sock(&cf_sk->sk); | ||
797 | return 0; | ||
798 | |||
799 | default: | ||
800 | return -ENOPROTOOPT; | ||
801 | } | ||
802 | |||
803 | return 0; | ||
804 | bad_sol: | ||
805 | return -ENOPROTOOPT; | ||
806 | |||
807 | } | ||
808 | |||
809 | /* | ||
810 | * caif_connect() - Connect a CAIF Socket | ||
811 | * Copied and modified af_irda.c:irda_connect(). | ||
812 | * | ||
813 | * Note : by consulting "errno", the user space caller may learn the cause | ||
814 | * of the failure. Most of them are visible in the function, others may come | ||
815 | * from subroutines called and are listed here : | ||
816 | * o -EAFNOSUPPORT: bad socket family or type. | ||
817 | * o -ESOCKTNOSUPPORT: bad socket type or protocol | ||
818 | * o -EINVAL: bad socket address, or CAIF link type | ||
819 | * o -ECONNREFUSED: remote end refused the connection. | ||
820 | * o -EINPROGRESS: connect request sent but timed out (or non-blocking) | ||
821 | * o -EISCONN: already connected. | ||
822 | * o -ETIMEDOUT: Connection timed out (send timeout) | ||
823 | * o -ENODEV: No link layer to send request | ||
824 | * o -ECONNRESET: Received Shutdown indication or lost link layer | ||
825 | * o -ENOMEM: Out of memory | ||
826 | * | ||
827 | * State Strategy: | ||
828 | * o sk_state: holds the CAIF_* protocol state, it's updated by | ||
829 | * caif_ctrl_cb. | ||
830 | * o sock->state: holds the SS_* socket state and is updated by connect and | ||
831 | * disconnect. | ||
832 | */ | ||
833 | static int caif_connect(struct socket *sock, struct sockaddr *uaddr, | ||
834 | int addr_len, int flags) | ||
835 | { | ||
836 | struct sock *sk = sock->sk; | ||
837 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
838 | long timeo; | ||
839 | int err; | ||
840 | lock_sock(sk); | ||
841 | |||
842 | err = -EAFNOSUPPORT; | ||
843 | if (uaddr->sa_family != AF_CAIF) | ||
844 | goto out; | ||
845 | |||
846 | err = -ESOCKTNOSUPPORT; | ||
847 | if (unlikely(!(sk->sk_type == SOCK_STREAM && | ||
848 | cf_sk->sk.sk_protocol == CAIFPROTO_AT) && | ||
849 | sk->sk_type != SOCK_SEQPACKET)) | ||
850 | goto out; | ||
851 | switch (sock->state) { | ||
852 | case SS_UNCONNECTED: | ||
853 | /* Normal case, a fresh connect */ | ||
854 | caif_assert(sk->sk_state == CAIF_DISCONNECTED); | ||
855 | break; | ||
856 | case SS_CONNECTING: | ||
857 | switch (sk->sk_state) { | ||
858 | case CAIF_CONNECTED: | ||
859 | sock->state = SS_CONNECTED; | ||
860 | err = -EISCONN; | ||
861 | goto out; | ||
862 | case CAIF_DISCONNECTED: | ||
863 | /* Reconnect allowed */ | ||
864 | break; | ||
865 | case CAIF_CONNECTING: | ||
866 | err = -EALREADY; | ||
867 | if (flags & O_NONBLOCK) | ||
868 | goto out; | ||
869 | goto wait_connect; | ||
870 | } | ||
871 | break; | ||
872 | case SS_CONNECTED: | ||
873 | caif_assert(sk->sk_state == CAIF_CONNECTED || | ||
874 | sk->sk_state == CAIF_DISCONNECTED); | ||
875 | if (sk->sk_shutdown & SHUTDOWN_MASK) { | ||
876 | /* Allow re-connect after SHUTDOWN_IND */ | ||
877 | caif_disconnect_client(&cf_sk->layer); | ||
878 | break; | ||
879 | } | ||
880 | /* No reconnect on a seqpacket socket */ | ||
881 | err = -EISCONN; | ||
882 | goto out; | ||
883 | case SS_DISCONNECTING: | ||
884 | case SS_FREE: | ||
885 | caif_assert(1); /*Should never happen */ | ||
886 | break; | ||
887 | } | ||
888 | sk->sk_state = CAIF_DISCONNECTED; | ||
889 | sock->state = SS_UNCONNECTED; | ||
890 | sk_stream_kill_queues(&cf_sk->sk); | ||
891 | |||
892 | err = -EINVAL; | ||
893 | if (addr_len != sizeof(struct sockaddr_caif) || | ||
894 | !uaddr) | ||
895 | goto out; | ||
896 | |||
897 | memcpy(&cf_sk->conn_req.sockaddr, uaddr, | ||
898 | sizeof(struct sockaddr_caif)); | ||
899 | |||
900 | /* Move to connecting socket, start sending Connect Requests */ | ||
901 | sock->state = SS_CONNECTING; | ||
902 | sk->sk_state = CAIF_CONNECTING; | ||
903 | |||
904 | dbfs_atomic_inc(&cnt.num_connect_req); | ||
905 | cf_sk->layer.receive = caif_sktrecv_cb; | ||
906 | err = caif_connect_client(&cf_sk->conn_req, | ||
907 | &cf_sk->layer); | ||
908 | if (err < 0) { | ||
909 | cf_sk->sk.sk_socket->state = SS_UNCONNECTED; | ||
910 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; | ||
911 | goto out; | ||
912 | } | ||
913 | |||
914 | err = -EINPROGRESS; | ||
915 | wait_connect: | ||
916 | |||
917 | if (sk->sk_state != CAIF_CONNECTED && (flags & O_NONBLOCK)) | ||
918 | goto out; | ||
919 | |||
920 | timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); | ||
921 | |||
922 | release_sock(sk); | ||
923 | err = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
924 | sk->sk_state != CAIF_CONNECTING, | ||
925 | timeo); | ||
926 | lock_sock(sk); | ||
927 | if (err < 0) | ||
928 | goto out; /* -ERESTARTSYS */ | ||
929 | if (err == 0 && sk->sk_state != CAIF_CONNECTED) { | ||
930 | err = -ETIMEDOUT; | ||
931 | goto out; | ||
932 | } | ||
933 | |||
934 | if (sk->sk_state != CAIF_CONNECTED) { | ||
935 | sock->state = SS_UNCONNECTED; | ||
936 | err = sock_error(sk); | ||
937 | if (!err) | ||
938 | err = -ECONNREFUSED; | ||
939 | goto out; | ||
940 | } | ||
941 | sock->state = SS_CONNECTED; | ||
942 | err = 0; | ||
943 | out: | ||
944 | release_sock(sk); | ||
945 | return err; | ||
946 | } | ||
947 | |||
948 | |||
949 | /* | ||
950 | * caif_release() - Disconnect a CAIF Socket | ||
951 | * Copied and modified af_irda.c:irda_release(). | ||
952 | */ | ||
953 | static int caif_release(struct socket *sock) | ||
954 | { | ||
955 | struct sock *sk = sock->sk; | ||
956 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
957 | int res = 0; | ||
958 | |||
959 | if (!sk) | ||
960 | return 0; | ||
961 | |||
962 | set_tx_flow_off(cf_sk); | ||
963 | |||
964 | /* | ||
965 | * Ensure that packets are not queued after this point in time. | ||
966 | * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock, | ||
967 | * this ensures no packets when sock is dead. | ||
968 | */ | ||
969 | spin_lock(&sk->sk_receive_queue.lock); | ||
970 | sock_set_flag(sk, SOCK_DEAD); | ||
971 | spin_unlock(&sk->sk_receive_queue.lock); | ||
972 | sock->sk = NULL; | ||
973 | |||
974 | dbfs_atomic_inc(&cnt.num_disconnect); | ||
975 | |||
976 | if (cf_sk->debugfs_socket_dir != NULL) | ||
977 | debugfs_remove_recursive(cf_sk->debugfs_socket_dir); | ||
978 | |||
979 | lock_sock(&(cf_sk->sk)); | ||
980 | sk->sk_state = CAIF_DISCONNECTED; | ||
981 | sk->sk_shutdown = SHUTDOWN_MASK; | ||
982 | |||
983 | if (cf_sk->sk.sk_socket->state == SS_CONNECTED || | ||
984 | cf_sk->sk.sk_socket->state == SS_CONNECTING) | ||
985 | res = caif_disconnect_client(&cf_sk->layer); | ||
986 | |||
987 | cf_sk->sk.sk_socket->state = SS_DISCONNECTING; | ||
988 | wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP); | ||
989 | |||
990 | sock_orphan(sk); | ||
991 | cf_sk->layer.dn = NULL; | ||
992 | sk_stream_kill_queues(&cf_sk->sk); | ||
993 | release_sock(sk); | ||
994 | sock_put(sk); | ||
995 | return res; | ||
996 | } | ||
997 | |||
998 | /* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */ | ||
999 | static unsigned int caif_poll(struct file *file, | ||
1000 | struct socket *sock, poll_table *wait) | ||
1001 | { | ||
1002 | struct sock *sk = sock->sk; | ||
1003 | unsigned int mask; | ||
1004 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
1005 | |||
1006 | sock_poll_wait(file, sk_sleep(sk), wait); | ||
1007 | mask = 0; | ||
1008 | |||
1009 | /* exceptional events? */ | ||
1010 | if (sk->sk_err) | ||
1011 | mask |= POLLERR; | ||
1012 | if (sk->sk_shutdown == SHUTDOWN_MASK) | ||
1013 | mask |= POLLHUP; | ||
1014 | if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
1015 | mask |= POLLRDHUP; | ||
1016 | |||
1017 | /* readable? */ | ||
1018 | if (!skb_queue_empty(&sk->sk_receive_queue) || | ||
1019 | (sk->sk_shutdown & RCV_SHUTDOWN)) | ||
1020 | mask |= POLLIN | POLLRDNORM; | ||
1021 | |||
1022 | /* Connection-based need to check for termination and startup */ | ||
1023 | if (sk->sk_state == CAIF_DISCONNECTED) | ||
1024 | mask |= POLLHUP; | ||
1025 | |||
1026 | /* | ||
1027 | * we set writable also when the other side has shut down the | ||
1028 | * connection. This prevents stuck sockets. | ||
1029 | */ | ||
1030 | if (sock_writeable(sk) && tx_flow_is_on(cf_sk)) | ||
1031 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | ||
1032 | |||
1033 | return mask; | ||
1034 | } | ||
1035 | |||
1036 | static const struct proto_ops caif_seqpacket_ops = { | ||
1037 | .family = PF_CAIF, | ||
1038 | .owner = THIS_MODULE, | ||
1039 | .release = caif_release, | ||
1040 | .bind = sock_no_bind, | ||
1041 | .connect = caif_connect, | ||
1042 | .socketpair = sock_no_socketpair, | ||
1043 | .accept = sock_no_accept, | ||
1044 | .getname = sock_no_getname, | ||
1045 | .poll = caif_poll, | ||
1046 | .ioctl = sock_no_ioctl, | ||
1047 | .listen = sock_no_listen, | ||
1048 | .shutdown = sock_no_shutdown, | ||
1049 | .setsockopt = setsockopt, | ||
1050 | .getsockopt = sock_no_getsockopt, | ||
1051 | .sendmsg = caif_seqpkt_sendmsg, | ||
1052 | .recvmsg = caif_seqpkt_recvmsg, | ||
1053 | .mmap = sock_no_mmap, | ||
1054 | .sendpage = sock_no_sendpage, | ||
1055 | }; | ||
1056 | |||
1057 | static const struct proto_ops caif_stream_ops = { | ||
1058 | .family = PF_CAIF, | ||
1059 | .owner = THIS_MODULE, | ||
1060 | .release = caif_release, | ||
1061 | .bind = sock_no_bind, | ||
1062 | .connect = caif_connect, | ||
1063 | .socketpair = sock_no_socketpair, | ||
1064 | .accept = sock_no_accept, | ||
1065 | .getname = sock_no_getname, | ||
1066 | .poll = caif_poll, | ||
1067 | .ioctl = sock_no_ioctl, | ||
1068 | .listen = sock_no_listen, | ||
1069 | .shutdown = sock_no_shutdown, | ||
1070 | .setsockopt = setsockopt, | ||
1071 | .getsockopt = sock_no_getsockopt, | ||
1072 | .sendmsg = caif_stream_sendmsg, | ||
1073 | .recvmsg = caif_stream_recvmsg, | ||
1074 | .mmap = sock_no_mmap, | ||
1075 | .sendpage = sock_no_sendpage, | ||
1076 | }; | ||
1077 | |||
1078 | /* This function is called when a socket is finally destroyed. */ | ||
1079 | static void caif_sock_destructor(struct sock *sk) | ||
1080 | { | ||
1081 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
1082 | caif_assert(!atomic_read(&sk->sk_wmem_alloc)); | ||
1083 | caif_assert(sk_unhashed(sk)); | ||
1084 | caif_assert(!sk->sk_socket); | ||
1085 | if (!sock_flag(sk, SOCK_DEAD)) { | ||
1086 | pr_info("Attempt to release alive CAIF socket: %p\n", sk); | ||
1087 | return; | ||
1088 | } | ||
1089 | sk_stream_kill_queues(&cf_sk->sk); | ||
1090 | dbfs_atomic_dec(&cnt.caif_nr_socks); | ||
1091 | } | ||
1092 | |||
1093 | static int caif_create(struct net *net, struct socket *sock, int protocol, | ||
1094 | int kern) | ||
1095 | { | ||
1096 | struct sock *sk = NULL; | ||
1097 | struct caifsock *cf_sk = NULL; | ||
1098 | static struct proto prot = {.name = "PF_CAIF", | ||
1099 | .owner = THIS_MODULE, | ||
1100 | .obj_size = sizeof(struct caifsock), | ||
1101 | }; | ||
1102 | |||
1103 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN)) | ||
1104 | return -EPERM; | ||
1105 | /* | ||
1106 | * The sock->type specifies the socket type to use. | ||
1107 | * The CAIF socket is a packet stream in the sense | ||
1108 | * that it is packet based. CAIF trusts the reliability | ||
1109 | * of the link, no resending is implemented. | ||
1110 | */ | ||
1111 | if (sock->type == SOCK_SEQPACKET) | ||
1112 | sock->ops = &caif_seqpacket_ops; | ||
1113 | else if (sock->type == SOCK_STREAM) | ||
1114 | sock->ops = &caif_stream_ops; | ||
1115 | else | ||
1116 | return -ESOCKTNOSUPPORT; | ||
1117 | |||
1118 | if (protocol < 0 || protocol >= CAIFPROTO_MAX) | ||
1119 | return -EPROTONOSUPPORT; | ||
1120 | /* | ||
1121 | * Set the socket state to unconnected. The socket state | ||
1122 | * is really not used at all in the net/core or socket.c but the | ||
1123 | * initialization makes sure that sock->state is not uninitialized. | ||
1124 | */ | ||
1125 | sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot); | ||
1126 | if (!sk) | ||
1127 | return -ENOMEM; | ||
1128 | |||
1129 | cf_sk = container_of(sk, struct caifsock, sk); | ||
1130 | |||
1131 | /* Store the protocol */ | ||
1132 | sk->sk_protocol = (unsigned char) protocol; | ||
1133 | |||
1134 | /* Sendbuf dictates the amount of outbound packets not yet sent */ | ||
1135 | sk->sk_sndbuf = CAIF_DEF_SNDBUF; | ||
1136 | sk->sk_rcvbuf = CAIF_DEF_RCVBUF; | ||
1137 | |||
1138 | /* | ||
1139 | * Lock in order to try to stop someone from opening the socket | ||
1140 | * too early. | ||
1141 | */ | ||
1142 | lock_sock(&(cf_sk->sk)); | ||
1143 | |||
1144 | /* Initialize the nozero default sock structure data. */ | ||
1145 | sock_init_data(sock, sk); | ||
1146 | sk->sk_destruct = caif_sock_destructor; | ||
1147 | |||
1148 | mutex_init(&cf_sk->readlock); /* single task reading lock */ | ||
1149 | cf_sk->layer.ctrlcmd = caif_ctrl_cb; | ||
1150 | cf_sk->sk.sk_socket->state = SS_UNCONNECTED; | ||
1151 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; | ||
1152 | |||
1153 | set_tx_flow_off(cf_sk); | ||
1154 | set_rx_flow_on(cf_sk); | ||
1155 | |||
1156 | /* Set default options on configuration */ | ||
1157 | cf_sk->conn_req.priority = CAIF_PRIO_NORMAL; | ||
1158 | cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY; | ||
1159 | cf_sk->conn_req.protocol = protocol; | ||
1160 | /* Increase the number of sockets created. */ | ||
1161 | dbfs_atomic_inc(&cnt.caif_nr_socks); | ||
1162 | #ifdef CONFIG_DEBUG_FS | ||
1163 | if (!IS_ERR(debugfsdir)) { | ||
1164 | /* Fill in some information concerning the misc socket. */ | ||
1165 | snprintf(cf_sk->name, sizeof(cf_sk->name), "cfsk%d", | ||
1166 | atomic_read(&cnt.caif_nr_socks)); | ||
1167 | |||
1168 | cf_sk->debugfs_socket_dir = | ||
1169 | debugfs_create_dir(cf_sk->name, debugfsdir); | ||
1170 | debugfs_create_u32("sk_state", S_IRUSR | S_IWUSR, | ||
1171 | cf_sk->debugfs_socket_dir, | ||
1172 | (u32 *) &cf_sk->sk.sk_state); | ||
1173 | debugfs_create_u32("flow_state", S_IRUSR | S_IWUSR, | ||
1174 | cf_sk->debugfs_socket_dir, &cf_sk->flow_state); | ||
1175 | debugfs_create_u32("sk_rmem_alloc", S_IRUSR | S_IWUSR, | ||
1176 | cf_sk->debugfs_socket_dir, | ||
1177 | (u32 *) &cf_sk->sk.sk_rmem_alloc); | ||
1178 | debugfs_create_u32("sk_wmem_alloc", S_IRUSR | S_IWUSR, | ||
1179 | cf_sk->debugfs_socket_dir, | ||
1180 | (u32 *) &cf_sk->sk.sk_wmem_alloc); | ||
1181 | debugfs_create_u32("identity", S_IRUSR | S_IWUSR, | ||
1182 | cf_sk->debugfs_socket_dir, | ||
1183 | (u32 *) &cf_sk->layer.id); | ||
1184 | } | ||
1185 | #endif | ||
1186 | release_sock(&cf_sk->sk); | ||
1187 | return 0; | ||
1188 | } | ||
1189 | |||
1190 | |||
1191 | static struct net_proto_family caif_family_ops = { | ||
1192 | .family = PF_CAIF, | ||
1193 | .create = caif_create, | ||
1194 | .owner = THIS_MODULE, | ||
1195 | }; | ||
1196 | |||
1197 | int af_caif_init(void) | ||
1198 | { | ||
1199 | int err = sock_register(&caif_family_ops); | ||
1200 | if (!err) | ||
1201 | return err; | ||
1202 | return 0; | ||
1203 | } | ||
1204 | |||
1205 | static int __init caif_sktinit_module(void) | ||
1206 | { | ||
1207 | #ifdef CONFIG_DEBUG_FS | ||
1208 | debugfsdir = debugfs_create_dir("caif_sk", NULL); | ||
1209 | if (!IS_ERR(debugfsdir)) { | ||
1210 | debugfs_create_u32("num_sockets", S_IRUSR | S_IWUSR, | ||
1211 | debugfsdir, | ||
1212 | (u32 *) &cnt.caif_nr_socks); | ||
1213 | debugfs_create_u32("num_connect_req", S_IRUSR | S_IWUSR, | ||
1214 | debugfsdir, | ||
1215 | (u32 *) &cnt.num_connect_req); | ||
1216 | debugfs_create_u32("num_connect_resp", S_IRUSR | S_IWUSR, | ||
1217 | debugfsdir, | ||
1218 | (u32 *) &cnt.num_connect_resp); | ||
1219 | debugfs_create_u32("num_connect_fail_resp", S_IRUSR | S_IWUSR, | ||
1220 | debugfsdir, | ||
1221 | (u32 *) &cnt.num_connect_fail_resp); | ||
1222 | debugfs_create_u32("num_disconnect", S_IRUSR | S_IWUSR, | ||
1223 | debugfsdir, | ||
1224 | (u32 *) &cnt.num_disconnect); | ||
1225 | debugfs_create_u32("num_remote_shutdown_ind", | ||
1226 | S_IRUSR | S_IWUSR, debugfsdir, | ||
1227 | (u32 *) &cnt.num_remote_shutdown_ind); | ||
1228 | debugfs_create_u32("num_tx_flow_off_ind", S_IRUSR | S_IWUSR, | ||
1229 | debugfsdir, | ||
1230 | (u32 *) &cnt.num_tx_flow_off_ind); | ||
1231 | debugfs_create_u32("num_tx_flow_on_ind", S_IRUSR | S_IWUSR, | ||
1232 | debugfsdir, | ||
1233 | (u32 *) &cnt.num_tx_flow_on_ind); | ||
1234 | debugfs_create_u32("num_rx_flow_off", S_IRUSR | S_IWUSR, | ||
1235 | debugfsdir, | ||
1236 | (u32 *) &cnt.num_rx_flow_off); | ||
1237 | debugfs_create_u32("num_rx_flow_on", S_IRUSR | S_IWUSR, | ||
1238 | debugfsdir, | ||
1239 | (u32 *) &cnt.num_rx_flow_on); | ||
1240 | } | ||
1241 | #endif | ||
1242 | return af_caif_init(); | ||
1243 | } | ||
1244 | |||
1245 | static void __exit caif_sktexit_module(void) | ||
1246 | { | ||
1247 | sock_unregister(PF_CAIF); | ||
1248 | if (debugfsdir != NULL) | ||
1249 | debugfs_remove_recursive(debugfsdir); | ||
1250 | } | ||
1251 | module_init(caif_sktinit_module); | ||
1252 | module_exit(caif_sktexit_module); | ||
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c new file mode 100644 index 000000000000..df43f264d9fb --- /dev/null +++ b/net/caif/cfcnfg.c | |||
@@ -0,0 +1,470 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/stddef.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <net/caif/caif_layer.h> | ||
10 | #include <net/caif/cfpkt.h> | ||
11 | #include <net/caif/cfcnfg.h> | ||
12 | #include <net/caif/cfctrl.h> | ||
13 | #include <net/caif/cfmuxl.h> | ||
14 | #include <net/caif/cffrml.h> | ||
15 | #include <net/caif/cfserl.h> | ||
16 | #include <net/caif/cfsrvl.h> | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <asm/atomic.h> | ||
20 | |||
21 | #define MAX_PHY_LAYERS 7 | ||
22 | #define PHY_NAME_LEN 20 | ||
23 | |||
24 | #define container_obj(layr) container_of(layr, struct cfcnfg, layer) | ||
25 | |||
26 | /* Information about CAIF physical interfaces held by Config Module in order | ||
27 | * to manage physical interfaces | ||
28 | */ | ||
29 | struct cfcnfg_phyinfo { | ||
30 | /* Pointer to the layer below the MUX (framing layer) */ | ||
31 | struct cflayer *frm_layer; | ||
32 | /* Pointer to the lowest actual physical layer */ | ||
33 | struct cflayer *phy_layer; | ||
34 | /* Unique identifier of the physical interface */ | ||
35 | unsigned int id; | ||
36 | /* Preference of the physical in interface */ | ||
37 | enum cfcnfg_phy_preference pref; | ||
38 | |||
39 | /* Reference count, number of channels using the device */ | ||
40 | int phy_ref_count; | ||
41 | |||
42 | /* Information about the physical device */ | ||
43 | struct dev_info dev_info; | ||
44 | }; | ||
45 | |||
46 | struct cfcnfg { | ||
47 | struct cflayer layer; | ||
48 | struct cflayer *ctrl; | ||
49 | struct cflayer *mux; | ||
50 | u8 last_phyid; | ||
51 | struct cfcnfg_phyinfo phy_layers[MAX_PHY_LAYERS]; | ||
52 | }; | ||
53 | |||
54 | static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, | ||
55 | enum cfctrl_srv serv, u8 phyid, | ||
56 | struct cflayer *adapt_layer); | ||
57 | static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id); | ||
58 | static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, | ||
59 | struct cflayer *adapt_layer); | ||
60 | static void cfctrl_resp_func(void); | ||
61 | static void cfctrl_enum_resp(void); | ||
62 | |||
63 | struct cfcnfg *cfcnfg_create(void) | ||
64 | { | ||
65 | struct cfcnfg *this; | ||
66 | struct cfctrl_rsp *resp; | ||
67 | /* Initiate this layer */ | ||
68 | this = kzalloc(sizeof(struct cfcnfg), GFP_ATOMIC); | ||
69 | if (!this) { | ||
70 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
71 | return NULL; | ||
72 | } | ||
73 | this->mux = cfmuxl_create(); | ||
74 | if (!this->mux) | ||
75 | goto out_of_mem; | ||
76 | this->ctrl = cfctrl_create(); | ||
77 | if (!this->ctrl) | ||
78 | goto out_of_mem; | ||
79 | /* Initiate response functions */ | ||
80 | resp = cfctrl_get_respfuncs(this->ctrl); | ||
81 | resp->enum_rsp = cfctrl_enum_resp; | ||
82 | resp->linkerror_ind = cfctrl_resp_func; | ||
83 | resp->linkdestroy_rsp = cfcnfg_linkdestroy_rsp; | ||
84 | resp->sleep_rsp = cfctrl_resp_func; | ||
85 | resp->wake_rsp = cfctrl_resp_func; | ||
86 | resp->restart_rsp = cfctrl_resp_func; | ||
87 | resp->radioset_rsp = cfctrl_resp_func; | ||
88 | resp->linksetup_rsp = cfcnfg_linkup_rsp; | ||
89 | resp->reject_rsp = cfcnfg_reject_rsp; | ||
90 | |||
91 | this->last_phyid = 1; | ||
92 | |||
93 | cfmuxl_set_uplayer(this->mux, this->ctrl, 0); | ||
94 | layer_set_dn(this->ctrl, this->mux); | ||
95 | layer_set_up(this->ctrl, this); | ||
96 | return this; | ||
97 | out_of_mem: | ||
98 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
99 | kfree(this->mux); | ||
100 | kfree(this->ctrl); | ||
101 | kfree(this); | ||
102 | return NULL; | ||
103 | } | ||
104 | EXPORT_SYMBOL(cfcnfg_create); | ||
105 | |||
106 | void cfcnfg_remove(struct cfcnfg *cfg) | ||
107 | { | ||
108 | if (cfg) { | ||
109 | kfree(cfg->mux); | ||
110 | kfree(cfg->ctrl); | ||
111 | kfree(cfg); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static void cfctrl_resp_func(void) | ||
116 | { | ||
117 | } | ||
118 | |||
119 | static void cfctrl_enum_resp(void) | ||
120 | { | ||
121 | } | ||
122 | |||
123 | struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, | ||
124 | enum cfcnfg_phy_preference phy_pref) | ||
125 | { | ||
126 | u16 i; | ||
127 | |||
128 | /* Try to match with specified preference */ | ||
129 | for (i = 1; i < MAX_PHY_LAYERS; i++) { | ||
130 | if (cnfg->phy_layers[i].id == i && | ||
131 | cnfg->phy_layers[i].pref == phy_pref && | ||
132 | cnfg->phy_layers[i].frm_layer != NULL) { | ||
133 | caif_assert(cnfg->phy_layers != NULL); | ||
134 | caif_assert(cnfg->phy_layers[i].id == i); | ||
135 | return &cnfg->phy_layers[i].dev_info; | ||
136 | } | ||
137 | } | ||
138 | /* Otherwise just return something */ | ||
139 | for (i = 1; i < MAX_PHY_LAYERS; i++) { | ||
140 | if (cnfg->phy_layers[i].id == i) { | ||
141 | caif_assert(cnfg->phy_layers != NULL); | ||
142 | caif_assert(cnfg->phy_layers[i].id == i); | ||
143 | return &cnfg->phy_layers[i].dev_info; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | return NULL; | ||
148 | } | ||
149 | |||
150 | static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo(struct cfcnfg *cnfg, | ||
151 | u8 phyid) | ||
152 | { | ||
153 | int i; | ||
154 | /* Try to match with specified preference */ | ||
155 | for (i = 0; i < MAX_PHY_LAYERS; i++) | ||
156 | if (cnfg->phy_layers[i].frm_layer != NULL && | ||
157 | cnfg->phy_layers[i].id == phyid) | ||
158 | return &cnfg->phy_layers[i]; | ||
159 | return NULL; | ||
160 | } | ||
161 | |||
162 | int cfcnfg_get_named(struct cfcnfg *cnfg, char *name) | ||
163 | { | ||
164 | int i; | ||
165 | |||
166 | /* Try to match with specified name */ | ||
167 | for (i = 0; i < MAX_PHY_LAYERS; i++) { | ||
168 | if (cnfg->phy_layers[i].frm_layer != NULL | ||
169 | && strcmp(cnfg->phy_layers[i].phy_layer->name, | ||
170 | name) == 0) | ||
171 | return cnfg->phy_layers[i].frm_layer->id; | ||
172 | } | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer) | ||
177 | { | ||
178 | u8 channel_id = 0; | ||
179 | int ret = 0; | ||
180 | struct cflayer *servl = NULL; | ||
181 | struct cfcnfg_phyinfo *phyinfo = NULL; | ||
182 | u8 phyid = 0; | ||
183 | caif_assert(adap_layer != NULL); | ||
184 | channel_id = adap_layer->id; | ||
185 | if (adap_layer->dn == NULL || channel_id == 0) { | ||
186 | pr_err("CAIF: %s():adap_layer->id is 0\n", __func__); | ||
187 | ret = -ENOTCONN; | ||
188 | goto end; | ||
189 | } | ||
190 | servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id); | ||
191 | if (servl == NULL) | ||
192 | goto end; | ||
193 | layer_set_up(servl, NULL); | ||
194 | ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer); | ||
195 | if (servl == NULL) { | ||
196 | pr_err("CAIF: %s(): PROTOCOL ERROR " | ||
197 | "- Error removing service_layer Channel_Id(%d)", | ||
198 | __func__, channel_id); | ||
199 | ret = -EINVAL; | ||
200 | goto end; | ||
201 | } | ||
202 | caif_assert(channel_id == servl->id); | ||
203 | if (adap_layer->dn != NULL) { | ||
204 | phyid = cfsrvl_getphyid(adap_layer->dn); | ||
205 | |||
206 | phyinfo = cfcnfg_get_phyinfo(cnfg, phyid); | ||
207 | if (phyinfo == NULL) { | ||
208 | pr_warning("CAIF: %s(): " | ||
209 | "No interface to send disconnect to\n", | ||
210 | __func__); | ||
211 | ret = -ENODEV; | ||
212 | goto end; | ||
213 | } | ||
214 | if (phyinfo->id != phyid || | ||
215 | phyinfo->phy_layer->id != phyid || | ||
216 | phyinfo->frm_layer->id != phyid) { | ||
217 | pr_err("CAIF: %s(): " | ||
218 | "Inconsistency in phy registration\n", | ||
219 | __func__); | ||
220 | ret = -EINVAL; | ||
221 | goto end; | ||
222 | } | ||
223 | } | ||
224 | if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 && | ||
225 | phyinfo->phy_layer != NULL && | ||
226 | phyinfo->phy_layer->modemcmd != NULL) { | ||
227 | phyinfo->phy_layer->modemcmd(phyinfo->phy_layer, | ||
228 | _CAIF_MODEMCMD_PHYIF_USELESS); | ||
229 | } | ||
230 | end: | ||
231 | cfsrvl_put(servl); | ||
232 | cfctrl_cancel_req(cnfg->ctrl, adap_layer); | ||
233 | if (adap_layer->ctrlcmd != NULL) | ||
234 | adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0); | ||
235 | return ret; | ||
236 | |||
237 | } | ||
238 | EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer); | ||
239 | |||
240 | void cfcnfg_release_adap_layer(struct cflayer *adap_layer) | ||
241 | { | ||
242 | if (adap_layer->dn) | ||
243 | cfsrvl_put(adap_layer->dn); | ||
244 | } | ||
245 | EXPORT_SYMBOL(cfcnfg_release_adap_layer); | ||
246 | |||
247 | static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) | ||
248 | { | ||
249 | } | ||
250 | |||
251 | int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, | ||
252 | struct cfctrl_link_param *param, | ||
253 | struct cflayer *adap_layer) | ||
254 | { | ||
255 | struct cflayer *frml; | ||
256 | if (adap_layer == NULL) { | ||
257 | pr_err("CAIF: %s(): adap_layer is zero", __func__); | ||
258 | return -EINVAL; | ||
259 | } | ||
260 | if (adap_layer->receive == NULL) { | ||
261 | pr_err("CAIF: %s(): adap_layer->receive is NULL", __func__); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | if (adap_layer->ctrlcmd == NULL) { | ||
265 | pr_err("CAIF: %s(): adap_layer->ctrlcmd == NULL", __func__); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | frml = cnfg->phy_layers[param->phyid].frm_layer; | ||
269 | if (frml == NULL) { | ||
270 | pr_err("CAIF: %s(): Specified PHY type does not exist!", | ||
271 | __func__); | ||
272 | return -ENODEV; | ||
273 | } | ||
274 | caif_assert(param->phyid == cnfg->phy_layers[param->phyid].id); | ||
275 | caif_assert(cnfg->phy_layers[param->phyid].frm_layer->id == | ||
276 | param->phyid); | ||
277 | caif_assert(cnfg->phy_layers[param->phyid].phy_layer->id == | ||
278 | param->phyid); | ||
279 | /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ | ||
280 | cfctrl_enum_req(cnfg->ctrl, param->phyid); | ||
281 | return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); | ||
282 | } | ||
283 | EXPORT_SYMBOL(cfcnfg_add_adaptation_layer); | ||
284 | |||
285 | static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, | ||
286 | struct cflayer *adapt_layer) | ||
287 | { | ||
288 | if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL) | ||
289 | adapt_layer->ctrlcmd(adapt_layer, | ||
290 | CAIF_CTRLCMD_INIT_FAIL_RSP, 0); | ||
291 | } | ||
292 | |||
293 | static void | ||
294 | cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, | ||
295 | u8 phyid, struct cflayer *adapt_layer) | ||
296 | { | ||
297 | struct cfcnfg *cnfg = container_obj(layer); | ||
298 | struct cflayer *servicel = NULL; | ||
299 | struct cfcnfg_phyinfo *phyinfo; | ||
300 | if (adapt_layer == NULL) { | ||
301 | pr_debug("CAIF: %s(): link setup response " | ||
302 | "but no client exist, send linkdown back\n", | ||
303 | __func__); | ||
304 | cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL); | ||
305 | return; | ||
306 | } | ||
307 | |||
308 | caif_assert(cnfg != NULL); | ||
309 | caif_assert(phyid != 0); | ||
310 | phyinfo = &cnfg->phy_layers[phyid]; | ||
311 | caif_assert(phyinfo != NULL); | ||
312 | caif_assert(phyinfo->id == phyid); | ||
313 | caif_assert(phyinfo->phy_layer != NULL); | ||
314 | caif_assert(phyinfo->phy_layer->id == phyid); | ||
315 | |||
316 | if (phyinfo != NULL && | ||
317 | phyinfo->phy_ref_count++ == 0 && | ||
318 | phyinfo->phy_layer != NULL && | ||
319 | phyinfo->phy_layer->modemcmd != NULL) { | ||
320 | caif_assert(phyinfo->phy_layer->id == phyid); | ||
321 | phyinfo->phy_layer->modemcmd(phyinfo->phy_layer, | ||
322 | _CAIF_MODEMCMD_PHYIF_USEFULL); | ||
323 | |||
324 | } | ||
325 | adapt_layer->id = channel_id; | ||
326 | |||
327 | switch (serv) { | ||
328 | case CFCTRL_SRV_VEI: | ||
329 | servicel = cfvei_create(channel_id, &phyinfo->dev_info); | ||
330 | break; | ||
331 | case CFCTRL_SRV_DATAGRAM: | ||
332 | servicel = cfdgml_create(channel_id, &phyinfo->dev_info); | ||
333 | break; | ||
334 | case CFCTRL_SRV_RFM: | ||
335 | servicel = cfrfml_create(channel_id, &phyinfo->dev_info); | ||
336 | break; | ||
337 | case CFCTRL_SRV_UTIL: | ||
338 | servicel = cfutill_create(channel_id, &phyinfo->dev_info); | ||
339 | break; | ||
340 | case CFCTRL_SRV_VIDEO: | ||
341 | servicel = cfvidl_create(channel_id, &phyinfo->dev_info); | ||
342 | break; | ||
343 | case CFCTRL_SRV_DBG: | ||
344 | servicel = cfdbgl_create(channel_id, &phyinfo->dev_info); | ||
345 | break; | ||
346 | default: | ||
347 | pr_err("CAIF: %s(): Protocol error. " | ||
348 | "Link setup response - unknown channel type\n", | ||
349 | __func__); | ||
350 | return; | ||
351 | } | ||
352 | if (!servicel) { | ||
353 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
354 | return; | ||
355 | } | ||
356 | layer_set_dn(servicel, cnfg->mux); | ||
357 | cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id); | ||
358 | layer_set_up(servicel, adapt_layer); | ||
359 | layer_set_dn(adapt_layer, servicel); | ||
360 | cfsrvl_get(servicel); | ||
361 | servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0); | ||
362 | } | ||
363 | |||
364 | void | ||
365 | cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, | ||
366 | void *dev, struct cflayer *phy_layer, u16 *phyid, | ||
367 | enum cfcnfg_phy_preference pref, | ||
368 | bool fcs, bool stx) | ||
369 | { | ||
370 | struct cflayer *frml; | ||
371 | struct cflayer *phy_driver = NULL; | ||
372 | int i; | ||
373 | |||
374 | |||
375 | if (cnfg->phy_layers[cnfg->last_phyid].frm_layer == NULL) { | ||
376 | *phyid = cnfg->last_phyid; | ||
377 | |||
378 | /* range: * 1..(MAX_PHY_LAYERS-1) */ | ||
379 | cnfg->last_phyid = | ||
380 | (cnfg->last_phyid % (MAX_PHY_LAYERS - 1)) + 1; | ||
381 | } else { | ||
382 | *phyid = 0; | ||
383 | for (i = 1; i < MAX_PHY_LAYERS; i++) { | ||
384 | if (cnfg->phy_layers[i].frm_layer == NULL) { | ||
385 | *phyid = i; | ||
386 | break; | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | if (*phyid == 0) { | ||
391 | pr_err("CAIF: %s(): No Available PHY ID\n", __func__); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | switch (phy_type) { | ||
396 | case CFPHYTYPE_FRAG: | ||
397 | phy_driver = | ||
398 | cfserl_create(CFPHYTYPE_FRAG, *phyid, stx); | ||
399 | if (!phy_driver) { | ||
400 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
401 | return; | ||
402 | } | ||
403 | |||
404 | break; | ||
405 | case CFPHYTYPE_CAIF: | ||
406 | phy_driver = NULL; | ||
407 | break; | ||
408 | default: | ||
409 | pr_err("CAIF: %s(): %d", __func__, phy_type); | ||
410 | return; | ||
411 | break; | ||
412 | } | ||
413 | |||
414 | phy_layer->id = *phyid; | ||
415 | cnfg->phy_layers[*phyid].pref = pref; | ||
416 | cnfg->phy_layers[*phyid].id = *phyid; | ||
417 | cnfg->phy_layers[*phyid].dev_info.id = *phyid; | ||
418 | cnfg->phy_layers[*phyid].dev_info.dev = dev; | ||
419 | cnfg->phy_layers[*phyid].phy_layer = phy_layer; | ||
420 | cnfg->phy_layers[*phyid].phy_ref_count = 0; | ||
421 | phy_layer->type = phy_type; | ||
422 | frml = cffrml_create(*phyid, fcs); | ||
423 | if (!frml) { | ||
424 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
425 | return; | ||
426 | } | ||
427 | cnfg->phy_layers[*phyid].frm_layer = frml; | ||
428 | cfmuxl_set_dnlayer(cnfg->mux, frml, *phyid); | ||
429 | layer_set_up(frml, cnfg->mux); | ||
430 | |||
431 | if (phy_driver != NULL) { | ||
432 | phy_driver->id = *phyid; | ||
433 | layer_set_dn(frml, phy_driver); | ||
434 | layer_set_up(phy_driver, frml); | ||
435 | layer_set_dn(phy_driver, phy_layer); | ||
436 | layer_set_up(phy_layer, phy_driver); | ||
437 | } else { | ||
438 | layer_set_dn(frml, phy_layer); | ||
439 | layer_set_up(phy_layer, frml); | ||
440 | } | ||
441 | } | ||
442 | EXPORT_SYMBOL(cfcnfg_add_phy_layer); | ||
443 | |||
444 | int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) | ||
445 | { | ||
446 | struct cflayer *frml, *frml_dn; | ||
447 | u16 phyid; | ||
448 | phyid = phy_layer->id; | ||
449 | caif_assert(phyid == cnfg->phy_layers[phyid].id); | ||
450 | caif_assert(phy_layer == cnfg->phy_layers[phyid].phy_layer); | ||
451 | caif_assert(phy_layer->id == phyid); | ||
452 | caif_assert(cnfg->phy_layers[phyid].frm_layer->id == phyid); | ||
453 | |||
454 | memset(&cnfg->phy_layers[phy_layer->id], 0, | ||
455 | sizeof(struct cfcnfg_phyinfo)); | ||
456 | frml = cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id); | ||
457 | frml_dn = frml->dn; | ||
458 | cffrml_set_uplayer(frml, NULL); | ||
459 | cffrml_set_dnlayer(frml, NULL); | ||
460 | kfree(frml); | ||
461 | |||
462 | if (phy_layer != frml_dn) { | ||
463 | layer_set_up(frml_dn, NULL); | ||
464 | layer_set_dn(frml_dn, NULL); | ||
465 | kfree(frml_dn); | ||
466 | } | ||
467 | layer_set_up(phy_layer, NULL); | ||
468 | return 0; | ||
469 | } | ||
470 | EXPORT_SYMBOL(cfcnfg_del_phy_layer); | ||
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c new file mode 100644 index 000000000000..0ffe1e1ce901 --- /dev/null +++ b/net/caif/cfctrl.c | |||
@@ -0,0 +1,692 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/stddef.h> | ||
8 | #include <linux/spinlock.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <net/caif/caif_layer.h> | ||
11 | #include <net/caif/cfpkt.h> | ||
12 | #include <net/caif/cfctrl.h> | ||
13 | |||
14 | #define container_obj(layr) container_of(layr, struct cfctrl, serv.layer) | ||
15 | #define UTILITY_NAME_LENGTH 16 | ||
16 | #define CFPKT_CTRL_PKT_LEN 20 | ||
17 | |||
18 | |||
19 | #ifdef CAIF_NO_LOOP | ||
20 | static int handle_loop(struct cfctrl *ctrl, | ||
21 | int cmd, struct cfpkt *pkt){ | ||
22 | return CAIF_FAILURE; | ||
23 | } | ||
24 | #else | ||
25 | static int handle_loop(struct cfctrl *ctrl, | ||
26 | int cmd, struct cfpkt *pkt); | ||
27 | #endif | ||
28 | static int cfctrl_recv(struct cflayer *layr, struct cfpkt *pkt); | ||
29 | static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
30 | int phyid); | ||
31 | |||
32 | |||
33 | struct cflayer *cfctrl_create(void) | ||
34 | { | ||
35 | struct dev_info dev_info; | ||
36 | struct cfctrl *this = | ||
37 | kmalloc(sizeof(struct cfctrl), GFP_ATOMIC); | ||
38 | if (!this) { | ||
39 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
40 | return NULL; | ||
41 | } | ||
42 | caif_assert(offsetof(struct cfctrl, serv.layer) == 0); | ||
43 | memset(&dev_info, 0, sizeof(dev_info)); | ||
44 | dev_info.id = 0xff; | ||
45 | memset(this, 0, sizeof(*this)); | ||
46 | cfsrvl_init(&this->serv, 0, &dev_info); | ||
47 | spin_lock_init(&this->info_list_lock); | ||
48 | atomic_set(&this->req_seq_no, 1); | ||
49 | atomic_set(&this->rsp_seq_no, 1); | ||
50 | this->serv.layer.receive = cfctrl_recv; | ||
51 | sprintf(this->serv.layer.name, "ctrl"); | ||
52 | this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; | ||
53 | spin_lock_init(&this->loop_linkid_lock); | ||
54 | this->loop_linkid = 1; | ||
55 | return &this->serv.layer; | ||
56 | } | ||
57 | |||
58 | static bool param_eq(struct cfctrl_link_param *p1, struct cfctrl_link_param *p2) | ||
59 | { | ||
60 | bool eq = | ||
61 | p1->linktype == p2->linktype && | ||
62 | p1->priority == p2->priority && | ||
63 | p1->phyid == p2->phyid && | ||
64 | p1->endpoint == p2->endpoint && p1->chtype == p2->chtype; | ||
65 | |||
66 | if (!eq) | ||
67 | return false; | ||
68 | |||
69 | switch (p1->linktype) { | ||
70 | case CFCTRL_SRV_VEI: | ||
71 | return true; | ||
72 | case CFCTRL_SRV_DATAGRAM: | ||
73 | return p1->u.datagram.connid == p2->u.datagram.connid; | ||
74 | case CFCTRL_SRV_RFM: | ||
75 | return | ||
76 | p1->u.rfm.connid == p2->u.rfm.connid && | ||
77 | strcmp(p1->u.rfm.volume, p2->u.rfm.volume) == 0; | ||
78 | case CFCTRL_SRV_UTIL: | ||
79 | return | ||
80 | p1->u.utility.fifosize_kb == p2->u.utility.fifosize_kb | ||
81 | && p1->u.utility.fifosize_bufs == | ||
82 | p2->u.utility.fifosize_bufs | ||
83 | && strcmp(p1->u.utility.name, p2->u.utility.name) == 0 | ||
84 | && p1->u.utility.paramlen == p2->u.utility.paramlen | ||
85 | && memcmp(p1->u.utility.params, p2->u.utility.params, | ||
86 | p1->u.utility.paramlen) == 0; | ||
87 | |||
88 | case CFCTRL_SRV_VIDEO: | ||
89 | return p1->u.video.connid == p2->u.video.connid; | ||
90 | case CFCTRL_SRV_DBG: | ||
91 | return true; | ||
92 | case CFCTRL_SRV_DECM: | ||
93 | return false; | ||
94 | default: | ||
95 | return false; | ||
96 | } | ||
97 | return false; | ||
98 | } | ||
99 | |||
100 | bool cfctrl_req_eq(struct cfctrl_request_info *r1, | ||
101 | struct cfctrl_request_info *r2) | ||
102 | { | ||
103 | if (r1->cmd != r2->cmd) | ||
104 | return false; | ||
105 | if (r1->cmd == CFCTRL_CMD_LINK_SETUP) | ||
106 | return param_eq(&r1->param, &r2->param); | ||
107 | else | ||
108 | return r1->channel_id == r2->channel_id; | ||
109 | } | ||
110 | |||
111 | /* Insert request at the end */ | ||
112 | void cfctrl_insert_req(struct cfctrl *ctrl, | ||
113 | struct cfctrl_request_info *req) | ||
114 | { | ||
115 | struct cfctrl_request_info *p; | ||
116 | spin_lock(&ctrl->info_list_lock); | ||
117 | req->next = NULL; | ||
118 | atomic_inc(&ctrl->req_seq_no); | ||
119 | req->sequence_no = atomic_read(&ctrl->req_seq_no); | ||
120 | if (ctrl->first_req == NULL) { | ||
121 | ctrl->first_req = req; | ||
122 | spin_unlock(&ctrl->info_list_lock); | ||
123 | return; | ||
124 | } | ||
125 | p = ctrl->first_req; | ||
126 | while (p->next != NULL) | ||
127 | p = p->next; | ||
128 | p->next = req; | ||
129 | spin_unlock(&ctrl->info_list_lock); | ||
130 | } | ||
131 | |||
132 | /* Compare and remove request */ | ||
133 | struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, | ||
134 | struct cfctrl_request_info *req) | ||
135 | { | ||
136 | struct cfctrl_request_info *p; | ||
137 | struct cfctrl_request_info *ret; | ||
138 | |||
139 | spin_lock(&ctrl->info_list_lock); | ||
140 | if (ctrl->first_req == NULL) { | ||
141 | spin_unlock(&ctrl->info_list_lock); | ||
142 | return NULL; | ||
143 | } | ||
144 | |||
145 | if (cfctrl_req_eq(req, ctrl->first_req)) { | ||
146 | ret = ctrl->first_req; | ||
147 | caif_assert(ctrl->first_req); | ||
148 | atomic_set(&ctrl->rsp_seq_no, | ||
149 | ctrl->first_req->sequence_no); | ||
150 | ctrl->first_req = ctrl->first_req->next; | ||
151 | spin_unlock(&ctrl->info_list_lock); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | p = ctrl->first_req; | ||
156 | |||
157 | while (p->next != NULL) { | ||
158 | if (cfctrl_req_eq(req, p->next)) { | ||
159 | pr_warning("CAIF: %s(): Requests are not " | ||
160 | "received in order\n", | ||
161 | __func__); | ||
162 | ret = p->next; | ||
163 | atomic_set(&ctrl->rsp_seq_no, | ||
164 | p->next->sequence_no); | ||
165 | p->next = p->next->next; | ||
166 | spin_unlock(&ctrl->info_list_lock); | ||
167 | return ret; | ||
168 | } | ||
169 | p = p->next; | ||
170 | } | ||
171 | spin_unlock(&ctrl->info_list_lock); | ||
172 | |||
173 | pr_warning("CAIF: %s(): Request does not match\n", | ||
174 | __func__); | ||
175 | return NULL; | ||
176 | } | ||
177 | |||
178 | struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer) | ||
179 | { | ||
180 | struct cfctrl *this = container_obj(layer); | ||
181 | return &this->res; | ||
182 | } | ||
183 | |||
184 | void cfctrl_set_dnlayer(struct cflayer *this, struct cflayer *dn) | ||
185 | { | ||
186 | this->dn = dn; | ||
187 | } | ||
188 | |||
189 | void cfctrl_set_uplayer(struct cflayer *this, struct cflayer *up) | ||
190 | { | ||
191 | this->up = up; | ||
192 | } | ||
193 | |||
194 | static void init_info(struct caif_payload_info *info, struct cfctrl *cfctrl) | ||
195 | { | ||
196 | info->hdr_len = 0; | ||
197 | info->channel_id = cfctrl->serv.layer.id; | ||
198 | info->dev_info = &cfctrl->serv.dev_info; | ||
199 | } | ||
200 | |||
201 | void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid) | ||
202 | { | ||
203 | struct cfctrl *cfctrl = container_obj(layer); | ||
204 | int ret; | ||
205 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
206 | if (!pkt) { | ||
207 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
208 | return; | ||
209 | } | ||
210 | caif_assert(offsetof(struct cfctrl, serv.layer) == 0); | ||
211 | init_info(cfpkt_info(pkt), cfctrl); | ||
212 | cfpkt_info(pkt)->dev_info->id = physlinkid; | ||
213 | cfctrl->serv.dev_info.id = physlinkid; | ||
214 | cfpkt_addbdy(pkt, CFCTRL_CMD_ENUM); | ||
215 | cfpkt_addbdy(pkt, physlinkid); | ||
216 | ret = | ||
217 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | ||
218 | if (ret < 0) { | ||
219 | pr_err("CAIF: %s(): Could not transmit enum message\n", | ||
220 | __func__); | ||
221 | cfpkt_destroy(pkt); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | int cfctrl_linkup_request(struct cflayer *layer, | ||
226 | struct cfctrl_link_param *param, | ||
227 | struct cflayer *user_layer) | ||
228 | { | ||
229 | struct cfctrl *cfctrl = container_obj(layer); | ||
230 | u32 tmp32; | ||
231 | u16 tmp16; | ||
232 | u8 tmp8; | ||
233 | struct cfctrl_request_info *req; | ||
234 | int ret; | ||
235 | char utility_name[16]; | ||
236 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
237 | if (!pkt) { | ||
238 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
239 | return -ENOMEM; | ||
240 | } | ||
241 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); | ||
242 | cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype); | ||
243 | cfpkt_addbdy(pkt, (param->priority << 3) + param->phyid); | ||
244 | cfpkt_addbdy(pkt, param->endpoint & 0x03); | ||
245 | |||
246 | switch (param->linktype) { | ||
247 | case CFCTRL_SRV_VEI: | ||
248 | break; | ||
249 | case CFCTRL_SRV_VIDEO: | ||
250 | cfpkt_addbdy(pkt, (u8) param->u.video.connid); | ||
251 | break; | ||
252 | case CFCTRL_SRV_DBG: | ||
253 | break; | ||
254 | case CFCTRL_SRV_DATAGRAM: | ||
255 | tmp32 = cpu_to_le32(param->u.datagram.connid); | ||
256 | cfpkt_add_body(pkt, &tmp32, 4); | ||
257 | break; | ||
258 | case CFCTRL_SRV_RFM: | ||
259 | /* Construct a frame, convert DatagramConnectionID to network | ||
260 | * format long and copy it out... | ||
261 | */ | ||
262 | tmp32 = cpu_to_le32(param->u.rfm.connid); | ||
263 | cfpkt_add_body(pkt, &tmp32, 4); | ||
264 | /* Add volume name, including zero termination... */ | ||
265 | cfpkt_add_body(pkt, param->u.rfm.volume, | ||
266 | strlen(param->u.rfm.volume) + 1); | ||
267 | break; | ||
268 | case CFCTRL_SRV_UTIL: | ||
269 | tmp16 = cpu_to_le16(param->u.utility.fifosize_kb); | ||
270 | cfpkt_add_body(pkt, &tmp16, 2); | ||
271 | tmp16 = cpu_to_le16(param->u.utility.fifosize_bufs); | ||
272 | cfpkt_add_body(pkt, &tmp16, 2); | ||
273 | memset(utility_name, 0, sizeof(utility_name)); | ||
274 | strncpy(utility_name, param->u.utility.name, | ||
275 | UTILITY_NAME_LENGTH - 1); | ||
276 | cfpkt_add_body(pkt, utility_name, UTILITY_NAME_LENGTH); | ||
277 | tmp8 = param->u.utility.paramlen; | ||
278 | cfpkt_add_body(pkt, &tmp8, 1); | ||
279 | cfpkt_add_body(pkt, param->u.utility.params, | ||
280 | param->u.utility.paramlen); | ||
281 | break; | ||
282 | default: | ||
283 | pr_warning("CAIF: %s():Request setup of bad link type = %d\n", | ||
284 | __func__, param->linktype); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | req = kzalloc(sizeof(*req), GFP_KERNEL); | ||
288 | if (!req) { | ||
289 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
290 | return -ENOMEM; | ||
291 | } | ||
292 | req->client_layer = user_layer; | ||
293 | req->cmd = CFCTRL_CMD_LINK_SETUP; | ||
294 | req->param = *param; | ||
295 | cfctrl_insert_req(cfctrl, req); | ||
296 | init_info(cfpkt_info(pkt), cfctrl); | ||
297 | /* | ||
298 | * NOTE:Always send linkup and linkdown request on the same | ||
299 | * device as the payload. Otherwise old queued up payload | ||
300 | * might arrive with the newly allocated channel ID. | ||
301 | */ | ||
302 | cfpkt_info(pkt)->dev_info->id = param->phyid; | ||
303 | ret = | ||
304 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | ||
305 | if (ret < 0) { | ||
306 | pr_err("CAIF: %s(): Could not transmit linksetup request\n", | ||
307 | __func__); | ||
308 | cfpkt_destroy(pkt); | ||
309 | return -ENODEV; | ||
310 | } | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, | ||
315 | struct cflayer *client) | ||
316 | { | ||
317 | int ret; | ||
318 | struct cfctrl *cfctrl = container_obj(layer); | ||
319 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
320 | if (!pkt) { | ||
321 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
322 | return -ENOMEM; | ||
323 | } | ||
324 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY); | ||
325 | cfpkt_addbdy(pkt, channelid); | ||
326 | init_info(cfpkt_info(pkt), cfctrl); | ||
327 | ret = | ||
328 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | ||
329 | if (ret < 0) { | ||
330 | pr_err("CAIF: %s(): Could not transmit link-down request\n", | ||
331 | __func__); | ||
332 | cfpkt_destroy(pkt); | ||
333 | } | ||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | void cfctrl_sleep_req(struct cflayer *layer) | ||
338 | { | ||
339 | int ret; | ||
340 | struct cfctrl *cfctrl = container_obj(layer); | ||
341 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
342 | if (!pkt) { | ||
343 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
344 | return; | ||
345 | } | ||
346 | cfpkt_addbdy(pkt, CFCTRL_CMD_SLEEP); | ||
347 | init_info(cfpkt_info(pkt), cfctrl); | ||
348 | ret = | ||
349 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | ||
350 | if (ret < 0) | ||
351 | cfpkt_destroy(pkt); | ||
352 | } | ||
353 | |||
354 | void cfctrl_wake_req(struct cflayer *layer) | ||
355 | { | ||
356 | int ret; | ||
357 | struct cfctrl *cfctrl = container_obj(layer); | ||
358 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
359 | if (!pkt) { | ||
360 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
361 | return; | ||
362 | } | ||
363 | cfpkt_addbdy(pkt, CFCTRL_CMD_WAKE); | ||
364 | init_info(cfpkt_info(pkt), cfctrl); | ||
365 | ret = | ||
366 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | ||
367 | if (ret < 0) | ||
368 | cfpkt_destroy(pkt); | ||
369 | } | ||
370 | |||
371 | void cfctrl_getstartreason_req(struct cflayer *layer) | ||
372 | { | ||
373 | int ret; | ||
374 | struct cfctrl *cfctrl = container_obj(layer); | ||
375 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
376 | if (!pkt) { | ||
377 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
378 | return; | ||
379 | } | ||
380 | cfpkt_addbdy(pkt, CFCTRL_CMD_START_REASON); | ||
381 | init_info(cfpkt_info(pkt), cfctrl); | ||
382 | ret = | ||
383 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | ||
384 | if (ret < 0) | ||
385 | cfpkt_destroy(pkt); | ||
386 | } | ||
387 | |||
388 | |||
389 | void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) | ||
390 | { | ||
391 | struct cfctrl_request_info *p, *req; | ||
392 | struct cfctrl *ctrl = container_obj(layr); | ||
393 | spin_lock(&ctrl->info_list_lock); | ||
394 | |||
395 | if (ctrl->first_req == NULL) { | ||
396 | spin_unlock(&ctrl->info_list_lock); | ||
397 | return; | ||
398 | } | ||
399 | |||
400 | if (ctrl->first_req->client_layer == adap_layer) { | ||
401 | |||
402 | req = ctrl->first_req; | ||
403 | ctrl->first_req = ctrl->first_req->next; | ||
404 | kfree(req); | ||
405 | } | ||
406 | |||
407 | p = ctrl->first_req; | ||
408 | while (p != NULL && p->next != NULL) { | ||
409 | if (p->next->client_layer == adap_layer) { | ||
410 | |||
411 | req = p->next; | ||
412 | p->next = p->next->next; | ||
413 | kfree(p->next); | ||
414 | } | ||
415 | p = p->next; | ||
416 | } | ||
417 | |||
418 | spin_unlock(&ctrl->info_list_lock); | ||
419 | } | ||
420 | |||
421 | static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | ||
422 | { | ||
423 | u8 cmdrsp; | ||
424 | u8 cmd; | ||
425 | int ret = -1; | ||
426 | u16 tmp16; | ||
427 | u8 len; | ||
428 | u8 param[255]; | ||
429 | u8 linkid; | ||
430 | struct cfctrl *cfctrl = container_obj(layer); | ||
431 | struct cfctrl_request_info rsp, *req; | ||
432 | |||
433 | |||
434 | cfpkt_extr_head(pkt, &cmdrsp, 1); | ||
435 | cmd = cmdrsp & CFCTRL_CMD_MASK; | ||
436 | if (cmd != CFCTRL_CMD_LINK_ERR | ||
437 | && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) { | ||
438 | if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) | ||
439 | cmdrsp |= CFCTRL_ERR_BIT; | ||
440 | } | ||
441 | |||
442 | switch (cmd) { | ||
443 | case CFCTRL_CMD_LINK_SETUP: | ||
444 | { | ||
445 | enum cfctrl_srv serv; | ||
446 | enum cfctrl_srv servtype; | ||
447 | u8 endpoint; | ||
448 | u8 physlinkid; | ||
449 | u8 prio; | ||
450 | u8 tmp; | ||
451 | u32 tmp32; | ||
452 | u8 *cp; | ||
453 | int i; | ||
454 | struct cfctrl_link_param linkparam; | ||
455 | memset(&linkparam, 0, sizeof(linkparam)); | ||
456 | |||
457 | cfpkt_extr_head(pkt, &tmp, 1); | ||
458 | |||
459 | serv = tmp & CFCTRL_SRV_MASK; | ||
460 | linkparam.linktype = serv; | ||
461 | |||
462 | servtype = tmp >> 4; | ||
463 | linkparam.chtype = servtype; | ||
464 | |||
465 | cfpkt_extr_head(pkt, &tmp, 1); | ||
466 | physlinkid = tmp & 0x07; | ||
467 | prio = tmp >> 3; | ||
468 | |||
469 | linkparam.priority = prio; | ||
470 | linkparam.phyid = physlinkid; | ||
471 | cfpkt_extr_head(pkt, &endpoint, 1); | ||
472 | linkparam.endpoint = endpoint & 0x03; | ||
473 | |||
474 | switch (serv) { | ||
475 | case CFCTRL_SRV_VEI: | ||
476 | case CFCTRL_SRV_DBG: | ||
477 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
478 | break; | ||
479 | /* Link ID */ | ||
480 | cfpkt_extr_head(pkt, &linkid, 1); | ||
481 | break; | ||
482 | case CFCTRL_SRV_VIDEO: | ||
483 | cfpkt_extr_head(pkt, &tmp, 1); | ||
484 | linkparam.u.video.connid = tmp; | ||
485 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
486 | break; | ||
487 | /* Link ID */ | ||
488 | cfpkt_extr_head(pkt, &linkid, 1); | ||
489 | break; | ||
490 | |||
491 | case CFCTRL_SRV_DATAGRAM: | ||
492 | cfpkt_extr_head(pkt, &tmp32, 4); | ||
493 | linkparam.u.datagram.connid = | ||
494 | le32_to_cpu(tmp32); | ||
495 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
496 | break; | ||
497 | /* Link ID */ | ||
498 | cfpkt_extr_head(pkt, &linkid, 1); | ||
499 | break; | ||
500 | case CFCTRL_SRV_RFM: | ||
501 | /* Construct a frame, convert | ||
502 | * DatagramConnectionID | ||
503 | * to network format long and copy it out... | ||
504 | */ | ||
505 | cfpkt_extr_head(pkt, &tmp32, 4); | ||
506 | linkparam.u.rfm.connid = | ||
507 | le32_to_cpu(tmp32); | ||
508 | cp = (u8 *) linkparam.u.rfm.volume; | ||
509 | for (cfpkt_extr_head(pkt, &tmp, 1); | ||
510 | cfpkt_more(pkt) && tmp != '\0'; | ||
511 | cfpkt_extr_head(pkt, &tmp, 1)) | ||
512 | *cp++ = tmp; | ||
513 | *cp = '\0'; | ||
514 | |||
515 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
516 | break; | ||
517 | /* Link ID */ | ||
518 | cfpkt_extr_head(pkt, &linkid, 1); | ||
519 | |||
520 | break; | ||
521 | case CFCTRL_SRV_UTIL: | ||
522 | /* Construct a frame, convert | ||
523 | * DatagramConnectionID | ||
524 | * to network format long and copy it out... | ||
525 | */ | ||
526 | /* Fifosize KB */ | ||
527 | cfpkt_extr_head(pkt, &tmp16, 2); | ||
528 | linkparam.u.utility.fifosize_kb = | ||
529 | le16_to_cpu(tmp16); | ||
530 | /* Fifosize bufs */ | ||
531 | cfpkt_extr_head(pkt, &tmp16, 2); | ||
532 | linkparam.u.utility.fifosize_bufs = | ||
533 | le16_to_cpu(tmp16); | ||
534 | /* name */ | ||
535 | cp = (u8 *) linkparam.u.utility.name; | ||
536 | caif_assert(sizeof(linkparam.u.utility.name) | ||
537 | >= UTILITY_NAME_LENGTH); | ||
538 | for (i = 0; | ||
539 | i < UTILITY_NAME_LENGTH | ||
540 | && cfpkt_more(pkt); i++) { | ||
541 | cfpkt_extr_head(pkt, &tmp, 1); | ||
542 | *cp++ = tmp; | ||
543 | } | ||
544 | /* Length */ | ||
545 | cfpkt_extr_head(pkt, &len, 1); | ||
546 | linkparam.u.utility.paramlen = len; | ||
547 | /* Param Data */ | ||
548 | cp = linkparam.u.utility.params; | ||
549 | while (cfpkt_more(pkt) && len--) { | ||
550 | cfpkt_extr_head(pkt, &tmp, 1); | ||
551 | *cp++ = tmp; | ||
552 | } | ||
553 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
554 | break; | ||
555 | /* Link ID */ | ||
556 | cfpkt_extr_head(pkt, &linkid, 1); | ||
557 | /* Length */ | ||
558 | cfpkt_extr_head(pkt, &len, 1); | ||
559 | /* Param Data */ | ||
560 | cfpkt_extr_head(pkt, ¶m, len); | ||
561 | break; | ||
562 | default: | ||
563 | pr_warning("CAIF: %s(): Request setup " | ||
564 | "- invalid link type (%d)", | ||
565 | __func__, serv); | ||
566 | goto error; | ||
567 | } | ||
568 | |||
569 | rsp.cmd = cmd; | ||
570 | rsp.param = linkparam; | ||
571 | req = cfctrl_remove_req(cfctrl, &rsp); | ||
572 | |||
573 | if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) || | ||
574 | cfpkt_erroneous(pkt)) { | ||
575 | pr_err("CAIF: %s(): Invalid O/E bit or parse " | ||
576 | "error on CAIF control channel", | ||
577 | __func__); | ||
578 | cfctrl->res.reject_rsp(cfctrl->serv.layer.up, | ||
579 | 0, | ||
580 | req ? req->client_layer | ||
581 | : NULL); | ||
582 | } else { | ||
583 | cfctrl->res.linksetup_rsp(cfctrl->serv. | ||
584 | layer.up, linkid, | ||
585 | serv, physlinkid, | ||
586 | req ? req-> | ||
587 | client_layer : NULL); | ||
588 | } | ||
589 | |||
590 | if (req != NULL) | ||
591 | kfree(req); | ||
592 | } | ||
593 | break; | ||
594 | case CFCTRL_CMD_LINK_DESTROY: | ||
595 | cfpkt_extr_head(pkt, &linkid, 1); | ||
596 | cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid); | ||
597 | break; | ||
598 | case CFCTRL_CMD_LINK_ERR: | ||
599 | pr_err("CAIF: %s(): Frame Error Indication received\n", | ||
600 | __func__); | ||
601 | cfctrl->res.linkerror_ind(); | ||
602 | break; | ||
603 | case CFCTRL_CMD_ENUM: | ||
604 | cfctrl->res.enum_rsp(); | ||
605 | break; | ||
606 | case CFCTRL_CMD_SLEEP: | ||
607 | cfctrl->res.sleep_rsp(); | ||
608 | break; | ||
609 | case CFCTRL_CMD_WAKE: | ||
610 | cfctrl->res.wake_rsp(); | ||
611 | break; | ||
612 | case CFCTRL_CMD_LINK_RECONF: | ||
613 | cfctrl->res.restart_rsp(); | ||
614 | break; | ||
615 | case CFCTRL_CMD_RADIO_SET: | ||
616 | cfctrl->res.radioset_rsp(); | ||
617 | break; | ||
618 | default: | ||
619 | pr_err("CAIF: %s(): Unrecognized Control Frame\n", __func__); | ||
620 | goto error; | ||
621 | break; | ||
622 | } | ||
623 | ret = 0; | ||
624 | error: | ||
625 | cfpkt_destroy(pkt); | ||
626 | return ret; | ||
627 | } | ||
628 | |||
629 | static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
630 | int phyid) | ||
631 | { | ||
632 | struct cfctrl *this = container_obj(layr); | ||
633 | switch (ctrl) { | ||
634 | case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: | ||
635 | case CAIF_CTRLCMD_FLOW_OFF_IND: | ||
636 | spin_lock(&this->info_list_lock); | ||
637 | if (this->first_req != NULL) { | ||
638 | pr_debug("CAIF: %s(): Received flow off in " | ||
639 | "control layer", __func__); | ||
640 | } | ||
641 | spin_unlock(&this->info_list_lock); | ||
642 | break; | ||
643 | default: | ||
644 | break; | ||
645 | } | ||
646 | } | ||
647 | |||
648 | #ifndef CAIF_NO_LOOP | ||
649 | static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) | ||
650 | { | ||
651 | static int last_linkid; | ||
652 | u8 linkid, linktype, tmp; | ||
653 | switch (cmd) { | ||
654 | case CFCTRL_CMD_LINK_SETUP: | ||
655 | spin_lock(&ctrl->loop_linkid_lock); | ||
656 | for (linkid = last_linkid + 1; linkid < 255; linkid++) | ||
657 | if (!ctrl->loop_linkused[linkid]) | ||
658 | goto found; | ||
659 | for (linkid = last_linkid - 1; linkid > 0; linkid--) | ||
660 | if (!ctrl->loop_linkused[linkid]) | ||
661 | goto found; | ||
662 | spin_unlock(&ctrl->loop_linkid_lock); | ||
663 | pr_err("CAIF: %s(): Out of link-ids\n", __func__); | ||
664 | return -EINVAL; | ||
665 | found: | ||
666 | if (!ctrl->loop_linkused[linkid]) | ||
667 | ctrl->loop_linkused[linkid] = 1; | ||
668 | |||
669 | last_linkid = linkid; | ||
670 | |||
671 | cfpkt_add_trail(pkt, &linkid, 1); | ||
672 | spin_unlock(&ctrl->loop_linkid_lock); | ||
673 | cfpkt_peek_head(pkt, &linktype, 1); | ||
674 | if (linktype == CFCTRL_SRV_UTIL) { | ||
675 | tmp = 0x01; | ||
676 | cfpkt_add_trail(pkt, &tmp, 1); | ||
677 | cfpkt_add_trail(pkt, &tmp, 1); | ||
678 | } | ||
679 | break; | ||
680 | |||
681 | case CFCTRL_CMD_LINK_DESTROY: | ||
682 | spin_lock(&ctrl->loop_linkid_lock); | ||
683 | cfpkt_peek_head(pkt, &linkid, 1); | ||
684 | ctrl->loop_linkused[linkid] = 0; | ||
685 | spin_unlock(&ctrl->loop_linkid_lock); | ||
686 | break; | ||
687 | default: | ||
688 | break; | ||
689 | } | ||
690 | return CAIF_SUCCESS; | ||
691 | } | ||
692 | #endif | ||
diff --git a/net/caif/cfdbgl.c b/net/caif/cfdbgl.c new file mode 100644 index 000000000000..ab6b6dc34cf8 --- /dev/null +++ b/net/caif/cfdbgl.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/stddef.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <net/caif/caif_layer.h> | ||
10 | #include <net/caif/cfsrvl.h> | ||
11 | #include <net/caif/cfpkt.h> | ||
12 | |||
13 | static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt); | ||
14 | static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt); | ||
15 | |||
16 | struct cflayer *cfdbgl_create(u8 channel_id, struct dev_info *dev_info) | ||
17 | { | ||
18 | struct cfsrvl *dbg = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC); | ||
19 | if (!dbg) { | ||
20 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
21 | return NULL; | ||
22 | } | ||
23 | caif_assert(offsetof(struct cfsrvl, layer) == 0); | ||
24 | memset(dbg, 0, sizeof(struct cfsrvl)); | ||
25 | cfsrvl_init(dbg, channel_id, dev_info); | ||
26 | dbg->layer.receive = cfdbgl_receive; | ||
27 | dbg->layer.transmit = cfdbgl_transmit; | ||
28 | snprintf(dbg->layer.name, CAIF_LAYER_NAME_SZ - 1, "dbg%d", channel_id); | ||
29 | return &dbg->layer; | ||
30 | } | ||
31 | |||
32 | static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt) | ||
33 | { | ||
34 | return layr->up->receive(layr->up, pkt); | ||
35 | } | ||
36 | |||
37 | static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt) | ||
38 | { | ||
39 | return layr->dn->transmit(layr->dn, pkt); | ||
40 | } | ||
diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c new file mode 100644 index 000000000000..53194840ecb6 --- /dev/null +++ b/net/caif/cfdgml.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/stddef.h> | ||
8 | #include <linux/spinlock.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <net/caif/caif_layer.h> | ||
11 | #include <net/caif/cfsrvl.h> | ||
12 | #include <net/caif/cfpkt.h> | ||
13 | |||
14 | #define container_obj(layr) ((struct cfsrvl *) layr) | ||
15 | |||
16 | #define DGM_CMD_BIT 0x80 | ||
17 | #define DGM_FLOW_OFF 0x81 | ||
18 | #define DGM_FLOW_ON 0x80 | ||
19 | #define DGM_CTRL_PKT_SIZE 1 | ||
20 | |||
21 | static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt); | ||
22 | static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt); | ||
23 | |||
24 | struct cflayer *cfdgml_create(u8 channel_id, struct dev_info *dev_info) | ||
25 | { | ||
26 | struct cfsrvl *dgm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC); | ||
27 | if (!dgm) { | ||
28 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
29 | return NULL; | ||
30 | } | ||
31 | caif_assert(offsetof(struct cfsrvl, layer) == 0); | ||
32 | memset(dgm, 0, sizeof(struct cfsrvl)); | ||
33 | cfsrvl_init(dgm, channel_id, dev_info); | ||
34 | dgm->layer.receive = cfdgml_receive; | ||
35 | dgm->layer.transmit = cfdgml_transmit; | ||
36 | snprintf(dgm->layer.name, CAIF_LAYER_NAME_SZ - 1, "dgm%d", channel_id); | ||
37 | dgm->layer.name[CAIF_LAYER_NAME_SZ - 1] = '\0'; | ||
38 | return &dgm->layer; | ||
39 | } | ||
40 | |||
41 | static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt) | ||
42 | { | ||
43 | u8 cmd = -1; | ||
44 | u8 dgmhdr[3]; | ||
45 | int ret; | ||
46 | caif_assert(layr->up != NULL); | ||
47 | caif_assert(layr->receive != NULL); | ||
48 | caif_assert(layr->ctrlcmd != NULL); | ||
49 | |||
50 | if (cfpkt_extr_head(pkt, &cmd, 1) < 0) { | ||
51 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
52 | cfpkt_destroy(pkt); | ||
53 | return -EPROTO; | ||
54 | } | ||
55 | |||
56 | if ((cmd & DGM_CMD_BIT) == 0) { | ||
57 | if (cfpkt_extr_head(pkt, &dgmhdr, 3) < 0) { | ||
58 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
59 | cfpkt_destroy(pkt); | ||
60 | return -EPROTO; | ||
61 | } | ||
62 | ret = layr->up->receive(layr->up, pkt); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | switch (cmd) { | ||
67 | case DGM_FLOW_OFF: /* FLOW OFF */ | ||
68 | layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0); | ||
69 | cfpkt_destroy(pkt); | ||
70 | return 0; | ||
71 | case DGM_FLOW_ON: /* FLOW ON */ | ||
72 | layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0); | ||
73 | cfpkt_destroy(pkt); | ||
74 | return 0; | ||
75 | default: | ||
76 | cfpkt_destroy(pkt); | ||
77 | pr_info("CAIF: %s(): Unknown datagram control %d (0x%x)\n", | ||
78 | __func__, cmd, cmd); | ||
79 | return -EPROTO; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) | ||
84 | { | ||
85 | u32 zero = 0; | ||
86 | struct caif_payload_info *info; | ||
87 | struct cfsrvl *service = container_obj(layr); | ||
88 | int ret; | ||
89 | if (!cfsrvl_ready(service, &ret)) | ||
90 | return ret; | ||
91 | |||
92 | cfpkt_add_head(pkt, &zero, 4); | ||
93 | |||
94 | /* Add info for MUX-layer to route the packet out. */ | ||
95 | info = cfpkt_info(pkt); | ||
96 | info->channel_id = service->layer.id; | ||
97 | /* To optimize alignment, we add up the size of CAIF header | ||
98 | * before payload. | ||
99 | */ | ||
100 | info->hdr_len = 4; | ||
101 | info->dev_info = &service->dev_info; | ||
102 | ret = layr->dn->transmit(layr->dn, pkt); | ||
103 | if (ret < 0) { | ||
104 | u32 tmp32; | ||
105 | cfpkt_extr_head(pkt, &tmp32, 4); | ||
106 | } | ||
107 | return ret; | ||
108 | } | ||
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c new file mode 100644 index 000000000000..e86a4ca3b217 --- /dev/null +++ b/net/caif/cffrml.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * CAIF Framing Layer. | ||
3 | * | ||
4 | * Copyright (C) ST-Ericsson AB 2010 | ||
5 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
6 | * License terms: GNU General Public License (GPL) version 2 | ||
7 | */ | ||
8 | |||
9 | #include <linux/stddef.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/crc-ccitt.h> | ||
13 | #include <net/caif/caif_layer.h> | ||
14 | #include <net/caif/cfpkt.h> | ||
15 | #include <net/caif/cffrml.h> | ||
16 | |||
17 | #define container_obj(layr) container_of(layr, struct cffrml, layer) | ||
18 | |||
19 | struct cffrml { | ||
20 | struct cflayer layer; | ||
21 | bool dofcs; /* !< FCS active */ | ||
22 | }; | ||
23 | |||
24 | static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); | ||
25 | static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt); | ||
26 | static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
27 | int phyid); | ||
28 | |||
29 | static u32 cffrml_rcv_error; | ||
30 | static u32 cffrml_rcv_checsum_error; | ||
31 | struct cflayer *cffrml_create(u16 phyid, bool use_fcs) | ||
32 | { | ||
33 | struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC); | ||
34 | if (!this) { | ||
35 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
36 | return NULL; | ||
37 | } | ||
38 | caif_assert(offsetof(struct cffrml, layer) == 0); | ||
39 | |||
40 | memset(this, 0, sizeof(struct cflayer)); | ||
41 | this->layer.receive = cffrml_receive; | ||
42 | this->layer.transmit = cffrml_transmit; | ||
43 | this->layer.ctrlcmd = cffrml_ctrlcmd; | ||
44 | snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "frm%d", phyid); | ||
45 | this->dofcs = use_fcs; | ||
46 | this->layer.id = phyid; | ||
47 | return (struct cflayer *) this; | ||
48 | } | ||
49 | |||
50 | void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) | ||
51 | { | ||
52 | this->up = up; | ||
53 | } | ||
54 | |||
55 | void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn) | ||
56 | { | ||
57 | this->dn = dn; | ||
58 | } | ||
59 | |||
60 | static u16 cffrml_checksum(u16 chks, void *buf, u16 len) | ||
61 | { | ||
62 | /* FIXME: FCS should be moved to glue in order to use OS-Specific | ||
63 | * solutions | ||
64 | */ | ||
65 | return crc_ccitt(chks, buf, len); | ||
66 | } | ||
67 | |||
68 | static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) | ||
69 | { | ||
70 | u16 tmp; | ||
71 | u16 len; | ||
72 | u16 hdrchks; | ||
73 | u16 pktchks; | ||
74 | struct cffrml *this; | ||
75 | this = container_obj(layr); | ||
76 | |||
77 | cfpkt_extr_head(pkt, &tmp, 2); | ||
78 | len = le16_to_cpu(tmp); | ||
79 | |||
80 | /* Subtract for FCS on length if FCS is not used. */ | ||
81 | if (!this->dofcs) | ||
82 | len -= 2; | ||
83 | |||
84 | if (cfpkt_setlen(pkt, len) < 0) { | ||
85 | ++cffrml_rcv_error; | ||
86 | pr_err("CAIF: %s():Framing length error (%d)\n", __func__, len); | ||
87 | cfpkt_destroy(pkt); | ||
88 | return -EPROTO; | ||
89 | } | ||
90 | /* | ||
91 | * Don't do extract if FCS is false, rather do setlen - then we don't | ||
92 | * get a cache-miss. | ||
93 | */ | ||
94 | if (this->dofcs) { | ||
95 | cfpkt_extr_trail(pkt, &tmp, 2); | ||
96 | hdrchks = le16_to_cpu(tmp); | ||
97 | pktchks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); | ||
98 | if (pktchks != hdrchks) { | ||
99 | cfpkt_add_trail(pkt, &tmp, 2); | ||
100 | ++cffrml_rcv_error; | ||
101 | ++cffrml_rcv_checsum_error; | ||
102 | pr_info("CAIF: %s(): Frame checksum error " | ||
103 | "(0x%x != 0x%x)\n", __func__, hdrchks, pktchks); | ||
104 | return -EILSEQ; | ||
105 | } | ||
106 | } | ||
107 | if (cfpkt_erroneous(pkt)) { | ||
108 | ++cffrml_rcv_error; | ||
109 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
110 | cfpkt_destroy(pkt); | ||
111 | return -EPROTO; | ||
112 | } | ||
113 | return layr->up->receive(layr->up, pkt); | ||
114 | } | ||
115 | |||
116 | static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) | ||
117 | { | ||
118 | int tmp; | ||
119 | u16 chks; | ||
120 | u16 len; | ||
121 | int ret; | ||
122 | struct cffrml *this = container_obj(layr); | ||
123 | if (this->dofcs) { | ||
124 | chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); | ||
125 | tmp = cpu_to_le16(chks); | ||
126 | cfpkt_add_trail(pkt, &tmp, 2); | ||
127 | } else { | ||
128 | cfpkt_pad_trail(pkt, 2); | ||
129 | } | ||
130 | len = cfpkt_getlen(pkt); | ||
131 | tmp = cpu_to_le16(len); | ||
132 | cfpkt_add_head(pkt, &tmp, 2); | ||
133 | cfpkt_info(pkt)->hdr_len += 2; | ||
134 | if (cfpkt_erroneous(pkt)) { | ||
135 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
136 | return -EPROTO; | ||
137 | } | ||
138 | ret = layr->dn->transmit(layr->dn, pkt); | ||
139 | if (ret < 0) { | ||
140 | /* Remove header on faulty packet. */ | ||
141 | cfpkt_extr_head(pkt, &tmp, 2); | ||
142 | } | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
147 | int phyid) | ||
148 | { | ||
149 | if (layr->up->ctrlcmd) | ||
150 | layr->up->ctrlcmd(layr->up, ctrl, layr->id); | ||
151 | } | ||
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c new file mode 100644 index 000000000000..7372f27f1d32 --- /dev/null +++ b/net/caif/cfmuxl.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | #include <linux/stddef.h> | ||
7 | #include <linux/spinlock.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <net/caif/cfpkt.h> | ||
10 | #include <net/caif/cfmuxl.h> | ||
11 | #include <net/caif/cfsrvl.h> | ||
12 | #include <net/caif/cffrml.h> | ||
13 | |||
14 | #define container_obj(layr) container_of(layr, struct cfmuxl, layer) | ||
15 | |||
16 | #define CAIF_CTRL_CHANNEL 0 | ||
17 | #define UP_CACHE_SIZE 8 | ||
18 | #define DN_CACHE_SIZE 8 | ||
19 | |||
20 | struct cfmuxl { | ||
21 | struct cflayer layer; | ||
22 | struct list_head srvl_list; | ||
23 | struct list_head frml_list; | ||
24 | struct cflayer *up_cache[UP_CACHE_SIZE]; | ||
25 | struct cflayer *dn_cache[DN_CACHE_SIZE]; | ||
26 | /* | ||
27 | * Set when inserting or removing downwards layers. | ||
28 | */ | ||
29 | spinlock_t transmit_lock; | ||
30 | |||
31 | /* | ||
32 | * Set when inserting or removing upwards layers. | ||
33 | */ | ||
34 | spinlock_t receive_lock; | ||
35 | |||
36 | }; | ||
37 | |||
38 | static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt); | ||
39 | static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt); | ||
40 | static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
41 | int phyid); | ||
42 | static struct cflayer *get_up(struct cfmuxl *muxl, u16 id); | ||
43 | |||
44 | struct cflayer *cfmuxl_create(void) | ||
45 | { | ||
46 | struct cfmuxl *this = kmalloc(sizeof(struct cfmuxl), GFP_ATOMIC); | ||
47 | if (!this) | ||
48 | return NULL; | ||
49 | memset(this, 0, sizeof(*this)); | ||
50 | this->layer.receive = cfmuxl_receive; | ||
51 | this->layer.transmit = cfmuxl_transmit; | ||
52 | this->layer.ctrlcmd = cfmuxl_ctrlcmd; | ||
53 | INIT_LIST_HEAD(&this->srvl_list); | ||
54 | INIT_LIST_HEAD(&this->frml_list); | ||
55 | spin_lock_init(&this->transmit_lock); | ||
56 | spin_lock_init(&this->receive_lock); | ||
57 | snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "mux"); | ||
58 | return &this->layer; | ||
59 | } | ||
60 | |||
61 | int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid) | ||
62 | { | ||
63 | struct cfmuxl *muxl = container_obj(layr); | ||
64 | spin_lock(&muxl->receive_lock); | ||
65 | cfsrvl_get(up); | ||
66 | list_add(&up->node, &muxl->srvl_list); | ||
67 | spin_unlock(&muxl->receive_lock); | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | bool cfmuxl_is_phy_inuse(struct cflayer *layr, u8 phyid) | ||
72 | { | ||
73 | struct list_head *node; | ||
74 | struct cflayer *layer; | ||
75 | struct cfmuxl *muxl = container_obj(layr); | ||
76 | bool match = false; | ||
77 | spin_lock(&muxl->receive_lock); | ||
78 | |||
79 | list_for_each(node, &muxl->srvl_list) { | ||
80 | layer = list_entry(node, struct cflayer, node); | ||
81 | if (cfsrvl_phyid_match(layer, phyid)) { | ||
82 | match = true; | ||
83 | break; | ||
84 | } | ||
85 | |||
86 | } | ||
87 | spin_unlock(&muxl->receive_lock); | ||
88 | return match; | ||
89 | } | ||
90 | |||
91 | u8 cfmuxl_get_phyid(struct cflayer *layr, u8 channel_id) | ||
92 | { | ||
93 | struct cflayer *up; | ||
94 | int phyid; | ||
95 | struct cfmuxl *muxl = container_obj(layr); | ||
96 | spin_lock(&muxl->receive_lock); | ||
97 | up = get_up(muxl, channel_id); | ||
98 | if (up != NULL) | ||
99 | phyid = cfsrvl_getphyid(up); | ||
100 | else | ||
101 | phyid = 0; | ||
102 | spin_unlock(&muxl->receive_lock); | ||
103 | return phyid; | ||
104 | } | ||
105 | |||
106 | int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *dn, u8 phyid) | ||
107 | { | ||
108 | struct cfmuxl *muxl = (struct cfmuxl *) layr; | ||
109 | spin_lock(&muxl->transmit_lock); | ||
110 | list_add(&dn->node, &muxl->frml_list); | ||
111 | spin_unlock(&muxl->transmit_lock); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static struct cflayer *get_from_id(struct list_head *list, u16 id) | ||
116 | { | ||
117 | struct list_head *node; | ||
118 | struct cflayer *layer; | ||
119 | list_for_each(node, list) { | ||
120 | layer = list_entry(node, struct cflayer, node); | ||
121 | if (layer->id == id) | ||
122 | return layer; | ||
123 | } | ||
124 | return NULL; | ||
125 | } | ||
126 | |||
127 | struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid) | ||
128 | { | ||
129 | struct cfmuxl *muxl = container_obj(layr); | ||
130 | struct cflayer *dn; | ||
131 | spin_lock(&muxl->transmit_lock); | ||
132 | memset(muxl->dn_cache, 0, sizeof(muxl->dn_cache)); | ||
133 | dn = get_from_id(&muxl->frml_list, phyid); | ||
134 | if (dn == NULL) { | ||
135 | spin_unlock(&muxl->transmit_lock); | ||
136 | return NULL; | ||
137 | } | ||
138 | list_del(&dn->node); | ||
139 | caif_assert(dn != NULL); | ||
140 | spin_unlock(&muxl->transmit_lock); | ||
141 | return dn; | ||
142 | } | ||
143 | |||
144 | /* Invariant: lock is taken */ | ||
145 | static struct cflayer *get_up(struct cfmuxl *muxl, u16 id) | ||
146 | { | ||
147 | struct cflayer *up; | ||
148 | int idx = id % UP_CACHE_SIZE; | ||
149 | up = muxl->up_cache[idx]; | ||
150 | if (up == NULL || up->id != id) { | ||
151 | up = get_from_id(&muxl->srvl_list, id); | ||
152 | muxl->up_cache[idx] = up; | ||
153 | } | ||
154 | return up; | ||
155 | } | ||
156 | |||
157 | /* Invariant: lock is taken */ | ||
158 | static struct cflayer *get_dn(struct cfmuxl *muxl, struct dev_info *dev_info) | ||
159 | { | ||
160 | struct cflayer *dn; | ||
161 | int idx = dev_info->id % DN_CACHE_SIZE; | ||
162 | dn = muxl->dn_cache[idx]; | ||
163 | if (dn == NULL || dn->id != dev_info->id) { | ||
164 | dn = get_from_id(&muxl->frml_list, dev_info->id); | ||
165 | muxl->dn_cache[idx] = dn; | ||
166 | } | ||
167 | return dn; | ||
168 | } | ||
169 | |||
170 | struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id) | ||
171 | { | ||
172 | struct cflayer *up; | ||
173 | struct cfmuxl *muxl = container_obj(layr); | ||
174 | spin_lock(&muxl->receive_lock); | ||
175 | up = get_up(muxl, id); | ||
176 | if (up == NULL) | ||
177 | return NULL; | ||
178 | memset(muxl->up_cache, 0, sizeof(muxl->up_cache)); | ||
179 | list_del(&up->node); | ||
180 | cfsrvl_put(up); | ||
181 | spin_unlock(&muxl->receive_lock); | ||
182 | return up; | ||
183 | } | ||
184 | |||
185 | static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt) | ||
186 | { | ||
187 | int ret; | ||
188 | struct cfmuxl *muxl = container_obj(layr); | ||
189 | u8 id; | ||
190 | struct cflayer *up; | ||
191 | if (cfpkt_extr_head(pkt, &id, 1) < 0) { | ||
192 | pr_err("CAIF: %s(): erroneous Caif Packet\n", __func__); | ||
193 | cfpkt_destroy(pkt); | ||
194 | return -EPROTO; | ||
195 | } | ||
196 | |||
197 | spin_lock(&muxl->receive_lock); | ||
198 | up = get_up(muxl, id); | ||
199 | spin_unlock(&muxl->receive_lock); | ||
200 | if (up == NULL) { | ||
201 | pr_info("CAIF: %s():Received data on unknown link ID = %d " | ||
202 | "(0x%x) up == NULL", __func__, id, id); | ||
203 | cfpkt_destroy(pkt); | ||
204 | /* | ||
205 | * Don't return ERROR, since modem misbehaves and sends out | ||
206 | * flow on before linksetup response. | ||
207 | */ | ||
208 | return /* CFGLU_EPROT; */ 0; | ||
209 | } | ||
210 | cfsrvl_get(up); | ||
211 | ret = up->receive(up, pkt); | ||
212 | cfsrvl_put(up); | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt) | ||
217 | { | ||
218 | int ret; | ||
219 | struct cfmuxl *muxl = container_obj(layr); | ||
220 | u8 linkid; | ||
221 | struct cflayer *dn; | ||
222 | struct caif_payload_info *info = cfpkt_info(pkt); | ||
223 | dn = get_dn(muxl, cfpkt_info(pkt)->dev_info); | ||
224 | if (dn == NULL) { | ||
225 | pr_warning("CAIF: %s(): Send data on unknown phy " | ||
226 | "ID = %d (0x%x)\n", | ||
227 | __func__, info->dev_info->id, info->dev_info->id); | ||
228 | return -ENOTCONN; | ||
229 | } | ||
230 | info->hdr_len += 1; | ||
231 | linkid = info->channel_id; | ||
232 | cfpkt_add_head(pkt, &linkid, 1); | ||
233 | ret = dn->transmit(dn, pkt); | ||
234 | /* Remove MUX protocol header upon error. */ | ||
235 | if (ret < 0) | ||
236 | cfpkt_extr_head(pkt, &linkid, 1); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
241 | int phyid) | ||
242 | { | ||
243 | struct cfmuxl *muxl = container_obj(layr); | ||
244 | struct list_head *node; | ||
245 | struct cflayer *layer; | ||
246 | list_for_each(node, &muxl->srvl_list) { | ||
247 | layer = list_entry(node, struct cflayer, node); | ||
248 | if (cfsrvl_phyid_match(layer, phyid)) | ||
249 | layer->ctrlcmd(layer, ctrl, phyid); | ||
250 | } | ||
251 | } | ||
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c new file mode 100644 index 000000000000..83fff2ff6658 --- /dev/null +++ b/net/caif/cfpkt_skbuff.c | |||
@@ -0,0 +1,571 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/string.h> | ||
8 | #include <linux/skbuff.h> | ||
9 | #include <linux/hardirq.h> | ||
10 | #include <net/caif/cfpkt.h> | ||
11 | |||
12 | #define PKT_PREFIX CAIF_NEEDED_HEADROOM | ||
13 | #define PKT_POSTFIX CAIF_NEEDED_TAILROOM | ||
14 | #define PKT_LEN_WHEN_EXTENDING 128 | ||
15 | #define PKT_ERROR(pkt, errmsg) do { \ | ||
16 | cfpkt_priv(pkt)->erronous = true; \ | ||
17 | skb_reset_tail_pointer(&pkt->skb); \ | ||
18 | pr_warning("CAIF: " errmsg);\ | ||
19 | } while (0) | ||
20 | |||
21 | struct cfpktq { | ||
22 | struct sk_buff_head head; | ||
23 | atomic_t count; | ||
24 | /* Lock protects count updates */ | ||
25 | spinlock_t lock; | ||
26 | }; | ||
27 | |||
28 | /* | ||
29 | * net/caif/ is generic and does not | ||
30 | * understand SKB, so we do this typecast | ||
31 | */ | ||
32 | struct cfpkt { | ||
33 | struct sk_buff skb; | ||
34 | }; | ||
35 | |||
36 | /* Private data inside SKB */ | ||
37 | struct cfpkt_priv_data { | ||
38 | struct dev_info dev_info; | ||
39 | bool erronous; | ||
40 | }; | ||
41 | |||
42 | inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) | ||
43 | { | ||
44 | return (struct cfpkt_priv_data *) pkt->skb.cb; | ||
45 | } | ||
46 | |||
47 | inline bool is_erronous(struct cfpkt *pkt) | ||
48 | { | ||
49 | return cfpkt_priv(pkt)->erronous; | ||
50 | } | ||
51 | |||
52 | inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) | ||
53 | { | ||
54 | return &pkt->skb; | ||
55 | } | ||
56 | |||
57 | inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) | ||
58 | { | ||
59 | return (struct cfpkt *) skb; | ||
60 | } | ||
61 | |||
62 | |||
63 | struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt) | ||
64 | { | ||
65 | struct cfpkt *pkt = skb_to_pkt(nativepkt); | ||
66 | cfpkt_priv(pkt)->erronous = false; | ||
67 | return pkt; | ||
68 | } | ||
69 | EXPORT_SYMBOL(cfpkt_fromnative); | ||
70 | |||
71 | void *cfpkt_tonative(struct cfpkt *pkt) | ||
72 | { | ||
73 | return (void *) pkt; | ||
74 | } | ||
75 | EXPORT_SYMBOL(cfpkt_tonative); | ||
76 | |||
77 | static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx) | ||
78 | { | ||
79 | struct sk_buff *skb; | ||
80 | |||
81 | if (likely(in_interrupt())) | ||
82 | skb = alloc_skb(len + pfx, GFP_ATOMIC); | ||
83 | else | ||
84 | skb = alloc_skb(len + pfx, GFP_KERNEL); | ||
85 | |||
86 | if (unlikely(skb == NULL)) | ||
87 | return NULL; | ||
88 | |||
89 | skb_reserve(skb, pfx); | ||
90 | return skb_to_pkt(skb); | ||
91 | } | ||
92 | |||
93 | inline struct cfpkt *cfpkt_create(u16 len) | ||
94 | { | ||
95 | return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); | ||
96 | } | ||
97 | EXPORT_SYMBOL(cfpkt_create); | ||
98 | |||
99 | void cfpkt_destroy(struct cfpkt *pkt) | ||
100 | { | ||
101 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
102 | kfree_skb(skb); | ||
103 | } | ||
104 | EXPORT_SYMBOL(cfpkt_destroy); | ||
105 | |||
106 | inline bool cfpkt_more(struct cfpkt *pkt) | ||
107 | { | ||
108 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
109 | return skb->len > 0; | ||
110 | } | ||
111 | EXPORT_SYMBOL(cfpkt_more); | ||
112 | |||
113 | int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) | ||
114 | { | ||
115 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
116 | if (skb_headlen(skb) >= len) { | ||
117 | memcpy(data, skb->data, len); | ||
118 | return 0; | ||
119 | } | ||
120 | return !cfpkt_extr_head(pkt, data, len) && | ||
121 | !cfpkt_add_head(pkt, data, len); | ||
122 | } | ||
123 | EXPORT_SYMBOL(cfpkt_peek_head); | ||
124 | |||
125 | int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) | ||
126 | { | ||
127 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
128 | u8 *from; | ||
129 | if (unlikely(is_erronous(pkt))) | ||
130 | return -EPROTO; | ||
131 | |||
132 | if (unlikely(len > skb->len)) { | ||
133 | PKT_ERROR(pkt, "cfpkt_extr_head read beyond end of packet\n"); | ||
134 | return -EPROTO; | ||
135 | } | ||
136 | |||
137 | if (unlikely(len > skb_headlen(skb))) { | ||
138 | if (unlikely(skb_linearize(skb) != 0)) { | ||
139 | PKT_ERROR(pkt, "cfpkt_extr_head linearize failed\n"); | ||
140 | return -EPROTO; | ||
141 | } | ||
142 | } | ||
143 | from = skb_pull(skb, len); | ||
144 | from -= len; | ||
145 | memcpy(data, from, len); | ||
146 | return 0; | ||
147 | } | ||
148 | EXPORT_SYMBOL(cfpkt_extr_head); | ||
149 | |||
150 | int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) | ||
151 | { | ||
152 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
153 | u8 *data = dta; | ||
154 | u8 *from; | ||
155 | if (unlikely(is_erronous(pkt))) | ||
156 | return -EPROTO; | ||
157 | |||
158 | if (unlikely(skb_linearize(skb) != 0)) { | ||
159 | PKT_ERROR(pkt, "cfpkt_extr_trail linearize failed\n"); | ||
160 | return -EPROTO; | ||
161 | } | ||
162 | if (unlikely(skb->data + len > skb_tail_pointer(skb))) { | ||
163 | PKT_ERROR(pkt, "cfpkt_extr_trail read beyond end of packet\n"); | ||
164 | return -EPROTO; | ||
165 | } | ||
166 | from = skb_tail_pointer(skb) - len; | ||
167 | skb_trim(skb, skb->len - len); | ||
168 | memcpy(data, from, len); | ||
169 | return 0; | ||
170 | } | ||
171 | EXPORT_SYMBOL(cfpkt_extr_trail); | ||
172 | |||
173 | int cfpkt_pad_trail(struct cfpkt *pkt, u16 len) | ||
174 | { | ||
175 | return cfpkt_add_body(pkt, NULL, len); | ||
176 | } | ||
177 | EXPORT_SYMBOL(cfpkt_pad_trail); | ||
178 | |||
179 | int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) | ||
180 | { | ||
181 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
182 | struct sk_buff *lastskb; | ||
183 | u8 *to; | ||
184 | u16 addlen = 0; | ||
185 | |||
186 | |||
187 | if (unlikely(is_erronous(pkt))) | ||
188 | return -EPROTO; | ||
189 | |||
190 | lastskb = skb; | ||
191 | |||
192 | /* Check whether we need to add space at the tail */ | ||
193 | if (unlikely(skb_tailroom(skb) < len)) { | ||
194 | if (likely(len < PKT_LEN_WHEN_EXTENDING)) | ||
195 | addlen = PKT_LEN_WHEN_EXTENDING; | ||
196 | else | ||
197 | addlen = len; | ||
198 | } | ||
199 | |||
200 | /* Check whether we need to change the SKB before writing to the tail */ | ||
201 | if (unlikely((addlen > 0) || skb_cloned(skb) || skb_shared(skb))) { | ||
202 | |||
203 | /* Make sure data is writable */ | ||
204 | if (unlikely(skb_cow_data(skb, addlen, &lastskb) < 0)) { | ||
205 | PKT_ERROR(pkt, "cfpkt_add_body: cow failed\n"); | ||
206 | return -EPROTO; | ||
207 | } | ||
208 | /* | ||
209 | * Is the SKB non-linear after skb_cow_data()? If so, we are | ||
210 | * going to add data to the last SKB, so we need to adjust | ||
211 | * lengths of the top SKB. | ||
212 | */ | ||
213 | if (lastskb != skb) { | ||
214 | pr_warning("CAIF: %s(): Packet is non-linear\n", | ||
215 | __func__); | ||
216 | skb->len += len; | ||
217 | skb->data_len += len; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | /* All set to put the last SKB and optionally write data there. */ | ||
222 | to = skb_put(lastskb, len); | ||
223 | if (likely(data)) | ||
224 | memcpy(to, data, len); | ||
225 | return 0; | ||
226 | } | ||
227 | EXPORT_SYMBOL(cfpkt_add_body); | ||
228 | |||
229 | inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data) | ||
230 | { | ||
231 | return cfpkt_add_body(pkt, &data, 1); | ||
232 | } | ||
233 | EXPORT_SYMBOL(cfpkt_addbdy); | ||
234 | |||
235 | int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) | ||
236 | { | ||
237 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
238 | struct sk_buff *lastskb; | ||
239 | u8 *to; | ||
240 | const u8 *data = data2; | ||
241 | if (unlikely(is_erronous(pkt))) | ||
242 | return -EPROTO; | ||
243 | if (unlikely(skb_headroom(skb) < len)) { | ||
244 | PKT_ERROR(pkt, "cfpkt_add_head: no headroom\n"); | ||
245 | return -EPROTO; | ||
246 | } | ||
247 | |||
248 | /* Make sure data is writable */ | ||
249 | if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) { | ||
250 | PKT_ERROR(pkt, "cfpkt_add_head: cow failed\n"); | ||
251 | return -EPROTO; | ||
252 | } | ||
253 | |||
254 | to = skb_push(skb, len); | ||
255 | memcpy(to, data, len); | ||
256 | return 0; | ||
257 | } | ||
258 | EXPORT_SYMBOL(cfpkt_add_head); | ||
259 | |||
260 | inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len) | ||
261 | { | ||
262 | return cfpkt_add_body(pkt, data, len); | ||
263 | } | ||
264 | EXPORT_SYMBOL(cfpkt_add_trail); | ||
265 | |||
266 | inline u16 cfpkt_getlen(struct cfpkt *pkt) | ||
267 | { | ||
268 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
269 | return skb->len; | ||
270 | } | ||
271 | EXPORT_SYMBOL(cfpkt_getlen); | ||
272 | |||
273 | inline u16 cfpkt_iterate(struct cfpkt *pkt, | ||
274 | u16 (*iter_func)(u16, void *, u16), | ||
275 | u16 data) | ||
276 | { | ||
277 | /* | ||
278 | * Don't care about the performance hit of linearizing, | ||
279 | * Checksum should not be used on high-speed interfaces anyway. | ||
280 | */ | ||
281 | if (unlikely(is_erronous(pkt))) | ||
282 | return -EPROTO; | ||
283 | if (unlikely(skb_linearize(&pkt->skb) != 0)) { | ||
284 | PKT_ERROR(pkt, "cfpkt_iterate: linearize failed\n"); | ||
285 | return -EPROTO; | ||
286 | } | ||
287 | return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt)); | ||
288 | } | ||
289 | EXPORT_SYMBOL(cfpkt_iterate); | ||
290 | |||
291 | int cfpkt_setlen(struct cfpkt *pkt, u16 len) | ||
292 | { | ||
293 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
294 | |||
295 | |||
296 | if (unlikely(is_erronous(pkt))) | ||
297 | return -EPROTO; | ||
298 | |||
299 | if (likely(len <= skb->len)) { | ||
300 | if (unlikely(skb->data_len)) | ||
301 | ___pskb_trim(skb, len); | ||
302 | else | ||
303 | skb_trim(skb, len); | ||
304 | |||
305 | return cfpkt_getlen(pkt); | ||
306 | } | ||
307 | |||
308 | /* Need to expand SKB */ | ||
309 | if (unlikely(!cfpkt_pad_trail(pkt, len - skb->len))) | ||
310 | PKT_ERROR(pkt, "cfpkt_setlen: skb_pad_trail failed\n"); | ||
311 | |||
312 | return cfpkt_getlen(pkt); | ||
313 | } | ||
314 | EXPORT_SYMBOL(cfpkt_setlen); | ||
315 | |||
316 | struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len) | ||
317 | { | ||
318 | struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); | ||
319 | if (unlikely(data != NULL)) | ||
320 | cfpkt_add_body(pkt, data, len); | ||
321 | return pkt; | ||
322 | } | ||
323 | EXPORT_SYMBOL(cfpkt_create_uplink); | ||
324 | |||
325 | struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, | ||
326 | struct cfpkt *addpkt, | ||
327 | u16 expectlen) | ||
328 | { | ||
329 | struct sk_buff *dst = pkt_to_skb(dstpkt); | ||
330 | struct sk_buff *add = pkt_to_skb(addpkt); | ||
331 | u16 addlen = skb_headlen(add); | ||
332 | u16 neededtailspace; | ||
333 | struct sk_buff *tmp; | ||
334 | u16 dstlen; | ||
335 | u16 createlen; | ||
336 | if (unlikely(is_erronous(dstpkt) || is_erronous(addpkt))) { | ||
337 | cfpkt_destroy(addpkt); | ||
338 | return dstpkt; | ||
339 | } | ||
340 | if (expectlen > addlen) | ||
341 | neededtailspace = expectlen; | ||
342 | else | ||
343 | neededtailspace = addlen; | ||
344 | |||
345 | if (dst->tail + neededtailspace > dst->end) { | ||
346 | /* Create a dumplicate of 'dst' with more tail space */ | ||
347 | dstlen = skb_headlen(dst); | ||
348 | createlen = dstlen + neededtailspace; | ||
349 | tmp = pkt_to_skb( | ||
350 | cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX)); | ||
351 | if (!tmp) | ||
352 | return NULL; | ||
353 | skb_set_tail_pointer(tmp, dstlen); | ||
354 | tmp->len = dstlen; | ||
355 | memcpy(tmp->data, dst->data, dstlen); | ||
356 | cfpkt_destroy(dstpkt); | ||
357 | dst = tmp; | ||
358 | } | ||
359 | memcpy(skb_tail_pointer(dst), add->data, skb_headlen(add)); | ||
360 | cfpkt_destroy(addpkt); | ||
361 | dst->tail += addlen; | ||
362 | dst->len += addlen; | ||
363 | return skb_to_pkt(dst); | ||
364 | } | ||
365 | EXPORT_SYMBOL(cfpkt_append); | ||
366 | |||
367 | struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) | ||
368 | { | ||
369 | struct sk_buff *skb2; | ||
370 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
371 | u8 *split = skb->data + pos; | ||
372 | u16 len2nd = skb_tail_pointer(skb) - split; | ||
373 | |||
374 | if (unlikely(is_erronous(pkt))) | ||
375 | return NULL; | ||
376 | |||
377 | if (skb->data + pos > skb_tail_pointer(skb)) { | ||
378 | PKT_ERROR(pkt, | ||
379 | "cfpkt_split: trying to split beyond end of packet"); | ||
380 | return NULL; | ||
381 | } | ||
382 | |||
383 | /* Create a new packet for the second part of the data */ | ||
384 | skb2 = pkt_to_skb( | ||
385 | cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX, | ||
386 | PKT_PREFIX)); | ||
387 | |||
388 | if (skb2 == NULL) | ||
389 | return NULL; | ||
390 | |||
391 | /* Reduce the length of the original packet */ | ||
392 | skb_set_tail_pointer(skb, pos); | ||
393 | skb->len = pos; | ||
394 | |||
395 | memcpy(skb2->data, split, len2nd); | ||
396 | skb2->tail += len2nd; | ||
397 | skb2->len += len2nd; | ||
398 | return skb_to_pkt(skb2); | ||
399 | } | ||
400 | EXPORT_SYMBOL(cfpkt_split); | ||
401 | |||
402 | char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen) | ||
403 | { | ||
404 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
405 | char *p = buf; | ||
406 | int i; | ||
407 | |||
408 | /* | ||
409 | * Sanity check buffer length, it needs to be at least as large as | ||
410 | * the header info: ~=50+ bytes | ||
411 | */ | ||
412 | if (buflen < 50) | ||
413 | return NULL; | ||
414 | |||
415 | snprintf(buf, buflen, "%s: pkt:%p len:%ld(%ld+%ld) {%ld,%ld} data: [", | ||
416 | is_erronous(pkt) ? "ERRONOUS-SKB" : | ||
417 | (skb->data_len != 0 ? "COMPLEX-SKB" : "SKB"), | ||
418 | skb, | ||
419 | (long) skb->len, | ||
420 | (long) (skb_tail_pointer(skb) - skb->data), | ||
421 | (long) skb->data_len, | ||
422 | (long) (skb->data - skb->head), | ||
423 | (long) (skb_tail_pointer(skb) - skb->head)); | ||
424 | p = buf + strlen(buf); | ||
425 | |||
426 | for (i = 0; i < skb_tail_pointer(skb) - skb->data && i < 300; i++) { | ||
427 | if (p > buf + buflen - 10) { | ||
428 | sprintf(p, "..."); | ||
429 | p = buf + strlen(buf); | ||
430 | break; | ||
431 | } | ||
432 | sprintf(p, "%02x,", skb->data[i]); | ||
433 | p = buf + strlen(buf); | ||
434 | } | ||
435 | sprintf(p, "]\n"); | ||
436 | return buf; | ||
437 | } | ||
438 | EXPORT_SYMBOL(cfpkt_log_pkt); | ||
439 | |||
440 | int cfpkt_raw_append(struct cfpkt *pkt, void **buf, unsigned int buflen) | ||
441 | { | ||
442 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
443 | struct sk_buff *lastskb; | ||
444 | |||
445 | caif_assert(buf != NULL); | ||
446 | if (unlikely(is_erronous(pkt))) | ||
447 | return -EPROTO; | ||
448 | /* Make sure SKB is writable */ | ||
449 | if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) { | ||
450 | PKT_ERROR(pkt, "cfpkt_raw_append: skb_cow_data failed\n"); | ||
451 | return -EPROTO; | ||
452 | } | ||
453 | |||
454 | if (unlikely(skb_linearize(skb) != 0)) { | ||
455 | PKT_ERROR(pkt, "cfpkt_raw_append: linearize failed\n"); | ||
456 | return -EPROTO; | ||
457 | } | ||
458 | |||
459 | if (unlikely(skb_tailroom(skb) < buflen)) { | ||
460 | PKT_ERROR(pkt, "cfpkt_raw_append: buffer too short - failed\n"); | ||
461 | return -EPROTO; | ||
462 | } | ||
463 | |||
464 | *buf = skb_put(skb, buflen); | ||
465 | return 1; | ||
466 | } | ||
467 | EXPORT_SYMBOL(cfpkt_raw_append); | ||
468 | |||
469 | int cfpkt_raw_extract(struct cfpkt *pkt, void **buf, unsigned int buflen) | ||
470 | { | ||
471 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
472 | |||
473 | caif_assert(buf != NULL); | ||
474 | if (unlikely(is_erronous(pkt))) | ||
475 | return -EPROTO; | ||
476 | |||
477 | if (unlikely(buflen > skb->len)) { | ||
478 | PKT_ERROR(pkt, "cfpkt_raw_extract: buflen too large " | ||
479 | "- failed\n"); | ||
480 | return -EPROTO; | ||
481 | } | ||
482 | |||
483 | if (unlikely(buflen > skb_headlen(skb))) { | ||
484 | if (unlikely(skb_linearize(skb) != 0)) { | ||
485 | PKT_ERROR(pkt, "cfpkt_raw_extract: linearize failed\n"); | ||
486 | return -EPROTO; | ||
487 | } | ||
488 | } | ||
489 | |||
490 | *buf = skb->data; | ||
491 | skb_pull(skb, buflen); | ||
492 | |||
493 | return 1; | ||
494 | } | ||
495 | EXPORT_SYMBOL(cfpkt_raw_extract); | ||
496 | |||
497 | inline bool cfpkt_erroneous(struct cfpkt *pkt) | ||
498 | { | ||
499 | return cfpkt_priv(pkt)->erronous; | ||
500 | } | ||
501 | EXPORT_SYMBOL(cfpkt_erroneous); | ||
502 | |||
503 | struct cfpktq *cfpktq_create(void) | ||
504 | { | ||
505 | struct cfpktq *q = kmalloc(sizeof(struct cfpktq), GFP_ATOMIC); | ||
506 | if (!q) | ||
507 | return NULL; | ||
508 | skb_queue_head_init(&q->head); | ||
509 | atomic_set(&q->count, 0); | ||
510 | spin_lock_init(&q->lock); | ||
511 | return q; | ||
512 | } | ||
513 | EXPORT_SYMBOL(cfpktq_create); | ||
514 | |||
515 | void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, unsigned short prio) | ||
516 | { | ||
517 | atomic_inc(&pktq->count); | ||
518 | spin_lock(&pktq->lock); | ||
519 | skb_queue_tail(&pktq->head, pkt_to_skb(pkt)); | ||
520 | spin_unlock(&pktq->lock); | ||
521 | |||
522 | } | ||
523 | EXPORT_SYMBOL(cfpkt_queue); | ||
524 | |||
525 | struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq) | ||
526 | { | ||
527 | struct cfpkt *tmp; | ||
528 | spin_lock(&pktq->lock); | ||
529 | tmp = skb_to_pkt(skb_peek(&pktq->head)); | ||
530 | spin_unlock(&pktq->lock); | ||
531 | return tmp; | ||
532 | } | ||
533 | EXPORT_SYMBOL(cfpkt_qpeek); | ||
534 | |||
535 | struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq) | ||
536 | { | ||
537 | struct cfpkt *pkt; | ||
538 | spin_lock(&pktq->lock); | ||
539 | pkt = skb_to_pkt(skb_dequeue(&pktq->head)); | ||
540 | if (pkt) { | ||
541 | atomic_dec(&pktq->count); | ||
542 | caif_assert(atomic_read(&pktq->count) >= 0); | ||
543 | } | ||
544 | spin_unlock(&pktq->lock); | ||
545 | return pkt; | ||
546 | } | ||
547 | EXPORT_SYMBOL(cfpkt_dequeue); | ||
548 | |||
549 | int cfpkt_qcount(struct cfpktq *pktq) | ||
550 | { | ||
551 | return atomic_read(&pktq->count); | ||
552 | } | ||
553 | EXPORT_SYMBOL(cfpkt_qcount); | ||
554 | |||
555 | struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt) | ||
556 | { | ||
557 | struct cfpkt *clone; | ||
558 | clone = skb_to_pkt(skb_clone(pkt_to_skb(pkt), GFP_ATOMIC)); | ||
559 | /* Free original packet. */ | ||
560 | cfpkt_destroy(pkt); | ||
561 | if (!clone) | ||
562 | return NULL; | ||
563 | return clone; | ||
564 | } | ||
565 | EXPORT_SYMBOL(cfpkt_clone_release); | ||
566 | |||
567 | struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) | ||
568 | { | ||
569 | return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb; | ||
570 | } | ||
571 | EXPORT_SYMBOL(cfpkt_info); | ||
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c new file mode 100644 index 000000000000..cd2830fec935 --- /dev/null +++ b/net/caif/cfrfml.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/stddef.h> | ||
8 | #include <linux/spinlock.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <net/caif/caif_layer.h> | ||
11 | #include <net/caif/cfsrvl.h> | ||
12 | #include <net/caif/cfpkt.h> | ||
13 | |||
14 | #define container_obj(layr) container_of(layr, struct cfsrvl, layer) | ||
15 | |||
16 | #define RFM_SEGMENTATION_BIT 0x01 | ||
17 | #define RFM_PAYLOAD 0x00 | ||
18 | #define RFM_CMD_BIT 0x80 | ||
19 | #define RFM_FLOW_OFF 0x81 | ||
20 | #define RFM_FLOW_ON 0x80 | ||
21 | #define RFM_SET_PIN 0x82 | ||
22 | #define RFM_CTRL_PKT_SIZE 1 | ||
23 | |||
24 | static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt); | ||
25 | static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt); | ||
26 | static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl); | ||
27 | |||
28 | struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info) | ||
29 | { | ||
30 | struct cfsrvl *rfm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC); | ||
31 | if (!rfm) { | ||
32 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
33 | return NULL; | ||
34 | } | ||
35 | caif_assert(offsetof(struct cfsrvl, layer) == 0); | ||
36 | memset(rfm, 0, sizeof(struct cfsrvl)); | ||
37 | cfsrvl_init(rfm, channel_id, dev_info); | ||
38 | rfm->layer.modemcmd = cfservl_modemcmd; | ||
39 | rfm->layer.receive = cfrfml_receive; | ||
40 | rfm->layer.transmit = cfrfml_transmit; | ||
41 | snprintf(rfm->layer.name, CAIF_LAYER_NAME_SZ, "rfm%d", channel_id); | ||
42 | return &rfm->layer; | ||
43 | } | ||
44 | |||
45 | static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) | ||
46 | { | ||
47 | return -EPROTO; | ||
48 | } | ||
49 | |||
50 | static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt) | ||
51 | { | ||
52 | u8 tmp; | ||
53 | bool segmented; | ||
54 | int ret; | ||
55 | caif_assert(layr->up != NULL); | ||
56 | caif_assert(layr->receive != NULL); | ||
57 | |||
58 | /* | ||
59 | * RFM is taking care of segmentation and stripping of | ||
60 | * segmentation bit. | ||
61 | */ | ||
62 | if (cfpkt_extr_head(pkt, &tmp, 1) < 0) { | ||
63 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
64 | cfpkt_destroy(pkt); | ||
65 | return -EPROTO; | ||
66 | } | ||
67 | segmented = tmp & RFM_SEGMENTATION_BIT; | ||
68 | caif_assert(!segmented); | ||
69 | |||
70 | ret = layr->up->receive(layr->up, pkt); | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt) | ||
75 | { | ||
76 | u8 tmp = 0; | ||
77 | int ret; | ||
78 | struct cfsrvl *service = container_obj(layr); | ||
79 | |||
80 | caif_assert(layr->dn != NULL); | ||
81 | caif_assert(layr->dn->transmit != NULL); | ||
82 | |||
83 | if (!cfsrvl_ready(service, &ret)) | ||
84 | return ret; | ||
85 | |||
86 | if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { | ||
87 | pr_err("CAIF: %s():Packet too large - size=%d\n", | ||
88 | __func__, cfpkt_getlen(pkt)); | ||
89 | return -EOVERFLOW; | ||
90 | } | ||
91 | if (cfpkt_add_head(pkt, &tmp, 1) < 0) { | ||
92 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
93 | return -EPROTO; | ||
94 | } | ||
95 | |||
96 | /* Add info for MUX-layer to route the packet out. */ | ||
97 | cfpkt_info(pkt)->channel_id = service->layer.id; | ||
98 | /* | ||
99 | * To optimize alignment, we add up the size of CAIF header before | ||
100 | * payload. | ||
101 | */ | ||
102 | cfpkt_info(pkt)->hdr_len = 1; | ||
103 | cfpkt_info(pkt)->dev_info = &service->dev_info; | ||
104 | ret = layr->dn->transmit(layr->dn, pkt); | ||
105 | if (ret < 0) | ||
106 | cfpkt_extr_head(pkt, &tmp, 1); | ||
107 | return ret; | ||
108 | } | ||
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c new file mode 100644 index 000000000000..06029ea2da2f --- /dev/null +++ b/net/caif/cfserl.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/stddef.h> | ||
8 | #include <linux/spinlock.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <net/caif/caif_layer.h> | ||
11 | #include <net/caif/cfpkt.h> | ||
12 | #include <net/caif/cfserl.h> | ||
13 | |||
14 | #define container_obj(layr) ((struct cfserl *) layr) | ||
15 | |||
16 | #define CFSERL_STX 0x02 | ||
17 | #define CAIF_MINIUM_PACKET_SIZE 4 | ||
18 | struct cfserl { | ||
19 | struct cflayer layer; | ||
20 | struct cfpkt *incomplete_frm; | ||
21 | /* Protects parallel processing of incoming packets */ | ||
22 | spinlock_t sync; | ||
23 | bool usestx; | ||
24 | }; | ||
25 | #define STXLEN(layr) (layr->usestx ? 1 : 0) | ||
26 | |||
27 | static int cfserl_receive(struct cflayer *layr, struct cfpkt *pkt); | ||
28 | static int cfserl_transmit(struct cflayer *layr, struct cfpkt *pkt); | ||
29 | static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
30 | int phyid); | ||
31 | |||
32 | struct cflayer *cfserl_create(int type, int instance, bool use_stx) | ||
33 | { | ||
34 | struct cfserl *this = kmalloc(sizeof(struct cfserl), GFP_ATOMIC); | ||
35 | if (!this) { | ||
36 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
37 | return NULL; | ||
38 | } | ||
39 | caif_assert(offsetof(struct cfserl, layer) == 0); | ||
40 | memset(this, 0, sizeof(struct cfserl)); | ||
41 | this->layer.receive = cfserl_receive; | ||
42 | this->layer.transmit = cfserl_transmit; | ||
43 | this->layer.ctrlcmd = cfserl_ctrlcmd; | ||
44 | this->layer.type = type; | ||
45 | this->usestx = use_stx; | ||
46 | spin_lock_init(&this->sync); | ||
47 | snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "ser1"); | ||
48 | return &this->layer; | ||
49 | } | ||
50 | |||
51 | static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt) | ||
52 | { | ||
53 | struct cfserl *layr = container_obj(l); | ||
54 | u16 pkt_len; | ||
55 | struct cfpkt *pkt = NULL; | ||
56 | struct cfpkt *tail_pkt = NULL; | ||
57 | u8 tmp8; | ||
58 | u16 tmp; | ||
59 | u8 stx = CFSERL_STX; | ||
60 | int ret; | ||
61 | u16 expectlen = 0; | ||
62 | caif_assert(newpkt != NULL); | ||
63 | spin_lock(&layr->sync); | ||
64 | |||
65 | if (layr->incomplete_frm != NULL) { | ||
66 | |||
67 | layr->incomplete_frm = | ||
68 | cfpkt_append(layr->incomplete_frm, newpkt, expectlen); | ||
69 | pkt = layr->incomplete_frm; | ||
70 | } else { | ||
71 | pkt = newpkt; | ||
72 | } | ||
73 | layr->incomplete_frm = NULL; | ||
74 | |||
75 | do { | ||
76 | /* Search for STX at start of pkt if STX is used */ | ||
77 | if (layr->usestx) { | ||
78 | cfpkt_extr_head(pkt, &tmp8, 1); | ||
79 | if (tmp8 != CFSERL_STX) { | ||
80 | while (cfpkt_more(pkt) | ||
81 | && tmp8 != CFSERL_STX) { | ||
82 | cfpkt_extr_head(pkt, &tmp8, 1); | ||
83 | } | ||
84 | if (!cfpkt_more(pkt)) { | ||
85 | cfpkt_destroy(pkt); | ||
86 | layr->incomplete_frm = NULL; | ||
87 | spin_unlock(&layr->sync); | ||
88 | return -EPROTO; | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | pkt_len = cfpkt_getlen(pkt); | ||
94 | |||
95 | /* | ||
96 | * pkt_len is the accumulated length of the packet data | ||
97 | * we have received so far. | ||
98 | * Exit if frame doesn't hold length. | ||
99 | */ | ||
100 | |||
101 | if (pkt_len < 2) { | ||
102 | if (layr->usestx) | ||
103 | cfpkt_add_head(pkt, &stx, 1); | ||
104 | layr->incomplete_frm = pkt; | ||
105 | spin_unlock(&layr->sync); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Find length of frame. | ||
111 | * expectlen is the length we need for a full frame. | ||
112 | */ | ||
113 | cfpkt_peek_head(pkt, &tmp, 2); | ||
114 | expectlen = le16_to_cpu(tmp) + 2; | ||
115 | /* | ||
116 | * Frame error handling | ||
117 | */ | ||
118 | if (expectlen < CAIF_MINIUM_PACKET_SIZE | ||
119 | || expectlen > CAIF_MAX_FRAMESIZE) { | ||
120 | if (!layr->usestx) { | ||
121 | if (pkt != NULL) | ||
122 | cfpkt_destroy(pkt); | ||
123 | layr->incomplete_frm = NULL; | ||
124 | expectlen = 0; | ||
125 | spin_unlock(&layr->sync); | ||
126 | return -EPROTO; | ||
127 | } | ||
128 | continue; | ||
129 | } | ||
130 | |||
131 | if (pkt_len < expectlen) { | ||
132 | /* Too little received data */ | ||
133 | if (layr->usestx) | ||
134 | cfpkt_add_head(pkt, &stx, 1); | ||
135 | layr->incomplete_frm = pkt; | ||
136 | spin_unlock(&layr->sync); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Enough data for at least one frame. | ||
142 | * Split the frame, if too long | ||
143 | */ | ||
144 | if (pkt_len > expectlen) | ||
145 | tail_pkt = cfpkt_split(pkt, expectlen); | ||
146 | else | ||
147 | tail_pkt = NULL; | ||
148 | |||
149 | /* Send the first part of packet upwards.*/ | ||
150 | spin_unlock(&layr->sync); | ||
151 | ret = layr->layer.up->receive(layr->layer.up, pkt); | ||
152 | spin_lock(&layr->sync); | ||
153 | if (ret == -EILSEQ) { | ||
154 | if (layr->usestx) { | ||
155 | if (tail_pkt != NULL) | ||
156 | pkt = cfpkt_append(pkt, tail_pkt, 0); | ||
157 | |||
158 | /* Start search for next STX if frame failed */ | ||
159 | continue; | ||
160 | } else { | ||
161 | cfpkt_destroy(pkt); | ||
162 | pkt = NULL; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | pkt = tail_pkt; | ||
167 | |||
168 | } while (pkt != NULL); | ||
169 | |||
170 | spin_unlock(&layr->sync); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int cfserl_transmit(struct cflayer *layer, struct cfpkt *newpkt) | ||
175 | { | ||
176 | struct cfserl *layr = container_obj(layer); | ||
177 | int ret; | ||
178 | u8 tmp8 = CFSERL_STX; | ||
179 | if (layr->usestx) | ||
180 | cfpkt_add_head(newpkt, &tmp8, 1); | ||
181 | ret = layer->dn->transmit(layer->dn, newpkt); | ||
182 | if (ret < 0) | ||
183 | cfpkt_extr_head(newpkt, &tmp8, 1); | ||
184 | |||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
189 | int phyid) | ||
190 | { | ||
191 | layr->up->ctrlcmd(layr->up, ctrl, phyid); | ||
192 | } | ||
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c new file mode 100644 index 000000000000..aff31f34528f --- /dev/null +++ b/net/caif/cfsrvl.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <net/caif/caif_layer.h> | ||
12 | #include <net/caif/cfsrvl.h> | ||
13 | #include <net/caif/cfpkt.h> | ||
14 | |||
15 | #define SRVL_CTRL_PKT_SIZE 1 | ||
16 | #define SRVL_FLOW_OFF 0x81 | ||
17 | #define SRVL_FLOW_ON 0x80 | ||
18 | #define SRVL_SET_PIN 0x82 | ||
19 | #define SRVL_CTRL_PKT_SIZE 1 | ||
20 | |||
21 | #define container_obj(layr) container_of(layr, struct cfsrvl, layer) | ||
22 | |||
23 | static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
24 | int phyid) | ||
25 | { | ||
26 | struct cfsrvl *service = container_obj(layr); | ||
27 | caif_assert(layr->up != NULL); | ||
28 | caif_assert(layr->up->ctrlcmd != NULL); | ||
29 | switch (ctrl) { | ||
30 | case CAIF_CTRLCMD_INIT_RSP: | ||
31 | service->open = true; | ||
32 | layr->up->ctrlcmd(layr->up, ctrl, phyid); | ||
33 | break; | ||
34 | case CAIF_CTRLCMD_DEINIT_RSP: | ||
35 | case CAIF_CTRLCMD_INIT_FAIL_RSP: | ||
36 | service->open = false; | ||
37 | layr->up->ctrlcmd(layr->up, ctrl, phyid); | ||
38 | break; | ||
39 | case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: | ||
40 | if (phyid != service->dev_info.id) | ||
41 | break; | ||
42 | if (service->modem_flow_on) | ||
43 | layr->up->ctrlcmd(layr->up, | ||
44 | CAIF_CTRLCMD_FLOW_OFF_IND, phyid); | ||
45 | service->phy_flow_on = false; | ||
46 | break; | ||
47 | case _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND: | ||
48 | if (phyid != service->dev_info.id) | ||
49 | return; | ||
50 | if (service->modem_flow_on) { | ||
51 | layr->up->ctrlcmd(layr->up, | ||
52 | CAIF_CTRLCMD_FLOW_ON_IND, | ||
53 | phyid); | ||
54 | } | ||
55 | service->phy_flow_on = true; | ||
56 | break; | ||
57 | case CAIF_CTRLCMD_FLOW_OFF_IND: | ||
58 | if (service->phy_flow_on) { | ||
59 | layr->up->ctrlcmd(layr->up, | ||
60 | CAIF_CTRLCMD_FLOW_OFF_IND, phyid); | ||
61 | } | ||
62 | service->modem_flow_on = false; | ||
63 | break; | ||
64 | case CAIF_CTRLCMD_FLOW_ON_IND: | ||
65 | if (service->phy_flow_on) { | ||
66 | layr->up->ctrlcmd(layr->up, | ||
67 | CAIF_CTRLCMD_FLOW_ON_IND, phyid); | ||
68 | } | ||
69 | service->modem_flow_on = true; | ||
70 | break; | ||
71 | case _CAIF_CTRLCMD_PHYIF_DOWN_IND: | ||
72 | /* In case interface is down, let's fake a remove shutdown */ | ||
73 | layr->up->ctrlcmd(layr->up, | ||
74 | CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, phyid); | ||
75 | break; | ||
76 | case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: | ||
77 | layr->up->ctrlcmd(layr->up, ctrl, phyid); | ||
78 | break; | ||
79 | default: | ||
80 | pr_warning("CAIF: %s(): " | ||
81 | "Unexpected ctrl in cfsrvl (%d)\n", __func__, ctrl); | ||
82 | /* We have both modem and phy flow on, send flow on */ | ||
83 | layr->up->ctrlcmd(layr->up, ctrl, phyid); | ||
84 | service->phy_flow_on = true; | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) | ||
90 | { | ||
91 | struct cfsrvl *service = container_obj(layr); | ||
92 | caif_assert(layr != NULL); | ||
93 | caif_assert(layr->dn != NULL); | ||
94 | caif_assert(layr->dn->transmit != NULL); | ||
95 | switch (ctrl) { | ||
96 | case CAIF_MODEMCMD_FLOW_ON_REQ: | ||
97 | { | ||
98 | struct cfpkt *pkt; | ||
99 | struct caif_payload_info *info; | ||
100 | u8 flow_on = SRVL_FLOW_ON; | ||
101 | pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE); | ||
102 | if (!pkt) { | ||
103 | pr_warning("CAIF: %s(): Out of memory\n", | ||
104 | __func__); | ||
105 | return -ENOMEM; | ||
106 | } | ||
107 | |||
108 | if (cfpkt_add_head(pkt, &flow_on, 1) < 0) { | ||
109 | pr_err("CAIF: %s(): Packet is erroneous!\n", | ||
110 | __func__); | ||
111 | cfpkt_destroy(pkt); | ||
112 | return -EPROTO; | ||
113 | } | ||
114 | info = cfpkt_info(pkt); | ||
115 | info->channel_id = service->layer.id; | ||
116 | info->hdr_len = 1; | ||
117 | info->dev_info = &service->dev_info; | ||
118 | return layr->dn->transmit(layr->dn, pkt); | ||
119 | } | ||
120 | case CAIF_MODEMCMD_FLOW_OFF_REQ: | ||
121 | { | ||
122 | struct cfpkt *pkt; | ||
123 | struct caif_payload_info *info; | ||
124 | u8 flow_off = SRVL_FLOW_OFF; | ||
125 | pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE); | ||
126 | if (cfpkt_add_head(pkt, &flow_off, 1) < 0) { | ||
127 | pr_err("CAIF: %s(): Packet is erroneous!\n", | ||
128 | __func__); | ||
129 | cfpkt_destroy(pkt); | ||
130 | return -EPROTO; | ||
131 | } | ||
132 | info = cfpkt_info(pkt); | ||
133 | info->channel_id = service->layer.id; | ||
134 | info->hdr_len = 1; | ||
135 | info->dev_info = &service->dev_info; | ||
136 | return layr->dn->transmit(layr->dn, pkt); | ||
137 | } | ||
138 | default: | ||
139 | break; | ||
140 | } | ||
141 | return -EINVAL; | ||
142 | } | ||
143 | |||
144 | void cfservl_destroy(struct cflayer *layer) | ||
145 | { | ||
146 | kfree(layer); | ||
147 | } | ||
148 | |||
149 | void cfsrvl_init(struct cfsrvl *service, | ||
150 | u8 channel_id, | ||
151 | struct dev_info *dev_info) | ||
152 | { | ||
153 | caif_assert(offsetof(struct cfsrvl, layer) == 0); | ||
154 | service->open = false; | ||
155 | service->modem_flow_on = true; | ||
156 | service->phy_flow_on = true; | ||
157 | service->layer.id = channel_id; | ||
158 | service->layer.ctrlcmd = cfservl_ctrlcmd; | ||
159 | service->layer.modemcmd = cfservl_modemcmd; | ||
160 | service->dev_info = *dev_info; | ||
161 | kref_init(&service->ref); | ||
162 | } | ||
163 | |||
164 | void cfsrvl_release(struct kref *kref) | ||
165 | { | ||
166 | struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); | ||
167 | kfree(service); | ||
168 | } | ||
169 | |||
170 | bool cfsrvl_ready(struct cfsrvl *service, int *err) | ||
171 | { | ||
172 | if (service->open && service->modem_flow_on && service->phy_flow_on) | ||
173 | return true; | ||
174 | if (!service->open) { | ||
175 | *err = -ENOTCONN; | ||
176 | return false; | ||
177 | } | ||
178 | caif_assert(!(service->modem_flow_on && service->phy_flow_on)); | ||
179 | *err = -EAGAIN; | ||
180 | return false; | ||
181 | } | ||
182 | u8 cfsrvl_getphyid(struct cflayer *layer) | ||
183 | { | ||
184 | struct cfsrvl *servl = container_obj(layer); | ||
185 | return servl->dev_info.id; | ||
186 | } | ||
187 | |||
188 | bool cfsrvl_phyid_match(struct cflayer *layer, int phyid) | ||
189 | { | ||
190 | struct cfsrvl *servl = container_obj(layer); | ||
191 | return servl->dev_info.id == phyid; | ||
192 | } | ||
diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c new file mode 100644 index 000000000000..5fd2c9ea8b42 --- /dev/null +++ b/net/caif/cfutill.c | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <net/caif/caif_layer.h> | ||
12 | #include <net/caif/cfsrvl.h> | ||
13 | #include <net/caif/cfpkt.h> | ||
14 | |||
15 | #define container_obj(layr) ((struct cfsrvl *) layr) | ||
16 | #define UTIL_PAYLOAD 0x00 | ||
17 | #define UTIL_CMD_BIT 0x80 | ||
18 | #define UTIL_REMOTE_SHUTDOWN 0x82 | ||
19 | #define UTIL_FLOW_OFF 0x81 | ||
20 | #define UTIL_FLOW_ON 0x80 | ||
21 | #define UTIL_CTRL_PKT_SIZE 1 | ||
22 | static int cfutill_receive(struct cflayer *layr, struct cfpkt *pkt); | ||
23 | static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt); | ||
24 | |||
25 | struct cflayer *cfutill_create(u8 channel_id, struct dev_info *dev_info) | ||
26 | { | ||
27 | struct cfsrvl *util = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC); | ||
28 | if (!util) { | ||
29 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
30 | return NULL; | ||
31 | } | ||
32 | caif_assert(offsetof(struct cfsrvl, layer) == 0); | ||
33 | memset(util, 0, sizeof(struct cfsrvl)); | ||
34 | cfsrvl_init(util, channel_id, dev_info); | ||
35 | util->layer.receive = cfutill_receive; | ||
36 | util->layer.transmit = cfutill_transmit; | ||
37 | snprintf(util->layer.name, CAIF_LAYER_NAME_SZ - 1, "util1"); | ||
38 | return &util->layer; | ||
39 | } | ||
40 | |||
41 | static int cfutill_receive(struct cflayer *layr, struct cfpkt *pkt) | ||
42 | { | ||
43 | u8 cmd = -1; | ||
44 | struct cfsrvl *service = container_obj(layr); | ||
45 | caif_assert(layr != NULL); | ||
46 | caif_assert(layr->up != NULL); | ||
47 | caif_assert(layr->up->receive != NULL); | ||
48 | caif_assert(layr->up->ctrlcmd != NULL); | ||
49 | if (cfpkt_extr_head(pkt, &cmd, 1) < 0) { | ||
50 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
51 | cfpkt_destroy(pkt); | ||
52 | return -EPROTO; | ||
53 | } | ||
54 | |||
55 | switch (cmd) { | ||
56 | case UTIL_PAYLOAD: | ||
57 | return layr->up->receive(layr->up, pkt); | ||
58 | case UTIL_FLOW_OFF: | ||
59 | layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0); | ||
60 | cfpkt_destroy(pkt); | ||
61 | return 0; | ||
62 | case UTIL_FLOW_ON: | ||
63 | layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0); | ||
64 | cfpkt_destroy(pkt); | ||
65 | return 0; | ||
66 | case UTIL_REMOTE_SHUTDOWN: /* Remote Shutdown Request */ | ||
67 | pr_err("CAIF: %s(): REMOTE SHUTDOWN REQUEST RECEIVED\n", | ||
68 | __func__); | ||
69 | layr->ctrlcmd(layr, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, 0); | ||
70 | service->open = false; | ||
71 | cfpkt_destroy(pkt); | ||
72 | return 0; | ||
73 | default: | ||
74 | cfpkt_destroy(pkt); | ||
75 | pr_warning("CAIF: %s(): Unknown service control %d (0x%x)\n", | ||
76 | __func__, cmd, cmd); | ||
77 | return -EPROTO; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt) | ||
82 | { | ||
83 | u8 zero = 0; | ||
84 | struct caif_payload_info *info; | ||
85 | int ret; | ||
86 | struct cfsrvl *service = container_obj(layr); | ||
87 | caif_assert(layr != NULL); | ||
88 | caif_assert(layr->dn != NULL); | ||
89 | caif_assert(layr->dn->transmit != NULL); | ||
90 | if (!cfsrvl_ready(service, &ret)) | ||
91 | return ret; | ||
92 | |||
93 | if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { | ||
94 | pr_err("CAIF: %s(): packet too large size=%d\n", | ||
95 | __func__, cfpkt_getlen(pkt)); | ||
96 | return -EOVERFLOW; | ||
97 | } | ||
98 | |||
99 | cfpkt_add_head(pkt, &zero, 1); | ||
100 | /* Add info for MUX-layer to route the packet out. */ | ||
101 | info = cfpkt_info(pkt); | ||
102 | info->channel_id = service->layer.id; | ||
103 | /* | ||
104 | * To optimize alignment, we add up the size of CAIF header before | ||
105 | * payload. | ||
106 | */ | ||
107 | info->hdr_len = 1; | ||
108 | info->dev_info = &service->dev_info; | ||
109 | ret = layr->dn->transmit(layr->dn, pkt); | ||
110 | if (ret < 0) { | ||
111 | u32 tmp32; | ||
112 | cfpkt_extr_head(pkt, &tmp32, 4); | ||
113 | } | ||
114 | return ret; | ||
115 | } | ||
diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c new file mode 100644 index 000000000000..0fd827f49491 --- /dev/null +++ b/net/caif/cfveil.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/stddef.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <net/caif/caif_layer.h> | ||
10 | #include <net/caif/cfsrvl.h> | ||
11 | #include <net/caif/cfpkt.h> | ||
12 | |||
13 | #define VEI_PAYLOAD 0x00 | ||
14 | #define VEI_CMD_BIT 0x80 | ||
15 | #define VEI_FLOW_OFF 0x81 | ||
16 | #define VEI_FLOW_ON 0x80 | ||
17 | #define VEI_SET_PIN 0x82 | ||
18 | #define VEI_CTRL_PKT_SIZE 1 | ||
19 | #define container_obj(layr) container_of(layr, struct cfsrvl, layer) | ||
20 | |||
21 | static int cfvei_receive(struct cflayer *layr, struct cfpkt *pkt); | ||
22 | static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt); | ||
23 | |||
24 | struct cflayer *cfvei_create(u8 channel_id, struct dev_info *dev_info) | ||
25 | { | ||
26 | struct cfsrvl *vei = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC); | ||
27 | if (!vei) { | ||
28 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
29 | return NULL; | ||
30 | } | ||
31 | caif_assert(offsetof(struct cfsrvl, layer) == 0); | ||
32 | memset(vei, 0, sizeof(struct cfsrvl)); | ||
33 | cfsrvl_init(vei, channel_id, dev_info); | ||
34 | vei->layer.receive = cfvei_receive; | ||
35 | vei->layer.transmit = cfvei_transmit; | ||
36 | snprintf(vei->layer.name, CAIF_LAYER_NAME_SZ - 1, "vei%d", channel_id); | ||
37 | return &vei->layer; | ||
38 | } | ||
39 | |||
40 | static int cfvei_receive(struct cflayer *layr, struct cfpkt *pkt) | ||
41 | { | ||
42 | u8 cmd; | ||
43 | int ret; | ||
44 | caif_assert(layr->up != NULL); | ||
45 | caif_assert(layr->receive != NULL); | ||
46 | caif_assert(layr->ctrlcmd != NULL); | ||
47 | |||
48 | |||
49 | if (cfpkt_extr_head(pkt, &cmd, 1) < 0) { | ||
50 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
51 | cfpkt_destroy(pkt); | ||
52 | return -EPROTO; | ||
53 | } | ||
54 | switch (cmd) { | ||
55 | case VEI_PAYLOAD: | ||
56 | ret = layr->up->receive(layr->up, pkt); | ||
57 | return ret; | ||
58 | case VEI_FLOW_OFF: | ||
59 | layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0); | ||
60 | cfpkt_destroy(pkt); | ||
61 | return 0; | ||
62 | case VEI_FLOW_ON: | ||
63 | layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0); | ||
64 | cfpkt_destroy(pkt); | ||
65 | return 0; | ||
66 | case VEI_SET_PIN: /* SET RS232 PIN */ | ||
67 | cfpkt_destroy(pkt); | ||
68 | return 0; | ||
69 | default: /* SET RS232 PIN */ | ||
70 | pr_warning("CAIF: %s():Unknown VEI control packet %d (0x%x)!\n", | ||
71 | __func__, cmd, cmd); | ||
72 | cfpkt_destroy(pkt); | ||
73 | return -EPROTO; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) | ||
78 | { | ||
79 | u8 tmp = 0; | ||
80 | struct caif_payload_info *info; | ||
81 | int ret; | ||
82 | struct cfsrvl *service = container_obj(layr); | ||
83 | if (!cfsrvl_ready(service, &ret)) | ||
84 | return ret; | ||
85 | caif_assert(layr->dn != NULL); | ||
86 | caif_assert(layr->dn->transmit != NULL); | ||
87 | if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { | ||
88 | pr_warning("CAIF: %s(): Packet too large - size=%d\n", | ||
89 | __func__, cfpkt_getlen(pkt)); | ||
90 | return -EOVERFLOW; | ||
91 | } | ||
92 | |||
93 | if (cfpkt_add_head(pkt, &tmp, 1) < 0) { | ||
94 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
95 | return -EPROTO; | ||
96 | } | ||
97 | |||
98 | /* Add info-> for MUX-layer to route the packet out. */ | ||
99 | info = cfpkt_info(pkt); | ||
100 | info->channel_id = service->layer.id; | ||
101 | info->hdr_len = 1; | ||
102 | info->dev_info = &service->dev_info; | ||
103 | ret = layr->dn->transmit(layr->dn, pkt); | ||
104 | if (ret < 0) | ||
105 | cfpkt_extr_head(pkt, &tmp, 1); | ||
106 | return ret; | ||
107 | } | ||
diff --git a/net/caif/cfvidl.c b/net/caif/cfvidl.c new file mode 100644 index 000000000000..89ad4ea239f1 --- /dev/null +++ b/net/caif/cfvidl.c | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <net/caif/caif_layer.h> | ||
12 | #include <net/caif/cfsrvl.h> | ||
13 | #include <net/caif/cfpkt.h> | ||
14 | |||
15 | #define container_obj(layr) ((struct cfsrvl *) layr) | ||
16 | |||
17 | static int cfvidl_receive(struct cflayer *layr, struct cfpkt *pkt); | ||
18 | static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt); | ||
19 | |||
20 | struct cflayer *cfvidl_create(u8 channel_id, struct dev_info *dev_info) | ||
21 | { | ||
22 | struct cfsrvl *vid = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC); | ||
23 | if (!vid) { | ||
24 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
25 | return NULL; | ||
26 | } | ||
27 | caif_assert(offsetof(struct cfsrvl, layer) == 0); | ||
28 | |||
29 | memset(vid, 0, sizeof(struct cfsrvl)); | ||
30 | cfsrvl_init(vid, channel_id, dev_info); | ||
31 | vid->layer.receive = cfvidl_receive; | ||
32 | vid->layer.transmit = cfvidl_transmit; | ||
33 | snprintf(vid->layer.name, CAIF_LAYER_NAME_SZ - 1, "vid1"); | ||
34 | return &vid->layer; | ||
35 | } | ||
36 | |||
37 | static int cfvidl_receive(struct cflayer *layr, struct cfpkt *pkt) | ||
38 | { | ||
39 | u32 videoheader; | ||
40 | if (cfpkt_extr_head(pkt, &videoheader, 4) < 0) { | ||
41 | pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); | ||
42 | cfpkt_destroy(pkt); | ||
43 | return -EPROTO; | ||
44 | } | ||
45 | return layr->up->receive(layr->up, pkt); | ||
46 | } | ||
47 | |||
48 | static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt) | ||
49 | { | ||
50 | struct cfsrvl *service = container_obj(layr); | ||
51 | struct caif_payload_info *info; | ||
52 | u32 videoheader = 0; | ||
53 | int ret; | ||
54 | if (!cfsrvl_ready(service, &ret)) | ||
55 | return ret; | ||
56 | cfpkt_add_head(pkt, &videoheader, 4); | ||
57 | /* Add info for MUX-layer to route the packet out */ | ||
58 | info = cfpkt_info(pkt); | ||
59 | info->channel_id = service->layer.id; | ||
60 | info->dev_info = &service->dev_info; | ||
61 | ret = layr->dn->transmit(layr->dn, pkt); | ||
62 | if (ret < 0) | ||
63 | cfpkt_extr_head(pkt, &videoheader, 4); | ||
64 | return ret; | ||
65 | } | ||
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c new file mode 100644 index 000000000000..610966abe2dc --- /dev/null +++ b/net/caif/chnl_net.c | |||
@@ -0,0 +1,467 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Authors: Sjur Brendeland/sjur.brandeland@stericsson.com | ||
4 | * Daniel Martensson / Daniel.Martensson@stericsson.com | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/version.h> | ||
9 | #include <linux/fs.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/if_ether.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/ip.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/sockios.h> | ||
18 | #include <linux/caif/if_caif.h> | ||
19 | #include <net/rtnetlink.h> | ||
20 | #include <net/caif/caif_layer.h> | ||
21 | #include <net/caif/cfcnfg.h> | ||
22 | #include <net/caif/cfpkt.h> | ||
23 | #include <net/caif/caif_dev.h> | ||
24 | |||
25 | /* GPRS PDP connection has MTU to 1500 */ | ||
26 | #define SIZE_MTU 1500 | ||
27 | /* 5 sec. connect timeout */ | ||
28 | #define CONNECT_TIMEOUT (5 * HZ) | ||
29 | #define CAIF_NET_DEFAULT_QUEUE_LEN 500 | ||
30 | |||
31 | #undef pr_debug | ||
32 | #define pr_debug pr_warning | ||
33 | |||
34 | /*This list is protected by the rtnl lock. */ | ||
35 | static LIST_HEAD(chnl_net_list); | ||
36 | |||
37 | MODULE_LICENSE("GPL"); | ||
38 | MODULE_ALIAS_RTNL_LINK("caif"); | ||
39 | |||
40 | enum caif_states { | ||
41 | CAIF_CONNECTED = 1, | ||
42 | CAIF_CONNECTING, | ||
43 | CAIF_DISCONNECTED, | ||
44 | CAIF_SHUTDOWN | ||
45 | }; | ||
46 | |||
47 | struct chnl_net { | ||
48 | struct cflayer chnl; | ||
49 | struct net_device_stats stats; | ||
50 | struct caif_connect_request conn_req; | ||
51 | struct list_head list_field; | ||
52 | struct net_device *netdev; | ||
53 | char name[256]; | ||
54 | wait_queue_head_t netmgmt_wq; | ||
55 | /* Flow status to remember and control the transmission. */ | ||
56 | bool flowenabled; | ||
57 | enum caif_states state; | ||
58 | }; | ||
59 | |||
60 | static void robust_list_del(struct list_head *delete_node) | ||
61 | { | ||
62 | struct list_head *list_node; | ||
63 | struct list_head *n; | ||
64 | ASSERT_RTNL(); | ||
65 | list_for_each_safe(list_node, n, &chnl_net_list) { | ||
66 | if (list_node == delete_node) { | ||
67 | list_del(list_node); | ||
68 | return; | ||
69 | } | ||
70 | } | ||
71 | WARN_ON(1); | ||
72 | } | ||
73 | |||
74 | static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) | ||
75 | { | ||
76 | struct sk_buff *skb; | ||
77 | struct chnl_net *priv = container_of(layr, struct chnl_net, chnl); | ||
78 | int pktlen; | ||
79 | int err = 0; | ||
80 | |||
81 | priv = container_of(layr, struct chnl_net, chnl); | ||
82 | |||
83 | if (!priv) | ||
84 | return -EINVAL; | ||
85 | |||
86 | /* Get length of CAIF packet. */ | ||
87 | pktlen = cfpkt_getlen(pkt); | ||
88 | |||
89 | skb = (struct sk_buff *) cfpkt_tonative(pkt); | ||
90 | /* Pass some minimum information and | ||
91 | * send the packet to the net stack. | ||
92 | */ | ||
93 | skb->dev = priv->netdev; | ||
94 | skb->protocol = htons(ETH_P_IP); | ||
95 | |||
96 | /* If we change the header in loop mode, the checksum is corrupted. */ | ||
97 | if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP) | ||
98 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
99 | else | ||
100 | skb->ip_summed = CHECKSUM_NONE; | ||
101 | |||
102 | if (in_interrupt()) | ||
103 | netif_rx(skb); | ||
104 | else | ||
105 | netif_rx_ni(skb); | ||
106 | |||
107 | /* Update statistics. */ | ||
108 | priv->netdev->stats.rx_packets++; | ||
109 | priv->netdev->stats.rx_bytes += pktlen; | ||
110 | |||
111 | return err; | ||
112 | } | ||
113 | |||
114 | static int delete_device(struct chnl_net *dev) | ||
115 | { | ||
116 | ASSERT_RTNL(); | ||
117 | if (dev->netdev) | ||
118 | unregister_netdevice(dev->netdev); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static void close_work(struct work_struct *work) | ||
123 | { | ||
124 | struct chnl_net *dev = NULL; | ||
125 | struct list_head *list_node; | ||
126 | struct list_head *_tmp; | ||
127 | /* May be called with or without RTNL lock held */ | ||
128 | int islocked = rtnl_is_locked(); | ||
129 | if (!islocked) | ||
130 | rtnl_lock(); | ||
131 | list_for_each_safe(list_node, _tmp, &chnl_net_list) { | ||
132 | dev = list_entry(list_node, struct chnl_net, list_field); | ||
133 | if (dev->state == CAIF_SHUTDOWN) | ||
134 | dev_close(dev->netdev); | ||
135 | } | ||
136 | if (!islocked) | ||
137 | rtnl_unlock(); | ||
138 | } | ||
139 | static DECLARE_WORK(close_worker, close_work); | ||
140 | |||
141 | static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, | ||
142 | int phyid) | ||
143 | { | ||
144 | struct chnl_net *priv = container_of(layr, struct chnl_net, chnl); | ||
145 | pr_debug("CAIF: %s(): NET flowctrl func called flow: %s\n", | ||
146 | __func__, | ||
147 | flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" : | ||
148 | flow == CAIF_CTRLCMD_INIT_RSP ? "INIT" : | ||
149 | flow == CAIF_CTRLCMD_FLOW_OFF_IND ? "OFF" : | ||
150 | flow == CAIF_CTRLCMD_DEINIT_RSP ? "CLOSE/DEINIT" : | ||
151 | flow == CAIF_CTRLCMD_INIT_FAIL_RSP ? "OPEN_FAIL" : | ||
152 | flow == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ? | ||
153 | "REMOTE_SHUTDOWN" : "UKNOWN CTRL COMMAND"); | ||
154 | |||
155 | |||
156 | |||
157 | switch (flow) { | ||
158 | case CAIF_CTRLCMD_FLOW_OFF_IND: | ||
159 | priv->flowenabled = false; | ||
160 | netif_stop_queue(priv->netdev); | ||
161 | break; | ||
162 | case CAIF_CTRLCMD_DEINIT_RSP: | ||
163 | priv->state = CAIF_DISCONNECTED; | ||
164 | break; | ||
165 | case CAIF_CTRLCMD_INIT_FAIL_RSP: | ||
166 | priv->state = CAIF_DISCONNECTED; | ||
167 | wake_up_interruptible(&priv->netmgmt_wq); | ||
168 | break; | ||
169 | case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: | ||
170 | priv->state = CAIF_SHUTDOWN; | ||
171 | netif_tx_disable(priv->netdev); | ||
172 | schedule_work(&close_worker); | ||
173 | break; | ||
174 | case CAIF_CTRLCMD_FLOW_ON_IND: | ||
175 | priv->flowenabled = true; | ||
176 | netif_wake_queue(priv->netdev); | ||
177 | break; | ||
178 | case CAIF_CTRLCMD_INIT_RSP: | ||
179 | priv->state = CAIF_CONNECTED; | ||
180 | priv->flowenabled = true; | ||
181 | netif_wake_queue(priv->netdev); | ||
182 | wake_up_interruptible(&priv->netmgmt_wq); | ||
183 | break; | ||
184 | default: | ||
185 | break; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
190 | { | ||
191 | struct chnl_net *priv; | ||
192 | struct cfpkt *pkt = NULL; | ||
193 | int len; | ||
194 | int result = -1; | ||
195 | /* Get our private data. */ | ||
196 | priv = netdev_priv(dev); | ||
197 | |||
198 | if (skb->len > priv->netdev->mtu) { | ||
199 | pr_warning("CAIF: %s(): Size of skb exceeded MTU\n", __func__); | ||
200 | return -ENOSPC; | ||
201 | } | ||
202 | |||
203 | if (!priv->flowenabled) { | ||
204 | pr_debug("CAIF: %s(): dropping packets flow off\n", __func__); | ||
205 | return NETDEV_TX_BUSY; | ||
206 | } | ||
207 | |||
208 | if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP) | ||
209 | swap(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); | ||
210 | |||
211 | /* Store original SKB length. */ | ||
212 | len = skb->len; | ||
213 | |||
214 | pkt = cfpkt_fromnative(CAIF_DIR_OUT, (void *) skb); | ||
215 | |||
216 | /* Send the packet down the stack. */ | ||
217 | result = priv->chnl.dn->transmit(priv->chnl.dn, pkt); | ||
218 | if (result) { | ||
219 | if (result == -EAGAIN) | ||
220 | result = NETDEV_TX_BUSY; | ||
221 | return result; | ||
222 | } | ||
223 | |||
224 | /* Update statistics. */ | ||
225 | dev->stats.tx_packets++; | ||
226 | dev->stats.tx_bytes += len; | ||
227 | |||
228 | return NETDEV_TX_OK; | ||
229 | } | ||
230 | |||
231 | static int chnl_net_open(struct net_device *dev) | ||
232 | { | ||
233 | struct chnl_net *priv = NULL; | ||
234 | int result = -1; | ||
235 | ASSERT_RTNL(); | ||
236 | priv = netdev_priv(dev); | ||
237 | if (!priv) { | ||
238 | pr_debug("CAIF: %s(): chnl_net_open: no priv\n", __func__); | ||
239 | return -ENODEV; | ||
240 | } | ||
241 | |||
242 | if (priv->state != CAIF_CONNECTING) { | ||
243 | priv->state = CAIF_CONNECTING; | ||
244 | result = caif_connect_client(&priv->conn_req, &priv->chnl); | ||
245 | if (result != 0) { | ||
246 | priv->state = CAIF_DISCONNECTED; | ||
247 | pr_debug("CAIF: %s(): err: " | ||
248 | "Unable to register and open device," | ||
249 | " Err:%d\n", | ||
250 | __func__, | ||
251 | result); | ||
252 | return result; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | result = wait_event_interruptible_timeout(priv->netmgmt_wq, | ||
257 | priv->state != CAIF_CONNECTING, | ||
258 | CONNECT_TIMEOUT); | ||
259 | |||
260 | if (result == -ERESTARTSYS) { | ||
261 | pr_debug("CAIF: %s(): wait_event_interruptible" | ||
262 | " woken by a signal\n", __func__); | ||
263 | return -ERESTARTSYS; | ||
264 | } | ||
265 | if (result == 0) { | ||
266 | pr_debug("CAIF: %s(): connect timeout\n", __func__); | ||
267 | caif_disconnect_client(&priv->chnl); | ||
268 | priv->state = CAIF_DISCONNECTED; | ||
269 | pr_debug("CAIF: %s(): state disconnected\n", __func__); | ||
270 | return -ETIMEDOUT; | ||
271 | } | ||
272 | |||
273 | if (priv->state != CAIF_CONNECTED) { | ||
274 | pr_debug("CAIF: %s(): connect failed\n", __func__); | ||
275 | return -ECONNREFUSED; | ||
276 | } | ||
277 | pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int chnl_net_stop(struct net_device *dev) | ||
282 | { | ||
283 | struct chnl_net *priv; | ||
284 | |||
285 | ASSERT_RTNL(); | ||
286 | priv = netdev_priv(dev); | ||
287 | priv->state = CAIF_DISCONNECTED; | ||
288 | caif_disconnect_client(&priv->chnl); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int chnl_net_init(struct net_device *dev) | ||
293 | { | ||
294 | struct chnl_net *priv; | ||
295 | ASSERT_RTNL(); | ||
296 | priv = netdev_priv(dev); | ||
297 | strncpy(priv->name, dev->name, sizeof(priv->name)); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static void chnl_net_uninit(struct net_device *dev) | ||
302 | { | ||
303 | struct chnl_net *priv; | ||
304 | ASSERT_RTNL(); | ||
305 | priv = netdev_priv(dev); | ||
306 | robust_list_del(&priv->list_field); | ||
307 | } | ||
308 | |||
309 | static const struct net_device_ops netdev_ops = { | ||
310 | .ndo_open = chnl_net_open, | ||
311 | .ndo_stop = chnl_net_stop, | ||
312 | .ndo_init = chnl_net_init, | ||
313 | .ndo_uninit = chnl_net_uninit, | ||
314 | .ndo_start_xmit = chnl_net_start_xmit, | ||
315 | }; | ||
316 | |||
317 | static void ipcaif_net_setup(struct net_device *dev) | ||
318 | { | ||
319 | struct chnl_net *priv; | ||
320 | dev->netdev_ops = &netdev_ops; | ||
321 | dev->destructor = free_netdev; | ||
322 | dev->flags |= IFF_NOARP; | ||
323 | dev->flags |= IFF_POINTOPOINT; | ||
324 | dev->needed_headroom = CAIF_NEEDED_HEADROOM; | ||
325 | dev->needed_tailroom = CAIF_NEEDED_TAILROOM; | ||
326 | dev->mtu = SIZE_MTU; | ||
327 | dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN; | ||
328 | |||
329 | priv = netdev_priv(dev); | ||
330 | priv->chnl.receive = chnl_recv_cb; | ||
331 | priv->chnl.ctrlcmd = chnl_flowctrl_cb; | ||
332 | priv->netdev = dev; | ||
333 | priv->conn_req.protocol = CAIFPROTO_DATAGRAM; | ||
334 | priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW; | ||
335 | priv->conn_req.priority = CAIF_PRIO_LOW; | ||
336 | /* Insert illegal value */ | ||
337 | priv->conn_req.sockaddr.u.dgm.connection_id = -1; | ||
338 | priv->flowenabled = false; | ||
339 | |||
340 | ASSERT_RTNL(); | ||
341 | init_waitqueue_head(&priv->netmgmt_wq); | ||
342 | list_add(&priv->list_field, &chnl_net_list); | ||
343 | } | ||
344 | |||
345 | |||
346 | static int ipcaif_fill_info(struct sk_buff *skb, const struct net_device *dev) | ||
347 | { | ||
348 | struct chnl_net *priv; | ||
349 | u8 loop; | ||
350 | priv = netdev_priv(dev); | ||
351 | NLA_PUT_U32(skb, IFLA_CAIF_IPV4_CONNID, | ||
352 | priv->conn_req.sockaddr.u.dgm.connection_id); | ||
353 | NLA_PUT_U32(skb, IFLA_CAIF_IPV6_CONNID, | ||
354 | priv->conn_req.sockaddr.u.dgm.connection_id); | ||
355 | loop = priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP; | ||
356 | NLA_PUT_U8(skb, IFLA_CAIF_LOOPBACK, loop); | ||
357 | |||
358 | |||
359 | return 0; | ||
360 | nla_put_failure: | ||
361 | return -EMSGSIZE; | ||
362 | |||
363 | } | ||
364 | |||
365 | static void caif_netlink_parms(struct nlattr *data[], | ||
366 | struct caif_connect_request *conn_req) | ||
367 | { | ||
368 | if (!data) { | ||
369 | pr_warning("CAIF: %s: no params data found\n", __func__); | ||
370 | return; | ||
371 | } | ||
372 | if (data[IFLA_CAIF_IPV4_CONNID]) | ||
373 | conn_req->sockaddr.u.dgm.connection_id = | ||
374 | nla_get_u32(data[IFLA_CAIF_IPV4_CONNID]); | ||
375 | if (data[IFLA_CAIF_IPV6_CONNID]) | ||
376 | conn_req->sockaddr.u.dgm.connection_id = | ||
377 | nla_get_u32(data[IFLA_CAIF_IPV6_CONNID]); | ||
378 | if (data[IFLA_CAIF_LOOPBACK]) { | ||
379 | if (nla_get_u8(data[IFLA_CAIF_LOOPBACK])) | ||
380 | conn_req->protocol = CAIFPROTO_DATAGRAM_LOOP; | ||
381 | else | ||
382 | conn_req->protocol = CAIFPROTO_DATAGRAM; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | static int ipcaif_newlink(struct net *src_net, struct net_device *dev, | ||
387 | struct nlattr *tb[], struct nlattr *data[]) | ||
388 | { | ||
389 | int ret; | ||
390 | struct chnl_net *caifdev; | ||
391 | ASSERT_RTNL(); | ||
392 | caifdev = netdev_priv(dev); | ||
393 | caif_netlink_parms(data, &caifdev->conn_req); | ||
394 | dev_net_set(caifdev->netdev, src_net); | ||
395 | |||
396 | ret = register_netdevice(dev); | ||
397 | if (ret) | ||
398 | pr_warning("CAIF: %s(): device rtml registration failed\n", | ||
399 | __func__); | ||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | static int ipcaif_changelink(struct net_device *dev, struct nlattr *tb[], | ||
404 | struct nlattr *data[]) | ||
405 | { | ||
406 | struct chnl_net *caifdev; | ||
407 | ASSERT_RTNL(); | ||
408 | caifdev = netdev_priv(dev); | ||
409 | caif_netlink_parms(data, &caifdev->conn_req); | ||
410 | netdev_state_change(dev); | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static size_t ipcaif_get_size(const struct net_device *dev) | ||
415 | { | ||
416 | return | ||
417 | /* IFLA_CAIF_IPV4_CONNID */ | ||
418 | nla_total_size(4) + | ||
419 | /* IFLA_CAIF_IPV6_CONNID */ | ||
420 | nla_total_size(4) + | ||
421 | /* IFLA_CAIF_LOOPBACK */ | ||
422 | nla_total_size(2) + | ||
423 | 0; | ||
424 | } | ||
425 | |||
426 | static const struct nla_policy ipcaif_policy[IFLA_CAIF_MAX + 1] = { | ||
427 | [IFLA_CAIF_IPV4_CONNID] = { .type = NLA_U32 }, | ||
428 | [IFLA_CAIF_IPV6_CONNID] = { .type = NLA_U32 }, | ||
429 | [IFLA_CAIF_LOOPBACK] = { .type = NLA_U8 } | ||
430 | }; | ||
431 | |||
432 | |||
433 | static struct rtnl_link_ops ipcaif_link_ops __read_mostly = { | ||
434 | .kind = "caif", | ||
435 | .priv_size = sizeof(struct chnl_net), | ||
436 | .setup = ipcaif_net_setup, | ||
437 | .maxtype = IFLA_CAIF_MAX, | ||
438 | .policy = ipcaif_policy, | ||
439 | .newlink = ipcaif_newlink, | ||
440 | .changelink = ipcaif_changelink, | ||
441 | .get_size = ipcaif_get_size, | ||
442 | .fill_info = ipcaif_fill_info, | ||
443 | |||
444 | }; | ||
445 | |||
446 | static int __init chnl_init_module(void) | ||
447 | { | ||
448 | return rtnl_link_register(&ipcaif_link_ops); | ||
449 | } | ||
450 | |||
451 | static void __exit chnl_exit_module(void) | ||
452 | { | ||
453 | struct chnl_net *dev = NULL; | ||
454 | struct list_head *list_node; | ||
455 | struct list_head *_tmp; | ||
456 | rtnl_link_unregister(&ipcaif_link_ops); | ||
457 | rtnl_lock(); | ||
458 | list_for_each_safe(list_node, _tmp, &chnl_net_list) { | ||
459 | dev = list_entry(list_node, struct chnl_net, list_field); | ||
460 | list_del(list_node); | ||
461 | delete_device(dev); | ||
462 | } | ||
463 | rtnl_unlock(); | ||
464 | } | ||
465 | |||
466 | module_init(chnl_init_module); | ||
467 | module_exit(chnl_exit_module); | ||
diff --git a/net/can/bcm.c b/net/can/bcm.c index 907dc871fac8..9c65e9deb9c3 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -713,8 +713,6 @@ static void bcm_remove_op(struct bcm_op *op) | |||
713 | kfree(op->last_frames); | 713 | kfree(op->last_frames); |
714 | 714 | ||
715 | kfree(op); | 715 | kfree(op); |
716 | |||
717 | return; | ||
718 | } | 716 | } |
719 | 717 | ||
720 | static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op) | 718 | static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op) |
diff --git a/net/core/Makefile b/net/core/Makefile index 08791ac3e05a..51c3eec850ef 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
@@ -7,7 +7,7 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ | |||
7 | 7 | ||
8 | obj-$(CONFIG_SYSCTL) += sysctl_net_core.o | 8 | obj-$(CONFIG_SYSCTL) += sysctl_net_core.o |
9 | 9 | ||
10 | obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ | 10 | obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ |
11 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o | 11 | neighbour.o rtnetlink.o utils.o link_watch.o filter.o |
12 | 12 | ||
13 | obj-$(CONFIG_XFRM) += flow.o | 13 | obj-$(CONFIG_XFRM) += flow.o |
diff --git a/net/core/datagram.c b/net/core/datagram.c index 2dccd4ee591b..e0097531417a 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -86,7 +86,7 @@ static int wait_for_packet(struct sock *sk, int *err, long *timeo_p) | |||
86 | int error; | 86 | int error; |
87 | DEFINE_WAIT_FUNC(wait, receiver_wake_function); | 87 | DEFINE_WAIT_FUNC(wait, receiver_wake_function); |
88 | 88 | ||
89 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 89 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
90 | 90 | ||
91 | /* Socket errors? */ | 91 | /* Socket errors? */ |
92 | error = sock_error(sk); | 92 | error = sock_error(sk); |
@@ -115,7 +115,7 @@ static int wait_for_packet(struct sock *sk, int *err, long *timeo_p) | |||
115 | error = 0; | 115 | error = 0; |
116 | *timeo_p = schedule_timeout(*timeo_p); | 116 | *timeo_p = schedule_timeout(*timeo_p); |
117 | out: | 117 | out: |
118 | finish_wait(sk->sk_sleep, &wait); | 118 | finish_wait(sk_sleep(sk), &wait); |
119 | return error; | 119 | return error; |
120 | interrupted: | 120 | interrupted: |
121 | error = sock_intr_errno(*timeo_p); | 121 | error = sock_intr_errno(*timeo_p); |
@@ -229,9 +229,18 @@ EXPORT_SYMBOL(skb_free_datagram); | |||
229 | 229 | ||
230 | void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) | 230 | void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) |
231 | { | 231 | { |
232 | lock_sock(sk); | 232 | if (likely(atomic_read(&skb->users) == 1)) |
233 | skb_free_datagram(sk, skb); | 233 | smp_rmb(); |
234 | release_sock(sk); | 234 | else if (likely(!atomic_dec_and_test(&skb->users))) |
235 | return; | ||
236 | |||
237 | lock_sock_bh(sk); | ||
238 | skb_orphan(skb); | ||
239 | sk_mem_reclaim_partial(sk); | ||
240 | unlock_sock_bh(sk); | ||
241 | |||
242 | /* skb is now orphaned, can be freed outside of locked section */ | ||
243 | __kfree_skb(skb); | ||
235 | } | 244 | } |
236 | EXPORT_SYMBOL(skb_free_datagram_locked); | 245 | EXPORT_SYMBOL(skb_free_datagram_locked); |
237 | 246 | ||
@@ -726,7 +735,7 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, | |||
726 | struct sock *sk = sock->sk; | 735 | struct sock *sk = sock->sk; |
727 | unsigned int mask; | 736 | unsigned int mask; |
728 | 737 | ||
729 | sock_poll_wait(file, sk->sk_sleep, wait); | 738 | sock_poll_wait(file, sk_sleep(sk), wait); |
730 | mask = 0; | 739 | mask = 0; |
731 | 740 | ||
732 | /* exceptional events? */ | 741 | /* exceptional events? */ |
diff --git a/net/core/dev.c b/net/core/dev.c index 264137fce3a2..6c820650b80f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -130,6 +130,7 @@ | |||
130 | #include <linux/jhash.h> | 130 | #include <linux/jhash.h> |
131 | #include <linux/random.h> | 131 | #include <linux/random.h> |
132 | #include <trace/events/napi.h> | 132 | #include <trace/events/napi.h> |
133 | #include <linux/pci.h> | ||
133 | 134 | ||
134 | #include "net-sysfs.h" | 135 | #include "net-sysfs.h" |
135 | 136 | ||
@@ -207,6 +208,20 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) | |||
207 | return &net->dev_index_head[ifindex & (NETDEV_HASHENTRIES - 1)]; | 208 | return &net->dev_index_head[ifindex & (NETDEV_HASHENTRIES - 1)]; |
208 | } | 209 | } |
209 | 210 | ||
211 | static inline void rps_lock(struct softnet_data *sd) | ||
212 | { | ||
213 | #ifdef CONFIG_RPS | ||
214 | spin_lock(&sd->input_pkt_queue.lock); | ||
215 | #endif | ||
216 | } | ||
217 | |||
218 | static inline void rps_unlock(struct softnet_data *sd) | ||
219 | { | ||
220 | #ifdef CONFIG_RPS | ||
221 | spin_unlock(&sd->input_pkt_queue.lock); | ||
222 | #endif | ||
223 | } | ||
224 | |||
210 | /* Device list insertion */ | 225 | /* Device list insertion */ |
211 | static int list_netdevice(struct net_device *dev) | 226 | static int list_netdevice(struct net_device *dev) |
212 | { | 227 | { |
@@ -249,7 +264,7 @@ static RAW_NOTIFIER_HEAD(netdev_chain); | |||
249 | * queue in the local softnet handler. | 264 | * queue in the local softnet handler. |
250 | */ | 265 | */ |
251 | 266 | ||
252 | DEFINE_PER_CPU(struct softnet_data, softnet_data); | 267 | DEFINE_PER_CPU_ALIGNED(struct softnet_data, softnet_data); |
253 | EXPORT_PER_CPU_SYMBOL(softnet_data); | 268 | EXPORT_PER_CPU_SYMBOL(softnet_data); |
254 | 269 | ||
255 | #ifdef CONFIG_LOCKDEP | 270 | #ifdef CONFIG_LOCKDEP |
@@ -773,14 +788,17 @@ EXPORT_SYMBOL(__dev_getfirstbyhwtype); | |||
773 | 788 | ||
774 | struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type) | 789 | struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type) |
775 | { | 790 | { |
776 | struct net_device *dev; | 791 | struct net_device *dev, *ret = NULL; |
777 | 792 | ||
778 | rtnl_lock(); | 793 | rcu_read_lock(); |
779 | dev = __dev_getfirstbyhwtype(net, type); | 794 | for_each_netdev_rcu(net, dev) |
780 | if (dev) | 795 | if (dev->type == type) { |
781 | dev_hold(dev); | 796 | dev_hold(dev); |
782 | rtnl_unlock(); | 797 | ret = dev; |
783 | return dev; | 798 | break; |
799 | } | ||
800 | rcu_read_unlock(); | ||
801 | return ret; | ||
784 | } | 802 | } |
785 | EXPORT_SYMBOL(dev_getfirstbyhwtype); | 803 | EXPORT_SYMBOL(dev_getfirstbyhwtype); |
786 | 804 | ||
@@ -1085,9 +1103,9 @@ void netdev_state_change(struct net_device *dev) | |||
1085 | } | 1103 | } |
1086 | EXPORT_SYMBOL(netdev_state_change); | 1104 | EXPORT_SYMBOL(netdev_state_change); |
1087 | 1105 | ||
1088 | void netdev_bonding_change(struct net_device *dev, unsigned long event) | 1106 | int netdev_bonding_change(struct net_device *dev, unsigned long event) |
1089 | { | 1107 | { |
1090 | call_netdevice_notifiers(event, dev); | 1108 | return call_netdevice_notifiers(event, dev); |
1091 | } | 1109 | } |
1092 | EXPORT_SYMBOL(netdev_bonding_change); | 1110 | EXPORT_SYMBOL(netdev_bonding_change); |
1093 | 1111 | ||
@@ -1417,6 +1435,7 @@ EXPORT_SYMBOL(unregister_netdevice_notifier); | |||
1417 | 1435 | ||
1418 | int call_netdevice_notifiers(unsigned long val, struct net_device *dev) | 1436 | int call_netdevice_notifiers(unsigned long val, struct net_device *dev) |
1419 | { | 1437 | { |
1438 | ASSERT_RTNL(); | ||
1420 | return raw_notifier_call_chain(&netdev_chain, val, dev); | 1439 | return raw_notifier_call_chain(&netdev_chain, val, dev); |
1421 | } | 1440 | } |
1422 | 1441 | ||
@@ -1435,7 +1454,7 @@ void net_disable_timestamp(void) | |||
1435 | } | 1454 | } |
1436 | EXPORT_SYMBOL(net_disable_timestamp); | 1455 | EXPORT_SYMBOL(net_disable_timestamp); |
1437 | 1456 | ||
1438 | static inline void net_timestamp(struct sk_buff *skb) | 1457 | static inline void net_timestamp_set(struct sk_buff *skb) |
1439 | { | 1458 | { |
1440 | if (atomic_read(&netstamp_needed)) | 1459 | if (atomic_read(&netstamp_needed)) |
1441 | __net_timestamp(skb); | 1460 | __net_timestamp(skb); |
@@ -1443,6 +1462,12 @@ static inline void net_timestamp(struct sk_buff *skb) | |||
1443 | skb->tstamp.tv64 = 0; | 1462 | skb->tstamp.tv64 = 0; |
1444 | } | 1463 | } |
1445 | 1464 | ||
1465 | static inline void net_timestamp_check(struct sk_buff *skb) | ||
1466 | { | ||
1467 | if (!skb->tstamp.tv64 && atomic_read(&netstamp_needed)) | ||
1468 | __net_timestamp(skb); | ||
1469 | } | ||
1470 | |||
1446 | /** | 1471 | /** |
1447 | * dev_forward_skb - loopback an skb to another netif | 1472 | * dev_forward_skb - loopback an skb to another netif |
1448 | * | 1473 | * |
@@ -1489,9 +1514,9 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) | |||
1489 | 1514 | ||
1490 | #ifdef CONFIG_NET_CLS_ACT | 1515 | #ifdef CONFIG_NET_CLS_ACT |
1491 | if (!(skb->tstamp.tv64 && (G_TC_FROM(skb->tc_verd) & AT_INGRESS))) | 1516 | if (!(skb->tstamp.tv64 && (G_TC_FROM(skb->tc_verd) & AT_INGRESS))) |
1492 | net_timestamp(skb); | 1517 | net_timestamp_set(skb); |
1493 | #else | 1518 | #else |
1494 | net_timestamp(skb); | 1519 | net_timestamp_set(skb); |
1495 | #endif | 1520 | #endif |
1496 | 1521 | ||
1497 | rcu_read_lock(); | 1522 | rcu_read_lock(); |
@@ -1537,8 +1562,9 @@ static inline void __netif_reschedule(struct Qdisc *q) | |||
1537 | 1562 | ||
1538 | local_irq_save(flags); | 1563 | local_irq_save(flags); |
1539 | sd = &__get_cpu_var(softnet_data); | 1564 | sd = &__get_cpu_var(softnet_data); |
1540 | q->next_sched = sd->output_queue; | 1565 | q->next_sched = NULL; |
1541 | sd->output_queue = q; | 1566 | *sd->output_queue_tailp = q; |
1567 | sd->output_queue_tailp = &q->next_sched; | ||
1542 | raise_softirq_irqoff(NET_TX_SOFTIRQ); | 1568 | raise_softirq_irqoff(NET_TX_SOFTIRQ); |
1543 | local_irq_restore(flags); | 1569 | local_irq_restore(flags); |
1544 | } | 1570 | } |
@@ -1783,18 +1809,27 @@ EXPORT_SYMBOL(netdev_rx_csum_fault); | |||
1783 | * 2. No high memory really exists on this machine. | 1809 | * 2. No high memory really exists on this machine. |
1784 | */ | 1810 | */ |
1785 | 1811 | ||
1786 | static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb) | 1812 | static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) |
1787 | { | 1813 | { |
1788 | #ifdef CONFIG_HIGHMEM | 1814 | #ifdef CONFIG_HIGHMEM |
1789 | int i; | 1815 | int i; |
1816 | if (!(dev->features & NETIF_F_HIGHDMA)) { | ||
1817 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) | ||
1818 | if (PageHighMem(skb_shinfo(skb)->frags[i].page)) | ||
1819 | return 1; | ||
1820 | } | ||
1790 | 1821 | ||
1791 | if (dev->features & NETIF_F_HIGHDMA) | 1822 | if (PCI_DMA_BUS_IS_PHYS) { |
1792 | return 0; | 1823 | struct device *pdev = dev->dev.parent; |
1793 | |||
1794 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) | ||
1795 | if (PageHighMem(skb_shinfo(skb)->frags[i].page)) | ||
1796 | return 1; | ||
1797 | 1824 | ||
1825 | if (!pdev) | ||
1826 | return 0; | ||
1827 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
1828 | dma_addr_t addr = page_to_phys(skb_shinfo(skb)->frags[i].page); | ||
1829 | if (!pdev->dma_mask || addr + PAGE_SIZE - 1 > *pdev->dma_mask) | ||
1830 | return 1; | ||
1831 | } | ||
1832 | } | ||
1798 | #endif | 1833 | #endif |
1799 | return 0; | 1834 | return 0; |
1800 | } | 1835 | } |
@@ -1852,6 +1887,17 @@ static int dev_gso_segment(struct sk_buff *skb) | |||
1852 | return 0; | 1887 | return 0; |
1853 | } | 1888 | } |
1854 | 1889 | ||
1890 | /* | ||
1891 | * Try to orphan skb early, right before transmission by the device. | ||
1892 | * We cannot orphan skb if tx timestamp is requested, since | ||
1893 | * drivers need to call skb_tstamp_tx() to send the timestamp. | ||
1894 | */ | ||
1895 | static inline void skb_orphan_try(struct sk_buff *skb) | ||
1896 | { | ||
1897 | if (!skb_tx(skb)->flags) | ||
1898 | skb_orphan(skb); | ||
1899 | } | ||
1900 | |||
1855 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | 1901 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, |
1856 | struct netdev_queue *txq) | 1902 | struct netdev_queue *txq) |
1857 | { | 1903 | { |
@@ -1862,13 +1908,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | |||
1862 | if (!list_empty(&ptype_all)) | 1908 | if (!list_empty(&ptype_all)) |
1863 | dev_queue_xmit_nit(skb, dev); | 1909 | dev_queue_xmit_nit(skb, dev); |
1864 | 1910 | ||
1865 | if (netif_needs_gso(dev, skb)) { | ||
1866 | if (unlikely(dev_gso_segment(skb))) | ||
1867 | goto out_kfree_skb; | ||
1868 | if (skb->next) | ||
1869 | goto gso; | ||
1870 | } | ||
1871 | |||
1872 | /* | 1911 | /* |
1873 | * If device doesnt need skb->dst, release it right now while | 1912 | * If device doesnt need skb->dst, release it right now while |
1874 | * its hot in this cpu cache | 1913 | * its hot in this cpu cache |
@@ -1876,23 +1915,18 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | |||
1876 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) | 1915 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) |
1877 | skb_dst_drop(skb); | 1916 | skb_dst_drop(skb); |
1878 | 1917 | ||
1918 | skb_orphan_try(skb); | ||
1919 | |||
1920 | if (netif_needs_gso(dev, skb)) { | ||
1921 | if (unlikely(dev_gso_segment(skb))) | ||
1922 | goto out_kfree_skb; | ||
1923 | if (skb->next) | ||
1924 | goto gso; | ||
1925 | } | ||
1926 | |||
1879 | rc = ops->ndo_start_xmit(skb, dev); | 1927 | rc = ops->ndo_start_xmit(skb, dev); |
1880 | if (rc == NETDEV_TX_OK) | 1928 | if (rc == NETDEV_TX_OK) |
1881 | txq_trans_update(txq); | 1929 | txq_trans_update(txq); |
1882 | /* | ||
1883 | * TODO: if skb_orphan() was called by | ||
1884 | * dev->hard_start_xmit() (for example, the unmodified | ||
1885 | * igb driver does that; bnx2 doesn't), then | ||
1886 | * skb_tx_software_timestamp() will be unable to send | ||
1887 | * back the time stamp. | ||
1888 | * | ||
1889 | * How can this be prevented? Always create another | ||
1890 | * reference to the socket before calling | ||
1891 | * dev->hard_start_xmit()? Prevent that skb_orphan() | ||
1892 | * does anything in dev->hard_start_xmit() by clearing | ||
1893 | * the skb destructor before the call and restoring it | ||
1894 | * afterwards, then doing the skb_orphan() ourselves? | ||
1895 | */ | ||
1896 | return rc; | 1930 | return rc; |
1897 | } | 1931 | } |
1898 | 1932 | ||
@@ -1931,7 +1965,7 @@ out_kfree_skb: | |||
1931 | return rc; | 1965 | return rc; |
1932 | } | 1966 | } |
1933 | 1967 | ||
1934 | static u32 skb_tx_hashrnd; | 1968 | static u32 hashrnd __read_mostly; |
1935 | 1969 | ||
1936 | u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) | 1970 | u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) |
1937 | { | 1971 | { |
@@ -1947,9 +1981,9 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) | |||
1947 | if (skb->sk && skb->sk->sk_hash) | 1981 | if (skb->sk && skb->sk->sk_hash) |
1948 | hash = skb->sk->sk_hash; | 1982 | hash = skb->sk->sk_hash; |
1949 | else | 1983 | else |
1950 | hash = skb->protocol; | 1984 | hash = (__force u16) skb->protocol; |
1951 | 1985 | ||
1952 | hash = jhash_1word(hash, skb_tx_hashrnd); | 1986 | hash = jhash_1word(hash, hashrnd); |
1953 | 1987 | ||
1954 | return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); | 1988 | return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); |
1955 | } | 1989 | } |
@@ -1959,10 +1993,9 @@ static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index) | |||
1959 | { | 1993 | { |
1960 | if (unlikely(queue_index >= dev->real_num_tx_queues)) { | 1994 | if (unlikely(queue_index >= dev->real_num_tx_queues)) { |
1961 | if (net_ratelimit()) { | 1995 | if (net_ratelimit()) { |
1962 | WARN(1, "%s selects TX queue %d, but " | 1996 | pr_warning("%s selects TX queue %d, but " |
1963 | "real number of TX queues is %d\n", | 1997 | "real number of TX queues is %d\n", |
1964 | dev->name, queue_index, | 1998 | dev->name, queue_index, dev->real_num_tx_queues); |
1965 | dev->real_num_tx_queues); | ||
1966 | } | 1999 | } |
1967 | return 0; | 2000 | return 0; |
1968 | } | 2001 | } |
@@ -1989,7 +2022,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, | |||
1989 | queue_index = skb_tx_hash(dev, skb); | 2022 | queue_index = skb_tx_hash(dev, skb); |
1990 | 2023 | ||
1991 | if (sk) { | 2024 | if (sk) { |
1992 | struct dst_entry *dst = rcu_dereference_bh(sk->sk_dst_cache); | 2025 | struct dst_entry *dst = rcu_dereference_check(sk->sk_dst_cache, 1); |
1993 | 2026 | ||
1994 | if (dst && skb_dst(skb) == dst) | 2027 | if (dst && skb_dst(skb) == dst) |
1995 | sk_tx_queue_set(sk, queue_index); | 2028 | sk_tx_queue_set(sk, queue_index); |
@@ -2019,6 +2052,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, | |||
2019 | * waiting to be sent out; and the qdisc is not running - | 2052 | * waiting to be sent out; and the qdisc is not running - |
2020 | * xmit the skb directly. | 2053 | * xmit the skb directly. |
2021 | */ | 2054 | */ |
2055 | if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE)) | ||
2056 | skb_dst_force(skb); | ||
2022 | __qdisc_update_bstats(q, skb->len); | 2057 | __qdisc_update_bstats(q, skb->len); |
2023 | if (sch_direct_xmit(skb, q, dev, txq, root_lock)) | 2058 | if (sch_direct_xmit(skb, q, dev, txq, root_lock)) |
2024 | __qdisc_run(q); | 2059 | __qdisc_run(q); |
@@ -2027,6 +2062,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, | |||
2027 | 2062 | ||
2028 | rc = NET_XMIT_SUCCESS; | 2063 | rc = NET_XMIT_SUCCESS; |
2029 | } else { | 2064 | } else { |
2065 | skb_dst_force(skb); | ||
2030 | rc = qdisc_enqueue_root(skb, q); | 2066 | rc = qdisc_enqueue_root(skb, q); |
2031 | qdisc_run(q); | 2067 | qdisc_run(q); |
2032 | } | 2068 | } |
@@ -2174,11 +2210,249 @@ EXPORT_SYMBOL(dev_queue_xmit); | |||
2174 | =======================================================================*/ | 2210 | =======================================================================*/ |
2175 | 2211 | ||
2176 | int netdev_max_backlog __read_mostly = 1000; | 2212 | int netdev_max_backlog __read_mostly = 1000; |
2213 | int netdev_tstamp_prequeue __read_mostly = 1; | ||
2177 | int netdev_budget __read_mostly = 300; | 2214 | int netdev_budget __read_mostly = 300; |
2178 | int weight_p __read_mostly = 64; /* old backlog weight */ | 2215 | int weight_p __read_mostly = 64; /* old backlog weight */ |
2179 | 2216 | ||
2180 | DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; | 2217 | /* Called with irq disabled */ |
2218 | static inline void ____napi_schedule(struct softnet_data *sd, | ||
2219 | struct napi_struct *napi) | ||
2220 | { | ||
2221 | list_add_tail(&napi->poll_list, &sd->poll_list); | ||
2222 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
2223 | } | ||
2224 | |||
2225 | #ifdef CONFIG_RPS | ||
2226 | |||
2227 | /* One global table that all flow-based protocols share. */ | ||
2228 | struct rps_sock_flow_table *rps_sock_flow_table __read_mostly; | ||
2229 | EXPORT_SYMBOL(rps_sock_flow_table); | ||
2230 | |||
2231 | /* | ||
2232 | * get_rps_cpu is called from netif_receive_skb and returns the target | ||
2233 | * CPU from the RPS map of the receiving queue for a given skb. | ||
2234 | * rcu_read_lock must be held on entry. | ||
2235 | */ | ||
2236 | static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | ||
2237 | struct rps_dev_flow **rflowp) | ||
2238 | { | ||
2239 | struct ipv6hdr *ip6; | ||
2240 | struct iphdr *ip; | ||
2241 | struct netdev_rx_queue *rxqueue; | ||
2242 | struct rps_map *map; | ||
2243 | struct rps_dev_flow_table *flow_table; | ||
2244 | struct rps_sock_flow_table *sock_flow_table; | ||
2245 | int cpu = -1; | ||
2246 | u8 ip_proto; | ||
2247 | u16 tcpu; | ||
2248 | u32 addr1, addr2, ihl; | ||
2249 | union { | ||
2250 | u32 v32; | ||
2251 | u16 v16[2]; | ||
2252 | } ports; | ||
2253 | |||
2254 | if (skb_rx_queue_recorded(skb)) { | ||
2255 | u16 index = skb_get_rx_queue(skb); | ||
2256 | if (unlikely(index >= dev->num_rx_queues)) { | ||
2257 | if (net_ratelimit()) { | ||
2258 | pr_warning("%s received packet on queue " | ||
2259 | "%u, but number of RX queues is %u\n", | ||
2260 | dev->name, index, dev->num_rx_queues); | ||
2261 | } | ||
2262 | goto done; | ||
2263 | } | ||
2264 | rxqueue = dev->_rx + index; | ||
2265 | } else | ||
2266 | rxqueue = dev->_rx; | ||
2267 | |||
2268 | if (!rxqueue->rps_map && !rxqueue->rps_flow_table) | ||
2269 | goto done; | ||
2181 | 2270 | ||
2271 | if (skb->rxhash) | ||
2272 | goto got_hash; /* Skip hash computation on packet header */ | ||
2273 | |||
2274 | switch (skb->protocol) { | ||
2275 | case __constant_htons(ETH_P_IP): | ||
2276 | if (!pskb_may_pull(skb, sizeof(*ip))) | ||
2277 | goto done; | ||
2278 | |||
2279 | ip = (struct iphdr *) skb->data; | ||
2280 | ip_proto = ip->protocol; | ||
2281 | addr1 = (__force u32) ip->saddr; | ||
2282 | addr2 = (__force u32) ip->daddr; | ||
2283 | ihl = ip->ihl; | ||
2284 | break; | ||
2285 | case __constant_htons(ETH_P_IPV6): | ||
2286 | if (!pskb_may_pull(skb, sizeof(*ip6))) | ||
2287 | goto done; | ||
2288 | |||
2289 | ip6 = (struct ipv6hdr *) skb->data; | ||
2290 | ip_proto = ip6->nexthdr; | ||
2291 | addr1 = (__force u32) ip6->saddr.s6_addr32[3]; | ||
2292 | addr2 = (__force u32) ip6->daddr.s6_addr32[3]; | ||
2293 | ihl = (40 >> 2); | ||
2294 | break; | ||
2295 | default: | ||
2296 | goto done; | ||
2297 | } | ||
2298 | switch (ip_proto) { | ||
2299 | case IPPROTO_TCP: | ||
2300 | case IPPROTO_UDP: | ||
2301 | case IPPROTO_DCCP: | ||
2302 | case IPPROTO_ESP: | ||
2303 | case IPPROTO_AH: | ||
2304 | case IPPROTO_SCTP: | ||
2305 | case IPPROTO_UDPLITE: | ||
2306 | if (pskb_may_pull(skb, (ihl * 4) + 4)) { | ||
2307 | ports.v32 = * (__force u32 *) (skb->data + (ihl * 4)); | ||
2308 | if (ports.v16[1] < ports.v16[0]) | ||
2309 | swap(ports.v16[0], ports.v16[1]); | ||
2310 | break; | ||
2311 | } | ||
2312 | default: | ||
2313 | ports.v32 = 0; | ||
2314 | break; | ||
2315 | } | ||
2316 | |||
2317 | /* get a consistent hash (same value on both flow directions) */ | ||
2318 | if (addr2 < addr1) | ||
2319 | swap(addr1, addr2); | ||
2320 | skb->rxhash = jhash_3words(addr1, addr2, ports.v32, hashrnd); | ||
2321 | if (!skb->rxhash) | ||
2322 | skb->rxhash = 1; | ||
2323 | |||
2324 | got_hash: | ||
2325 | flow_table = rcu_dereference(rxqueue->rps_flow_table); | ||
2326 | sock_flow_table = rcu_dereference(rps_sock_flow_table); | ||
2327 | if (flow_table && sock_flow_table) { | ||
2328 | u16 next_cpu; | ||
2329 | struct rps_dev_flow *rflow; | ||
2330 | |||
2331 | rflow = &flow_table->flows[skb->rxhash & flow_table->mask]; | ||
2332 | tcpu = rflow->cpu; | ||
2333 | |||
2334 | next_cpu = sock_flow_table->ents[skb->rxhash & | ||
2335 | sock_flow_table->mask]; | ||
2336 | |||
2337 | /* | ||
2338 | * If the desired CPU (where last recvmsg was done) is | ||
2339 | * different from current CPU (one in the rx-queue flow | ||
2340 | * table entry), switch if one of the following holds: | ||
2341 | * - Current CPU is unset (equal to RPS_NO_CPU). | ||
2342 | * - Current CPU is offline. | ||
2343 | * - The current CPU's queue tail has advanced beyond the | ||
2344 | * last packet that was enqueued using this table entry. | ||
2345 | * This guarantees that all previous packets for the flow | ||
2346 | * have been dequeued, thus preserving in order delivery. | ||
2347 | */ | ||
2348 | if (unlikely(tcpu != next_cpu) && | ||
2349 | (tcpu == RPS_NO_CPU || !cpu_online(tcpu) || | ||
2350 | ((int)(per_cpu(softnet_data, tcpu).input_queue_head - | ||
2351 | rflow->last_qtail)) >= 0)) { | ||
2352 | tcpu = rflow->cpu = next_cpu; | ||
2353 | if (tcpu != RPS_NO_CPU) | ||
2354 | rflow->last_qtail = per_cpu(softnet_data, | ||
2355 | tcpu).input_queue_head; | ||
2356 | } | ||
2357 | if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) { | ||
2358 | *rflowp = rflow; | ||
2359 | cpu = tcpu; | ||
2360 | goto done; | ||
2361 | } | ||
2362 | } | ||
2363 | |||
2364 | map = rcu_dereference(rxqueue->rps_map); | ||
2365 | if (map) { | ||
2366 | tcpu = map->cpus[((u64) skb->rxhash * map->len) >> 32]; | ||
2367 | |||
2368 | if (cpu_online(tcpu)) { | ||
2369 | cpu = tcpu; | ||
2370 | goto done; | ||
2371 | } | ||
2372 | } | ||
2373 | |||
2374 | done: | ||
2375 | return cpu; | ||
2376 | } | ||
2377 | |||
2378 | /* Called from hardirq (IPI) context */ | ||
2379 | static void rps_trigger_softirq(void *data) | ||
2380 | { | ||
2381 | struct softnet_data *sd = data; | ||
2382 | |||
2383 | ____napi_schedule(sd, &sd->backlog); | ||
2384 | sd->received_rps++; | ||
2385 | } | ||
2386 | |||
2387 | #endif /* CONFIG_RPS */ | ||
2388 | |||
2389 | /* | ||
2390 | * Check if this softnet_data structure is another cpu one | ||
2391 | * If yes, queue it to our IPI list and return 1 | ||
2392 | * If no, return 0 | ||
2393 | */ | ||
2394 | static int rps_ipi_queued(struct softnet_data *sd) | ||
2395 | { | ||
2396 | #ifdef CONFIG_RPS | ||
2397 | struct softnet_data *mysd = &__get_cpu_var(softnet_data); | ||
2398 | |||
2399 | if (sd != mysd) { | ||
2400 | sd->rps_ipi_next = mysd->rps_ipi_list; | ||
2401 | mysd->rps_ipi_list = sd; | ||
2402 | |||
2403 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
2404 | return 1; | ||
2405 | } | ||
2406 | #endif /* CONFIG_RPS */ | ||
2407 | return 0; | ||
2408 | } | ||
2409 | |||
2410 | /* | ||
2411 | * enqueue_to_backlog is called to queue an skb to a per CPU backlog | ||
2412 | * queue (may be a remote CPU queue). | ||
2413 | */ | ||
2414 | static int enqueue_to_backlog(struct sk_buff *skb, int cpu, | ||
2415 | unsigned int *qtail) | ||
2416 | { | ||
2417 | struct softnet_data *sd; | ||
2418 | unsigned long flags; | ||
2419 | |||
2420 | sd = &per_cpu(softnet_data, cpu); | ||
2421 | |||
2422 | local_irq_save(flags); | ||
2423 | |||
2424 | rps_lock(sd); | ||
2425 | if (skb_queue_len(&sd->input_pkt_queue) <= netdev_max_backlog) { | ||
2426 | if (skb_queue_len(&sd->input_pkt_queue)) { | ||
2427 | enqueue: | ||
2428 | __skb_queue_tail(&sd->input_pkt_queue, skb); | ||
2429 | #ifdef CONFIG_RPS | ||
2430 | *qtail = sd->input_queue_head + | ||
2431 | skb_queue_len(&sd->input_pkt_queue); | ||
2432 | #endif | ||
2433 | rps_unlock(sd); | ||
2434 | local_irq_restore(flags); | ||
2435 | return NET_RX_SUCCESS; | ||
2436 | } | ||
2437 | |||
2438 | /* Schedule NAPI for backlog device | ||
2439 | * We can use non atomic operation since we own the queue lock | ||
2440 | */ | ||
2441 | if (!__test_and_set_bit(NAPI_STATE_SCHED, &sd->backlog.state)) { | ||
2442 | if (!rps_ipi_queued(sd)) | ||
2443 | ____napi_schedule(sd, &sd->backlog); | ||
2444 | } | ||
2445 | goto enqueue; | ||
2446 | } | ||
2447 | |||
2448 | sd->dropped++; | ||
2449 | rps_unlock(sd); | ||
2450 | |||
2451 | local_irq_restore(flags); | ||
2452 | |||
2453 | kfree_skb(skb); | ||
2454 | return NET_RX_DROP; | ||
2455 | } | ||
2182 | 2456 | ||
2183 | /** | 2457 | /** |
2184 | * netif_rx - post buffer to the network code | 2458 | * netif_rx - post buffer to the network code |
@@ -2197,41 +2471,38 @@ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; | |||
2197 | 2471 | ||
2198 | int netif_rx(struct sk_buff *skb) | 2472 | int netif_rx(struct sk_buff *skb) |
2199 | { | 2473 | { |
2200 | struct softnet_data *queue; | 2474 | int ret; |
2201 | unsigned long flags; | ||
2202 | 2475 | ||
2203 | /* if netpoll wants it, pretend we never saw it */ | 2476 | /* if netpoll wants it, pretend we never saw it */ |
2204 | if (netpoll_rx(skb)) | 2477 | if (netpoll_rx(skb)) |
2205 | return NET_RX_DROP; | 2478 | return NET_RX_DROP; |
2206 | 2479 | ||
2207 | if (!skb->tstamp.tv64) | 2480 | if (netdev_tstamp_prequeue) |
2208 | net_timestamp(skb); | 2481 | net_timestamp_check(skb); |
2209 | 2482 | ||
2210 | /* | 2483 | #ifdef CONFIG_RPS |
2211 | * The code is rearranged so that the path is the most | 2484 | { |
2212 | * short when CPU is congested, but is still operating. | 2485 | struct rps_dev_flow voidflow, *rflow = &voidflow; |
2213 | */ | 2486 | int cpu; |
2214 | local_irq_save(flags); | ||
2215 | queue = &__get_cpu_var(softnet_data); | ||
2216 | 2487 | ||
2217 | __get_cpu_var(netdev_rx_stat).total++; | 2488 | rcu_read_lock(); |
2218 | if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { | ||
2219 | if (queue->input_pkt_queue.qlen) { | ||
2220 | enqueue: | ||
2221 | __skb_queue_tail(&queue->input_pkt_queue, skb); | ||
2222 | local_irq_restore(flags); | ||
2223 | return NET_RX_SUCCESS; | ||
2224 | } | ||
2225 | 2489 | ||
2226 | napi_schedule(&queue->backlog); | 2490 | cpu = get_rps_cpu(skb->dev, skb, &rflow); |
2227 | goto enqueue; | 2491 | if (cpu < 0) |
2228 | } | 2492 | cpu = smp_processor_id(); |
2229 | 2493 | ||
2230 | __get_cpu_var(netdev_rx_stat).dropped++; | 2494 | ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); |
2231 | local_irq_restore(flags); | ||
2232 | 2495 | ||
2233 | kfree_skb(skb); | 2496 | rcu_read_unlock(); |
2234 | return NET_RX_DROP; | 2497 | } |
2498 | #else | ||
2499 | { | ||
2500 | unsigned int qtail; | ||
2501 | ret = enqueue_to_backlog(skb, get_cpu(), &qtail); | ||
2502 | put_cpu(); | ||
2503 | } | ||
2504 | #endif | ||
2505 | return ret; | ||
2235 | } | 2506 | } |
2236 | EXPORT_SYMBOL(netif_rx); | 2507 | EXPORT_SYMBOL(netif_rx); |
2237 | 2508 | ||
@@ -2276,6 +2547,7 @@ static void net_tx_action(struct softirq_action *h) | |||
2276 | local_irq_disable(); | 2547 | local_irq_disable(); |
2277 | head = sd->output_queue; | 2548 | head = sd->output_queue; |
2278 | sd->output_queue = NULL; | 2549 | sd->output_queue = NULL; |
2550 | sd->output_queue_tailp = &sd->output_queue; | ||
2279 | local_irq_enable(); | 2551 | local_irq_enable(); |
2280 | 2552 | ||
2281 | while (head) { | 2553 | while (head) { |
@@ -2352,7 +2624,8 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb, | |||
2352 | #endif | 2624 | #endif |
2353 | 2625 | ||
2354 | #if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE) | 2626 | #if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE) |
2355 | struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly; | 2627 | struct sk_buff *(*macvlan_handle_frame_hook)(struct macvlan_port *p, |
2628 | struct sk_buff *skb) __read_mostly; | ||
2356 | EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook); | 2629 | EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook); |
2357 | 2630 | ||
2358 | static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, | 2631 | static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, |
@@ -2360,14 +2633,17 @@ static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, | |||
2360 | int *ret, | 2633 | int *ret, |
2361 | struct net_device *orig_dev) | 2634 | struct net_device *orig_dev) |
2362 | { | 2635 | { |
2363 | if (skb->dev->macvlan_port == NULL) | 2636 | struct macvlan_port *port; |
2637 | |||
2638 | port = rcu_dereference(skb->dev->macvlan_port); | ||
2639 | if (!port) | ||
2364 | return skb; | 2640 | return skb; |
2365 | 2641 | ||
2366 | if (*pt_prev) { | 2642 | if (*pt_prev) { |
2367 | *ret = deliver_skb(skb, *pt_prev, orig_dev); | 2643 | *ret = deliver_skb(skb, *pt_prev, orig_dev); |
2368 | *pt_prev = NULL; | 2644 | *pt_prev = NULL; |
2369 | } | 2645 | } |
2370 | return macvlan_handle_frame_hook(skb); | 2646 | return macvlan_handle_frame_hook(port, skb); |
2371 | } | 2647 | } |
2372 | #else | 2648 | #else |
2373 | #define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb) | 2649 | #define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb) |
@@ -2468,22 +2744,56 @@ void netif_nit_deliver(struct sk_buff *skb) | |||
2468 | rcu_read_unlock(); | 2744 | rcu_read_unlock(); |
2469 | } | 2745 | } |
2470 | 2746 | ||
2471 | /** | 2747 | static inline void skb_bond_set_mac_by_master(struct sk_buff *skb, |
2472 | * netif_receive_skb - process receive buffer from network | 2748 | struct net_device *master) |
2473 | * @skb: buffer to process | 2749 | { |
2474 | * | 2750 | if (skb->pkt_type == PACKET_HOST) { |
2475 | * netif_receive_skb() is the main receive data processing function. | 2751 | u16 *dest = (u16 *) eth_hdr(skb)->h_dest; |
2476 | * It always succeeds. The buffer may be dropped during processing | 2752 | |
2477 | * for congestion control or by the protocol layers. | 2753 | memcpy(dest, master->dev_addr, ETH_ALEN); |
2478 | * | 2754 | } |
2479 | * This function may only be called from softirq context and interrupts | 2755 | } |
2480 | * should be enabled. | 2756 | |
2481 | * | 2757 | /* On bonding slaves other than the currently active slave, suppress |
2482 | * Return values (usually ignored): | 2758 | * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and |
2483 | * NET_RX_SUCCESS: no congestion | 2759 | * ARP on active-backup slaves with arp_validate enabled. |
2484 | * NET_RX_DROP: packet was dropped | ||
2485 | */ | 2760 | */ |
2486 | int netif_receive_skb(struct sk_buff *skb) | 2761 | int __skb_bond_should_drop(struct sk_buff *skb, struct net_device *master) |
2762 | { | ||
2763 | struct net_device *dev = skb->dev; | ||
2764 | |||
2765 | if (master->priv_flags & IFF_MASTER_ARPMON) | ||
2766 | dev->last_rx = jiffies; | ||
2767 | |||
2768 | if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) { | ||
2769 | /* Do address unmangle. The local destination address | ||
2770 | * will be always the one master has. Provides the right | ||
2771 | * functionality in a bridge. | ||
2772 | */ | ||
2773 | skb_bond_set_mac_by_master(skb, master); | ||
2774 | } | ||
2775 | |||
2776 | if (dev->priv_flags & IFF_SLAVE_INACTIVE) { | ||
2777 | if ((dev->priv_flags & IFF_SLAVE_NEEDARP) && | ||
2778 | skb->protocol == __cpu_to_be16(ETH_P_ARP)) | ||
2779 | return 0; | ||
2780 | |||
2781 | if (master->priv_flags & IFF_MASTER_ALB) { | ||
2782 | if (skb->pkt_type != PACKET_BROADCAST && | ||
2783 | skb->pkt_type != PACKET_MULTICAST) | ||
2784 | return 0; | ||
2785 | } | ||
2786 | if (master->priv_flags & IFF_MASTER_8023AD && | ||
2787 | skb->protocol == __cpu_to_be16(ETH_P_SLOW)) | ||
2788 | return 0; | ||
2789 | |||
2790 | return 1; | ||
2791 | } | ||
2792 | return 0; | ||
2793 | } | ||
2794 | EXPORT_SYMBOL(__skb_bond_should_drop); | ||
2795 | |||
2796 | static int __netif_receive_skb(struct sk_buff *skb) | ||
2487 | { | 2797 | { |
2488 | struct packet_type *ptype, *pt_prev; | 2798 | struct packet_type *ptype, *pt_prev; |
2489 | struct net_device *orig_dev; | 2799 | struct net_device *orig_dev; |
@@ -2493,8 +2803,8 @@ int netif_receive_skb(struct sk_buff *skb) | |||
2493 | int ret = NET_RX_DROP; | 2803 | int ret = NET_RX_DROP; |
2494 | __be16 type; | 2804 | __be16 type; |
2495 | 2805 | ||
2496 | if (!skb->tstamp.tv64) | 2806 | if (!netdev_tstamp_prequeue) |
2497 | net_timestamp(skb); | 2807 | net_timestamp_check(skb); |
2498 | 2808 | ||
2499 | if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb)) | 2809 | if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb)) |
2500 | return NET_RX_SUCCESS; | 2810 | return NET_RX_SUCCESS; |
@@ -2516,7 +2826,7 @@ int netif_receive_skb(struct sk_buff *skb) | |||
2516 | skb->dev = master; | 2826 | skb->dev = master; |
2517 | } | 2827 | } |
2518 | 2828 | ||
2519 | __get_cpu_var(netdev_rx_stat).total++; | 2829 | __get_cpu_var(softnet_data).processed++; |
2520 | 2830 | ||
2521 | skb_reset_network_header(skb); | 2831 | skb_reset_network_header(skb); |
2522 | skb_reset_transport_header(skb); | 2832 | skb_reset_transport_header(skb); |
@@ -2594,20 +2904,77 @@ out: | |||
2594 | rcu_read_unlock(); | 2904 | rcu_read_unlock(); |
2595 | return ret; | 2905 | return ret; |
2596 | } | 2906 | } |
2907 | |||
2908 | /** | ||
2909 | * netif_receive_skb - process receive buffer from network | ||
2910 | * @skb: buffer to process | ||
2911 | * | ||
2912 | * netif_receive_skb() is the main receive data processing function. | ||
2913 | * It always succeeds. The buffer may be dropped during processing | ||
2914 | * for congestion control or by the protocol layers. | ||
2915 | * | ||
2916 | * This function may only be called from softirq context and interrupts | ||
2917 | * should be enabled. | ||
2918 | * | ||
2919 | * Return values (usually ignored): | ||
2920 | * NET_RX_SUCCESS: no congestion | ||
2921 | * NET_RX_DROP: packet was dropped | ||
2922 | */ | ||
2923 | int netif_receive_skb(struct sk_buff *skb) | ||
2924 | { | ||
2925 | if (netdev_tstamp_prequeue) | ||
2926 | net_timestamp_check(skb); | ||
2927 | |||
2928 | #ifdef CONFIG_RPS | ||
2929 | { | ||
2930 | struct rps_dev_flow voidflow, *rflow = &voidflow; | ||
2931 | int cpu, ret; | ||
2932 | |||
2933 | rcu_read_lock(); | ||
2934 | |||
2935 | cpu = get_rps_cpu(skb->dev, skb, &rflow); | ||
2936 | |||
2937 | if (cpu >= 0) { | ||
2938 | ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); | ||
2939 | rcu_read_unlock(); | ||
2940 | } else { | ||
2941 | rcu_read_unlock(); | ||
2942 | ret = __netif_receive_skb(skb); | ||
2943 | } | ||
2944 | |||
2945 | return ret; | ||
2946 | } | ||
2947 | #else | ||
2948 | return __netif_receive_skb(skb); | ||
2949 | #endif | ||
2950 | } | ||
2597 | EXPORT_SYMBOL(netif_receive_skb); | 2951 | EXPORT_SYMBOL(netif_receive_skb); |
2598 | 2952 | ||
2599 | /* Network device is going away, flush any packets still pending */ | 2953 | /* Network device is going away, flush any packets still pending |
2954 | * Called with irqs disabled. | ||
2955 | */ | ||
2600 | static void flush_backlog(void *arg) | 2956 | static void flush_backlog(void *arg) |
2601 | { | 2957 | { |
2602 | struct net_device *dev = arg; | 2958 | struct net_device *dev = arg; |
2603 | struct softnet_data *queue = &__get_cpu_var(softnet_data); | 2959 | struct softnet_data *sd = &__get_cpu_var(softnet_data); |
2604 | struct sk_buff *skb, *tmp; | 2960 | struct sk_buff *skb, *tmp; |
2605 | 2961 | ||
2606 | skb_queue_walk_safe(&queue->input_pkt_queue, skb, tmp) | 2962 | rps_lock(sd); |
2963 | skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { | ||
2607 | if (skb->dev == dev) { | 2964 | if (skb->dev == dev) { |
2608 | __skb_unlink(skb, &queue->input_pkt_queue); | 2965 | __skb_unlink(skb, &sd->input_pkt_queue); |
2609 | kfree_skb(skb); | 2966 | kfree_skb(skb); |
2967 | input_queue_head_add(sd, 1); | ||
2610 | } | 2968 | } |
2969 | } | ||
2970 | rps_unlock(sd); | ||
2971 | |||
2972 | skb_queue_walk_safe(&sd->process_queue, skb, tmp) { | ||
2973 | if (skb->dev == dev) { | ||
2974 | __skb_unlink(skb, &sd->process_queue); | ||
2975 | kfree_skb(skb); | ||
2976 | } | ||
2977 | } | ||
2611 | } | 2978 | } |
2612 | 2979 | ||
2613 | static int napi_gro_complete(struct sk_buff *skb) | 2980 | static int napi_gro_complete(struct sk_buff *skb) |
@@ -2910,27 +3277,85 @@ gro_result_t napi_gro_frags(struct napi_struct *napi) | |||
2910 | } | 3277 | } |
2911 | EXPORT_SYMBOL(napi_gro_frags); | 3278 | EXPORT_SYMBOL(napi_gro_frags); |
2912 | 3279 | ||
3280 | /* | ||
3281 | * net_rps_action sends any pending IPI's for rps. | ||
3282 | * Note: called with local irq disabled, but exits with local irq enabled. | ||
3283 | */ | ||
3284 | static void net_rps_action_and_irq_enable(struct softnet_data *sd) | ||
3285 | { | ||
3286 | #ifdef CONFIG_RPS | ||
3287 | struct softnet_data *remsd = sd->rps_ipi_list; | ||
3288 | |||
3289 | if (remsd) { | ||
3290 | sd->rps_ipi_list = NULL; | ||
3291 | |||
3292 | local_irq_enable(); | ||
3293 | |||
3294 | /* Send pending IPI's to kick RPS processing on remote cpus. */ | ||
3295 | while (remsd) { | ||
3296 | struct softnet_data *next = remsd->rps_ipi_next; | ||
3297 | |||
3298 | if (cpu_online(remsd->cpu)) | ||
3299 | __smp_call_function_single(remsd->cpu, | ||
3300 | &remsd->csd, 0); | ||
3301 | remsd = next; | ||
3302 | } | ||
3303 | } else | ||
3304 | #endif | ||
3305 | local_irq_enable(); | ||
3306 | } | ||
3307 | |||
2913 | static int process_backlog(struct napi_struct *napi, int quota) | 3308 | static int process_backlog(struct napi_struct *napi, int quota) |
2914 | { | 3309 | { |
2915 | int work = 0; | 3310 | int work = 0; |
2916 | struct softnet_data *queue = &__get_cpu_var(softnet_data); | 3311 | struct softnet_data *sd = container_of(napi, struct softnet_data, backlog); |
2917 | unsigned long start_time = jiffies; | ||
2918 | 3312 | ||
3313 | #ifdef CONFIG_RPS | ||
3314 | /* Check if we have pending ipi, its better to send them now, | ||
3315 | * not waiting net_rx_action() end. | ||
3316 | */ | ||
3317 | if (sd->rps_ipi_list) { | ||
3318 | local_irq_disable(); | ||
3319 | net_rps_action_and_irq_enable(sd); | ||
3320 | } | ||
3321 | #endif | ||
2919 | napi->weight = weight_p; | 3322 | napi->weight = weight_p; |
2920 | do { | 3323 | local_irq_disable(); |
3324 | while (work < quota) { | ||
2921 | struct sk_buff *skb; | 3325 | struct sk_buff *skb; |
3326 | unsigned int qlen; | ||
2922 | 3327 | ||
2923 | local_irq_disable(); | 3328 | while ((skb = __skb_dequeue(&sd->process_queue))) { |
2924 | skb = __skb_dequeue(&queue->input_pkt_queue); | ||
2925 | if (!skb) { | ||
2926 | __napi_complete(napi); | ||
2927 | local_irq_enable(); | 3329 | local_irq_enable(); |
2928 | break; | 3330 | __netif_receive_skb(skb); |
3331 | if (++work >= quota) | ||
3332 | return work; | ||
3333 | local_irq_disable(); | ||
2929 | } | 3334 | } |
2930 | local_irq_enable(); | ||
2931 | 3335 | ||
2932 | netif_receive_skb(skb); | 3336 | rps_lock(sd); |
2933 | } while (++work < quota && jiffies == start_time); | 3337 | qlen = skb_queue_len(&sd->input_pkt_queue); |
3338 | if (qlen) { | ||
3339 | input_queue_head_add(sd, qlen); | ||
3340 | skb_queue_splice_tail_init(&sd->input_pkt_queue, | ||
3341 | &sd->process_queue); | ||
3342 | } | ||
3343 | if (qlen < quota - work) { | ||
3344 | /* | ||
3345 | * Inline a custom version of __napi_complete(). | ||
3346 | * only current cpu owns and manipulates this napi, | ||
3347 | * and NAPI_STATE_SCHED is the only possible flag set on backlog. | ||
3348 | * we can use a plain write instead of clear_bit(), | ||
3349 | * and we dont need an smp_mb() memory barrier. | ||
3350 | */ | ||
3351 | list_del(&napi->poll_list); | ||
3352 | napi->state = 0; | ||
3353 | |||
3354 | quota = work + qlen; | ||
3355 | } | ||
3356 | rps_unlock(sd); | ||
3357 | } | ||
3358 | local_irq_enable(); | ||
2934 | 3359 | ||
2935 | return work; | 3360 | return work; |
2936 | } | 3361 | } |
@@ -2946,8 +3371,7 @@ void __napi_schedule(struct napi_struct *n) | |||
2946 | unsigned long flags; | 3371 | unsigned long flags; |
2947 | 3372 | ||
2948 | local_irq_save(flags); | 3373 | local_irq_save(flags); |
2949 | list_add_tail(&n->poll_list, &__get_cpu_var(softnet_data).poll_list); | 3374 | ____napi_schedule(&__get_cpu_var(softnet_data), n); |
2950 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
2951 | local_irq_restore(flags); | 3375 | local_irq_restore(flags); |
2952 | } | 3376 | } |
2953 | EXPORT_SYMBOL(__napi_schedule); | 3377 | EXPORT_SYMBOL(__napi_schedule); |
@@ -3018,17 +3442,16 @@ void netif_napi_del(struct napi_struct *napi) | |||
3018 | } | 3442 | } |
3019 | EXPORT_SYMBOL(netif_napi_del); | 3443 | EXPORT_SYMBOL(netif_napi_del); |
3020 | 3444 | ||
3021 | |||
3022 | static void net_rx_action(struct softirq_action *h) | 3445 | static void net_rx_action(struct softirq_action *h) |
3023 | { | 3446 | { |
3024 | struct list_head *list = &__get_cpu_var(softnet_data).poll_list; | 3447 | struct softnet_data *sd = &__get_cpu_var(softnet_data); |
3025 | unsigned long time_limit = jiffies + 2; | 3448 | unsigned long time_limit = jiffies + 2; |
3026 | int budget = netdev_budget; | 3449 | int budget = netdev_budget; |
3027 | void *have; | 3450 | void *have; |
3028 | 3451 | ||
3029 | local_irq_disable(); | 3452 | local_irq_disable(); |
3030 | 3453 | ||
3031 | while (!list_empty(list)) { | 3454 | while (!list_empty(&sd->poll_list)) { |
3032 | struct napi_struct *n; | 3455 | struct napi_struct *n; |
3033 | int work, weight; | 3456 | int work, weight; |
3034 | 3457 | ||
@@ -3046,7 +3469,7 @@ static void net_rx_action(struct softirq_action *h) | |||
3046 | * entries to the tail of this list, and only ->poll() | 3469 | * entries to the tail of this list, and only ->poll() |
3047 | * calls can remove this head entry from the list. | 3470 | * calls can remove this head entry from the list. |
3048 | */ | 3471 | */ |
3049 | n = list_first_entry(list, struct napi_struct, poll_list); | 3472 | n = list_first_entry(&sd->poll_list, struct napi_struct, poll_list); |
3050 | 3473 | ||
3051 | have = netpoll_poll_lock(n); | 3474 | have = netpoll_poll_lock(n); |
3052 | 3475 | ||
@@ -3081,13 +3504,13 @@ static void net_rx_action(struct softirq_action *h) | |||
3081 | napi_complete(n); | 3504 | napi_complete(n); |
3082 | local_irq_disable(); | 3505 | local_irq_disable(); |
3083 | } else | 3506 | } else |
3084 | list_move_tail(&n->poll_list, list); | 3507 | list_move_tail(&n->poll_list, &sd->poll_list); |
3085 | } | 3508 | } |
3086 | 3509 | ||
3087 | netpoll_poll_unlock(have); | 3510 | netpoll_poll_unlock(have); |
3088 | } | 3511 | } |
3089 | out: | 3512 | out: |
3090 | local_irq_enable(); | 3513 | net_rps_action_and_irq_enable(sd); |
3091 | 3514 | ||
3092 | #ifdef CONFIG_NET_DMA | 3515 | #ifdef CONFIG_NET_DMA |
3093 | /* | 3516 | /* |
@@ -3100,7 +3523,7 @@ out: | |||
3100 | return; | 3523 | return; |
3101 | 3524 | ||
3102 | softnet_break: | 3525 | softnet_break: |
3103 | __get_cpu_var(netdev_rx_stat).time_squeeze++; | 3526 | sd->time_squeeze++; |
3104 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | 3527 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); |
3105 | goto out; | 3528 | goto out; |
3106 | } | 3529 | } |
@@ -3301,17 +3724,17 @@ static int dev_seq_show(struct seq_file *seq, void *v) | |||
3301 | return 0; | 3724 | return 0; |
3302 | } | 3725 | } |
3303 | 3726 | ||
3304 | static struct netif_rx_stats *softnet_get_online(loff_t *pos) | 3727 | static struct softnet_data *softnet_get_online(loff_t *pos) |
3305 | { | 3728 | { |
3306 | struct netif_rx_stats *rc = NULL; | 3729 | struct softnet_data *sd = NULL; |
3307 | 3730 | ||
3308 | while (*pos < nr_cpu_ids) | 3731 | while (*pos < nr_cpu_ids) |
3309 | if (cpu_online(*pos)) { | 3732 | if (cpu_online(*pos)) { |
3310 | rc = &per_cpu(netdev_rx_stat, *pos); | 3733 | sd = &per_cpu(softnet_data, *pos); |
3311 | break; | 3734 | break; |
3312 | } else | 3735 | } else |
3313 | ++*pos; | 3736 | ++*pos; |
3314 | return rc; | 3737 | return sd; |
3315 | } | 3738 | } |
3316 | 3739 | ||
3317 | static void *softnet_seq_start(struct seq_file *seq, loff_t *pos) | 3740 | static void *softnet_seq_start(struct seq_file *seq, loff_t *pos) |
@@ -3331,12 +3754,12 @@ static void softnet_seq_stop(struct seq_file *seq, void *v) | |||
3331 | 3754 | ||
3332 | static int softnet_seq_show(struct seq_file *seq, void *v) | 3755 | static int softnet_seq_show(struct seq_file *seq, void *v) |
3333 | { | 3756 | { |
3334 | struct netif_rx_stats *s = v; | 3757 | struct softnet_data *sd = v; |
3335 | 3758 | ||
3336 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n", | 3759 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", |
3337 | s->total, s->dropped, s->time_squeeze, 0, | 3760 | sd->processed, sd->dropped, sd->time_squeeze, 0, |
3338 | 0, 0, 0, 0, /* was fastroute */ | 3761 | 0, 0, 0, 0, /* was fastroute */ |
3339 | s->cpu_collision); | 3762 | sd->cpu_collision, sd->received_rps); |
3340 | return 0; | 3763 | return 0; |
3341 | } | 3764 | } |
3342 | 3765 | ||
@@ -3559,11 +3982,10 @@ int netdev_set_master(struct net_device *slave, struct net_device *master) | |||
3559 | 3982 | ||
3560 | slave->master = master; | 3983 | slave->master = master; |
3561 | 3984 | ||
3562 | synchronize_net(); | 3985 | if (old) { |
3563 | 3986 | synchronize_net(); | |
3564 | if (old) | ||
3565 | dev_put(old); | 3987 | dev_put(old); |
3566 | 3988 | } | |
3567 | if (master) | 3989 | if (master) |
3568 | slave->flags |= IFF_SLAVE; | 3990 | slave->flags |= IFF_SLAVE; |
3569 | else | 3991 | else |
@@ -3740,562 +4162,6 @@ void dev_set_rx_mode(struct net_device *dev) | |||
3740 | netif_addr_unlock_bh(dev); | 4162 | netif_addr_unlock_bh(dev); |
3741 | } | 4163 | } |
3742 | 4164 | ||
3743 | /* hw addresses list handling functions */ | ||
3744 | |||
3745 | static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, | ||
3746 | int addr_len, unsigned char addr_type) | ||
3747 | { | ||
3748 | struct netdev_hw_addr *ha; | ||
3749 | int alloc_size; | ||
3750 | |||
3751 | if (addr_len > MAX_ADDR_LEN) | ||
3752 | return -EINVAL; | ||
3753 | |||
3754 | list_for_each_entry(ha, &list->list, list) { | ||
3755 | if (!memcmp(ha->addr, addr, addr_len) && | ||
3756 | ha->type == addr_type) { | ||
3757 | ha->refcount++; | ||
3758 | return 0; | ||
3759 | } | ||
3760 | } | ||
3761 | |||
3762 | |||
3763 | alloc_size = sizeof(*ha); | ||
3764 | if (alloc_size < L1_CACHE_BYTES) | ||
3765 | alloc_size = L1_CACHE_BYTES; | ||
3766 | ha = kmalloc(alloc_size, GFP_ATOMIC); | ||
3767 | if (!ha) | ||
3768 | return -ENOMEM; | ||
3769 | memcpy(ha->addr, addr, addr_len); | ||
3770 | ha->type = addr_type; | ||
3771 | ha->refcount = 1; | ||
3772 | ha->synced = false; | ||
3773 | list_add_tail_rcu(&ha->list, &list->list); | ||
3774 | list->count++; | ||
3775 | return 0; | ||
3776 | } | ||
3777 | |||
3778 | static void ha_rcu_free(struct rcu_head *head) | ||
3779 | { | ||
3780 | struct netdev_hw_addr *ha; | ||
3781 | |||
3782 | ha = container_of(head, struct netdev_hw_addr, rcu_head); | ||
3783 | kfree(ha); | ||
3784 | } | ||
3785 | |||
3786 | static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, | ||
3787 | int addr_len, unsigned char addr_type) | ||
3788 | { | ||
3789 | struct netdev_hw_addr *ha; | ||
3790 | |||
3791 | list_for_each_entry(ha, &list->list, list) { | ||
3792 | if (!memcmp(ha->addr, addr, addr_len) && | ||
3793 | (ha->type == addr_type || !addr_type)) { | ||
3794 | if (--ha->refcount) | ||
3795 | return 0; | ||
3796 | list_del_rcu(&ha->list); | ||
3797 | call_rcu(&ha->rcu_head, ha_rcu_free); | ||
3798 | list->count--; | ||
3799 | return 0; | ||
3800 | } | ||
3801 | } | ||
3802 | return -ENOENT; | ||
3803 | } | ||
3804 | |||
3805 | static int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, | ||
3806 | struct netdev_hw_addr_list *from_list, | ||
3807 | int addr_len, | ||
3808 | unsigned char addr_type) | ||
3809 | { | ||
3810 | int err; | ||
3811 | struct netdev_hw_addr *ha, *ha2; | ||
3812 | unsigned char type; | ||
3813 | |||
3814 | list_for_each_entry(ha, &from_list->list, list) { | ||
3815 | type = addr_type ? addr_type : ha->type; | ||
3816 | err = __hw_addr_add(to_list, ha->addr, addr_len, type); | ||
3817 | if (err) | ||
3818 | goto unroll; | ||
3819 | } | ||
3820 | return 0; | ||
3821 | |||
3822 | unroll: | ||
3823 | list_for_each_entry(ha2, &from_list->list, list) { | ||
3824 | if (ha2 == ha) | ||
3825 | break; | ||
3826 | type = addr_type ? addr_type : ha2->type; | ||
3827 | __hw_addr_del(to_list, ha2->addr, addr_len, type); | ||
3828 | } | ||
3829 | return err; | ||
3830 | } | ||
3831 | |||
3832 | static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, | ||
3833 | struct netdev_hw_addr_list *from_list, | ||
3834 | int addr_len, | ||
3835 | unsigned char addr_type) | ||
3836 | { | ||
3837 | struct netdev_hw_addr *ha; | ||
3838 | unsigned char type; | ||
3839 | |||
3840 | list_for_each_entry(ha, &from_list->list, list) { | ||
3841 | type = addr_type ? addr_type : ha->type; | ||
3842 | __hw_addr_del(to_list, ha->addr, addr_len, addr_type); | ||
3843 | } | ||
3844 | } | ||
3845 | |||
3846 | static int __hw_addr_sync(struct netdev_hw_addr_list *to_list, | ||
3847 | struct netdev_hw_addr_list *from_list, | ||
3848 | int addr_len) | ||
3849 | { | ||
3850 | int err = 0; | ||
3851 | struct netdev_hw_addr *ha, *tmp; | ||
3852 | |||
3853 | list_for_each_entry_safe(ha, tmp, &from_list->list, list) { | ||
3854 | if (!ha->synced) { | ||
3855 | err = __hw_addr_add(to_list, ha->addr, | ||
3856 | addr_len, ha->type); | ||
3857 | if (err) | ||
3858 | break; | ||
3859 | ha->synced = true; | ||
3860 | ha->refcount++; | ||
3861 | } else if (ha->refcount == 1) { | ||
3862 | __hw_addr_del(to_list, ha->addr, addr_len, ha->type); | ||
3863 | __hw_addr_del(from_list, ha->addr, addr_len, ha->type); | ||
3864 | } | ||
3865 | } | ||
3866 | return err; | ||
3867 | } | ||
3868 | |||
3869 | static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, | ||
3870 | struct netdev_hw_addr_list *from_list, | ||
3871 | int addr_len) | ||
3872 | { | ||
3873 | struct netdev_hw_addr *ha, *tmp; | ||
3874 | |||
3875 | list_for_each_entry_safe(ha, tmp, &from_list->list, list) { | ||
3876 | if (ha->synced) { | ||
3877 | __hw_addr_del(to_list, ha->addr, | ||
3878 | addr_len, ha->type); | ||
3879 | ha->synced = false; | ||
3880 | __hw_addr_del(from_list, ha->addr, | ||
3881 | addr_len, ha->type); | ||
3882 | } | ||
3883 | } | ||
3884 | } | ||
3885 | |||
3886 | static void __hw_addr_flush(struct netdev_hw_addr_list *list) | ||
3887 | { | ||
3888 | struct netdev_hw_addr *ha, *tmp; | ||
3889 | |||
3890 | list_for_each_entry_safe(ha, tmp, &list->list, list) { | ||
3891 | list_del_rcu(&ha->list); | ||
3892 | call_rcu(&ha->rcu_head, ha_rcu_free); | ||
3893 | } | ||
3894 | list->count = 0; | ||
3895 | } | ||
3896 | |||
3897 | static void __hw_addr_init(struct netdev_hw_addr_list *list) | ||
3898 | { | ||
3899 | INIT_LIST_HEAD(&list->list); | ||
3900 | list->count = 0; | ||
3901 | } | ||
3902 | |||
3903 | /* Device addresses handling functions */ | ||
3904 | |||
3905 | static void dev_addr_flush(struct net_device *dev) | ||
3906 | { | ||
3907 | /* rtnl_mutex must be held here */ | ||
3908 | |||
3909 | __hw_addr_flush(&dev->dev_addrs); | ||
3910 | dev->dev_addr = NULL; | ||
3911 | } | ||
3912 | |||
3913 | static int dev_addr_init(struct net_device *dev) | ||
3914 | { | ||
3915 | unsigned char addr[MAX_ADDR_LEN]; | ||
3916 | struct netdev_hw_addr *ha; | ||
3917 | int err; | ||
3918 | |||
3919 | /* rtnl_mutex must be held here */ | ||
3920 | |||
3921 | __hw_addr_init(&dev->dev_addrs); | ||
3922 | memset(addr, 0, sizeof(addr)); | ||
3923 | err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr), | ||
3924 | NETDEV_HW_ADDR_T_LAN); | ||
3925 | if (!err) { | ||
3926 | /* | ||
3927 | * Get the first (previously created) address from the list | ||
3928 | * and set dev_addr pointer to this location. | ||
3929 | */ | ||
3930 | ha = list_first_entry(&dev->dev_addrs.list, | ||
3931 | struct netdev_hw_addr, list); | ||
3932 | dev->dev_addr = ha->addr; | ||
3933 | } | ||
3934 | return err; | ||
3935 | } | ||
3936 | |||
3937 | /** | ||
3938 | * dev_addr_add - Add a device address | ||
3939 | * @dev: device | ||
3940 | * @addr: address to add | ||
3941 | * @addr_type: address type | ||
3942 | * | ||
3943 | * Add a device address to the device or increase the reference count if | ||
3944 | * it already exists. | ||
3945 | * | ||
3946 | * The caller must hold the rtnl_mutex. | ||
3947 | */ | ||
3948 | int dev_addr_add(struct net_device *dev, unsigned char *addr, | ||
3949 | unsigned char addr_type) | ||
3950 | { | ||
3951 | int err; | ||
3952 | |||
3953 | ASSERT_RTNL(); | ||
3954 | |||
3955 | err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type); | ||
3956 | if (!err) | ||
3957 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | ||
3958 | return err; | ||
3959 | } | ||
3960 | EXPORT_SYMBOL(dev_addr_add); | ||
3961 | |||
3962 | /** | ||
3963 | * dev_addr_del - Release a device address. | ||
3964 | * @dev: device | ||
3965 | * @addr: address to delete | ||
3966 | * @addr_type: address type | ||
3967 | * | ||
3968 | * Release reference to a device address and remove it from the device | ||
3969 | * if the reference count drops to zero. | ||
3970 | * | ||
3971 | * The caller must hold the rtnl_mutex. | ||
3972 | */ | ||
3973 | int dev_addr_del(struct net_device *dev, unsigned char *addr, | ||
3974 | unsigned char addr_type) | ||
3975 | { | ||
3976 | int err; | ||
3977 | struct netdev_hw_addr *ha; | ||
3978 | |||
3979 | ASSERT_RTNL(); | ||
3980 | |||
3981 | /* | ||
3982 | * We can not remove the first address from the list because | ||
3983 | * dev->dev_addr points to that. | ||
3984 | */ | ||
3985 | ha = list_first_entry(&dev->dev_addrs.list, | ||
3986 | struct netdev_hw_addr, list); | ||
3987 | if (ha->addr == dev->dev_addr && ha->refcount == 1) | ||
3988 | return -ENOENT; | ||
3989 | |||
3990 | err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, | ||
3991 | addr_type); | ||
3992 | if (!err) | ||
3993 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | ||
3994 | return err; | ||
3995 | } | ||
3996 | EXPORT_SYMBOL(dev_addr_del); | ||
3997 | |||
3998 | /** | ||
3999 | * dev_addr_add_multiple - Add device addresses from another device | ||
4000 | * @to_dev: device to which addresses will be added | ||
4001 | * @from_dev: device from which addresses will be added | ||
4002 | * @addr_type: address type - 0 means type will be used from from_dev | ||
4003 | * | ||
4004 | * Add device addresses of the one device to another. | ||
4005 | ** | ||
4006 | * The caller must hold the rtnl_mutex. | ||
4007 | */ | ||
4008 | int dev_addr_add_multiple(struct net_device *to_dev, | ||
4009 | struct net_device *from_dev, | ||
4010 | unsigned char addr_type) | ||
4011 | { | ||
4012 | int err; | ||
4013 | |||
4014 | ASSERT_RTNL(); | ||
4015 | |||
4016 | if (from_dev->addr_len != to_dev->addr_len) | ||
4017 | return -EINVAL; | ||
4018 | err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, | ||
4019 | to_dev->addr_len, addr_type); | ||
4020 | if (!err) | ||
4021 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); | ||
4022 | return err; | ||
4023 | } | ||
4024 | EXPORT_SYMBOL(dev_addr_add_multiple); | ||
4025 | |||
4026 | /** | ||
4027 | * dev_addr_del_multiple - Delete device addresses by another device | ||
4028 | * @to_dev: device where the addresses will be deleted | ||
4029 | * @from_dev: device by which addresses the addresses will be deleted | ||
4030 | * @addr_type: address type - 0 means type will used from from_dev | ||
4031 | * | ||
4032 | * Deletes addresses in to device by the list of addresses in from device. | ||
4033 | * | ||
4034 | * The caller must hold the rtnl_mutex. | ||
4035 | */ | ||
4036 | int dev_addr_del_multiple(struct net_device *to_dev, | ||
4037 | struct net_device *from_dev, | ||
4038 | unsigned char addr_type) | ||
4039 | { | ||
4040 | ASSERT_RTNL(); | ||
4041 | |||
4042 | if (from_dev->addr_len != to_dev->addr_len) | ||
4043 | return -EINVAL; | ||
4044 | __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, | ||
4045 | to_dev->addr_len, addr_type); | ||
4046 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); | ||
4047 | return 0; | ||
4048 | } | ||
4049 | EXPORT_SYMBOL(dev_addr_del_multiple); | ||
4050 | |||
4051 | /* multicast addresses handling functions */ | ||
4052 | |||
4053 | int __dev_addr_delete(struct dev_addr_list **list, int *count, | ||
4054 | void *addr, int alen, int glbl) | ||
4055 | { | ||
4056 | struct dev_addr_list *da; | ||
4057 | |||
4058 | for (; (da = *list) != NULL; list = &da->next) { | ||
4059 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
4060 | alen == da->da_addrlen) { | ||
4061 | if (glbl) { | ||
4062 | int old_glbl = da->da_gusers; | ||
4063 | da->da_gusers = 0; | ||
4064 | if (old_glbl == 0) | ||
4065 | break; | ||
4066 | } | ||
4067 | if (--da->da_users) | ||
4068 | return 0; | ||
4069 | |||
4070 | *list = da->next; | ||
4071 | kfree(da); | ||
4072 | (*count)--; | ||
4073 | return 0; | ||
4074 | } | ||
4075 | } | ||
4076 | return -ENOENT; | ||
4077 | } | ||
4078 | |||
4079 | int __dev_addr_add(struct dev_addr_list **list, int *count, | ||
4080 | void *addr, int alen, int glbl) | ||
4081 | { | ||
4082 | struct dev_addr_list *da; | ||
4083 | |||
4084 | for (da = *list; da != NULL; da = da->next) { | ||
4085 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
4086 | da->da_addrlen == alen) { | ||
4087 | if (glbl) { | ||
4088 | int old_glbl = da->da_gusers; | ||
4089 | da->da_gusers = 1; | ||
4090 | if (old_glbl) | ||
4091 | return 0; | ||
4092 | } | ||
4093 | da->da_users++; | ||
4094 | return 0; | ||
4095 | } | ||
4096 | } | ||
4097 | |||
4098 | da = kzalloc(sizeof(*da), GFP_ATOMIC); | ||
4099 | if (da == NULL) | ||
4100 | return -ENOMEM; | ||
4101 | memcpy(da->da_addr, addr, alen); | ||
4102 | da->da_addrlen = alen; | ||
4103 | da->da_users = 1; | ||
4104 | da->da_gusers = glbl ? 1 : 0; | ||
4105 | da->next = *list; | ||
4106 | *list = da; | ||
4107 | (*count)++; | ||
4108 | return 0; | ||
4109 | } | ||
4110 | |||
4111 | /** | ||
4112 | * dev_unicast_delete - Release secondary unicast address. | ||
4113 | * @dev: device | ||
4114 | * @addr: address to delete | ||
4115 | * | ||
4116 | * Release reference to a secondary unicast address and remove it | ||
4117 | * from the device if the reference count drops to zero. | ||
4118 | * | ||
4119 | * The caller must hold the rtnl_mutex. | ||
4120 | */ | ||
4121 | int dev_unicast_delete(struct net_device *dev, void *addr) | ||
4122 | { | ||
4123 | int err; | ||
4124 | |||
4125 | ASSERT_RTNL(); | ||
4126 | |||
4127 | netif_addr_lock_bh(dev); | ||
4128 | err = __hw_addr_del(&dev->uc, addr, dev->addr_len, | ||
4129 | NETDEV_HW_ADDR_T_UNICAST); | ||
4130 | if (!err) | ||
4131 | __dev_set_rx_mode(dev); | ||
4132 | netif_addr_unlock_bh(dev); | ||
4133 | return err; | ||
4134 | } | ||
4135 | EXPORT_SYMBOL(dev_unicast_delete); | ||
4136 | |||
4137 | /** | ||
4138 | * dev_unicast_add - add a secondary unicast address | ||
4139 | * @dev: device | ||
4140 | * @addr: address to add | ||
4141 | * | ||
4142 | * Add a secondary unicast address to the device or increase | ||
4143 | * the reference count if it already exists. | ||
4144 | * | ||
4145 | * The caller must hold the rtnl_mutex. | ||
4146 | */ | ||
4147 | int dev_unicast_add(struct net_device *dev, void *addr) | ||
4148 | { | ||
4149 | int err; | ||
4150 | |||
4151 | ASSERT_RTNL(); | ||
4152 | |||
4153 | netif_addr_lock_bh(dev); | ||
4154 | err = __hw_addr_add(&dev->uc, addr, dev->addr_len, | ||
4155 | NETDEV_HW_ADDR_T_UNICAST); | ||
4156 | if (!err) | ||
4157 | __dev_set_rx_mode(dev); | ||
4158 | netif_addr_unlock_bh(dev); | ||
4159 | return err; | ||
4160 | } | ||
4161 | EXPORT_SYMBOL(dev_unicast_add); | ||
4162 | |||
4163 | int __dev_addr_sync(struct dev_addr_list **to, int *to_count, | ||
4164 | struct dev_addr_list **from, int *from_count) | ||
4165 | { | ||
4166 | struct dev_addr_list *da, *next; | ||
4167 | int err = 0; | ||
4168 | |||
4169 | da = *from; | ||
4170 | while (da != NULL) { | ||
4171 | next = da->next; | ||
4172 | if (!da->da_synced) { | ||
4173 | err = __dev_addr_add(to, to_count, | ||
4174 | da->da_addr, da->da_addrlen, 0); | ||
4175 | if (err < 0) | ||
4176 | break; | ||
4177 | da->da_synced = 1; | ||
4178 | da->da_users++; | ||
4179 | } else if (da->da_users == 1) { | ||
4180 | __dev_addr_delete(to, to_count, | ||
4181 | da->da_addr, da->da_addrlen, 0); | ||
4182 | __dev_addr_delete(from, from_count, | ||
4183 | da->da_addr, da->da_addrlen, 0); | ||
4184 | } | ||
4185 | da = next; | ||
4186 | } | ||
4187 | return err; | ||
4188 | } | ||
4189 | EXPORT_SYMBOL_GPL(__dev_addr_sync); | ||
4190 | |||
4191 | void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, | ||
4192 | struct dev_addr_list **from, int *from_count) | ||
4193 | { | ||
4194 | struct dev_addr_list *da, *next; | ||
4195 | |||
4196 | da = *from; | ||
4197 | while (da != NULL) { | ||
4198 | next = da->next; | ||
4199 | if (da->da_synced) { | ||
4200 | __dev_addr_delete(to, to_count, | ||
4201 | da->da_addr, da->da_addrlen, 0); | ||
4202 | da->da_synced = 0; | ||
4203 | __dev_addr_delete(from, from_count, | ||
4204 | da->da_addr, da->da_addrlen, 0); | ||
4205 | } | ||
4206 | da = next; | ||
4207 | } | ||
4208 | } | ||
4209 | EXPORT_SYMBOL_GPL(__dev_addr_unsync); | ||
4210 | |||
4211 | /** | ||
4212 | * dev_unicast_sync - Synchronize device's unicast list to another device | ||
4213 | * @to: destination device | ||
4214 | * @from: source device | ||
4215 | * | ||
4216 | * Add newly added addresses to the destination device and release | ||
4217 | * addresses that have no users left. The source device must be | ||
4218 | * locked by netif_tx_lock_bh. | ||
4219 | * | ||
4220 | * This function is intended to be called from the dev->set_rx_mode | ||
4221 | * function of layered software devices. | ||
4222 | */ | ||
4223 | int dev_unicast_sync(struct net_device *to, struct net_device *from) | ||
4224 | { | ||
4225 | int err = 0; | ||
4226 | |||
4227 | if (to->addr_len != from->addr_len) | ||
4228 | return -EINVAL; | ||
4229 | |||
4230 | netif_addr_lock_bh(to); | ||
4231 | err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); | ||
4232 | if (!err) | ||
4233 | __dev_set_rx_mode(to); | ||
4234 | netif_addr_unlock_bh(to); | ||
4235 | return err; | ||
4236 | } | ||
4237 | EXPORT_SYMBOL(dev_unicast_sync); | ||
4238 | |||
4239 | /** | ||
4240 | * dev_unicast_unsync - Remove synchronized addresses from the destination device | ||
4241 | * @to: destination device | ||
4242 | * @from: source device | ||
4243 | * | ||
4244 | * Remove all addresses that were added to the destination device by | ||
4245 | * dev_unicast_sync(). This function is intended to be called from the | ||
4246 | * dev->stop function of layered software devices. | ||
4247 | */ | ||
4248 | void dev_unicast_unsync(struct net_device *to, struct net_device *from) | ||
4249 | { | ||
4250 | if (to->addr_len != from->addr_len) | ||
4251 | return; | ||
4252 | |||
4253 | netif_addr_lock_bh(from); | ||
4254 | netif_addr_lock(to); | ||
4255 | __hw_addr_unsync(&to->uc, &from->uc, to->addr_len); | ||
4256 | __dev_set_rx_mode(to); | ||
4257 | netif_addr_unlock(to); | ||
4258 | netif_addr_unlock_bh(from); | ||
4259 | } | ||
4260 | EXPORT_SYMBOL(dev_unicast_unsync); | ||
4261 | |||
4262 | static void dev_unicast_flush(struct net_device *dev) | ||
4263 | { | ||
4264 | netif_addr_lock_bh(dev); | ||
4265 | __hw_addr_flush(&dev->uc); | ||
4266 | netif_addr_unlock_bh(dev); | ||
4267 | } | ||
4268 | |||
4269 | static void dev_unicast_init(struct net_device *dev) | ||
4270 | { | ||
4271 | __hw_addr_init(&dev->uc); | ||
4272 | } | ||
4273 | |||
4274 | |||
4275 | static void __dev_addr_discard(struct dev_addr_list **list) | ||
4276 | { | ||
4277 | struct dev_addr_list *tmp; | ||
4278 | |||
4279 | while (*list != NULL) { | ||
4280 | tmp = *list; | ||
4281 | *list = tmp->next; | ||
4282 | if (tmp->da_users > tmp->da_gusers) | ||
4283 | printk("__dev_addr_discard: address leakage! " | ||
4284 | "da_users=%d\n", tmp->da_users); | ||
4285 | kfree(tmp); | ||
4286 | } | ||
4287 | } | ||
4288 | |||
4289 | static void dev_addr_discard(struct net_device *dev) | ||
4290 | { | ||
4291 | netif_addr_lock_bh(dev); | ||
4292 | |||
4293 | __dev_addr_discard(&dev->mc_list); | ||
4294 | netdev_mc_count(dev) = 0; | ||
4295 | |||
4296 | netif_addr_unlock_bh(dev); | ||
4297 | } | ||
4298 | |||
4299 | /** | 4165 | /** |
4300 | * dev_get_flags - get flags reported to userspace | 4166 | * dev_get_flags - get flags reported to userspace |
4301 | * @dev: device | 4167 | * @dev: device |
@@ -4606,8 +4472,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
4606 | return -EINVAL; | 4472 | return -EINVAL; |
4607 | if (!netif_device_present(dev)) | 4473 | if (!netif_device_present(dev)) |
4608 | return -ENODEV; | 4474 | return -ENODEV; |
4609 | return dev_mc_add(dev, ifr->ifr_hwaddr.sa_data, | 4475 | return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data); |
4610 | dev->addr_len, 1); | ||
4611 | 4476 | ||
4612 | case SIOCDELMULTI: | 4477 | case SIOCDELMULTI: |
4613 | if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) || | 4478 | if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) || |
@@ -4615,8 +4480,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | |||
4615 | return -EINVAL; | 4480 | return -EINVAL; |
4616 | if (!netif_device_present(dev)) | 4481 | if (!netif_device_present(dev)) |
4617 | return -ENODEV; | 4482 | return -ENODEV; |
4618 | return dev_mc_delete(dev, ifr->ifr_hwaddr.sa_data, | 4483 | return dev_mc_del_global(dev, ifr->ifr_hwaddr.sa_data); |
4619 | dev->addr_len, 1); | ||
4620 | 4484 | ||
4621 | case SIOCSIFTXQLEN: | 4485 | case SIOCSIFTXQLEN: |
4622 | if (ifr->ifr_qlen < 0) | 4486 | if (ifr->ifr_qlen < 0) |
@@ -4923,8 +4787,8 @@ static void rollback_registered_many(struct list_head *head) | |||
4923 | /* | 4787 | /* |
4924 | * Flush the unicast and multicast chains | 4788 | * Flush the unicast and multicast chains |
4925 | */ | 4789 | */ |
4926 | dev_unicast_flush(dev); | 4790 | dev_uc_flush(dev); |
4927 | dev_addr_discard(dev); | 4791 | dev_mc_flush(dev); |
4928 | 4792 | ||
4929 | if (dev->netdev_ops->ndo_uninit) | 4793 | if (dev->netdev_ops->ndo_uninit) |
4930 | dev->netdev_ops->ndo_uninit(dev); | 4794 | dev->netdev_ops->ndo_uninit(dev); |
@@ -5073,6 +4937,24 @@ int register_netdevice(struct net_device *dev) | |||
5073 | 4937 | ||
5074 | dev->iflink = -1; | 4938 | dev->iflink = -1; |
5075 | 4939 | ||
4940 | #ifdef CONFIG_RPS | ||
4941 | if (!dev->num_rx_queues) { | ||
4942 | /* | ||
4943 | * Allocate a single RX queue if driver never called | ||
4944 | * alloc_netdev_mq | ||
4945 | */ | ||
4946 | |||
4947 | dev->_rx = kzalloc(sizeof(struct netdev_rx_queue), GFP_KERNEL); | ||
4948 | if (!dev->_rx) { | ||
4949 | ret = -ENOMEM; | ||
4950 | goto out; | ||
4951 | } | ||
4952 | |||
4953 | dev->_rx->first = dev->_rx; | ||
4954 | atomic_set(&dev->_rx->count, 1); | ||
4955 | dev->num_rx_queues = 1; | ||
4956 | } | ||
4957 | #endif | ||
5076 | /* Init, if this function is available */ | 4958 | /* Init, if this function is available */ |
5077 | if (dev->netdev_ops->ndo_init) { | 4959 | if (dev->netdev_ops->ndo_init) { |
5078 | ret = dev->netdev_ops->ndo_init(dev); | 4960 | ret = dev->netdev_ops->ndo_init(dev); |
@@ -5433,6 +5315,10 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5433 | struct net_device *dev; | 5315 | struct net_device *dev; |
5434 | size_t alloc_size; | 5316 | size_t alloc_size; |
5435 | struct net_device *p; | 5317 | struct net_device *p; |
5318 | #ifdef CONFIG_RPS | ||
5319 | struct netdev_rx_queue *rx; | ||
5320 | int i; | ||
5321 | #endif | ||
5436 | 5322 | ||
5437 | BUG_ON(strlen(name) >= sizeof(dev->name)); | 5323 | BUG_ON(strlen(name) >= sizeof(dev->name)); |
5438 | 5324 | ||
@@ -5458,13 +5344,32 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5458 | goto free_p; | 5344 | goto free_p; |
5459 | } | 5345 | } |
5460 | 5346 | ||
5347 | #ifdef CONFIG_RPS | ||
5348 | rx = kcalloc(queue_count, sizeof(struct netdev_rx_queue), GFP_KERNEL); | ||
5349 | if (!rx) { | ||
5350 | printk(KERN_ERR "alloc_netdev: Unable to allocate " | ||
5351 | "rx queues.\n"); | ||
5352 | goto free_tx; | ||
5353 | } | ||
5354 | |||
5355 | atomic_set(&rx->count, queue_count); | ||
5356 | |||
5357 | /* | ||
5358 | * Set a pointer to first element in the array which holds the | ||
5359 | * reference count. | ||
5360 | */ | ||
5361 | for (i = 0; i < queue_count; i++) | ||
5362 | rx[i].first = rx; | ||
5363 | #endif | ||
5364 | |||
5461 | dev = PTR_ALIGN(p, NETDEV_ALIGN); | 5365 | dev = PTR_ALIGN(p, NETDEV_ALIGN); |
5462 | dev->padded = (char *)dev - (char *)p; | 5366 | dev->padded = (char *)dev - (char *)p; |
5463 | 5367 | ||
5464 | if (dev_addr_init(dev)) | 5368 | if (dev_addr_init(dev)) |
5465 | goto free_tx; | 5369 | goto free_rx; |
5466 | 5370 | ||
5467 | dev_unicast_init(dev); | 5371 | dev_mc_init(dev); |
5372 | dev_uc_init(dev); | ||
5468 | 5373 | ||
5469 | dev_net_set(dev, &init_net); | 5374 | dev_net_set(dev, &init_net); |
5470 | 5375 | ||
@@ -5472,6 +5377,11 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5472 | dev->num_tx_queues = queue_count; | 5377 | dev->num_tx_queues = queue_count; |
5473 | dev->real_num_tx_queues = queue_count; | 5378 | dev->real_num_tx_queues = queue_count; |
5474 | 5379 | ||
5380 | #ifdef CONFIG_RPS | ||
5381 | dev->_rx = rx; | ||
5382 | dev->num_rx_queues = queue_count; | ||
5383 | #endif | ||
5384 | |||
5475 | dev->gso_max_size = GSO_MAX_SIZE; | 5385 | dev->gso_max_size = GSO_MAX_SIZE; |
5476 | 5386 | ||
5477 | netdev_init_queues(dev); | 5387 | netdev_init_queues(dev); |
@@ -5486,9 +5396,12 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5486 | strcpy(dev->name, name); | 5396 | strcpy(dev->name, name); |
5487 | return dev; | 5397 | return dev; |
5488 | 5398 | ||
5399 | free_rx: | ||
5400 | #ifdef CONFIG_RPS | ||
5401 | kfree(rx); | ||
5489 | free_tx: | 5402 | free_tx: |
5403 | #endif | ||
5490 | kfree(tx); | 5404 | kfree(tx); |
5491 | |||
5492 | free_p: | 5405 | free_p: |
5493 | kfree(p); | 5406 | kfree(p); |
5494 | return NULL; | 5407 | return NULL; |
@@ -5690,8 +5603,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
5690 | /* | 5603 | /* |
5691 | * Flush the unicast and multicast chains | 5604 | * Flush the unicast and multicast chains |
5692 | */ | 5605 | */ |
5693 | dev_unicast_flush(dev); | 5606 | dev_uc_flush(dev); |
5694 | dev_addr_discard(dev); | 5607 | dev_mc_flush(dev); |
5695 | 5608 | ||
5696 | netdev_unregister_kobject(dev); | 5609 | netdev_unregister_kobject(dev); |
5697 | 5610 | ||
@@ -5734,7 +5647,6 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
5734 | void *ocpu) | 5647 | void *ocpu) |
5735 | { | 5648 | { |
5736 | struct sk_buff **list_skb; | 5649 | struct sk_buff **list_skb; |
5737 | struct Qdisc **list_net; | ||
5738 | struct sk_buff *skb; | 5650 | struct sk_buff *skb; |
5739 | unsigned int cpu, oldcpu = (unsigned long)ocpu; | 5651 | unsigned int cpu, oldcpu = (unsigned long)ocpu; |
5740 | struct softnet_data *sd, *oldsd; | 5652 | struct softnet_data *sd, *oldsd; |
@@ -5755,19 +5667,23 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
5755 | *list_skb = oldsd->completion_queue; | 5667 | *list_skb = oldsd->completion_queue; |
5756 | oldsd->completion_queue = NULL; | 5668 | oldsd->completion_queue = NULL; |
5757 | 5669 | ||
5758 | /* Find end of our output_queue. */ | ||
5759 | list_net = &sd->output_queue; | ||
5760 | while (*list_net) | ||
5761 | list_net = &(*list_net)->next_sched; | ||
5762 | /* Append output queue from offline CPU. */ | 5670 | /* Append output queue from offline CPU. */ |
5763 | *list_net = oldsd->output_queue; | 5671 | if (oldsd->output_queue) { |
5764 | oldsd->output_queue = NULL; | 5672 | *sd->output_queue_tailp = oldsd->output_queue; |
5673 | sd->output_queue_tailp = oldsd->output_queue_tailp; | ||
5674 | oldsd->output_queue = NULL; | ||
5675 | oldsd->output_queue_tailp = &oldsd->output_queue; | ||
5676 | } | ||
5765 | 5677 | ||
5766 | raise_softirq_irqoff(NET_TX_SOFTIRQ); | 5678 | raise_softirq_irqoff(NET_TX_SOFTIRQ); |
5767 | local_irq_enable(); | 5679 | local_irq_enable(); |
5768 | 5680 | ||
5769 | /* Process offline CPU's input_pkt_queue */ | 5681 | /* Process offline CPU's input_pkt_queue */ |
5770 | while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) | 5682 | while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { |
5683 | netif_rx(skb); | ||
5684 | input_queue_head_add(oldsd, 1); | ||
5685 | } | ||
5686 | while ((skb = __skb_dequeue(&oldsd->process_queue))) | ||
5771 | netif_rx(skb); | 5687 | netif_rx(skb); |
5772 | 5688 | ||
5773 | return NOTIFY_OK; | 5689 | return NOTIFY_OK; |
@@ -5984,17 +5900,26 @@ static int __init net_dev_init(void) | |||
5984 | */ | 5900 | */ |
5985 | 5901 | ||
5986 | for_each_possible_cpu(i) { | 5902 | for_each_possible_cpu(i) { |
5987 | struct softnet_data *queue; | 5903 | struct softnet_data *sd = &per_cpu(softnet_data, i); |
5988 | 5904 | ||
5989 | queue = &per_cpu(softnet_data, i); | 5905 | memset(sd, 0, sizeof(*sd)); |
5990 | skb_queue_head_init(&queue->input_pkt_queue); | 5906 | skb_queue_head_init(&sd->input_pkt_queue); |
5991 | queue->completion_queue = NULL; | 5907 | skb_queue_head_init(&sd->process_queue); |
5992 | INIT_LIST_HEAD(&queue->poll_list); | 5908 | sd->completion_queue = NULL; |
5909 | INIT_LIST_HEAD(&sd->poll_list); | ||
5910 | sd->output_queue = NULL; | ||
5911 | sd->output_queue_tailp = &sd->output_queue; | ||
5912 | #ifdef CONFIG_RPS | ||
5913 | sd->csd.func = rps_trigger_softirq; | ||
5914 | sd->csd.info = sd; | ||
5915 | sd->csd.flags = 0; | ||
5916 | sd->cpu = i; | ||
5917 | #endif | ||
5993 | 5918 | ||
5994 | queue->backlog.poll = process_backlog; | 5919 | sd->backlog.poll = process_backlog; |
5995 | queue->backlog.weight = weight_p; | 5920 | sd->backlog.weight = weight_p; |
5996 | queue->backlog.gro_list = NULL; | 5921 | sd->backlog.gro_list = NULL; |
5997 | queue->backlog.gro_count = 0; | 5922 | sd->backlog.gro_count = 0; |
5998 | } | 5923 | } |
5999 | 5924 | ||
6000 | dev_boot_phase = 0; | 5925 | dev_boot_phase = 0; |
@@ -6029,7 +5954,7 @@ subsys_initcall(net_dev_init); | |||
6029 | 5954 | ||
6030 | static int __init initialize_hashrnd(void) | 5955 | static int __init initialize_hashrnd(void) |
6031 | { | 5956 | { |
6032 | get_random_bytes(&skb_tx_hashrnd, sizeof(skb_tx_hashrnd)); | 5957 | get_random_bytes(&hashrnd, sizeof(hashrnd)); |
6033 | return 0; | 5958 | return 0; |
6034 | } | 5959 | } |
6035 | 5960 | ||
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c new file mode 100644 index 000000000000..508f9c18992f --- /dev/null +++ b/net/core/dev_addr_lists.c | |||
@@ -0,0 +1,741 @@ | |||
1 | /* | ||
2 | * net/core/dev_addr_lists.c - Functions for handling net device lists | ||
3 | * Copyright (c) 2010 Jiri Pirko <jpirko@redhat.com> | ||
4 | * | ||
5 | * This file contains functions for working with unicast, multicast and device | ||
6 | * addresses lists. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/netdevice.h> | ||
15 | #include <linux/rtnetlink.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/proc_fs.h> | ||
18 | |||
19 | /* | ||
20 | * General list handling functions | ||
21 | */ | ||
22 | |||
23 | static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, | ||
24 | unsigned char *addr, int addr_len, | ||
25 | unsigned char addr_type, bool global) | ||
26 | { | ||
27 | struct netdev_hw_addr *ha; | ||
28 | int alloc_size; | ||
29 | |||
30 | if (addr_len > MAX_ADDR_LEN) | ||
31 | return -EINVAL; | ||
32 | |||
33 | list_for_each_entry(ha, &list->list, list) { | ||
34 | if (!memcmp(ha->addr, addr, addr_len) && | ||
35 | ha->type == addr_type) { | ||
36 | if (global) { | ||
37 | /* check if addr is already used as global */ | ||
38 | if (ha->global_use) | ||
39 | return 0; | ||
40 | else | ||
41 | ha->global_use = true; | ||
42 | } | ||
43 | ha->refcount++; | ||
44 | return 0; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | |||
49 | alloc_size = sizeof(*ha); | ||
50 | if (alloc_size < L1_CACHE_BYTES) | ||
51 | alloc_size = L1_CACHE_BYTES; | ||
52 | ha = kmalloc(alloc_size, GFP_ATOMIC); | ||
53 | if (!ha) | ||
54 | return -ENOMEM; | ||
55 | memcpy(ha->addr, addr, addr_len); | ||
56 | ha->type = addr_type; | ||
57 | ha->refcount = 1; | ||
58 | ha->global_use = global; | ||
59 | ha->synced = false; | ||
60 | list_add_tail_rcu(&ha->list, &list->list); | ||
61 | list->count++; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, | ||
66 | int addr_len, unsigned char addr_type) | ||
67 | { | ||
68 | return __hw_addr_add_ex(list, addr, addr_len, addr_type, false); | ||
69 | } | ||
70 | |||
71 | static void ha_rcu_free(struct rcu_head *head) | ||
72 | { | ||
73 | struct netdev_hw_addr *ha; | ||
74 | |||
75 | ha = container_of(head, struct netdev_hw_addr, rcu_head); | ||
76 | kfree(ha); | ||
77 | } | ||
78 | |||
79 | static int __hw_addr_del_ex(struct netdev_hw_addr_list *list, | ||
80 | unsigned char *addr, int addr_len, | ||
81 | unsigned char addr_type, bool global) | ||
82 | { | ||
83 | struct netdev_hw_addr *ha; | ||
84 | |||
85 | list_for_each_entry(ha, &list->list, list) { | ||
86 | if (!memcmp(ha->addr, addr, addr_len) && | ||
87 | (ha->type == addr_type || !addr_type)) { | ||
88 | if (global) { | ||
89 | if (!ha->global_use) | ||
90 | break; | ||
91 | else | ||
92 | ha->global_use = false; | ||
93 | } | ||
94 | if (--ha->refcount) | ||
95 | return 0; | ||
96 | list_del_rcu(&ha->list); | ||
97 | call_rcu(&ha->rcu_head, ha_rcu_free); | ||
98 | list->count--; | ||
99 | return 0; | ||
100 | } | ||
101 | } | ||
102 | return -ENOENT; | ||
103 | } | ||
104 | |||
105 | static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, | ||
106 | int addr_len, unsigned char addr_type) | ||
107 | { | ||
108 | return __hw_addr_del_ex(list, addr, addr_len, addr_type, false); | ||
109 | } | ||
110 | |||
111 | int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, | ||
112 | struct netdev_hw_addr_list *from_list, | ||
113 | int addr_len, unsigned char addr_type) | ||
114 | { | ||
115 | int err; | ||
116 | struct netdev_hw_addr *ha, *ha2; | ||
117 | unsigned char type; | ||
118 | |||
119 | list_for_each_entry(ha, &from_list->list, list) { | ||
120 | type = addr_type ? addr_type : ha->type; | ||
121 | err = __hw_addr_add(to_list, ha->addr, addr_len, type); | ||
122 | if (err) | ||
123 | goto unroll; | ||
124 | } | ||
125 | return 0; | ||
126 | |||
127 | unroll: | ||
128 | list_for_each_entry(ha2, &from_list->list, list) { | ||
129 | if (ha2 == ha) | ||
130 | break; | ||
131 | type = addr_type ? addr_type : ha2->type; | ||
132 | __hw_addr_del(to_list, ha2->addr, addr_len, type); | ||
133 | } | ||
134 | return err; | ||
135 | } | ||
136 | EXPORT_SYMBOL(__hw_addr_add_multiple); | ||
137 | |||
138 | void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, | ||
139 | struct netdev_hw_addr_list *from_list, | ||
140 | int addr_len, unsigned char addr_type) | ||
141 | { | ||
142 | struct netdev_hw_addr *ha; | ||
143 | unsigned char type; | ||
144 | |||
145 | list_for_each_entry(ha, &from_list->list, list) { | ||
146 | type = addr_type ? addr_type : ha->type; | ||
147 | __hw_addr_del(to_list, ha->addr, addr_len, addr_type); | ||
148 | } | ||
149 | } | ||
150 | EXPORT_SYMBOL(__hw_addr_del_multiple); | ||
151 | |||
152 | int __hw_addr_sync(struct netdev_hw_addr_list *to_list, | ||
153 | struct netdev_hw_addr_list *from_list, | ||
154 | int addr_len) | ||
155 | { | ||
156 | int err = 0; | ||
157 | struct netdev_hw_addr *ha, *tmp; | ||
158 | |||
159 | list_for_each_entry_safe(ha, tmp, &from_list->list, list) { | ||
160 | if (!ha->synced) { | ||
161 | err = __hw_addr_add(to_list, ha->addr, | ||
162 | addr_len, ha->type); | ||
163 | if (err) | ||
164 | break; | ||
165 | ha->synced = true; | ||
166 | ha->refcount++; | ||
167 | } else if (ha->refcount == 1) { | ||
168 | __hw_addr_del(to_list, ha->addr, addr_len, ha->type); | ||
169 | __hw_addr_del(from_list, ha->addr, addr_len, ha->type); | ||
170 | } | ||
171 | } | ||
172 | return err; | ||
173 | } | ||
174 | EXPORT_SYMBOL(__hw_addr_sync); | ||
175 | |||
176 | void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, | ||
177 | struct netdev_hw_addr_list *from_list, | ||
178 | int addr_len) | ||
179 | { | ||
180 | struct netdev_hw_addr *ha, *tmp; | ||
181 | |||
182 | list_for_each_entry_safe(ha, tmp, &from_list->list, list) { | ||
183 | if (ha->synced) { | ||
184 | __hw_addr_del(to_list, ha->addr, | ||
185 | addr_len, ha->type); | ||
186 | ha->synced = false; | ||
187 | __hw_addr_del(from_list, ha->addr, | ||
188 | addr_len, ha->type); | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | EXPORT_SYMBOL(__hw_addr_unsync); | ||
193 | |||
194 | void __hw_addr_flush(struct netdev_hw_addr_list *list) | ||
195 | { | ||
196 | struct netdev_hw_addr *ha, *tmp; | ||
197 | |||
198 | list_for_each_entry_safe(ha, tmp, &list->list, list) { | ||
199 | list_del_rcu(&ha->list); | ||
200 | call_rcu(&ha->rcu_head, ha_rcu_free); | ||
201 | } | ||
202 | list->count = 0; | ||
203 | } | ||
204 | EXPORT_SYMBOL(__hw_addr_flush); | ||
205 | |||
206 | void __hw_addr_init(struct netdev_hw_addr_list *list) | ||
207 | { | ||
208 | INIT_LIST_HEAD(&list->list); | ||
209 | list->count = 0; | ||
210 | } | ||
211 | EXPORT_SYMBOL(__hw_addr_init); | ||
212 | |||
213 | /* | ||
214 | * Device addresses handling functions | ||
215 | */ | ||
216 | |||
217 | /** | ||
218 | * dev_addr_flush - Flush device address list | ||
219 | * @dev: device | ||
220 | * | ||
221 | * Flush device address list and reset ->dev_addr. | ||
222 | * | ||
223 | * The caller must hold the rtnl_mutex. | ||
224 | */ | ||
225 | void dev_addr_flush(struct net_device *dev) | ||
226 | { | ||
227 | /* rtnl_mutex must be held here */ | ||
228 | |||
229 | __hw_addr_flush(&dev->dev_addrs); | ||
230 | dev->dev_addr = NULL; | ||
231 | } | ||
232 | EXPORT_SYMBOL(dev_addr_flush); | ||
233 | |||
234 | /** | ||
235 | * dev_addr_init - Init device address list | ||
236 | * @dev: device | ||
237 | * | ||
238 | * Init device address list and create the first element, | ||
239 | * used by ->dev_addr. | ||
240 | * | ||
241 | * The caller must hold the rtnl_mutex. | ||
242 | */ | ||
243 | int dev_addr_init(struct net_device *dev) | ||
244 | { | ||
245 | unsigned char addr[MAX_ADDR_LEN]; | ||
246 | struct netdev_hw_addr *ha; | ||
247 | int err; | ||
248 | |||
249 | /* rtnl_mutex must be held here */ | ||
250 | |||
251 | __hw_addr_init(&dev->dev_addrs); | ||
252 | memset(addr, 0, sizeof(addr)); | ||
253 | err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr), | ||
254 | NETDEV_HW_ADDR_T_LAN); | ||
255 | if (!err) { | ||
256 | /* | ||
257 | * Get the first (previously created) address from the list | ||
258 | * and set dev_addr pointer to this location. | ||
259 | */ | ||
260 | ha = list_first_entry(&dev->dev_addrs.list, | ||
261 | struct netdev_hw_addr, list); | ||
262 | dev->dev_addr = ha->addr; | ||
263 | } | ||
264 | return err; | ||
265 | } | ||
266 | EXPORT_SYMBOL(dev_addr_init); | ||
267 | |||
268 | /** | ||
269 | * dev_addr_add - Add a device address | ||
270 | * @dev: device | ||
271 | * @addr: address to add | ||
272 | * @addr_type: address type | ||
273 | * | ||
274 | * Add a device address to the device or increase the reference count if | ||
275 | * it already exists. | ||
276 | * | ||
277 | * The caller must hold the rtnl_mutex. | ||
278 | */ | ||
279 | int dev_addr_add(struct net_device *dev, unsigned char *addr, | ||
280 | unsigned char addr_type) | ||
281 | { | ||
282 | int err; | ||
283 | |||
284 | ASSERT_RTNL(); | ||
285 | |||
286 | err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type); | ||
287 | if (!err) | ||
288 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | ||
289 | return err; | ||
290 | } | ||
291 | EXPORT_SYMBOL(dev_addr_add); | ||
292 | |||
293 | /** | ||
294 | * dev_addr_del - Release a device address. | ||
295 | * @dev: device | ||
296 | * @addr: address to delete | ||
297 | * @addr_type: address type | ||
298 | * | ||
299 | * Release reference to a device address and remove it from the device | ||
300 | * if the reference count drops to zero. | ||
301 | * | ||
302 | * The caller must hold the rtnl_mutex. | ||
303 | */ | ||
304 | int dev_addr_del(struct net_device *dev, unsigned char *addr, | ||
305 | unsigned char addr_type) | ||
306 | { | ||
307 | int err; | ||
308 | struct netdev_hw_addr *ha; | ||
309 | |||
310 | ASSERT_RTNL(); | ||
311 | |||
312 | /* | ||
313 | * We can not remove the first address from the list because | ||
314 | * dev->dev_addr points to that. | ||
315 | */ | ||
316 | ha = list_first_entry(&dev->dev_addrs.list, | ||
317 | struct netdev_hw_addr, list); | ||
318 | if (ha->addr == dev->dev_addr && ha->refcount == 1) | ||
319 | return -ENOENT; | ||
320 | |||
321 | err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, | ||
322 | addr_type); | ||
323 | if (!err) | ||
324 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | ||
325 | return err; | ||
326 | } | ||
327 | EXPORT_SYMBOL(dev_addr_del); | ||
328 | |||
329 | /** | ||
330 | * dev_addr_add_multiple - Add device addresses from another device | ||
331 | * @to_dev: device to which addresses will be added | ||
332 | * @from_dev: device from which addresses will be added | ||
333 | * @addr_type: address type - 0 means type will be used from from_dev | ||
334 | * | ||
335 | * Add device addresses of the one device to another. | ||
336 | ** | ||
337 | * The caller must hold the rtnl_mutex. | ||
338 | */ | ||
339 | int dev_addr_add_multiple(struct net_device *to_dev, | ||
340 | struct net_device *from_dev, | ||
341 | unsigned char addr_type) | ||
342 | { | ||
343 | int err; | ||
344 | |||
345 | ASSERT_RTNL(); | ||
346 | |||
347 | if (from_dev->addr_len != to_dev->addr_len) | ||
348 | return -EINVAL; | ||
349 | err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, | ||
350 | to_dev->addr_len, addr_type); | ||
351 | if (!err) | ||
352 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); | ||
353 | return err; | ||
354 | } | ||
355 | EXPORT_SYMBOL(dev_addr_add_multiple); | ||
356 | |||
357 | /** | ||
358 | * dev_addr_del_multiple - Delete device addresses by another device | ||
359 | * @to_dev: device where the addresses will be deleted | ||
360 | * @from_dev: device by which addresses the addresses will be deleted | ||
361 | * @addr_type: address type - 0 means type will used from from_dev | ||
362 | * | ||
363 | * Deletes addresses in to device by the list of addresses in from device. | ||
364 | * | ||
365 | * The caller must hold the rtnl_mutex. | ||
366 | */ | ||
367 | int dev_addr_del_multiple(struct net_device *to_dev, | ||
368 | struct net_device *from_dev, | ||
369 | unsigned char addr_type) | ||
370 | { | ||
371 | ASSERT_RTNL(); | ||
372 | |||
373 | if (from_dev->addr_len != to_dev->addr_len) | ||
374 | return -EINVAL; | ||
375 | __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, | ||
376 | to_dev->addr_len, addr_type); | ||
377 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); | ||
378 | return 0; | ||
379 | } | ||
380 | EXPORT_SYMBOL(dev_addr_del_multiple); | ||
381 | |||
382 | /* | ||
383 | * Unicast list handling functions | ||
384 | */ | ||
385 | |||
386 | /** | ||
387 | * dev_uc_add - Add a secondary unicast address | ||
388 | * @dev: device | ||
389 | * @addr: address to add | ||
390 | * | ||
391 | * Add a secondary unicast address to the device or increase | ||
392 | * the reference count if it already exists. | ||
393 | */ | ||
394 | int dev_uc_add(struct net_device *dev, unsigned char *addr) | ||
395 | { | ||
396 | int err; | ||
397 | |||
398 | netif_addr_lock_bh(dev); | ||
399 | err = __hw_addr_add(&dev->uc, addr, dev->addr_len, | ||
400 | NETDEV_HW_ADDR_T_UNICAST); | ||
401 | if (!err) | ||
402 | __dev_set_rx_mode(dev); | ||
403 | netif_addr_unlock_bh(dev); | ||
404 | return err; | ||
405 | } | ||
406 | EXPORT_SYMBOL(dev_uc_add); | ||
407 | |||
408 | /** | ||
409 | * dev_uc_del - Release secondary unicast address. | ||
410 | * @dev: device | ||
411 | * @addr: address to delete | ||
412 | * | ||
413 | * Release reference to a secondary unicast address and remove it | ||
414 | * from the device if the reference count drops to zero. | ||
415 | */ | ||
416 | int dev_uc_del(struct net_device *dev, unsigned char *addr) | ||
417 | { | ||
418 | int err; | ||
419 | |||
420 | netif_addr_lock_bh(dev); | ||
421 | err = __hw_addr_del(&dev->uc, addr, dev->addr_len, | ||
422 | NETDEV_HW_ADDR_T_UNICAST); | ||
423 | if (!err) | ||
424 | __dev_set_rx_mode(dev); | ||
425 | netif_addr_unlock_bh(dev); | ||
426 | return err; | ||
427 | } | ||
428 | EXPORT_SYMBOL(dev_uc_del); | ||
429 | |||
430 | /** | ||
431 | * dev_uc_sync - Synchronize device's unicast list to another device | ||
432 | * @to: destination device | ||
433 | * @from: source device | ||
434 | * | ||
435 | * Add newly added addresses to the destination device and release | ||
436 | * addresses that have no users left. The source device must be | ||
437 | * locked by netif_tx_lock_bh. | ||
438 | * | ||
439 | * This function is intended to be called from the dev->set_rx_mode | ||
440 | * function of layered software devices. | ||
441 | */ | ||
442 | int dev_uc_sync(struct net_device *to, struct net_device *from) | ||
443 | { | ||
444 | int err = 0; | ||
445 | |||
446 | if (to->addr_len != from->addr_len) | ||
447 | return -EINVAL; | ||
448 | |||
449 | netif_addr_lock_bh(to); | ||
450 | err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); | ||
451 | if (!err) | ||
452 | __dev_set_rx_mode(to); | ||
453 | netif_addr_unlock_bh(to); | ||
454 | return err; | ||
455 | } | ||
456 | EXPORT_SYMBOL(dev_uc_sync); | ||
457 | |||
458 | /** | ||
459 | * dev_uc_unsync - Remove synchronized addresses from the destination device | ||
460 | * @to: destination device | ||
461 | * @from: source device | ||
462 | * | ||
463 | * Remove all addresses that were added to the destination device by | ||
464 | * dev_uc_sync(). This function is intended to be called from the | ||
465 | * dev->stop function of layered software devices. | ||
466 | */ | ||
467 | void dev_uc_unsync(struct net_device *to, struct net_device *from) | ||
468 | { | ||
469 | if (to->addr_len != from->addr_len) | ||
470 | return; | ||
471 | |||
472 | netif_addr_lock_bh(from); | ||
473 | netif_addr_lock(to); | ||
474 | __hw_addr_unsync(&to->uc, &from->uc, to->addr_len); | ||
475 | __dev_set_rx_mode(to); | ||
476 | netif_addr_unlock(to); | ||
477 | netif_addr_unlock_bh(from); | ||
478 | } | ||
479 | EXPORT_SYMBOL(dev_uc_unsync); | ||
480 | |||
481 | /** | ||
482 | * dev_uc_flush - Flush unicast addresses | ||
483 | * @dev: device | ||
484 | * | ||
485 | * Flush unicast addresses. | ||
486 | */ | ||
487 | void dev_uc_flush(struct net_device *dev) | ||
488 | { | ||
489 | netif_addr_lock_bh(dev); | ||
490 | __hw_addr_flush(&dev->uc); | ||
491 | netif_addr_unlock_bh(dev); | ||
492 | } | ||
493 | EXPORT_SYMBOL(dev_uc_flush); | ||
494 | |||
495 | /** | ||
496 | * dev_uc_flush - Init unicast address list | ||
497 | * @dev: device | ||
498 | * | ||
499 | * Init unicast address list. | ||
500 | */ | ||
501 | void dev_uc_init(struct net_device *dev) | ||
502 | { | ||
503 | __hw_addr_init(&dev->uc); | ||
504 | } | ||
505 | EXPORT_SYMBOL(dev_uc_init); | ||
506 | |||
507 | /* | ||
508 | * Multicast list handling functions | ||
509 | */ | ||
510 | |||
511 | static int __dev_mc_add(struct net_device *dev, unsigned char *addr, | ||
512 | bool global) | ||
513 | { | ||
514 | int err; | ||
515 | |||
516 | netif_addr_lock_bh(dev); | ||
517 | err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len, | ||
518 | NETDEV_HW_ADDR_T_MULTICAST, global); | ||
519 | if (!err) | ||
520 | __dev_set_rx_mode(dev); | ||
521 | netif_addr_unlock_bh(dev); | ||
522 | return err; | ||
523 | } | ||
524 | /** | ||
525 | * dev_mc_add - Add a multicast address | ||
526 | * @dev: device | ||
527 | * @addr: address to add | ||
528 | * | ||
529 | * Add a multicast address to the device or increase | ||
530 | * the reference count if it already exists. | ||
531 | */ | ||
532 | int dev_mc_add(struct net_device *dev, unsigned char *addr) | ||
533 | { | ||
534 | return __dev_mc_add(dev, addr, false); | ||
535 | } | ||
536 | EXPORT_SYMBOL(dev_mc_add); | ||
537 | |||
538 | /** | ||
539 | * dev_mc_add_global - Add a global multicast address | ||
540 | * @dev: device | ||
541 | * @addr: address to add | ||
542 | * | ||
543 | * Add a global multicast address to the device. | ||
544 | */ | ||
545 | int dev_mc_add_global(struct net_device *dev, unsigned char *addr) | ||
546 | { | ||
547 | return __dev_mc_add(dev, addr, true); | ||
548 | } | ||
549 | EXPORT_SYMBOL(dev_mc_add_global); | ||
550 | |||
551 | static int __dev_mc_del(struct net_device *dev, unsigned char *addr, | ||
552 | bool global) | ||
553 | { | ||
554 | int err; | ||
555 | |||
556 | netif_addr_lock_bh(dev); | ||
557 | err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len, | ||
558 | NETDEV_HW_ADDR_T_MULTICAST, global); | ||
559 | if (!err) | ||
560 | __dev_set_rx_mode(dev); | ||
561 | netif_addr_unlock_bh(dev); | ||
562 | return err; | ||
563 | } | ||
564 | |||
565 | /** | ||
566 | * dev_mc_del - Delete a multicast address. | ||
567 | * @dev: device | ||
568 | * @addr: address to delete | ||
569 | * | ||
570 | * Release reference to a multicast address and remove it | ||
571 | * from the device if the reference count drops to zero. | ||
572 | */ | ||
573 | int dev_mc_del(struct net_device *dev, unsigned char *addr) | ||
574 | { | ||
575 | return __dev_mc_del(dev, addr, false); | ||
576 | } | ||
577 | EXPORT_SYMBOL(dev_mc_del); | ||
578 | |||
579 | /** | ||
580 | * dev_mc_del_global - Delete a global multicast address. | ||
581 | * @dev: device | ||
582 | * @addr: address to delete | ||
583 | * | ||
584 | * Release reference to a multicast address and remove it | ||
585 | * from the device if the reference count drops to zero. | ||
586 | */ | ||
587 | int dev_mc_del_global(struct net_device *dev, unsigned char *addr) | ||
588 | { | ||
589 | return __dev_mc_del(dev, addr, true); | ||
590 | } | ||
591 | EXPORT_SYMBOL(dev_mc_del_global); | ||
592 | |||
593 | /** | ||
594 | * dev_mc_sync - Synchronize device's unicast list to another device | ||
595 | * @to: destination device | ||
596 | * @from: source device | ||
597 | * | ||
598 | * Add newly added addresses to the destination device and release | ||
599 | * addresses that have no users left. The source device must be | ||
600 | * locked by netif_tx_lock_bh. | ||
601 | * | ||
602 | * This function is intended to be called from the dev->set_multicast_list | ||
603 | * or dev->set_rx_mode function of layered software devices. | ||
604 | */ | ||
605 | int dev_mc_sync(struct net_device *to, struct net_device *from) | ||
606 | { | ||
607 | int err = 0; | ||
608 | |||
609 | if (to->addr_len != from->addr_len) | ||
610 | return -EINVAL; | ||
611 | |||
612 | netif_addr_lock_bh(to); | ||
613 | err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); | ||
614 | if (!err) | ||
615 | __dev_set_rx_mode(to); | ||
616 | netif_addr_unlock_bh(to); | ||
617 | return err; | ||
618 | } | ||
619 | EXPORT_SYMBOL(dev_mc_sync); | ||
620 | |||
621 | /** | ||
622 | * dev_mc_unsync - Remove synchronized addresses from the destination device | ||
623 | * @to: destination device | ||
624 | * @from: source device | ||
625 | * | ||
626 | * Remove all addresses that were added to the destination device by | ||
627 | * dev_mc_sync(). This function is intended to be called from the | ||
628 | * dev->stop function of layered software devices. | ||
629 | */ | ||
630 | void dev_mc_unsync(struct net_device *to, struct net_device *from) | ||
631 | { | ||
632 | if (to->addr_len != from->addr_len) | ||
633 | return; | ||
634 | |||
635 | netif_addr_lock_bh(from); | ||
636 | netif_addr_lock(to); | ||
637 | __hw_addr_unsync(&to->mc, &from->mc, to->addr_len); | ||
638 | __dev_set_rx_mode(to); | ||
639 | netif_addr_unlock(to); | ||
640 | netif_addr_unlock_bh(from); | ||
641 | } | ||
642 | EXPORT_SYMBOL(dev_mc_unsync); | ||
643 | |||
644 | /** | ||
645 | * dev_mc_flush - Flush multicast addresses | ||
646 | * @dev: device | ||
647 | * | ||
648 | * Flush multicast addresses. | ||
649 | */ | ||
650 | void dev_mc_flush(struct net_device *dev) | ||
651 | { | ||
652 | netif_addr_lock_bh(dev); | ||
653 | __hw_addr_flush(&dev->mc); | ||
654 | netif_addr_unlock_bh(dev); | ||
655 | } | ||
656 | EXPORT_SYMBOL(dev_mc_flush); | ||
657 | |||
658 | /** | ||
659 | * dev_mc_flush - Init multicast address list | ||
660 | * @dev: device | ||
661 | * | ||
662 | * Init multicast address list. | ||
663 | */ | ||
664 | void dev_mc_init(struct net_device *dev) | ||
665 | { | ||
666 | __hw_addr_init(&dev->mc); | ||
667 | } | ||
668 | EXPORT_SYMBOL(dev_mc_init); | ||
669 | |||
670 | #ifdef CONFIG_PROC_FS | ||
671 | #include <linux/seq_file.h> | ||
672 | |||
673 | static int dev_mc_seq_show(struct seq_file *seq, void *v) | ||
674 | { | ||
675 | struct netdev_hw_addr *ha; | ||
676 | struct net_device *dev = v; | ||
677 | |||
678 | if (v == SEQ_START_TOKEN) | ||
679 | return 0; | ||
680 | |||
681 | netif_addr_lock_bh(dev); | ||
682 | netdev_for_each_mc_addr(ha, dev) { | ||
683 | int i; | ||
684 | |||
685 | seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex, | ||
686 | dev->name, ha->refcount, ha->global_use); | ||
687 | |||
688 | for (i = 0; i < dev->addr_len; i++) | ||
689 | seq_printf(seq, "%02x", ha->addr[i]); | ||
690 | |||
691 | seq_putc(seq, '\n'); | ||
692 | } | ||
693 | netif_addr_unlock_bh(dev); | ||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static const struct seq_operations dev_mc_seq_ops = { | ||
698 | .start = dev_seq_start, | ||
699 | .next = dev_seq_next, | ||
700 | .stop = dev_seq_stop, | ||
701 | .show = dev_mc_seq_show, | ||
702 | }; | ||
703 | |||
704 | static int dev_mc_seq_open(struct inode *inode, struct file *file) | ||
705 | { | ||
706 | return seq_open_net(inode, file, &dev_mc_seq_ops, | ||
707 | sizeof(struct seq_net_private)); | ||
708 | } | ||
709 | |||
710 | static const struct file_operations dev_mc_seq_fops = { | ||
711 | .owner = THIS_MODULE, | ||
712 | .open = dev_mc_seq_open, | ||
713 | .read = seq_read, | ||
714 | .llseek = seq_lseek, | ||
715 | .release = seq_release_net, | ||
716 | }; | ||
717 | |||
718 | #endif | ||
719 | |||
720 | static int __net_init dev_mc_net_init(struct net *net) | ||
721 | { | ||
722 | if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops)) | ||
723 | return -ENOMEM; | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | static void __net_exit dev_mc_net_exit(struct net *net) | ||
728 | { | ||
729 | proc_net_remove(net, "dev_mcast"); | ||
730 | } | ||
731 | |||
732 | static struct pernet_operations __net_initdata dev_mc_net_ops = { | ||
733 | .init = dev_mc_net_init, | ||
734 | .exit = dev_mc_net_exit, | ||
735 | }; | ||
736 | |||
737 | void __init dev_mcast_init(void) | ||
738 | { | ||
739 | register_pernet_subsys(&dev_mc_net_ops); | ||
740 | } | ||
741 | |||
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c deleted file mode 100644 index 3dc295beb483..000000000000 --- a/net/core/dev_mcast.c +++ /dev/null | |||
@@ -1,232 +0,0 @@ | |||
1 | /* | ||
2 | * Linux NET3: Multicast List maintenance. | ||
3 | * | ||
4 | * Authors: | ||
5 | * Tim Kordas <tjk@nostromo.eeap.cwru.edu> | ||
6 | * Richard Underwood <richard@wuzz.demon.co.uk> | ||
7 | * | ||
8 | * Stir fried together from the IP multicast and CAP patches above | ||
9 | * Alan Cox <alan@lxorguk.ukuu.org.uk> | ||
10 | * | ||
11 | * Fixes: | ||
12 | * Alan Cox : Update the device on a real delete | ||
13 | * rather than any time but... | ||
14 | * Alan Cox : IFF_ALLMULTI support. | ||
15 | * Alan Cox : New format set_multicast_list() calls. | ||
16 | * Gleb Natapov : Remove dev_mc_lock. | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version | ||
21 | * 2 of the License, or (at your option) any later version. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <asm/uaccess.h> | ||
26 | #include <asm/system.h> | ||
27 | #include <linux/bitops.h> | ||
28 | #include <linux/types.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/string.h> | ||
31 | #include <linux/mm.h> | ||
32 | #include <linux/socket.h> | ||
33 | #include <linux/sockios.h> | ||
34 | #include <linux/in.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/if_ether.h> | ||
38 | #include <linux/inet.h> | ||
39 | #include <linux/netdevice.h> | ||
40 | #include <linux/etherdevice.h> | ||
41 | #include <linux/proc_fs.h> | ||
42 | #include <linux/seq_file.h> | ||
43 | #include <linux/init.h> | ||
44 | #include <net/net_namespace.h> | ||
45 | #include <net/ip.h> | ||
46 | #include <net/route.h> | ||
47 | #include <linux/skbuff.h> | ||
48 | #include <net/sock.h> | ||
49 | #include <net/arp.h> | ||
50 | |||
51 | |||
52 | /* | ||
53 | * Device multicast list maintenance. | ||
54 | * | ||
55 | * This is used both by IP and by the user level maintenance functions. | ||
56 | * Unlike BSD we maintain a usage count on a given multicast address so | ||
57 | * that a casual user application can add/delete multicasts used by | ||
58 | * protocols without doing damage to the protocols when it deletes the | ||
59 | * entries. It also helps IP as it tracks overlapping maps. | ||
60 | * | ||
61 | * Device mc lists are changed by bh at least if IPv6 is enabled, | ||
62 | * so that it must be bh protected. | ||
63 | * | ||
64 | * We block accesses to device mc filters with netif_tx_lock. | ||
65 | */ | ||
66 | |||
67 | /* | ||
68 | * Delete a device level multicast | ||
69 | */ | ||
70 | |||
71 | int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl) | ||
72 | { | ||
73 | int err; | ||
74 | |||
75 | netif_addr_lock_bh(dev); | ||
76 | err = __dev_addr_delete(&dev->mc_list, &dev->mc_count, | ||
77 | addr, alen, glbl); | ||
78 | if (!err) { | ||
79 | /* | ||
80 | * We have altered the list, so the card | ||
81 | * loaded filter is now wrong. Fix it | ||
82 | */ | ||
83 | |||
84 | __dev_set_rx_mode(dev); | ||
85 | } | ||
86 | netif_addr_unlock_bh(dev); | ||
87 | return err; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * Add a device level multicast | ||
92 | */ | ||
93 | |||
94 | int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | ||
95 | { | ||
96 | int err; | ||
97 | |||
98 | netif_addr_lock_bh(dev); | ||
99 | if (alen != dev->addr_len) | ||
100 | err = -EINVAL; | ||
101 | else | ||
102 | err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); | ||
103 | if (!err) | ||
104 | __dev_set_rx_mode(dev); | ||
105 | netif_addr_unlock_bh(dev); | ||
106 | return err; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * dev_mc_sync - Synchronize device's multicast list to another device | ||
111 | * @to: destination device | ||
112 | * @from: source device | ||
113 | * | ||
114 | * Add newly added addresses to the destination device and release | ||
115 | * addresses that have no users left. The source device must be | ||
116 | * locked by netif_tx_lock_bh. | ||
117 | * | ||
118 | * This function is intended to be called from the dev->set_multicast_list | ||
119 | * or dev->set_rx_mode function of layered software devices. | ||
120 | */ | ||
121 | int dev_mc_sync(struct net_device *to, struct net_device *from) | ||
122 | { | ||
123 | int err = 0; | ||
124 | |||
125 | netif_addr_lock_bh(to); | ||
126 | err = __dev_addr_sync(&to->mc_list, &to->mc_count, | ||
127 | &from->mc_list, &from->mc_count); | ||
128 | if (!err) | ||
129 | __dev_set_rx_mode(to); | ||
130 | netif_addr_unlock_bh(to); | ||
131 | |||
132 | return err; | ||
133 | } | ||
134 | EXPORT_SYMBOL(dev_mc_sync); | ||
135 | |||
136 | |||
137 | /** | ||
138 | * dev_mc_unsync - Remove synchronized addresses from the destination | ||
139 | * device | ||
140 | * @to: destination device | ||
141 | * @from: source device | ||
142 | * | ||
143 | * Remove all addresses that were added to the destination device by | ||
144 | * dev_mc_sync(). This function is intended to be called from the | ||
145 | * dev->stop function of layered software devices. | ||
146 | */ | ||
147 | void dev_mc_unsync(struct net_device *to, struct net_device *from) | ||
148 | { | ||
149 | netif_addr_lock_bh(from); | ||
150 | netif_addr_lock(to); | ||
151 | |||
152 | __dev_addr_unsync(&to->mc_list, &to->mc_count, | ||
153 | &from->mc_list, &from->mc_count); | ||
154 | __dev_set_rx_mode(to); | ||
155 | |||
156 | netif_addr_unlock(to); | ||
157 | netif_addr_unlock_bh(from); | ||
158 | } | ||
159 | EXPORT_SYMBOL(dev_mc_unsync); | ||
160 | |||
161 | #ifdef CONFIG_PROC_FS | ||
162 | static int dev_mc_seq_show(struct seq_file *seq, void *v) | ||
163 | { | ||
164 | struct dev_addr_list *m; | ||
165 | struct net_device *dev = v; | ||
166 | |||
167 | if (v == SEQ_START_TOKEN) | ||
168 | return 0; | ||
169 | |||
170 | netif_addr_lock_bh(dev); | ||
171 | for (m = dev->mc_list; m; m = m->next) { | ||
172 | int i; | ||
173 | |||
174 | seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex, | ||
175 | dev->name, m->dmi_users, m->dmi_gusers); | ||
176 | |||
177 | for (i = 0; i < m->dmi_addrlen; i++) | ||
178 | seq_printf(seq, "%02x", m->dmi_addr[i]); | ||
179 | |||
180 | seq_putc(seq, '\n'); | ||
181 | } | ||
182 | netif_addr_unlock_bh(dev); | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static const struct seq_operations dev_mc_seq_ops = { | ||
187 | .start = dev_seq_start, | ||
188 | .next = dev_seq_next, | ||
189 | .stop = dev_seq_stop, | ||
190 | .show = dev_mc_seq_show, | ||
191 | }; | ||
192 | |||
193 | static int dev_mc_seq_open(struct inode *inode, struct file *file) | ||
194 | { | ||
195 | return seq_open_net(inode, file, &dev_mc_seq_ops, | ||
196 | sizeof(struct seq_net_private)); | ||
197 | } | ||
198 | |||
199 | static const struct file_operations dev_mc_seq_fops = { | ||
200 | .owner = THIS_MODULE, | ||
201 | .open = dev_mc_seq_open, | ||
202 | .read = seq_read, | ||
203 | .llseek = seq_lseek, | ||
204 | .release = seq_release_net, | ||
205 | }; | ||
206 | |||
207 | #endif | ||
208 | |||
209 | static int __net_init dev_mc_net_init(struct net *net) | ||
210 | { | ||
211 | if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops)) | ||
212 | return -ENOMEM; | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static void __net_exit dev_mc_net_exit(struct net *net) | ||
217 | { | ||
218 | proc_net_remove(net, "dev_mcast"); | ||
219 | } | ||
220 | |||
221 | static struct pernet_operations __net_initdata dev_mc_net_ops = { | ||
222 | .init = dev_mc_net_init, | ||
223 | .exit = dev_mc_net_exit, | ||
224 | }; | ||
225 | |||
226 | void __init dev_mcast_init(void) | ||
227 | { | ||
228 | register_pernet_subsys(&dev_mc_net_ops); | ||
229 | } | ||
230 | |||
231 | EXPORT_SYMBOL(dev_mc_add); | ||
232 | EXPORT_SYMBOL(dev_mc_delete); | ||
diff --git a/net/core/dst.c b/net/core/dst.c index f307bc18f6a0..9920722cc82b 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
@@ -44,7 +44,7 @@ static atomic_t dst_total = ATOMIC_INIT(0); | |||
44 | */ | 44 | */ |
45 | static struct { | 45 | static struct { |
46 | spinlock_t lock; | 46 | spinlock_t lock; |
47 | struct dst_entry *list; | 47 | struct dst_entry *list; |
48 | unsigned long timer_inc; | 48 | unsigned long timer_inc; |
49 | unsigned long timer_expires; | 49 | unsigned long timer_expires; |
50 | } dst_garbage = { | 50 | } dst_garbage = { |
@@ -52,7 +52,7 @@ static struct { | |||
52 | .timer_inc = DST_GC_MAX, | 52 | .timer_inc = DST_GC_MAX, |
53 | }; | 53 | }; |
54 | static void dst_gc_task(struct work_struct *work); | 54 | static void dst_gc_task(struct work_struct *work); |
55 | static void ___dst_free(struct dst_entry * dst); | 55 | static void ___dst_free(struct dst_entry *dst); |
56 | 56 | ||
57 | static DECLARE_DELAYED_WORK(dst_gc_work, dst_gc_task); | 57 | static DECLARE_DELAYED_WORK(dst_gc_work, dst_gc_task); |
58 | 58 | ||
@@ -136,8 +136,8 @@ loop: | |||
136 | } | 136 | } |
137 | expires = dst_garbage.timer_expires; | 137 | expires = dst_garbage.timer_expires; |
138 | /* | 138 | /* |
139 | * if the next desired timer is more than 4 seconds in the future | 139 | * if the next desired timer is more than 4 seconds in the |
140 | * then round the timer to whole seconds | 140 | * future then round the timer to whole seconds |
141 | */ | 141 | */ |
142 | if (expires > 4*HZ) | 142 | if (expires > 4*HZ) |
143 | expires = round_jiffies_relative(expires); | 143 | expires = round_jiffies_relative(expires); |
@@ -152,7 +152,8 @@ loop: | |||
152 | " expires: %lu elapsed: %lu us\n", | 152 | " expires: %lu elapsed: %lu us\n", |
153 | atomic_read(&dst_total), delayed, work_performed, | 153 | atomic_read(&dst_total), delayed, work_performed, |
154 | expires, | 154 | expires, |
155 | elapsed.tv_sec * USEC_PER_SEC + elapsed.tv_nsec / NSEC_PER_USEC); | 155 | elapsed.tv_sec * USEC_PER_SEC + |
156 | elapsed.tv_nsec / NSEC_PER_USEC); | ||
156 | #endif | 157 | #endif |
157 | } | 158 | } |
158 | 159 | ||
@@ -163,9 +164,9 @@ int dst_discard(struct sk_buff *skb) | |||
163 | } | 164 | } |
164 | EXPORT_SYMBOL(dst_discard); | 165 | EXPORT_SYMBOL(dst_discard); |
165 | 166 | ||
166 | void * dst_alloc(struct dst_ops * ops) | 167 | void *dst_alloc(struct dst_ops *ops) |
167 | { | 168 | { |
168 | struct dst_entry * dst; | 169 | struct dst_entry *dst; |
169 | 170 | ||
170 | if (ops->gc && atomic_read(&ops->entries) > ops->gc_thresh) { | 171 | if (ops->gc && atomic_read(&ops->entries) > ops->gc_thresh) { |
171 | if (ops->gc(ops)) | 172 | if (ops->gc(ops)) |
@@ -185,19 +186,20 @@ void * dst_alloc(struct dst_ops * ops) | |||
185 | atomic_inc(&ops->entries); | 186 | atomic_inc(&ops->entries); |
186 | return dst; | 187 | return dst; |
187 | } | 188 | } |
189 | EXPORT_SYMBOL(dst_alloc); | ||
188 | 190 | ||
189 | static void ___dst_free(struct dst_entry * dst) | 191 | static void ___dst_free(struct dst_entry *dst) |
190 | { | 192 | { |
191 | /* The first case (dev==NULL) is required, when | 193 | /* The first case (dev==NULL) is required, when |
192 | protocol module is unloaded. | 194 | protocol module is unloaded. |
193 | */ | 195 | */ |
194 | if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) { | 196 | if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) |
195 | dst->input = dst->output = dst_discard; | 197 | dst->input = dst->output = dst_discard; |
196 | } | ||
197 | dst->obsolete = 2; | 198 | dst->obsolete = 2; |
198 | } | 199 | } |
200 | EXPORT_SYMBOL(__dst_free); | ||
199 | 201 | ||
200 | void __dst_free(struct dst_entry * dst) | 202 | void __dst_free(struct dst_entry *dst) |
201 | { | 203 | { |
202 | spin_lock_bh(&dst_garbage.lock); | 204 | spin_lock_bh(&dst_garbage.lock); |
203 | ___dst_free(dst); | 205 | ___dst_free(dst); |
@@ -262,15 +264,16 @@ again: | |||
262 | } | 264 | } |
263 | return NULL; | 265 | return NULL; |
264 | } | 266 | } |
267 | EXPORT_SYMBOL(dst_destroy); | ||
265 | 268 | ||
266 | void dst_release(struct dst_entry *dst) | 269 | void dst_release(struct dst_entry *dst) |
267 | { | 270 | { |
268 | if (dst) { | 271 | if (dst) { |
269 | int newrefcnt; | 272 | int newrefcnt; |
270 | 273 | ||
271 | smp_mb__before_atomic_dec(); | 274 | smp_mb__before_atomic_dec(); |
272 | newrefcnt = atomic_dec_return(&dst->__refcnt); | 275 | newrefcnt = atomic_dec_return(&dst->__refcnt); |
273 | WARN_ON(newrefcnt < 0); | 276 | WARN_ON(newrefcnt < 0); |
274 | } | 277 | } |
275 | } | 278 | } |
276 | EXPORT_SYMBOL(dst_release); | 279 | EXPORT_SYMBOL(dst_release); |
@@ -283,8 +286,8 @@ EXPORT_SYMBOL(dst_release); | |||
283 | * | 286 | * |
284 | * Commented and originally written by Alexey. | 287 | * Commented and originally written by Alexey. |
285 | */ | 288 | */ |
286 | static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev, | 289 | static void dst_ifdown(struct dst_entry *dst, struct net_device *dev, |
287 | int unregister) | 290 | int unregister) |
288 | { | 291 | { |
289 | if (dst->ops->ifdown) | 292 | if (dst->ops->ifdown) |
290 | dst->ops->ifdown(dst, dev, unregister); | 293 | dst->ops->ifdown(dst, dev, unregister); |
@@ -306,7 +309,8 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
306 | } | 309 | } |
307 | } | 310 | } |
308 | 311 | ||
309 | static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr) | 312 | static int dst_dev_event(struct notifier_block *this, unsigned long event, |
313 | void *ptr) | ||
310 | { | 314 | { |
311 | struct net_device *dev = ptr; | 315 | struct net_device *dev = ptr; |
312 | struct dst_entry *dst, *last = NULL; | 316 | struct dst_entry *dst, *last = NULL; |
@@ -329,9 +333,8 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void | |||
329 | last->next = dst; | 333 | last->next = dst; |
330 | else | 334 | else |
331 | dst_busy_list = dst; | 335 | dst_busy_list = dst; |
332 | for (; dst; dst = dst->next) { | 336 | for (; dst; dst = dst->next) |
333 | dst_ifdown(dst, dev, event != NETDEV_DOWN); | 337 | dst_ifdown(dst, dev, event != NETDEV_DOWN); |
334 | } | ||
335 | mutex_unlock(&dst_gc_mutex); | 338 | mutex_unlock(&dst_gc_mutex); |
336 | break; | 339 | break; |
337 | } | 340 | } |
@@ -346,7 +349,3 @@ void __init dst_init(void) | |||
346 | { | 349 | { |
347 | register_netdevice_notifier(&dst_dev_notifier); | 350 | register_netdevice_notifier(&dst_dev_notifier); |
348 | } | 351 | } |
349 | |||
350 | EXPORT_SYMBOL(__dst_free); | ||
351 | EXPORT_SYMBOL(dst_alloc); | ||
352 | EXPORT_SYMBOL(dst_destroy); | ||
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 9d55c57f318a..a0f4964033d2 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -18,8 +18,8 @@ | |||
18 | #include <linux/ethtool.h> | 18 | #include <linux/ethtool.h> |
19 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
20 | #include <linux/bitops.h> | 20 | #include <linux/bitops.h> |
21 | #include <linux/uaccess.h> | ||
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
22 | #include <asm/uaccess.h> | ||
23 | 23 | ||
24 | /* | 24 | /* |
25 | * Some useful ethtool_ops methods that're device independent. | 25 | * Some useful ethtool_ops methods that're device independent. |
@@ -31,6 +31,7 @@ u32 ethtool_op_get_link(struct net_device *dev) | |||
31 | { | 31 | { |
32 | return netif_carrier_ok(dev) ? 1 : 0; | 32 | return netif_carrier_ok(dev) ? 1 : 0; |
33 | } | 33 | } |
34 | EXPORT_SYMBOL(ethtool_op_get_link); | ||
34 | 35 | ||
35 | u32 ethtool_op_get_rx_csum(struct net_device *dev) | 36 | u32 ethtool_op_get_rx_csum(struct net_device *dev) |
36 | { | 37 | { |
@@ -63,6 +64,7 @@ int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data) | |||
63 | 64 | ||
64 | return 0; | 65 | return 0; |
65 | } | 66 | } |
67 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); | ||
66 | 68 | ||
67 | int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data) | 69 | int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data) |
68 | { | 70 | { |
@@ -73,11 +75,13 @@ int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data) | |||
73 | 75 | ||
74 | return 0; | 76 | return 0; |
75 | } | 77 | } |
78 | EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum); | ||
76 | 79 | ||
77 | u32 ethtool_op_get_sg(struct net_device *dev) | 80 | u32 ethtool_op_get_sg(struct net_device *dev) |
78 | { | 81 | { |
79 | return (dev->features & NETIF_F_SG) != 0; | 82 | return (dev->features & NETIF_F_SG) != 0; |
80 | } | 83 | } |
84 | EXPORT_SYMBOL(ethtool_op_get_sg); | ||
81 | 85 | ||
82 | int ethtool_op_set_sg(struct net_device *dev, u32 data) | 86 | int ethtool_op_set_sg(struct net_device *dev, u32 data) |
83 | { | 87 | { |
@@ -88,11 +92,13 @@ int ethtool_op_set_sg(struct net_device *dev, u32 data) | |||
88 | 92 | ||
89 | return 0; | 93 | return 0; |
90 | } | 94 | } |
95 | EXPORT_SYMBOL(ethtool_op_set_sg); | ||
91 | 96 | ||
92 | u32 ethtool_op_get_tso(struct net_device *dev) | 97 | u32 ethtool_op_get_tso(struct net_device *dev) |
93 | { | 98 | { |
94 | return (dev->features & NETIF_F_TSO) != 0; | 99 | return (dev->features & NETIF_F_TSO) != 0; |
95 | } | 100 | } |
101 | EXPORT_SYMBOL(ethtool_op_get_tso); | ||
96 | 102 | ||
97 | int ethtool_op_set_tso(struct net_device *dev, u32 data) | 103 | int ethtool_op_set_tso(struct net_device *dev, u32 data) |
98 | { | 104 | { |
@@ -103,11 +109,13 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data) | |||
103 | 109 | ||
104 | return 0; | 110 | return 0; |
105 | } | 111 | } |
112 | EXPORT_SYMBOL(ethtool_op_set_tso); | ||
106 | 113 | ||
107 | u32 ethtool_op_get_ufo(struct net_device *dev) | 114 | u32 ethtool_op_get_ufo(struct net_device *dev) |
108 | { | 115 | { |
109 | return (dev->features & NETIF_F_UFO) != 0; | 116 | return (dev->features & NETIF_F_UFO) != 0; |
110 | } | 117 | } |
118 | EXPORT_SYMBOL(ethtool_op_get_ufo); | ||
111 | 119 | ||
112 | int ethtool_op_set_ufo(struct net_device *dev, u32 data) | 120 | int ethtool_op_set_ufo(struct net_device *dev, u32 data) |
113 | { | 121 | { |
@@ -117,12 +125,13 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data) | |||
117 | dev->features &= ~NETIF_F_UFO; | 125 | dev->features &= ~NETIF_F_UFO; |
118 | return 0; | 126 | return 0; |
119 | } | 127 | } |
128 | EXPORT_SYMBOL(ethtool_op_set_ufo); | ||
120 | 129 | ||
121 | /* the following list of flags are the same as their associated | 130 | /* the following list of flags are the same as their associated |
122 | * NETIF_F_xxx values in include/linux/netdevice.h | 131 | * NETIF_F_xxx values in include/linux/netdevice.h |
123 | */ | 132 | */ |
124 | static const u32 flags_dup_features = | 133 | static const u32 flags_dup_features = |
125 | (ETH_FLAG_LRO | ETH_FLAG_NTUPLE); | 134 | (ETH_FLAG_LRO | ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH); |
126 | 135 | ||
127 | u32 ethtool_op_get_flags(struct net_device *dev) | 136 | u32 ethtool_op_get_flags(struct net_device *dev) |
128 | { | 137 | { |
@@ -133,6 +142,7 @@ u32 ethtool_op_get_flags(struct net_device *dev) | |||
133 | 142 | ||
134 | return dev->features & flags_dup_features; | 143 | return dev->features & flags_dup_features; |
135 | } | 144 | } |
145 | EXPORT_SYMBOL(ethtool_op_get_flags); | ||
136 | 146 | ||
137 | int ethtool_op_set_flags(struct net_device *dev, u32 data) | 147 | int ethtool_op_set_flags(struct net_device *dev, u32 data) |
138 | { | 148 | { |
@@ -153,9 +163,15 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data) | |||
153 | features &= ~NETIF_F_NTUPLE; | 163 | features &= ~NETIF_F_NTUPLE; |
154 | } | 164 | } |
155 | 165 | ||
166 | if (data & ETH_FLAG_RXHASH) | ||
167 | features |= NETIF_F_RXHASH; | ||
168 | else | ||
169 | features &= ~NETIF_F_RXHASH; | ||
170 | |||
156 | dev->features = features; | 171 | dev->features = features; |
157 | return 0; | 172 | return 0; |
158 | } | 173 | } |
174 | EXPORT_SYMBOL(ethtool_op_set_flags); | ||
159 | 175 | ||
160 | void ethtool_ntuple_flush(struct net_device *dev) | 176 | void ethtool_ntuple_flush(struct net_device *dev) |
161 | { | 177 | { |
@@ -201,7 +217,8 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) | |||
201 | return dev->ethtool_ops->set_settings(dev, &cmd); | 217 | return dev->ethtool_ops->set_settings(dev, &cmd); |
202 | } | 218 | } |
203 | 219 | ||
204 | static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) | 220 | static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, |
221 | void __user *useraddr) | ||
205 | { | 222 | { |
206 | struct ethtool_drvinfo info; | 223 | struct ethtool_drvinfo info; |
207 | const struct ethtool_ops *ops = dev->ethtool_ops; | 224 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -241,7 +258,7 @@ static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, void _ | |||
241 | } | 258 | } |
242 | 259 | ||
243 | static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev, | 260 | static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev, |
244 | void __user *useraddr) | 261 | void __user *useraddr) |
245 | { | 262 | { |
246 | struct ethtool_sset_info info; | 263 | struct ethtool_sset_info info; |
247 | const struct ethtool_ops *ops = dev->ethtool_ops; | 264 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -300,7 +317,8 @@ out: | |||
300 | return ret; | 317 | return ret; |
301 | } | 318 | } |
302 | 319 | ||
303 | static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) | 320 | static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, |
321 | void __user *useraddr) | ||
304 | { | 322 | { |
305 | struct ethtool_rxnfc cmd; | 323 | struct ethtool_rxnfc cmd; |
306 | 324 | ||
@@ -313,7 +331,8 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, void __u | |||
313 | return dev->ethtool_ops->set_rxnfc(dev, &cmd); | 331 | return dev->ethtool_ops->set_rxnfc(dev, &cmd); |
314 | } | 332 | } |
315 | 333 | ||
316 | static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) | 334 | static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, |
335 | void __user *useraddr) | ||
317 | { | 336 | { |
318 | struct ethtool_rxnfc info; | 337 | struct ethtool_rxnfc info; |
319 | const struct ethtool_ops *ops = dev->ethtool_ops; | 338 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -358,8 +377,8 @@ err_out: | |||
358 | } | 377 | } |
359 | 378 | ||
360 | static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, | 379 | static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, |
361 | struct ethtool_rx_ntuple_flow_spec *spec, | 380 | struct ethtool_rx_ntuple_flow_spec *spec, |
362 | struct ethtool_rx_ntuple_flow_spec_container *fsc) | 381 | struct ethtool_rx_ntuple_flow_spec_container *fsc) |
363 | { | 382 | { |
364 | 383 | ||
365 | /* don't add filters forever */ | 384 | /* don't add filters forever */ |
@@ -385,7 +404,8 @@ static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, | |||
385 | list->count++; | 404 | list->count++; |
386 | } | 405 | } |
387 | 406 | ||
388 | static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) | 407 | static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, |
408 | void __user *useraddr) | ||
389 | { | 409 | { |
390 | struct ethtool_rx_ntuple cmd; | 410 | struct ethtool_rx_ntuple cmd; |
391 | const struct ethtool_ops *ops = dev->ethtool_ops; | 411 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -502,7 +522,7 @@ static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr) | |||
502 | p += ETH_GSTRING_LEN; | 522 | p += ETH_GSTRING_LEN; |
503 | num_strings++; | 523 | num_strings++; |
504 | goto unknown_filter; | 524 | goto unknown_filter; |
505 | }; | 525 | } |
506 | 526 | ||
507 | /* now the rest of the filters */ | 527 | /* now the rest of the filters */ |
508 | switch (fsc->fs.flow_type) { | 528 | switch (fsc->fs.flow_type) { |
@@ -510,125 +530,125 @@ static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr) | |||
510 | case UDP_V4_FLOW: | 530 | case UDP_V4_FLOW: |
511 | case SCTP_V4_FLOW: | 531 | case SCTP_V4_FLOW: |
512 | sprintf(p, "\tSrc IP addr: 0x%x\n", | 532 | sprintf(p, "\tSrc IP addr: 0x%x\n", |
513 | fsc->fs.h_u.tcp_ip4_spec.ip4src); | 533 | fsc->fs.h_u.tcp_ip4_spec.ip4src); |
514 | p += ETH_GSTRING_LEN; | 534 | p += ETH_GSTRING_LEN; |
515 | num_strings++; | 535 | num_strings++; |
516 | sprintf(p, "\tSrc IP mask: 0x%x\n", | 536 | sprintf(p, "\tSrc IP mask: 0x%x\n", |
517 | fsc->fs.m_u.tcp_ip4_spec.ip4src); | 537 | fsc->fs.m_u.tcp_ip4_spec.ip4src); |
518 | p += ETH_GSTRING_LEN; | 538 | p += ETH_GSTRING_LEN; |
519 | num_strings++; | 539 | num_strings++; |
520 | sprintf(p, "\tDest IP addr: 0x%x\n", | 540 | sprintf(p, "\tDest IP addr: 0x%x\n", |
521 | fsc->fs.h_u.tcp_ip4_spec.ip4dst); | 541 | fsc->fs.h_u.tcp_ip4_spec.ip4dst); |
522 | p += ETH_GSTRING_LEN; | 542 | p += ETH_GSTRING_LEN; |
523 | num_strings++; | 543 | num_strings++; |
524 | sprintf(p, "\tDest IP mask: 0x%x\n", | 544 | sprintf(p, "\tDest IP mask: 0x%x\n", |
525 | fsc->fs.m_u.tcp_ip4_spec.ip4dst); | 545 | fsc->fs.m_u.tcp_ip4_spec.ip4dst); |
526 | p += ETH_GSTRING_LEN; | 546 | p += ETH_GSTRING_LEN; |
527 | num_strings++; | 547 | num_strings++; |
528 | sprintf(p, "\tSrc Port: %d, mask: 0x%x\n", | 548 | sprintf(p, "\tSrc Port: %d, mask: 0x%x\n", |
529 | fsc->fs.h_u.tcp_ip4_spec.psrc, | 549 | fsc->fs.h_u.tcp_ip4_spec.psrc, |
530 | fsc->fs.m_u.tcp_ip4_spec.psrc); | 550 | fsc->fs.m_u.tcp_ip4_spec.psrc); |
531 | p += ETH_GSTRING_LEN; | 551 | p += ETH_GSTRING_LEN; |
532 | num_strings++; | 552 | num_strings++; |
533 | sprintf(p, "\tDest Port: %d, mask: 0x%x\n", | 553 | sprintf(p, "\tDest Port: %d, mask: 0x%x\n", |
534 | fsc->fs.h_u.tcp_ip4_spec.pdst, | 554 | fsc->fs.h_u.tcp_ip4_spec.pdst, |
535 | fsc->fs.m_u.tcp_ip4_spec.pdst); | 555 | fsc->fs.m_u.tcp_ip4_spec.pdst); |
536 | p += ETH_GSTRING_LEN; | 556 | p += ETH_GSTRING_LEN; |
537 | num_strings++; | 557 | num_strings++; |
538 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", | 558 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", |
539 | fsc->fs.h_u.tcp_ip4_spec.tos, | 559 | fsc->fs.h_u.tcp_ip4_spec.tos, |
540 | fsc->fs.m_u.tcp_ip4_spec.tos); | 560 | fsc->fs.m_u.tcp_ip4_spec.tos); |
541 | p += ETH_GSTRING_LEN; | 561 | p += ETH_GSTRING_LEN; |
542 | num_strings++; | 562 | num_strings++; |
543 | break; | 563 | break; |
544 | case AH_ESP_V4_FLOW: | 564 | case AH_ESP_V4_FLOW: |
545 | case ESP_V4_FLOW: | 565 | case ESP_V4_FLOW: |
546 | sprintf(p, "\tSrc IP addr: 0x%x\n", | 566 | sprintf(p, "\tSrc IP addr: 0x%x\n", |
547 | fsc->fs.h_u.ah_ip4_spec.ip4src); | 567 | fsc->fs.h_u.ah_ip4_spec.ip4src); |
548 | p += ETH_GSTRING_LEN; | 568 | p += ETH_GSTRING_LEN; |
549 | num_strings++; | 569 | num_strings++; |
550 | sprintf(p, "\tSrc IP mask: 0x%x\n", | 570 | sprintf(p, "\tSrc IP mask: 0x%x\n", |
551 | fsc->fs.m_u.ah_ip4_spec.ip4src); | 571 | fsc->fs.m_u.ah_ip4_spec.ip4src); |
552 | p += ETH_GSTRING_LEN; | 572 | p += ETH_GSTRING_LEN; |
553 | num_strings++; | 573 | num_strings++; |
554 | sprintf(p, "\tDest IP addr: 0x%x\n", | 574 | sprintf(p, "\tDest IP addr: 0x%x\n", |
555 | fsc->fs.h_u.ah_ip4_spec.ip4dst); | 575 | fsc->fs.h_u.ah_ip4_spec.ip4dst); |
556 | p += ETH_GSTRING_LEN; | 576 | p += ETH_GSTRING_LEN; |
557 | num_strings++; | 577 | num_strings++; |
558 | sprintf(p, "\tDest IP mask: 0x%x\n", | 578 | sprintf(p, "\tDest IP mask: 0x%x\n", |
559 | fsc->fs.m_u.ah_ip4_spec.ip4dst); | 579 | fsc->fs.m_u.ah_ip4_spec.ip4dst); |
560 | p += ETH_GSTRING_LEN; | 580 | p += ETH_GSTRING_LEN; |
561 | num_strings++; | 581 | num_strings++; |
562 | sprintf(p, "\tSPI: %d, mask: 0x%x\n", | 582 | sprintf(p, "\tSPI: %d, mask: 0x%x\n", |
563 | fsc->fs.h_u.ah_ip4_spec.spi, | 583 | fsc->fs.h_u.ah_ip4_spec.spi, |
564 | fsc->fs.m_u.ah_ip4_spec.spi); | 584 | fsc->fs.m_u.ah_ip4_spec.spi); |
565 | p += ETH_GSTRING_LEN; | 585 | p += ETH_GSTRING_LEN; |
566 | num_strings++; | 586 | num_strings++; |
567 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", | 587 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", |
568 | fsc->fs.h_u.ah_ip4_spec.tos, | 588 | fsc->fs.h_u.ah_ip4_spec.tos, |
569 | fsc->fs.m_u.ah_ip4_spec.tos); | 589 | fsc->fs.m_u.ah_ip4_spec.tos); |
570 | p += ETH_GSTRING_LEN; | 590 | p += ETH_GSTRING_LEN; |
571 | num_strings++; | 591 | num_strings++; |
572 | break; | 592 | break; |
573 | case IP_USER_FLOW: | 593 | case IP_USER_FLOW: |
574 | sprintf(p, "\tSrc IP addr: 0x%x\n", | 594 | sprintf(p, "\tSrc IP addr: 0x%x\n", |
575 | fsc->fs.h_u.raw_ip4_spec.ip4src); | 595 | fsc->fs.h_u.raw_ip4_spec.ip4src); |
576 | p += ETH_GSTRING_LEN; | 596 | p += ETH_GSTRING_LEN; |
577 | num_strings++; | 597 | num_strings++; |
578 | sprintf(p, "\tSrc IP mask: 0x%x\n", | 598 | sprintf(p, "\tSrc IP mask: 0x%x\n", |
579 | fsc->fs.m_u.raw_ip4_spec.ip4src); | 599 | fsc->fs.m_u.raw_ip4_spec.ip4src); |
580 | p += ETH_GSTRING_LEN; | 600 | p += ETH_GSTRING_LEN; |
581 | num_strings++; | 601 | num_strings++; |
582 | sprintf(p, "\tDest IP addr: 0x%x\n", | 602 | sprintf(p, "\tDest IP addr: 0x%x\n", |
583 | fsc->fs.h_u.raw_ip4_spec.ip4dst); | 603 | fsc->fs.h_u.raw_ip4_spec.ip4dst); |
584 | p += ETH_GSTRING_LEN; | 604 | p += ETH_GSTRING_LEN; |
585 | num_strings++; | 605 | num_strings++; |
586 | sprintf(p, "\tDest IP mask: 0x%x\n", | 606 | sprintf(p, "\tDest IP mask: 0x%x\n", |
587 | fsc->fs.m_u.raw_ip4_spec.ip4dst); | 607 | fsc->fs.m_u.raw_ip4_spec.ip4dst); |
588 | p += ETH_GSTRING_LEN; | 608 | p += ETH_GSTRING_LEN; |
589 | num_strings++; | 609 | num_strings++; |
590 | break; | 610 | break; |
591 | case IPV4_FLOW: | 611 | case IPV4_FLOW: |
592 | sprintf(p, "\tSrc IP addr: 0x%x\n", | 612 | sprintf(p, "\tSrc IP addr: 0x%x\n", |
593 | fsc->fs.h_u.usr_ip4_spec.ip4src); | 613 | fsc->fs.h_u.usr_ip4_spec.ip4src); |
594 | p += ETH_GSTRING_LEN; | 614 | p += ETH_GSTRING_LEN; |
595 | num_strings++; | 615 | num_strings++; |
596 | sprintf(p, "\tSrc IP mask: 0x%x\n", | 616 | sprintf(p, "\tSrc IP mask: 0x%x\n", |
597 | fsc->fs.m_u.usr_ip4_spec.ip4src); | 617 | fsc->fs.m_u.usr_ip4_spec.ip4src); |
598 | p += ETH_GSTRING_LEN; | 618 | p += ETH_GSTRING_LEN; |
599 | num_strings++; | 619 | num_strings++; |
600 | sprintf(p, "\tDest IP addr: 0x%x\n", | 620 | sprintf(p, "\tDest IP addr: 0x%x\n", |
601 | fsc->fs.h_u.usr_ip4_spec.ip4dst); | 621 | fsc->fs.h_u.usr_ip4_spec.ip4dst); |
602 | p += ETH_GSTRING_LEN; | 622 | p += ETH_GSTRING_LEN; |
603 | num_strings++; | 623 | num_strings++; |
604 | sprintf(p, "\tDest IP mask: 0x%x\n", | 624 | sprintf(p, "\tDest IP mask: 0x%x\n", |
605 | fsc->fs.m_u.usr_ip4_spec.ip4dst); | 625 | fsc->fs.m_u.usr_ip4_spec.ip4dst); |
606 | p += ETH_GSTRING_LEN; | 626 | p += ETH_GSTRING_LEN; |
607 | num_strings++; | 627 | num_strings++; |
608 | sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n", | 628 | sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n", |
609 | fsc->fs.h_u.usr_ip4_spec.l4_4_bytes, | 629 | fsc->fs.h_u.usr_ip4_spec.l4_4_bytes, |
610 | fsc->fs.m_u.usr_ip4_spec.l4_4_bytes); | 630 | fsc->fs.m_u.usr_ip4_spec.l4_4_bytes); |
611 | p += ETH_GSTRING_LEN; | 631 | p += ETH_GSTRING_LEN; |
612 | num_strings++; | 632 | num_strings++; |
613 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", | 633 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", |
614 | fsc->fs.h_u.usr_ip4_spec.tos, | 634 | fsc->fs.h_u.usr_ip4_spec.tos, |
615 | fsc->fs.m_u.usr_ip4_spec.tos); | 635 | fsc->fs.m_u.usr_ip4_spec.tos); |
616 | p += ETH_GSTRING_LEN; | 636 | p += ETH_GSTRING_LEN; |
617 | num_strings++; | 637 | num_strings++; |
618 | sprintf(p, "\tIP Version: %d, mask: 0x%x\n", | 638 | sprintf(p, "\tIP Version: %d, mask: 0x%x\n", |
619 | fsc->fs.h_u.usr_ip4_spec.ip_ver, | 639 | fsc->fs.h_u.usr_ip4_spec.ip_ver, |
620 | fsc->fs.m_u.usr_ip4_spec.ip_ver); | 640 | fsc->fs.m_u.usr_ip4_spec.ip_ver); |
621 | p += ETH_GSTRING_LEN; | 641 | p += ETH_GSTRING_LEN; |
622 | num_strings++; | 642 | num_strings++; |
623 | sprintf(p, "\tProtocol: %d, mask: 0x%x\n", | 643 | sprintf(p, "\tProtocol: %d, mask: 0x%x\n", |
624 | fsc->fs.h_u.usr_ip4_spec.proto, | 644 | fsc->fs.h_u.usr_ip4_spec.proto, |
625 | fsc->fs.m_u.usr_ip4_spec.proto); | 645 | fsc->fs.m_u.usr_ip4_spec.proto); |
626 | p += ETH_GSTRING_LEN; | 646 | p += ETH_GSTRING_LEN; |
627 | num_strings++; | 647 | num_strings++; |
628 | break; | 648 | break; |
629 | }; | 649 | } |
630 | sprintf(p, "\tVLAN: %d, mask: 0x%x\n", | 650 | sprintf(p, "\tVLAN: %d, mask: 0x%x\n", |
631 | fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask); | 651 | fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask); |
632 | p += ETH_GSTRING_LEN; | 652 | p += ETH_GSTRING_LEN; |
633 | num_strings++; | 653 | num_strings++; |
634 | sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data); | 654 | sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data); |
@@ -641,7 +661,7 @@ static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr) | |||
641 | sprintf(p, "\tAction: Drop\n"); | 661 | sprintf(p, "\tAction: Drop\n"); |
642 | else | 662 | else |
643 | sprintf(p, "\tAction: Direct to queue %d\n", | 663 | sprintf(p, "\tAction: Direct to queue %d\n", |
644 | fsc->fs.action); | 664 | fsc->fs.action); |
645 | p += ETH_GSTRING_LEN; | 665 | p += ETH_GSTRING_LEN; |
646 | num_strings++; | 666 | num_strings++; |
647 | unknown_filter: | 667 | unknown_filter: |
@@ -853,7 +873,8 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) | |||
853 | return ret; | 873 | return ret; |
854 | } | 874 | } |
855 | 875 | ||
856 | static noinline_for_stack int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) | 876 | static noinline_for_stack int ethtool_get_coalesce(struct net_device *dev, |
877 | void __user *useraddr) | ||
857 | { | 878 | { |
858 | struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE }; | 879 | struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE }; |
859 | 880 | ||
@@ -867,7 +888,8 @@ static noinline_for_stack int ethtool_get_coalesce(struct net_device *dev, void | |||
867 | return 0; | 888 | return 0; |
868 | } | 889 | } |
869 | 890 | ||
870 | static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) | 891 | static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev, |
892 | void __user *useraddr) | ||
871 | { | 893 | { |
872 | struct ethtool_coalesce coalesce; | 894 | struct ethtool_coalesce coalesce; |
873 | 895 | ||
@@ -971,6 +993,7 @@ static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr) | |||
971 | 993 | ||
972 | return dev->ethtool_ops->set_tx_csum(dev, edata.data); | 994 | return dev->ethtool_ops->set_tx_csum(dev, edata.data); |
973 | } | 995 | } |
996 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); | ||
974 | 997 | ||
975 | static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr) | 998 | static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr) |
976 | { | 999 | { |
@@ -1042,7 +1065,7 @@ static int ethtool_get_gso(struct net_device *dev, char __user *useraddr) | |||
1042 | 1065 | ||
1043 | edata.data = dev->features & NETIF_F_GSO; | 1066 | edata.data = dev->features & NETIF_F_GSO; |
1044 | if (copy_to_user(useraddr, &edata, sizeof(edata))) | 1067 | if (copy_to_user(useraddr, &edata, sizeof(edata))) |
1045 | return -EFAULT; | 1068 | return -EFAULT; |
1046 | return 0; | 1069 | return 0; |
1047 | } | 1070 | } |
1048 | 1071 | ||
@@ -1065,7 +1088,7 @@ static int ethtool_get_gro(struct net_device *dev, char __user *useraddr) | |||
1065 | 1088 | ||
1066 | edata.data = dev->features & NETIF_F_GRO; | 1089 | edata.data = dev->features & NETIF_F_GRO; |
1067 | if (copy_to_user(useraddr, &edata, sizeof(edata))) | 1090 | if (copy_to_user(useraddr, &edata, sizeof(edata))) |
1068 | return -EFAULT; | 1091 | return -EFAULT; |
1069 | return 0; | 1092 | return 0; |
1070 | } | 1093 | } |
1071 | 1094 | ||
@@ -1277,7 +1300,8 @@ static int ethtool_set_value(struct net_device *dev, char __user *useraddr, | |||
1277 | return actor(dev, edata.data); | 1300 | return actor(dev, edata.data); |
1278 | } | 1301 | } |
1279 | 1302 | ||
1280 | static noinline_for_stack int ethtool_flash_device(struct net_device *dev, char __user *useraddr) | 1303 | static noinline_for_stack int ethtool_flash_device(struct net_device *dev, |
1304 | char __user *useraddr) | ||
1281 | { | 1305 | { |
1282 | struct ethtool_flash efl; | 1306 | struct ethtool_flash efl; |
1283 | 1307 | ||
@@ -1306,11 +1330,11 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1306 | if (!dev->ethtool_ops) | 1330 | if (!dev->ethtool_ops) |
1307 | return -EOPNOTSUPP; | 1331 | return -EOPNOTSUPP; |
1308 | 1332 | ||
1309 | if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) | 1333 | if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) |
1310 | return -EFAULT; | 1334 | return -EFAULT; |
1311 | 1335 | ||
1312 | /* Allow some commands to be done by anyone */ | 1336 | /* Allow some commands to be done by anyone */ |
1313 | switch(ethcmd) { | 1337 | switch (ethcmd) { |
1314 | case ETHTOOL_GDRVINFO: | 1338 | case ETHTOOL_GDRVINFO: |
1315 | case ETHTOOL_GMSGLVL: | 1339 | case ETHTOOL_GMSGLVL: |
1316 | case ETHTOOL_GCOALESCE: | 1340 | case ETHTOOL_GCOALESCE: |
@@ -1338,10 +1362,11 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1338 | return -EPERM; | 1362 | return -EPERM; |
1339 | } | 1363 | } |
1340 | 1364 | ||
1341 | if (dev->ethtool_ops->begin) | 1365 | if (dev->ethtool_ops->begin) { |
1342 | if ((rc = dev->ethtool_ops->begin(dev)) < 0) | 1366 | rc = dev->ethtool_ops->begin(dev); |
1367 | if (rc < 0) | ||
1343 | return rc; | 1368 | return rc; |
1344 | 1369 | } | |
1345 | old_features = dev->features; | 1370 | old_features = dev->features; |
1346 | 1371 | ||
1347 | switch (ethcmd) { | 1372 | switch (ethcmd) { |
@@ -1531,16 +1556,3 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1531 | 1556 | ||
1532 | return rc; | 1557 | return rc; |
1533 | } | 1558 | } |
1534 | |||
1535 | EXPORT_SYMBOL(ethtool_op_get_link); | ||
1536 | EXPORT_SYMBOL(ethtool_op_get_sg); | ||
1537 | EXPORT_SYMBOL(ethtool_op_get_tso); | ||
1538 | EXPORT_SYMBOL(ethtool_op_set_sg); | ||
1539 | EXPORT_SYMBOL(ethtool_op_set_tso); | ||
1540 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); | ||
1541 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); | ||
1542 | EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum); | ||
1543 | EXPORT_SYMBOL(ethtool_op_set_ufo); | ||
1544 | EXPORT_SYMBOL(ethtool_op_get_ufo); | ||
1545 | EXPORT_SYMBOL(ethtool_op_set_flags); | ||
1546 | EXPORT_SYMBOL(ethtool_op_get_flags); | ||
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index d2c3e7dc2e5f..42e84e08a1be 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -39,6 +39,24 @@ int fib_default_rule_add(struct fib_rules_ops *ops, | |||
39 | } | 39 | } |
40 | EXPORT_SYMBOL(fib_default_rule_add); | 40 | EXPORT_SYMBOL(fib_default_rule_add); |
41 | 41 | ||
42 | u32 fib_default_rule_pref(struct fib_rules_ops *ops) | ||
43 | { | ||
44 | struct list_head *pos; | ||
45 | struct fib_rule *rule; | ||
46 | |||
47 | if (!list_empty(&ops->rules_list)) { | ||
48 | pos = ops->rules_list.next; | ||
49 | if (pos->next != &ops->rules_list) { | ||
50 | rule = list_entry(pos->next, struct fib_rule, list); | ||
51 | if (rule->pref) | ||
52 | return rule->pref - 1; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | EXPORT_SYMBOL(fib_default_rule_pref); | ||
59 | |||
42 | static void notify_rule_change(int event, struct fib_rule *rule, | 60 | static void notify_rule_change(int event, struct fib_rule *rule, |
43 | struct fib_rules_ops *ops, struct nlmsghdr *nlh, | 61 | struct fib_rules_ops *ops, struct nlmsghdr *nlh, |
44 | u32 pid); | 62 | u32 pid); |
@@ -104,12 +122,12 @@ errout: | |||
104 | } | 122 | } |
105 | 123 | ||
106 | struct fib_rules_ops * | 124 | struct fib_rules_ops * |
107 | fib_rules_register(struct fib_rules_ops *tmpl, struct net *net) | 125 | fib_rules_register(const struct fib_rules_ops *tmpl, struct net *net) |
108 | { | 126 | { |
109 | struct fib_rules_ops *ops; | 127 | struct fib_rules_ops *ops; |
110 | int err; | 128 | int err; |
111 | 129 | ||
112 | ops = kmemdup(tmpl, sizeof (*ops), GFP_KERNEL); | 130 | ops = kmemdup(tmpl, sizeof(*ops), GFP_KERNEL); |
113 | if (ops == NULL) | 131 | if (ops == NULL) |
114 | return ERR_PTR(-ENOMEM); | 132 | return ERR_PTR(-ENOMEM); |
115 | 133 | ||
@@ -124,7 +142,6 @@ fib_rules_register(struct fib_rules_ops *tmpl, struct net *net) | |||
124 | 142 | ||
125 | return ops; | 143 | return ops; |
126 | } | 144 | } |
127 | |||
128 | EXPORT_SYMBOL_GPL(fib_rules_register); | 145 | EXPORT_SYMBOL_GPL(fib_rules_register); |
129 | 146 | ||
130 | void fib_rules_cleanup_ops(struct fib_rules_ops *ops) | 147 | void fib_rules_cleanup_ops(struct fib_rules_ops *ops) |
@@ -158,7 +175,6 @@ void fib_rules_unregister(struct fib_rules_ops *ops) | |||
158 | 175 | ||
159 | call_rcu(&ops->rcu, fib_rules_put_rcu); | 176 | call_rcu(&ops->rcu, fib_rules_put_rcu); |
160 | } | 177 | } |
161 | |||
162 | EXPORT_SYMBOL_GPL(fib_rules_unregister); | 178 | EXPORT_SYMBOL_GPL(fib_rules_unregister); |
163 | 179 | ||
164 | static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops, | 180 | static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops, |
@@ -221,7 +237,6 @@ out: | |||
221 | 237 | ||
222 | return err; | 238 | return err; |
223 | } | 239 | } |
224 | |||
225 | EXPORT_SYMBOL_GPL(fib_rules_lookup); | 240 | EXPORT_SYMBOL_GPL(fib_rules_lookup); |
226 | 241 | ||
227 | static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, | 242 | static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, |
@@ -520,6 +535,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, | |||
520 | return -EMSGSIZE; | 535 | return -EMSGSIZE; |
521 | 536 | ||
522 | frh = nlmsg_data(nlh); | 537 | frh = nlmsg_data(nlh); |
538 | frh->family = ops->family; | ||
523 | frh->table = rule->table; | 539 | frh->table = rule->table; |
524 | NLA_PUT_U32(skb, FRA_TABLE, rule->table); | 540 | NLA_PUT_U32(skb, FRA_TABLE, rule->table); |
525 | frh->res1 = 0; | 541 | frh->res1 = 0; |
@@ -614,7 +630,7 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) | |||
614 | break; | 630 | break; |
615 | 631 | ||
616 | cb->args[1] = 0; | 632 | cb->args[1] = 0; |
617 | skip: | 633 | skip: |
618 | idx++; | 634 | idx++; |
619 | } | 635 | } |
620 | rcu_read_unlock(); | 636 | rcu_read_unlock(); |
@@ -686,7 +702,6 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event, | |||
686 | struct fib_rules_ops *ops; | 702 | struct fib_rules_ops *ops; |
687 | 703 | ||
688 | ASSERT_RTNL(); | 704 | ASSERT_RTNL(); |
689 | rcu_read_lock(); | ||
690 | 705 | ||
691 | switch (event) { | 706 | switch (event) { |
692 | case NETDEV_REGISTER: | 707 | case NETDEV_REGISTER: |
@@ -700,8 +715,6 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event, | |||
700 | break; | 715 | break; |
701 | } | 716 | } |
702 | 717 | ||
703 | rcu_read_unlock(); | ||
704 | |||
705 | return NOTIFY_DONE; | 718 | return NOTIFY_DONE; |
706 | } | 719 | } |
707 | 720 | ||
diff --git a/net/core/filter.c b/net/core/filter.c index ff943bed21af..da69fb728d32 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -302,6 +302,8 @@ load_b: | |||
302 | A = skb->pkt_type; | 302 | A = skb->pkt_type; |
303 | continue; | 303 | continue; |
304 | case SKF_AD_IFINDEX: | 304 | case SKF_AD_IFINDEX: |
305 | if (!skb->dev) | ||
306 | return 0; | ||
305 | A = skb->dev->ifindex; | 307 | A = skb->dev->ifindex; |
306 | continue; | 308 | continue; |
307 | case SKF_AD_MARK: | 309 | case SKF_AD_MARK: |
@@ -310,6 +312,11 @@ load_b: | |||
310 | case SKF_AD_QUEUE: | 312 | case SKF_AD_QUEUE: |
311 | A = skb->queue_mapping; | 313 | A = skb->queue_mapping; |
312 | continue; | 314 | continue; |
315 | case SKF_AD_HATYPE: | ||
316 | if (!skb->dev) | ||
317 | return 0; | ||
318 | A = skb->dev->type; | ||
319 | continue; | ||
313 | case SKF_AD_NLATTR: { | 320 | case SKF_AD_NLATTR: { |
314 | struct nlattr *nla; | 321 | struct nlattr *nla; |
315 | 322 | ||
diff --git a/net/core/flow.c b/net/core/flow.c index 96015871ecea..161900674009 100644 --- a/net/core/flow.c +++ b/net/core/flow.c | |||
@@ -26,113 +26,158 @@ | |||
26 | #include <linux/security.h> | 26 | #include <linux/security.h> |
27 | 27 | ||
28 | struct flow_cache_entry { | 28 | struct flow_cache_entry { |
29 | struct flow_cache_entry *next; | 29 | union { |
30 | u16 family; | 30 | struct hlist_node hlist; |
31 | u8 dir; | 31 | struct list_head gc_list; |
32 | u32 genid; | 32 | } u; |
33 | struct flowi key; | 33 | u16 family; |
34 | void *object; | 34 | u8 dir; |
35 | atomic_t *object_ref; | 35 | u32 genid; |
36 | struct flowi key; | ||
37 | struct flow_cache_object *object; | ||
36 | }; | 38 | }; |
37 | 39 | ||
38 | atomic_t flow_cache_genid = ATOMIC_INIT(0); | 40 | struct flow_cache_percpu { |
39 | 41 | struct hlist_head *hash_table; | |
40 | static u32 flow_hash_shift; | 42 | int hash_count; |
41 | #define flow_hash_size (1 << flow_hash_shift) | 43 | u32 hash_rnd; |
42 | static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables) = { NULL }; | 44 | int hash_rnd_recalc; |
43 | 45 | struct tasklet_struct flush_tasklet; | |
44 | #define flow_table(cpu) (per_cpu(flow_tables, cpu)) | 46 | }; |
45 | |||
46 | static struct kmem_cache *flow_cachep __read_mostly; | ||
47 | 47 | ||
48 | static int flow_lwm, flow_hwm; | 48 | struct flow_flush_info { |
49 | struct flow_cache *cache; | ||
50 | atomic_t cpuleft; | ||
51 | struct completion completion; | ||
52 | }; | ||
49 | 53 | ||
50 | struct flow_percpu_info { | 54 | struct flow_cache { |
51 | int hash_rnd_recalc; | 55 | u32 hash_shift; |
52 | u32 hash_rnd; | 56 | unsigned long order; |
53 | int count; | 57 | struct flow_cache_percpu *percpu; |
58 | struct notifier_block hotcpu_notifier; | ||
59 | int low_watermark; | ||
60 | int high_watermark; | ||
61 | struct timer_list rnd_timer; | ||
54 | }; | 62 | }; |
55 | static DEFINE_PER_CPU(struct flow_percpu_info, flow_hash_info) = { 0 }; | ||
56 | 63 | ||
57 | #define flow_hash_rnd_recalc(cpu) \ | 64 | atomic_t flow_cache_genid = ATOMIC_INIT(0); |
58 | (per_cpu(flow_hash_info, cpu).hash_rnd_recalc) | 65 | static struct flow_cache flow_cache_global; |
59 | #define flow_hash_rnd(cpu) \ | 66 | static struct kmem_cache *flow_cachep; |
60 | (per_cpu(flow_hash_info, cpu).hash_rnd) | ||
61 | #define flow_count(cpu) \ | ||
62 | (per_cpu(flow_hash_info, cpu).count) | ||
63 | 67 | ||
64 | static struct timer_list flow_hash_rnd_timer; | 68 | static DEFINE_SPINLOCK(flow_cache_gc_lock); |
69 | static LIST_HEAD(flow_cache_gc_list); | ||
65 | 70 | ||
66 | #define FLOW_HASH_RND_PERIOD (10 * 60 * HZ) | 71 | #define flow_cache_hash_size(cache) (1 << (cache)->hash_shift) |
67 | 72 | #define FLOW_HASH_RND_PERIOD (10 * 60 * HZ) | |
68 | struct flow_flush_info { | ||
69 | atomic_t cpuleft; | ||
70 | struct completion completion; | ||
71 | }; | ||
72 | static DEFINE_PER_CPU(struct tasklet_struct, flow_flush_tasklets) = { NULL }; | ||
73 | |||
74 | #define flow_flush_tasklet(cpu) (&per_cpu(flow_flush_tasklets, cpu)) | ||
75 | 73 | ||
76 | static void flow_cache_new_hashrnd(unsigned long arg) | 74 | static void flow_cache_new_hashrnd(unsigned long arg) |
77 | { | 75 | { |
76 | struct flow_cache *fc = (void *) arg; | ||
78 | int i; | 77 | int i; |
79 | 78 | ||
80 | for_each_possible_cpu(i) | 79 | for_each_possible_cpu(i) |
81 | flow_hash_rnd_recalc(i) = 1; | 80 | per_cpu_ptr(fc->percpu, i)->hash_rnd_recalc = 1; |
82 | 81 | ||
83 | flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; | 82 | fc->rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; |
84 | add_timer(&flow_hash_rnd_timer); | 83 | add_timer(&fc->rnd_timer); |
84 | } | ||
85 | |||
86 | static int flow_entry_valid(struct flow_cache_entry *fle) | ||
87 | { | ||
88 | if (atomic_read(&flow_cache_genid) != fle->genid) | ||
89 | return 0; | ||
90 | if (fle->object && !fle->object->ops->check(fle->object)) | ||
91 | return 0; | ||
92 | return 1; | ||
85 | } | 93 | } |
86 | 94 | ||
87 | static void flow_entry_kill(int cpu, struct flow_cache_entry *fle) | 95 | static void flow_entry_kill(struct flow_cache_entry *fle) |
88 | { | 96 | { |
89 | if (fle->object) | 97 | if (fle->object) |
90 | atomic_dec(fle->object_ref); | 98 | fle->object->ops->delete(fle->object); |
91 | kmem_cache_free(flow_cachep, fle); | 99 | kmem_cache_free(flow_cachep, fle); |
92 | flow_count(cpu)--; | ||
93 | } | 100 | } |
94 | 101 | ||
95 | static void __flow_cache_shrink(int cpu, int shrink_to) | 102 | static void flow_cache_gc_task(struct work_struct *work) |
96 | { | 103 | { |
97 | struct flow_cache_entry *fle, **flp; | 104 | struct list_head gc_list; |
98 | int i; | 105 | struct flow_cache_entry *fce, *n; |
99 | 106 | ||
100 | for (i = 0; i < flow_hash_size; i++) { | 107 | INIT_LIST_HEAD(&gc_list); |
101 | int k = 0; | 108 | spin_lock_bh(&flow_cache_gc_lock); |
109 | list_splice_tail_init(&flow_cache_gc_list, &gc_list); | ||
110 | spin_unlock_bh(&flow_cache_gc_lock); | ||
102 | 111 | ||
103 | flp = &flow_table(cpu)[i]; | 112 | list_for_each_entry_safe(fce, n, &gc_list, u.gc_list) |
104 | while ((fle = *flp) != NULL && k < shrink_to) { | 113 | flow_entry_kill(fce); |
105 | k++; | 114 | } |
106 | flp = &fle->next; | 115 | static DECLARE_WORK(flow_cache_gc_work, flow_cache_gc_task); |
107 | } | 116 | |
108 | while ((fle = *flp) != NULL) { | 117 | static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp, |
109 | *flp = fle->next; | 118 | int deleted, struct list_head *gc_list) |
110 | flow_entry_kill(cpu, fle); | 119 | { |
111 | } | 120 | if (deleted) { |
121 | fcp->hash_count -= deleted; | ||
122 | spin_lock_bh(&flow_cache_gc_lock); | ||
123 | list_splice_tail(gc_list, &flow_cache_gc_list); | ||
124 | spin_unlock_bh(&flow_cache_gc_lock); | ||
125 | schedule_work(&flow_cache_gc_work); | ||
112 | } | 126 | } |
113 | } | 127 | } |
114 | 128 | ||
115 | static void flow_cache_shrink(int cpu) | 129 | static void __flow_cache_shrink(struct flow_cache *fc, |
130 | struct flow_cache_percpu *fcp, | ||
131 | int shrink_to) | ||
116 | { | 132 | { |
117 | int shrink_to = flow_lwm / flow_hash_size; | 133 | struct flow_cache_entry *fle; |
134 | struct hlist_node *entry, *tmp; | ||
135 | LIST_HEAD(gc_list); | ||
136 | int i, deleted = 0; | ||
137 | |||
138 | for (i = 0; i < flow_cache_hash_size(fc); i++) { | ||
139 | int saved = 0; | ||
140 | |||
141 | hlist_for_each_entry_safe(fle, entry, tmp, | ||
142 | &fcp->hash_table[i], u.hlist) { | ||
143 | if (saved < shrink_to && | ||
144 | flow_entry_valid(fle)) { | ||
145 | saved++; | ||
146 | } else { | ||
147 | deleted++; | ||
148 | hlist_del(&fle->u.hlist); | ||
149 | list_add_tail(&fle->u.gc_list, &gc_list); | ||
150 | } | ||
151 | } | ||
152 | } | ||
118 | 153 | ||
119 | __flow_cache_shrink(cpu, shrink_to); | 154 | flow_cache_queue_garbage(fcp, deleted, &gc_list); |
120 | } | 155 | } |
121 | 156 | ||
122 | static void flow_new_hash_rnd(int cpu) | 157 | static void flow_cache_shrink(struct flow_cache *fc, |
158 | struct flow_cache_percpu *fcp) | ||
123 | { | 159 | { |
124 | get_random_bytes(&flow_hash_rnd(cpu), sizeof(u32)); | 160 | int shrink_to = fc->low_watermark / flow_cache_hash_size(fc); |
125 | flow_hash_rnd_recalc(cpu) = 0; | ||
126 | 161 | ||
127 | __flow_cache_shrink(cpu, 0); | 162 | __flow_cache_shrink(fc, fcp, shrink_to); |
128 | } | 163 | } |
129 | 164 | ||
130 | static u32 flow_hash_code(struct flowi *key, int cpu) | 165 | static void flow_new_hash_rnd(struct flow_cache *fc, |
166 | struct flow_cache_percpu *fcp) | ||
167 | { | ||
168 | get_random_bytes(&fcp->hash_rnd, sizeof(u32)); | ||
169 | fcp->hash_rnd_recalc = 0; | ||
170 | __flow_cache_shrink(fc, fcp, 0); | ||
171 | } | ||
172 | |||
173 | static u32 flow_hash_code(struct flow_cache *fc, | ||
174 | struct flow_cache_percpu *fcp, | ||
175 | struct flowi *key) | ||
131 | { | 176 | { |
132 | u32 *k = (u32 *) key; | 177 | u32 *k = (u32 *) key; |
133 | 178 | ||
134 | return (jhash2(k, (sizeof(*key) / sizeof(u32)), flow_hash_rnd(cpu)) & | 179 | return (jhash2(k, (sizeof(*key) / sizeof(u32)), fcp->hash_rnd) |
135 | (flow_hash_size - 1)); | 180 | & (flow_cache_hash_size(fc) - 1)); |
136 | } | 181 | } |
137 | 182 | ||
138 | #if (BITS_PER_LONG == 64) | 183 | #if (BITS_PER_LONG == 64) |
@@ -165,114 +210,117 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2) | |||
165 | return 0; | 210 | return 0; |
166 | } | 211 | } |
167 | 212 | ||
168 | void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir, | 213 | struct flow_cache_object * |
169 | flow_resolve_t resolver) | 214 | flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir, |
215 | flow_resolve_t resolver, void *ctx) | ||
170 | { | 216 | { |
171 | struct flow_cache_entry *fle, **head; | 217 | struct flow_cache *fc = &flow_cache_global; |
218 | struct flow_cache_percpu *fcp; | ||
219 | struct flow_cache_entry *fle, *tfle; | ||
220 | struct hlist_node *entry; | ||
221 | struct flow_cache_object *flo; | ||
172 | unsigned int hash; | 222 | unsigned int hash; |
173 | int cpu; | ||
174 | 223 | ||
175 | local_bh_disable(); | 224 | local_bh_disable(); |
176 | cpu = smp_processor_id(); | 225 | fcp = per_cpu_ptr(fc->percpu, smp_processor_id()); |
177 | 226 | ||
178 | fle = NULL; | 227 | fle = NULL; |
228 | flo = NULL; | ||
179 | /* Packet really early in init? Making flow_cache_init a | 229 | /* Packet really early in init? Making flow_cache_init a |
180 | * pre-smp initcall would solve this. --RR */ | 230 | * pre-smp initcall would solve this. --RR */ |
181 | if (!flow_table(cpu)) | 231 | if (!fcp->hash_table) |
182 | goto nocache; | 232 | goto nocache; |
183 | 233 | ||
184 | if (flow_hash_rnd_recalc(cpu)) | 234 | if (fcp->hash_rnd_recalc) |
185 | flow_new_hash_rnd(cpu); | 235 | flow_new_hash_rnd(fc, fcp); |
186 | hash = flow_hash_code(key, cpu); | ||
187 | 236 | ||
188 | head = &flow_table(cpu)[hash]; | 237 | hash = flow_hash_code(fc, fcp, key); |
189 | for (fle = *head; fle; fle = fle->next) { | 238 | hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) { |
190 | if (fle->family == family && | 239 | if (tfle->family == family && |
191 | fle->dir == dir && | 240 | tfle->dir == dir && |
192 | flow_key_compare(key, &fle->key) == 0) { | 241 | flow_key_compare(key, &tfle->key) == 0) { |
193 | if (fle->genid == atomic_read(&flow_cache_genid)) { | 242 | fle = tfle; |
194 | void *ret = fle->object; | ||
195 | |||
196 | if (ret) | ||
197 | atomic_inc(fle->object_ref); | ||
198 | local_bh_enable(); | ||
199 | |||
200 | return ret; | ||
201 | } | ||
202 | break; | 243 | break; |
203 | } | 244 | } |
204 | } | 245 | } |
205 | 246 | ||
206 | if (!fle) { | 247 | if (unlikely(!fle)) { |
207 | if (flow_count(cpu) > flow_hwm) | 248 | if (fcp->hash_count > fc->high_watermark) |
208 | flow_cache_shrink(cpu); | 249 | flow_cache_shrink(fc, fcp); |
209 | 250 | ||
210 | fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC); | 251 | fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC); |
211 | if (fle) { | 252 | if (fle) { |
212 | fle->next = *head; | ||
213 | *head = fle; | ||
214 | fle->family = family; | 253 | fle->family = family; |
215 | fle->dir = dir; | 254 | fle->dir = dir; |
216 | memcpy(&fle->key, key, sizeof(*key)); | 255 | memcpy(&fle->key, key, sizeof(*key)); |
217 | fle->object = NULL; | 256 | fle->object = NULL; |
218 | flow_count(cpu)++; | 257 | hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]); |
258 | fcp->hash_count++; | ||
219 | } | 259 | } |
260 | } else if (likely(fle->genid == atomic_read(&flow_cache_genid))) { | ||
261 | flo = fle->object; | ||
262 | if (!flo) | ||
263 | goto ret_object; | ||
264 | flo = flo->ops->get(flo); | ||
265 | if (flo) | ||
266 | goto ret_object; | ||
267 | } else if (fle->object) { | ||
268 | flo = fle->object; | ||
269 | flo->ops->delete(flo); | ||
270 | fle->object = NULL; | ||
220 | } | 271 | } |
221 | 272 | ||
222 | nocache: | 273 | nocache: |
223 | { | 274 | flo = NULL; |
224 | int err; | 275 | if (fle) { |
225 | void *obj; | 276 | flo = fle->object; |
226 | atomic_t *obj_ref; | 277 | fle->object = NULL; |
227 | |||
228 | err = resolver(net, key, family, dir, &obj, &obj_ref); | ||
229 | |||
230 | if (fle && !err) { | ||
231 | fle->genid = atomic_read(&flow_cache_genid); | ||
232 | |||
233 | if (fle->object) | ||
234 | atomic_dec(fle->object_ref); | ||
235 | |||
236 | fle->object = obj; | ||
237 | fle->object_ref = obj_ref; | ||
238 | if (obj) | ||
239 | atomic_inc(fle->object_ref); | ||
240 | } | ||
241 | local_bh_enable(); | ||
242 | |||
243 | if (err) | ||
244 | obj = ERR_PTR(err); | ||
245 | return obj; | ||
246 | } | 278 | } |
279 | flo = resolver(net, key, family, dir, flo, ctx); | ||
280 | if (fle) { | ||
281 | fle->genid = atomic_read(&flow_cache_genid); | ||
282 | if (!IS_ERR(flo)) | ||
283 | fle->object = flo; | ||
284 | else | ||
285 | fle->genid--; | ||
286 | } else { | ||
287 | if (flo && !IS_ERR(flo)) | ||
288 | flo->ops->delete(flo); | ||
289 | } | ||
290 | ret_object: | ||
291 | local_bh_enable(); | ||
292 | return flo; | ||
247 | } | 293 | } |
248 | 294 | ||
249 | static void flow_cache_flush_tasklet(unsigned long data) | 295 | static void flow_cache_flush_tasklet(unsigned long data) |
250 | { | 296 | { |
251 | struct flow_flush_info *info = (void *)data; | 297 | struct flow_flush_info *info = (void *)data; |
252 | int i; | 298 | struct flow_cache *fc = info->cache; |
253 | int cpu; | 299 | struct flow_cache_percpu *fcp; |
254 | 300 | struct flow_cache_entry *fle; | |
255 | cpu = smp_processor_id(); | 301 | struct hlist_node *entry, *tmp; |
256 | for (i = 0; i < flow_hash_size; i++) { | 302 | LIST_HEAD(gc_list); |
257 | struct flow_cache_entry *fle; | 303 | int i, deleted = 0; |
258 | 304 | ||
259 | fle = flow_table(cpu)[i]; | 305 | fcp = per_cpu_ptr(fc->percpu, smp_processor_id()); |
260 | for (; fle; fle = fle->next) { | 306 | for (i = 0; i < flow_cache_hash_size(fc); i++) { |
261 | unsigned genid = atomic_read(&flow_cache_genid); | 307 | hlist_for_each_entry_safe(fle, entry, tmp, |
262 | 308 | &fcp->hash_table[i], u.hlist) { | |
263 | if (!fle->object || fle->genid == genid) | 309 | if (flow_entry_valid(fle)) |
264 | continue; | 310 | continue; |
265 | 311 | ||
266 | fle->object = NULL; | 312 | deleted++; |
267 | atomic_dec(fle->object_ref); | 313 | hlist_del(&fle->u.hlist); |
314 | list_add_tail(&fle->u.gc_list, &gc_list); | ||
268 | } | 315 | } |
269 | } | 316 | } |
270 | 317 | ||
318 | flow_cache_queue_garbage(fcp, deleted, &gc_list); | ||
319 | |||
271 | if (atomic_dec_and_test(&info->cpuleft)) | 320 | if (atomic_dec_and_test(&info->cpuleft)) |
272 | complete(&info->completion); | 321 | complete(&info->completion); |
273 | } | 322 | } |
274 | 323 | ||
275 | static void flow_cache_flush_per_cpu(void *) __attribute__((__unused__)); | ||
276 | static void flow_cache_flush_per_cpu(void *data) | 324 | static void flow_cache_flush_per_cpu(void *data) |
277 | { | 325 | { |
278 | struct flow_flush_info *info = data; | 326 | struct flow_flush_info *info = data; |
@@ -280,8 +328,7 @@ static void flow_cache_flush_per_cpu(void *data) | |||
280 | struct tasklet_struct *tasklet; | 328 | struct tasklet_struct *tasklet; |
281 | 329 | ||
282 | cpu = smp_processor_id(); | 330 | cpu = smp_processor_id(); |
283 | 331 | tasklet = &per_cpu_ptr(info->cache->percpu, cpu)->flush_tasklet; | |
284 | tasklet = flow_flush_tasklet(cpu); | ||
285 | tasklet->data = (unsigned long)info; | 332 | tasklet->data = (unsigned long)info; |
286 | tasklet_schedule(tasklet); | 333 | tasklet_schedule(tasklet); |
287 | } | 334 | } |
@@ -294,6 +341,7 @@ void flow_cache_flush(void) | |||
294 | /* Don't want cpus going down or up during this. */ | 341 | /* Don't want cpus going down or up during this. */ |
295 | get_online_cpus(); | 342 | get_online_cpus(); |
296 | mutex_lock(&flow_flush_sem); | 343 | mutex_lock(&flow_flush_sem); |
344 | info.cache = &flow_cache_global; | ||
297 | atomic_set(&info.cpuleft, num_online_cpus()); | 345 | atomic_set(&info.cpuleft, num_online_cpus()); |
298 | init_completion(&info.completion); | 346 | init_completion(&info.completion); |
299 | 347 | ||
@@ -307,62 +355,75 @@ void flow_cache_flush(void) | |||
307 | put_online_cpus(); | 355 | put_online_cpus(); |
308 | } | 356 | } |
309 | 357 | ||
310 | static void __init flow_cache_cpu_prepare(int cpu) | 358 | static void __init flow_cache_cpu_prepare(struct flow_cache *fc, |
359 | struct flow_cache_percpu *fcp) | ||
311 | { | 360 | { |
312 | struct tasklet_struct *tasklet; | 361 | fcp->hash_table = (struct hlist_head *) |
313 | unsigned long order; | 362 | __get_free_pages(GFP_KERNEL|__GFP_ZERO, fc->order); |
314 | 363 | if (!fcp->hash_table) | |
315 | for (order = 0; | 364 | panic("NET: failed to allocate flow cache order %lu\n", fc->order); |
316 | (PAGE_SIZE << order) < | 365 | |
317 | (sizeof(struct flow_cache_entry *)*flow_hash_size); | 366 | fcp->hash_rnd_recalc = 1; |
318 | order++) | 367 | fcp->hash_count = 0; |
319 | /* NOTHING */; | 368 | tasklet_init(&fcp->flush_tasklet, flow_cache_flush_tasklet, 0); |
320 | |||
321 | flow_table(cpu) = (struct flow_cache_entry **) | ||
322 | __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); | ||
323 | if (!flow_table(cpu)) | ||
324 | panic("NET: failed to allocate flow cache order %lu\n", order); | ||
325 | |||
326 | flow_hash_rnd_recalc(cpu) = 1; | ||
327 | flow_count(cpu) = 0; | ||
328 | |||
329 | tasklet = flow_flush_tasklet(cpu); | ||
330 | tasklet_init(tasklet, flow_cache_flush_tasklet, 0); | ||
331 | } | 369 | } |
332 | 370 | ||
333 | static int flow_cache_cpu(struct notifier_block *nfb, | 371 | static int flow_cache_cpu(struct notifier_block *nfb, |
334 | unsigned long action, | 372 | unsigned long action, |
335 | void *hcpu) | 373 | void *hcpu) |
336 | { | 374 | { |
375 | struct flow_cache *fc = container_of(nfb, struct flow_cache, hotcpu_notifier); | ||
376 | int cpu = (unsigned long) hcpu; | ||
377 | struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu); | ||
378 | |||
337 | if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) | 379 | if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) |
338 | __flow_cache_shrink((unsigned long)hcpu, 0); | 380 | __flow_cache_shrink(fc, fcp, 0); |
339 | return NOTIFY_OK; | 381 | return NOTIFY_OK; |
340 | } | 382 | } |
341 | 383 | ||
342 | static int __init flow_cache_init(void) | 384 | static int flow_cache_init(struct flow_cache *fc) |
343 | { | 385 | { |
386 | unsigned long order; | ||
344 | int i; | 387 | int i; |
345 | 388 | ||
346 | flow_cachep = kmem_cache_create("flow_cache", | 389 | fc->hash_shift = 10; |
347 | sizeof(struct flow_cache_entry), | 390 | fc->low_watermark = 2 * flow_cache_hash_size(fc); |
348 | 0, SLAB_PANIC, | 391 | fc->high_watermark = 4 * flow_cache_hash_size(fc); |
349 | NULL); | 392 | |
350 | flow_hash_shift = 10; | 393 | for (order = 0; |
351 | flow_lwm = 2 * flow_hash_size; | 394 | (PAGE_SIZE << order) < |
352 | flow_hwm = 4 * flow_hash_size; | 395 | (sizeof(struct hlist_head)*flow_cache_hash_size(fc)); |
396 | order++) | ||
397 | /* NOTHING */; | ||
398 | fc->order = order; | ||
399 | fc->percpu = alloc_percpu(struct flow_cache_percpu); | ||
353 | 400 | ||
354 | setup_timer(&flow_hash_rnd_timer, flow_cache_new_hashrnd, 0); | 401 | setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd, |
355 | flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; | 402 | (unsigned long) fc); |
356 | add_timer(&flow_hash_rnd_timer); | 403 | fc->rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; |
404 | add_timer(&fc->rnd_timer); | ||
357 | 405 | ||
358 | for_each_possible_cpu(i) | 406 | for_each_possible_cpu(i) |
359 | flow_cache_cpu_prepare(i); | 407 | flow_cache_cpu_prepare(fc, per_cpu_ptr(fc->percpu, i)); |
408 | |||
409 | fc->hotcpu_notifier = (struct notifier_block){ | ||
410 | .notifier_call = flow_cache_cpu, | ||
411 | }; | ||
412 | register_hotcpu_notifier(&fc->hotcpu_notifier); | ||
360 | 413 | ||
361 | hotcpu_notifier(flow_cache_cpu, 0); | ||
362 | return 0; | 414 | return 0; |
363 | } | 415 | } |
364 | 416 | ||
365 | module_init(flow_cache_init); | 417 | static int __init flow_cache_init_global(void) |
418 | { | ||
419 | flow_cachep = kmem_cache_create("flow_cache", | ||
420 | sizeof(struct flow_cache_entry), | ||
421 | 0, SLAB_PANIC, NULL); | ||
422 | |||
423 | return flow_cache_init(&flow_cache_global); | ||
424 | } | ||
425 | |||
426 | module_init(flow_cache_init_global); | ||
366 | 427 | ||
367 | EXPORT_SYMBOL(flow_cache_genid); | 428 | EXPORT_SYMBOL(flow_cache_genid); |
368 | EXPORT_SYMBOL(flow_cache_lookup); | 429 | EXPORT_SYMBOL(flow_cache_lookup); |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 59cfc7d8fc45..c57c4b228bb5 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <net/sock.h> | 17 | #include <net/sock.h> |
18 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
19 | #include <linux/wireless.h> | 19 | #include <linux/wireless.h> |
20 | #include <linux/vmalloc.h> | ||
20 | #include <net/wext.h> | 21 | #include <net/wext.h> |
21 | 22 | ||
22 | #include "net-sysfs.h" | 23 | #include "net-sysfs.h" |
@@ -467,6 +468,304 @@ static struct attribute_group wireless_group = { | |||
467 | }; | 468 | }; |
468 | #endif | 469 | #endif |
469 | 470 | ||
471 | #ifdef CONFIG_RPS | ||
472 | /* | ||
473 | * RX queue sysfs structures and functions. | ||
474 | */ | ||
475 | struct rx_queue_attribute { | ||
476 | struct attribute attr; | ||
477 | ssize_t (*show)(struct netdev_rx_queue *queue, | ||
478 | struct rx_queue_attribute *attr, char *buf); | ||
479 | ssize_t (*store)(struct netdev_rx_queue *queue, | ||
480 | struct rx_queue_attribute *attr, const char *buf, size_t len); | ||
481 | }; | ||
482 | #define to_rx_queue_attr(_attr) container_of(_attr, \ | ||
483 | struct rx_queue_attribute, attr) | ||
484 | |||
485 | #define to_rx_queue(obj) container_of(obj, struct netdev_rx_queue, kobj) | ||
486 | |||
487 | static ssize_t rx_queue_attr_show(struct kobject *kobj, struct attribute *attr, | ||
488 | char *buf) | ||
489 | { | ||
490 | struct rx_queue_attribute *attribute = to_rx_queue_attr(attr); | ||
491 | struct netdev_rx_queue *queue = to_rx_queue(kobj); | ||
492 | |||
493 | if (!attribute->show) | ||
494 | return -EIO; | ||
495 | |||
496 | return attribute->show(queue, attribute, buf); | ||
497 | } | ||
498 | |||
499 | static ssize_t rx_queue_attr_store(struct kobject *kobj, struct attribute *attr, | ||
500 | const char *buf, size_t count) | ||
501 | { | ||
502 | struct rx_queue_attribute *attribute = to_rx_queue_attr(attr); | ||
503 | struct netdev_rx_queue *queue = to_rx_queue(kobj); | ||
504 | |||
505 | if (!attribute->store) | ||
506 | return -EIO; | ||
507 | |||
508 | return attribute->store(queue, attribute, buf, count); | ||
509 | } | ||
510 | |||
511 | static struct sysfs_ops rx_queue_sysfs_ops = { | ||
512 | .show = rx_queue_attr_show, | ||
513 | .store = rx_queue_attr_store, | ||
514 | }; | ||
515 | |||
516 | static ssize_t show_rps_map(struct netdev_rx_queue *queue, | ||
517 | struct rx_queue_attribute *attribute, char *buf) | ||
518 | { | ||
519 | struct rps_map *map; | ||
520 | cpumask_var_t mask; | ||
521 | size_t len = 0; | ||
522 | int i; | ||
523 | |||
524 | if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) | ||
525 | return -ENOMEM; | ||
526 | |||
527 | rcu_read_lock(); | ||
528 | map = rcu_dereference(queue->rps_map); | ||
529 | if (map) | ||
530 | for (i = 0; i < map->len; i++) | ||
531 | cpumask_set_cpu(map->cpus[i], mask); | ||
532 | |||
533 | len += cpumask_scnprintf(buf + len, PAGE_SIZE, mask); | ||
534 | if (PAGE_SIZE - len < 3) { | ||
535 | rcu_read_unlock(); | ||
536 | free_cpumask_var(mask); | ||
537 | return -EINVAL; | ||
538 | } | ||
539 | rcu_read_unlock(); | ||
540 | |||
541 | free_cpumask_var(mask); | ||
542 | len += sprintf(buf + len, "\n"); | ||
543 | return len; | ||
544 | } | ||
545 | |||
546 | static void rps_map_release(struct rcu_head *rcu) | ||
547 | { | ||
548 | struct rps_map *map = container_of(rcu, struct rps_map, rcu); | ||
549 | |||
550 | kfree(map); | ||
551 | } | ||
552 | |||
553 | static ssize_t store_rps_map(struct netdev_rx_queue *queue, | ||
554 | struct rx_queue_attribute *attribute, | ||
555 | const char *buf, size_t len) | ||
556 | { | ||
557 | struct rps_map *old_map, *map; | ||
558 | cpumask_var_t mask; | ||
559 | int err, cpu, i; | ||
560 | static DEFINE_SPINLOCK(rps_map_lock); | ||
561 | |||
562 | if (!capable(CAP_NET_ADMIN)) | ||
563 | return -EPERM; | ||
564 | |||
565 | if (!alloc_cpumask_var(&mask, GFP_KERNEL)) | ||
566 | return -ENOMEM; | ||
567 | |||
568 | err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits); | ||
569 | if (err) { | ||
570 | free_cpumask_var(mask); | ||
571 | return err; | ||
572 | } | ||
573 | |||
574 | map = kzalloc(max_t(unsigned, | ||
575 | RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES), | ||
576 | GFP_KERNEL); | ||
577 | if (!map) { | ||
578 | free_cpumask_var(mask); | ||
579 | return -ENOMEM; | ||
580 | } | ||
581 | |||
582 | i = 0; | ||
583 | for_each_cpu_and(cpu, mask, cpu_online_mask) | ||
584 | map->cpus[i++] = cpu; | ||
585 | |||
586 | if (i) | ||
587 | map->len = i; | ||
588 | else { | ||
589 | kfree(map); | ||
590 | map = NULL; | ||
591 | } | ||
592 | |||
593 | spin_lock(&rps_map_lock); | ||
594 | old_map = queue->rps_map; | ||
595 | rcu_assign_pointer(queue->rps_map, map); | ||
596 | spin_unlock(&rps_map_lock); | ||
597 | |||
598 | if (old_map) | ||
599 | call_rcu(&old_map->rcu, rps_map_release); | ||
600 | |||
601 | free_cpumask_var(mask); | ||
602 | return len; | ||
603 | } | ||
604 | |||
605 | static ssize_t show_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue, | ||
606 | struct rx_queue_attribute *attr, | ||
607 | char *buf) | ||
608 | { | ||
609 | struct rps_dev_flow_table *flow_table; | ||
610 | unsigned int val = 0; | ||
611 | |||
612 | rcu_read_lock(); | ||
613 | flow_table = rcu_dereference(queue->rps_flow_table); | ||
614 | if (flow_table) | ||
615 | val = flow_table->mask + 1; | ||
616 | rcu_read_unlock(); | ||
617 | |||
618 | return sprintf(buf, "%u\n", val); | ||
619 | } | ||
620 | |||
621 | static void rps_dev_flow_table_release_work(struct work_struct *work) | ||
622 | { | ||
623 | struct rps_dev_flow_table *table = container_of(work, | ||
624 | struct rps_dev_flow_table, free_work); | ||
625 | |||
626 | vfree(table); | ||
627 | } | ||
628 | |||
629 | static void rps_dev_flow_table_release(struct rcu_head *rcu) | ||
630 | { | ||
631 | struct rps_dev_flow_table *table = container_of(rcu, | ||
632 | struct rps_dev_flow_table, rcu); | ||
633 | |||
634 | INIT_WORK(&table->free_work, rps_dev_flow_table_release_work); | ||
635 | schedule_work(&table->free_work); | ||
636 | } | ||
637 | |||
638 | static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue, | ||
639 | struct rx_queue_attribute *attr, | ||
640 | const char *buf, size_t len) | ||
641 | { | ||
642 | unsigned int count; | ||
643 | char *endp; | ||
644 | struct rps_dev_flow_table *table, *old_table; | ||
645 | static DEFINE_SPINLOCK(rps_dev_flow_lock); | ||
646 | |||
647 | if (!capable(CAP_NET_ADMIN)) | ||
648 | return -EPERM; | ||
649 | |||
650 | count = simple_strtoul(buf, &endp, 0); | ||
651 | if (endp == buf) | ||
652 | return -EINVAL; | ||
653 | |||
654 | if (count) { | ||
655 | int i; | ||
656 | |||
657 | if (count > 1<<30) { | ||
658 | /* Enforce a limit to prevent overflow */ | ||
659 | return -EINVAL; | ||
660 | } | ||
661 | count = roundup_pow_of_two(count); | ||
662 | table = vmalloc(RPS_DEV_FLOW_TABLE_SIZE(count)); | ||
663 | if (!table) | ||
664 | return -ENOMEM; | ||
665 | |||
666 | table->mask = count - 1; | ||
667 | for (i = 0; i < count; i++) | ||
668 | table->flows[i].cpu = RPS_NO_CPU; | ||
669 | } else | ||
670 | table = NULL; | ||
671 | |||
672 | spin_lock(&rps_dev_flow_lock); | ||
673 | old_table = queue->rps_flow_table; | ||
674 | rcu_assign_pointer(queue->rps_flow_table, table); | ||
675 | spin_unlock(&rps_dev_flow_lock); | ||
676 | |||
677 | if (old_table) | ||
678 | call_rcu(&old_table->rcu, rps_dev_flow_table_release); | ||
679 | |||
680 | return len; | ||
681 | } | ||
682 | |||
683 | static struct rx_queue_attribute rps_cpus_attribute = | ||
684 | __ATTR(rps_cpus, S_IRUGO | S_IWUSR, show_rps_map, store_rps_map); | ||
685 | |||
686 | |||
687 | static struct rx_queue_attribute rps_dev_flow_table_cnt_attribute = | ||
688 | __ATTR(rps_flow_cnt, S_IRUGO | S_IWUSR, | ||
689 | show_rps_dev_flow_table_cnt, store_rps_dev_flow_table_cnt); | ||
690 | |||
691 | static struct attribute *rx_queue_default_attrs[] = { | ||
692 | &rps_cpus_attribute.attr, | ||
693 | &rps_dev_flow_table_cnt_attribute.attr, | ||
694 | NULL | ||
695 | }; | ||
696 | |||
697 | static void rx_queue_release(struct kobject *kobj) | ||
698 | { | ||
699 | struct netdev_rx_queue *queue = to_rx_queue(kobj); | ||
700 | struct netdev_rx_queue *first = queue->first; | ||
701 | |||
702 | if (queue->rps_map) | ||
703 | call_rcu(&queue->rps_map->rcu, rps_map_release); | ||
704 | |||
705 | if (queue->rps_flow_table) | ||
706 | call_rcu(&queue->rps_flow_table->rcu, | ||
707 | rps_dev_flow_table_release); | ||
708 | |||
709 | if (atomic_dec_and_test(&first->count)) | ||
710 | kfree(first); | ||
711 | } | ||
712 | |||
713 | static struct kobj_type rx_queue_ktype = { | ||
714 | .sysfs_ops = &rx_queue_sysfs_ops, | ||
715 | .release = rx_queue_release, | ||
716 | .default_attrs = rx_queue_default_attrs, | ||
717 | }; | ||
718 | |||
719 | static int rx_queue_add_kobject(struct net_device *net, int index) | ||
720 | { | ||
721 | struct netdev_rx_queue *queue = net->_rx + index; | ||
722 | struct kobject *kobj = &queue->kobj; | ||
723 | int error = 0; | ||
724 | |||
725 | kobj->kset = net->queues_kset; | ||
726 | error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL, | ||
727 | "rx-%u", index); | ||
728 | if (error) { | ||
729 | kobject_put(kobj); | ||
730 | return error; | ||
731 | } | ||
732 | |||
733 | kobject_uevent(kobj, KOBJ_ADD); | ||
734 | |||
735 | return error; | ||
736 | } | ||
737 | |||
738 | static int rx_queue_register_kobjects(struct net_device *net) | ||
739 | { | ||
740 | int i; | ||
741 | int error = 0; | ||
742 | |||
743 | net->queues_kset = kset_create_and_add("queues", | ||
744 | NULL, &net->dev.kobj); | ||
745 | if (!net->queues_kset) | ||
746 | return -ENOMEM; | ||
747 | for (i = 0; i < net->num_rx_queues; i++) { | ||
748 | error = rx_queue_add_kobject(net, i); | ||
749 | if (error) | ||
750 | break; | ||
751 | } | ||
752 | |||
753 | if (error) | ||
754 | while (--i >= 0) | ||
755 | kobject_put(&net->_rx[i].kobj); | ||
756 | |||
757 | return error; | ||
758 | } | ||
759 | |||
760 | static void rx_queue_remove_kobjects(struct net_device *net) | ||
761 | { | ||
762 | int i; | ||
763 | |||
764 | for (i = 0; i < net->num_rx_queues; i++) | ||
765 | kobject_put(&net->_rx[i].kobj); | ||
766 | kset_unregister(net->queues_kset); | ||
767 | } | ||
768 | #endif /* CONFIG_RPS */ | ||
470 | #endif /* CONFIG_SYSFS */ | 769 | #endif /* CONFIG_SYSFS */ |
471 | 770 | ||
472 | #ifdef CONFIG_HOTPLUG | 771 | #ifdef CONFIG_HOTPLUG |
@@ -530,6 +829,10 @@ void netdev_unregister_kobject(struct net_device * net) | |||
530 | if (!net_eq(dev_net(net), &init_net)) | 829 | if (!net_eq(dev_net(net), &init_net)) |
531 | return; | 830 | return; |
532 | 831 | ||
832 | #ifdef CONFIG_RPS | ||
833 | rx_queue_remove_kobjects(net); | ||
834 | #endif | ||
835 | |||
533 | device_del(dev); | 836 | device_del(dev); |
534 | } | 837 | } |
535 | 838 | ||
@@ -538,6 +841,7 @@ int netdev_register_kobject(struct net_device *net) | |||
538 | { | 841 | { |
539 | struct device *dev = &(net->dev); | 842 | struct device *dev = &(net->dev); |
540 | const struct attribute_group **groups = net->sysfs_groups; | 843 | const struct attribute_group **groups = net->sysfs_groups; |
844 | int error = 0; | ||
541 | 845 | ||
542 | dev->class = &net_class; | 846 | dev->class = &net_class; |
543 | dev->platform_data = net; | 847 | dev->platform_data = net; |
@@ -564,7 +868,19 @@ int netdev_register_kobject(struct net_device *net) | |||
564 | if (!net_eq(dev_net(net), &init_net)) | 868 | if (!net_eq(dev_net(net), &init_net)) |
565 | return 0; | 869 | return 0; |
566 | 870 | ||
567 | return device_add(dev); | 871 | error = device_add(dev); |
872 | if (error) | ||
873 | return error; | ||
874 | |||
875 | #ifdef CONFIG_RPS | ||
876 | error = rx_queue_register_kobjects(net); | ||
877 | if (error) { | ||
878 | device_del(dev); | ||
879 | return error; | ||
880 | } | ||
881 | #endif | ||
882 | |||
883 | return error; | ||
568 | } | 884 | } |
569 | 885 | ||
570 | int netdev_class_create_file(struct class_attribute *class_attr) | 886 | int netdev_class_create_file(struct class_attribute *class_attr) |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index bd8c4712ea24..c988e685433a 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -27,6 +27,51 @@ EXPORT_SYMBOL(init_net); | |||
27 | 27 | ||
28 | #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ | 28 | #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ |
29 | 29 | ||
30 | static void net_generic_release(struct rcu_head *rcu) | ||
31 | { | ||
32 | struct net_generic *ng; | ||
33 | |||
34 | ng = container_of(rcu, struct net_generic, rcu); | ||
35 | kfree(ng); | ||
36 | } | ||
37 | |||
38 | static int net_assign_generic(struct net *net, int id, void *data) | ||
39 | { | ||
40 | struct net_generic *ng, *old_ng; | ||
41 | |||
42 | BUG_ON(!mutex_is_locked(&net_mutex)); | ||
43 | BUG_ON(id == 0); | ||
44 | |||
45 | ng = old_ng = net->gen; | ||
46 | if (old_ng->len >= id) | ||
47 | goto assign; | ||
48 | |||
49 | ng = kzalloc(sizeof(struct net_generic) + | ||
50 | id * sizeof(void *), GFP_KERNEL); | ||
51 | if (ng == NULL) | ||
52 | return -ENOMEM; | ||
53 | |||
54 | /* | ||
55 | * Some synchronisation notes: | ||
56 | * | ||
57 | * The net_generic explores the net->gen array inside rcu | ||
58 | * read section. Besides once set the net->gen->ptr[x] | ||
59 | * pointer never changes (see rules in netns/generic.h). | ||
60 | * | ||
61 | * That said, we simply duplicate this array and schedule | ||
62 | * the old copy for kfree after a grace period. | ||
63 | */ | ||
64 | |||
65 | ng->len = id; | ||
66 | memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); | ||
67 | |||
68 | rcu_assign_pointer(net->gen, ng); | ||
69 | call_rcu(&old_ng->rcu, net_generic_release); | ||
70 | assign: | ||
71 | ng->ptr[id - 1] = data; | ||
72 | return 0; | ||
73 | } | ||
74 | |||
30 | static int ops_init(const struct pernet_operations *ops, struct net *net) | 75 | static int ops_init(const struct pernet_operations *ops, struct net *net) |
31 | { | 76 | { |
32 | int err; | 77 | int err; |
@@ -469,10 +514,10 @@ EXPORT_SYMBOL_GPL(register_pernet_subsys); | |||
469 | * addition run the exit method for all existing network | 514 | * addition run the exit method for all existing network |
470 | * namespaces. | 515 | * namespaces. |
471 | */ | 516 | */ |
472 | void unregister_pernet_subsys(struct pernet_operations *module) | 517 | void unregister_pernet_subsys(struct pernet_operations *ops) |
473 | { | 518 | { |
474 | mutex_lock(&net_mutex); | 519 | mutex_lock(&net_mutex); |
475 | unregister_pernet_operations(module); | 520 | unregister_pernet_operations(ops); |
476 | mutex_unlock(&net_mutex); | 521 | mutex_unlock(&net_mutex); |
477 | } | 522 | } |
478 | EXPORT_SYMBOL_GPL(unregister_pernet_subsys); | 523 | EXPORT_SYMBOL_GPL(unregister_pernet_subsys); |
@@ -526,49 +571,3 @@ void unregister_pernet_device(struct pernet_operations *ops) | |||
526 | mutex_unlock(&net_mutex); | 571 | mutex_unlock(&net_mutex); |
527 | } | 572 | } |
528 | EXPORT_SYMBOL_GPL(unregister_pernet_device); | 573 | EXPORT_SYMBOL_GPL(unregister_pernet_device); |
529 | |||
530 | static void net_generic_release(struct rcu_head *rcu) | ||
531 | { | ||
532 | struct net_generic *ng; | ||
533 | |||
534 | ng = container_of(rcu, struct net_generic, rcu); | ||
535 | kfree(ng); | ||
536 | } | ||
537 | |||
538 | int net_assign_generic(struct net *net, int id, void *data) | ||
539 | { | ||
540 | struct net_generic *ng, *old_ng; | ||
541 | |||
542 | BUG_ON(!mutex_is_locked(&net_mutex)); | ||
543 | BUG_ON(id == 0); | ||
544 | |||
545 | ng = old_ng = net->gen; | ||
546 | if (old_ng->len >= id) | ||
547 | goto assign; | ||
548 | |||
549 | ng = kzalloc(sizeof(struct net_generic) + | ||
550 | id * sizeof(void *), GFP_KERNEL); | ||
551 | if (ng == NULL) | ||
552 | return -ENOMEM; | ||
553 | |||
554 | /* | ||
555 | * Some synchronisation notes: | ||
556 | * | ||
557 | * The net_generic explores the net->gen array inside rcu | ||
558 | * read section. Besides once set the net->gen->ptr[x] | ||
559 | * pointer never changes (see rules in netns/generic.h). | ||
560 | * | ||
561 | * That said, we simply duplicate this array and schedule | ||
562 | * the old copy for kfree after a grace period. | ||
563 | */ | ||
564 | |||
565 | ng->len = id; | ||
566 | memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); | ||
567 | |||
568 | rcu_assign_pointer(net->gen, ng); | ||
569 | call_rcu(&old_ng->rcu, net_generic_release); | ||
570 | assign: | ||
571 | ng->ptr[id - 1] = data; | ||
572 | return 0; | ||
573 | } | ||
574 | EXPORT_SYMBOL_GPL(net_assign_generic); | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index a58f59b97597..94825b109551 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -179,9 +179,8 @@ static void service_arp_queue(struct netpoll_info *npi) | |||
179 | } | 179 | } |
180 | } | 180 | } |
181 | 181 | ||
182 | void netpoll_poll(struct netpoll *np) | 182 | void netpoll_poll_dev(struct net_device *dev) |
183 | { | 183 | { |
184 | struct net_device *dev = np->dev; | ||
185 | const struct net_device_ops *ops; | 184 | const struct net_device_ops *ops; |
186 | 185 | ||
187 | if (!dev || !netif_running(dev)) | 186 | if (!dev || !netif_running(dev)) |
@@ -201,6 +200,11 @@ void netpoll_poll(struct netpoll *np) | |||
201 | zap_completion_queue(); | 200 | zap_completion_queue(); |
202 | } | 201 | } |
203 | 202 | ||
203 | void netpoll_poll(struct netpoll *np) | ||
204 | { | ||
205 | netpoll_poll_dev(np->dev); | ||
206 | } | ||
207 | |||
204 | static void refill_skbs(void) | 208 | static void refill_skbs(void) |
205 | { | 209 | { |
206 | struct sk_buff *skb; | 210 | struct sk_buff *skb; |
@@ -282,7 +286,7 @@ static int netpoll_owner_active(struct net_device *dev) | |||
282 | return 0; | 286 | return 0; |
283 | } | 287 | } |
284 | 288 | ||
285 | static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | 289 | void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) |
286 | { | 290 | { |
287 | int status = NETDEV_TX_BUSY; | 291 | int status = NETDEV_TX_BUSY; |
288 | unsigned long tries; | 292 | unsigned long tries; |
@@ -308,7 +312,9 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | |||
308 | tries > 0; --tries) { | 312 | tries > 0; --tries) { |
309 | if (__netif_tx_trylock(txq)) { | 313 | if (__netif_tx_trylock(txq)) { |
310 | if (!netif_tx_queue_stopped(txq)) { | 314 | if (!netif_tx_queue_stopped(txq)) { |
315 | dev->priv_flags |= IFF_IN_NETPOLL; | ||
311 | status = ops->ndo_start_xmit(skb, dev); | 316 | status = ops->ndo_start_xmit(skb, dev); |
317 | dev->priv_flags &= ~IFF_IN_NETPOLL; | ||
312 | if (status == NETDEV_TX_OK) | 318 | if (status == NETDEV_TX_OK) |
313 | txq_trans_update(txq); | 319 | txq_trans_update(txq); |
314 | } | 320 | } |
@@ -756,7 +762,10 @@ int netpoll_setup(struct netpoll *np) | |||
756 | atomic_inc(&npinfo->refcnt); | 762 | atomic_inc(&npinfo->refcnt); |
757 | } | 763 | } |
758 | 764 | ||
759 | if (!ndev->netdev_ops->ndo_poll_controller) { | 765 | npinfo->netpoll = np; |
766 | |||
767 | if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) || | ||
768 | !ndev->netdev_ops->ndo_poll_controller) { | ||
760 | printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", | 769 | printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", |
761 | np->name, np->dev_name); | 770 | np->name, np->dev_name); |
762 | err = -ENOTSUPP; | 771 | err = -ENOTSUPP; |
@@ -878,6 +887,7 @@ void netpoll_cleanup(struct netpoll *np) | |||
878 | } | 887 | } |
879 | 888 | ||
880 | if (atomic_dec_and_test(&npinfo->refcnt)) { | 889 | if (atomic_dec_and_test(&npinfo->refcnt)) { |
890 | const struct net_device_ops *ops; | ||
881 | skb_queue_purge(&npinfo->arp_tx); | 891 | skb_queue_purge(&npinfo->arp_tx); |
882 | skb_queue_purge(&npinfo->txq); | 892 | skb_queue_purge(&npinfo->txq); |
883 | cancel_rearming_delayed_work(&npinfo->tx_work); | 893 | cancel_rearming_delayed_work(&npinfo->tx_work); |
@@ -885,7 +895,11 @@ void netpoll_cleanup(struct netpoll *np) | |||
885 | /* clean after last, unfinished work */ | 895 | /* clean after last, unfinished work */ |
886 | __skb_queue_purge(&npinfo->txq); | 896 | __skb_queue_purge(&npinfo->txq); |
887 | kfree(npinfo); | 897 | kfree(npinfo); |
888 | np->dev->npinfo = NULL; | 898 | ops = np->dev->netdev_ops; |
899 | if (ops->ndo_netpoll_cleanup) | ||
900 | ops->ndo_netpoll_cleanup(np->dev); | ||
901 | else | ||
902 | np->dev->npinfo = NULL; | ||
889 | } | 903 | } |
890 | } | 904 | } |
891 | 905 | ||
@@ -908,6 +922,7 @@ void netpoll_set_trap(int trap) | |||
908 | atomic_dec(&trapped); | 922 | atomic_dec(&trapped); |
909 | } | 923 | } |
910 | 924 | ||
925 | EXPORT_SYMBOL(netpoll_send_skb); | ||
911 | EXPORT_SYMBOL(netpoll_set_trap); | 926 | EXPORT_SYMBOL(netpoll_set_trap); |
912 | EXPORT_SYMBOL(netpoll_trap); | 927 | EXPORT_SYMBOL(netpoll_trap); |
913 | EXPORT_SYMBOL(netpoll_print_options); | 928 | EXPORT_SYMBOL(netpoll_print_options); |
@@ -915,4 +930,5 @@ EXPORT_SYMBOL(netpoll_parse_options); | |||
915 | EXPORT_SYMBOL(netpoll_setup); | 930 | EXPORT_SYMBOL(netpoll_setup); |
916 | EXPORT_SYMBOL(netpoll_cleanup); | 931 | EXPORT_SYMBOL(netpoll_cleanup); |
917 | EXPORT_SYMBOL(netpoll_send_udp); | 932 | EXPORT_SYMBOL(netpoll_send_udp); |
933 | EXPORT_SYMBOL(netpoll_poll_dev); | ||
918 | EXPORT_SYMBOL(netpoll_poll); | 934 | EXPORT_SYMBOL(netpoll_poll); |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 43923811bd6a..2ad68da418df 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -169,7 +169,7 @@ | |||
169 | #include <asm/dma.h> | 169 | #include <asm/dma.h> |
170 | #include <asm/div64.h> /* do_div */ | 170 | #include <asm/div64.h> /* do_div */ |
171 | 171 | ||
172 | #define VERSION "2.72" | 172 | #define VERSION "2.73" |
173 | #define IP_NAME_SZ 32 | 173 | #define IP_NAME_SZ 32 |
174 | #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ | 174 | #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ |
175 | #define MPLS_STACK_BOTTOM htonl(0x00000100) | 175 | #define MPLS_STACK_BOTTOM htonl(0x00000100) |
@@ -190,6 +190,7 @@ | |||
190 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ | 190 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ |
191 | #define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ | 191 | #define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ |
192 | #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ | 192 | #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ |
193 | #define F_NODE (1<<15) /* Node memory alloc*/ | ||
193 | 194 | ||
194 | /* Thread control flag bits */ | 195 | /* Thread control flag bits */ |
195 | #define T_STOP (1<<0) /* Stop run */ | 196 | #define T_STOP (1<<0) /* Stop run */ |
@@ -372,6 +373,7 @@ struct pktgen_dev { | |||
372 | 373 | ||
373 | u16 queue_map_min; | 374 | u16 queue_map_min; |
374 | u16 queue_map_max; | 375 | u16 queue_map_max; |
376 | int node; /* Memory node */ | ||
375 | 377 | ||
376 | #ifdef CONFIG_XFRM | 378 | #ifdef CONFIG_XFRM |
377 | __u8 ipsmode; /* IPSEC mode (config) */ | 379 | __u8 ipsmode; /* IPSEC mode (config) */ |
@@ -607,6 +609,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
607 | if (pkt_dev->traffic_class) | 609 | if (pkt_dev->traffic_class) |
608 | seq_printf(seq, " traffic_class: 0x%02x\n", pkt_dev->traffic_class); | 610 | seq_printf(seq, " traffic_class: 0x%02x\n", pkt_dev->traffic_class); |
609 | 611 | ||
612 | if (pkt_dev->node >= 0) | ||
613 | seq_printf(seq, " node: %d\n", pkt_dev->node); | ||
614 | |||
610 | seq_printf(seq, " Flags: "); | 615 | seq_printf(seq, " Flags: "); |
611 | 616 | ||
612 | if (pkt_dev->flags & F_IPV6) | 617 | if (pkt_dev->flags & F_IPV6) |
@@ -660,6 +665,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
660 | if (pkt_dev->flags & F_SVID_RND) | 665 | if (pkt_dev->flags & F_SVID_RND) |
661 | seq_printf(seq, "SVID_RND "); | 666 | seq_printf(seq, "SVID_RND "); |
662 | 667 | ||
668 | if (pkt_dev->flags & F_NODE) | ||
669 | seq_printf(seq, "NODE_ALLOC "); | ||
670 | |||
663 | seq_puts(seq, "\n"); | 671 | seq_puts(seq, "\n"); |
664 | 672 | ||
665 | /* not really stopped, more like last-running-at */ | 673 | /* not really stopped, more like last-running-at */ |
@@ -1074,6 +1082,21 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1074 | pkt_dev->dst_mac_count); | 1082 | pkt_dev->dst_mac_count); |
1075 | return count; | 1083 | return count; |
1076 | } | 1084 | } |
1085 | if (!strcmp(name, "node")) { | ||
1086 | len = num_arg(&user_buffer[i], 10, &value); | ||
1087 | if (len < 0) | ||
1088 | return len; | ||
1089 | |||
1090 | i += len; | ||
1091 | |||
1092 | if (node_possible(value)) { | ||
1093 | pkt_dev->node = value; | ||
1094 | sprintf(pg_result, "OK: node=%d", pkt_dev->node); | ||
1095 | } | ||
1096 | else | ||
1097 | sprintf(pg_result, "ERROR: node not possible"); | ||
1098 | return count; | ||
1099 | } | ||
1077 | if (!strcmp(name, "flag")) { | 1100 | if (!strcmp(name, "flag")) { |
1078 | char f[32]; | 1101 | char f[32]; |
1079 | memset(f, 0, 32); | 1102 | memset(f, 0, 32); |
@@ -1166,12 +1189,18 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1166 | else if (strcmp(f, "!IPV6") == 0) | 1189 | else if (strcmp(f, "!IPV6") == 0) |
1167 | pkt_dev->flags &= ~F_IPV6; | 1190 | pkt_dev->flags &= ~F_IPV6; |
1168 | 1191 | ||
1192 | else if (strcmp(f, "NODE_ALLOC") == 0) | ||
1193 | pkt_dev->flags |= F_NODE; | ||
1194 | |||
1195 | else if (strcmp(f, "!NODE_ALLOC") == 0) | ||
1196 | pkt_dev->flags &= ~F_NODE; | ||
1197 | |||
1169 | else { | 1198 | else { |
1170 | sprintf(pg_result, | 1199 | sprintf(pg_result, |
1171 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", | 1200 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", |
1172 | f, | 1201 | f, |
1173 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " | 1202 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " |
1174 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n"); | 1203 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC, NODE_ALLOC\n"); |
1175 | return count; | 1204 | return count; |
1176 | } | 1205 | } |
1177 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); | 1206 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); |
@@ -2572,9 +2601,27 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2572 | mod_cur_headers(pkt_dev); | 2601 | mod_cur_headers(pkt_dev); |
2573 | 2602 | ||
2574 | datalen = (odev->hard_header_len + 16) & ~0xf; | 2603 | datalen = (odev->hard_header_len + 16) & ~0xf; |
2575 | skb = __netdev_alloc_skb(odev, | 2604 | |
2576 | pkt_dev->cur_pkt_size + 64 | 2605 | if (pkt_dev->flags & F_NODE) { |
2577 | + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT); | 2606 | int node; |
2607 | |||
2608 | if (pkt_dev->node >= 0) | ||
2609 | node = pkt_dev->node; | ||
2610 | else | ||
2611 | node = numa_node_id(); | ||
2612 | |||
2613 | skb = __alloc_skb(NET_SKB_PAD + pkt_dev->cur_pkt_size + 64 | ||
2614 | + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT, 0, node); | ||
2615 | if (likely(skb)) { | ||
2616 | skb_reserve(skb, NET_SKB_PAD); | ||
2617 | skb->dev = odev; | ||
2618 | } | ||
2619 | } | ||
2620 | else | ||
2621 | skb = __netdev_alloc_skb(odev, | ||
2622 | pkt_dev->cur_pkt_size + 64 | ||
2623 | + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT); | ||
2624 | |||
2578 | if (!skb) { | 2625 | if (!skb) { |
2579 | sprintf(pkt_dev->result, "No memory"); | 2626 | sprintf(pkt_dev->result, "No memory"); |
2580 | return NULL; | 2627 | return NULL; |
@@ -3674,6 +3721,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
3674 | pkt_dev->svlan_p = 0; | 3721 | pkt_dev->svlan_p = 0; |
3675 | pkt_dev->svlan_cfi = 0; | 3722 | pkt_dev->svlan_cfi = 0; |
3676 | pkt_dev->svlan_id = 0xffff; | 3723 | pkt_dev->svlan_id = 0xffff; |
3724 | pkt_dev->node = -1; | ||
3677 | 3725 | ||
3678 | err = pktgen_setup_dev(pkt_dev, ifname); | 3726 | err = pktgen_setup_dev(pkt_dev, ifname); |
3679 | if (err) | 3727 | if (err) |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 31e85d327aa2..e4b9870e4706 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -98,7 +98,7 @@ int lockdep_rtnl_is_held(void) | |||
98 | EXPORT_SYMBOL(lockdep_rtnl_is_held); | 98 | EXPORT_SYMBOL(lockdep_rtnl_is_held); |
99 | #endif /* #ifdef CONFIG_PROVE_LOCKING */ | 99 | #endif /* #ifdef CONFIG_PROVE_LOCKING */ |
100 | 100 | ||
101 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; | 101 | static struct rtnl_link *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1]; |
102 | 102 | ||
103 | static inline int rtm_msgindex(int msgtype) | 103 | static inline int rtm_msgindex(int msgtype) |
104 | { | 104 | { |
@@ -118,7 +118,11 @@ static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex) | |||
118 | { | 118 | { |
119 | struct rtnl_link *tab; | 119 | struct rtnl_link *tab; |
120 | 120 | ||
121 | tab = rtnl_msg_handlers[protocol]; | 121 | if (protocol <= RTNL_FAMILY_MAX) |
122 | tab = rtnl_msg_handlers[protocol]; | ||
123 | else | ||
124 | tab = NULL; | ||
125 | |||
122 | if (tab == NULL || tab[msgindex].doit == NULL) | 126 | if (tab == NULL || tab[msgindex].doit == NULL) |
123 | tab = rtnl_msg_handlers[PF_UNSPEC]; | 127 | tab = rtnl_msg_handlers[PF_UNSPEC]; |
124 | 128 | ||
@@ -129,7 +133,11 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex) | |||
129 | { | 133 | { |
130 | struct rtnl_link *tab; | 134 | struct rtnl_link *tab; |
131 | 135 | ||
132 | tab = rtnl_msg_handlers[protocol]; | 136 | if (protocol <= RTNL_FAMILY_MAX) |
137 | tab = rtnl_msg_handlers[protocol]; | ||
138 | else | ||
139 | tab = NULL; | ||
140 | |||
133 | if (tab == NULL || tab[msgindex].dumpit == NULL) | 141 | if (tab == NULL || tab[msgindex].dumpit == NULL) |
134 | tab = rtnl_msg_handlers[PF_UNSPEC]; | 142 | tab = rtnl_msg_handlers[PF_UNSPEC]; |
135 | 143 | ||
@@ -159,7 +167,7 @@ int __rtnl_register(int protocol, int msgtype, | |||
159 | struct rtnl_link *tab; | 167 | struct rtnl_link *tab; |
160 | int msgindex; | 168 | int msgindex; |
161 | 169 | ||
162 | BUG_ON(protocol < 0 || protocol >= NPROTO); | 170 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
163 | msgindex = rtm_msgindex(msgtype); | 171 | msgindex = rtm_msgindex(msgtype); |
164 | 172 | ||
165 | tab = rtnl_msg_handlers[protocol]; | 173 | tab = rtnl_msg_handlers[protocol]; |
@@ -211,7 +219,7 @@ int rtnl_unregister(int protocol, int msgtype) | |||
211 | { | 219 | { |
212 | int msgindex; | 220 | int msgindex; |
213 | 221 | ||
214 | BUG_ON(protocol < 0 || protocol >= NPROTO); | 222 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
215 | msgindex = rtm_msgindex(msgtype); | 223 | msgindex = rtm_msgindex(msgtype); |
216 | 224 | ||
217 | if (rtnl_msg_handlers[protocol] == NULL) | 225 | if (rtnl_msg_handlers[protocol] == NULL) |
@@ -233,7 +241,7 @@ EXPORT_SYMBOL_GPL(rtnl_unregister); | |||
233 | */ | 241 | */ |
234 | void rtnl_unregister_all(int protocol) | 242 | void rtnl_unregister_all(int protocol) |
235 | { | 243 | { |
236 | BUG_ON(protocol < 0 || protocol >= NPROTO); | 244 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
237 | 245 | ||
238 | kfree(rtnl_msg_handlers[protocol]); | 246 | kfree(rtnl_msg_handlers[protocol]); |
239 | rtnl_msg_handlers[protocol] = NULL; | 247 | rtnl_msg_handlers[protocol] = NULL; |
@@ -600,7 +608,41 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
600 | 608 | ||
601 | a->rx_compressed = b->rx_compressed; | 609 | a->rx_compressed = b->rx_compressed; |
602 | a->tx_compressed = b->tx_compressed; | 610 | a->tx_compressed = b->tx_compressed; |
603 | }; | 611 | } |
612 | |||
613 | static void copy_rtnl_link_stats64(void *v, const struct net_device_stats *b) | ||
614 | { | ||
615 | struct rtnl_link_stats64 a; | ||
616 | |||
617 | a.rx_packets = b->rx_packets; | ||
618 | a.tx_packets = b->tx_packets; | ||
619 | a.rx_bytes = b->rx_bytes; | ||
620 | a.tx_bytes = b->tx_bytes; | ||
621 | a.rx_errors = b->rx_errors; | ||
622 | a.tx_errors = b->tx_errors; | ||
623 | a.rx_dropped = b->rx_dropped; | ||
624 | a.tx_dropped = b->tx_dropped; | ||
625 | |||
626 | a.multicast = b->multicast; | ||
627 | a.collisions = b->collisions; | ||
628 | |||
629 | a.rx_length_errors = b->rx_length_errors; | ||
630 | a.rx_over_errors = b->rx_over_errors; | ||
631 | a.rx_crc_errors = b->rx_crc_errors; | ||
632 | a.rx_frame_errors = b->rx_frame_errors; | ||
633 | a.rx_fifo_errors = b->rx_fifo_errors; | ||
634 | a.rx_missed_errors = b->rx_missed_errors; | ||
635 | |||
636 | a.tx_aborted_errors = b->tx_aborted_errors; | ||
637 | a.tx_carrier_errors = b->tx_carrier_errors; | ||
638 | a.tx_fifo_errors = b->tx_fifo_errors; | ||
639 | a.tx_heartbeat_errors = b->tx_heartbeat_errors; | ||
640 | a.tx_window_errors = b->tx_window_errors; | ||
641 | |||
642 | a.rx_compressed = b->rx_compressed; | ||
643 | a.tx_compressed = b->tx_compressed; | ||
644 | memcpy(v, &a, sizeof(a)); | ||
645 | } | ||
604 | 646 | ||
605 | /* All VF info */ | 647 | /* All VF info */ |
606 | static inline int rtnl_vfinfo_size(const struct net_device *dev) | 648 | static inline int rtnl_vfinfo_size(const struct net_device *dev) |
@@ -618,6 +660,31 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev) | |||
618 | return 0; | 660 | return 0; |
619 | } | 661 | } |
620 | 662 | ||
663 | static size_t rtnl_port_size(const struct net_device *dev) | ||
664 | { | ||
665 | size_t port_size = nla_total_size(4) /* PORT_VF */ | ||
666 | + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */ | ||
667 | + nla_total_size(sizeof(struct ifla_port_vsi)) | ||
668 | /* PORT_VSI_TYPE */ | ||
669 | + nla_total_size(PORT_UUID_MAX) /* PORT_INSTANCE_UUID */ | ||
670 | + nla_total_size(PORT_UUID_MAX) /* PORT_HOST_UUID */ | ||
671 | + nla_total_size(1) /* PROT_VDP_REQUEST */ | ||
672 | + nla_total_size(2); /* PORT_VDP_RESPONSE */ | ||
673 | size_t vf_ports_size = nla_total_size(sizeof(struct nlattr)); | ||
674 | size_t vf_port_size = nla_total_size(sizeof(struct nlattr)) | ||
675 | + port_size; | ||
676 | size_t port_self_size = nla_total_size(sizeof(struct nlattr)) | ||
677 | + port_size; | ||
678 | |||
679 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) | ||
680 | return 0; | ||
681 | if (dev_num_vf(dev->dev.parent)) | ||
682 | return port_self_size + vf_ports_size + | ||
683 | vf_port_size * dev_num_vf(dev->dev.parent); | ||
684 | else | ||
685 | return port_self_size; | ||
686 | } | ||
687 | |||
621 | static inline size_t if_nlmsg_size(const struct net_device *dev) | 688 | static inline size_t if_nlmsg_size(const struct net_device *dev) |
622 | { | 689 | { |
623 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 690 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
@@ -626,6 +693,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
626 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ | 693 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ |
627 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) | 694 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) |
628 | + nla_total_size(sizeof(struct rtnl_link_stats)) | 695 | + nla_total_size(sizeof(struct rtnl_link_stats)) |
696 | + nla_total_size(sizeof(struct rtnl_link_stats64)) | ||
629 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ | 697 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ |
630 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ | 698 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ |
631 | + nla_total_size(4) /* IFLA_TXQLEN */ | 699 | + nla_total_size(4) /* IFLA_TXQLEN */ |
@@ -637,9 +705,82 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
637 | + nla_total_size(1) /* IFLA_LINKMODE */ | 705 | + nla_total_size(1) /* IFLA_LINKMODE */ |
638 | + nla_total_size(4) /* IFLA_NUM_VF */ | 706 | + nla_total_size(4) /* IFLA_NUM_VF */ |
639 | + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ | 707 | + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ |
708 | + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ | ||
640 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ | 709 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ |
641 | } | 710 | } |
642 | 711 | ||
712 | static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev) | ||
713 | { | ||
714 | struct nlattr *vf_ports; | ||
715 | struct nlattr *vf_port; | ||
716 | int vf; | ||
717 | int err; | ||
718 | |||
719 | vf_ports = nla_nest_start(skb, IFLA_VF_PORTS); | ||
720 | if (!vf_ports) | ||
721 | return -EMSGSIZE; | ||
722 | |||
723 | for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) { | ||
724 | vf_port = nla_nest_start(skb, IFLA_VF_PORT); | ||
725 | if (!vf_port) { | ||
726 | nla_nest_cancel(skb, vf_ports); | ||
727 | return -EMSGSIZE; | ||
728 | } | ||
729 | NLA_PUT_U32(skb, IFLA_PORT_VF, vf); | ||
730 | err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb); | ||
731 | if (err) { | ||
732 | nla_put_failure: | ||
733 | nla_nest_cancel(skb, vf_port); | ||
734 | continue; | ||
735 | } | ||
736 | nla_nest_end(skb, vf_port); | ||
737 | } | ||
738 | |||
739 | nla_nest_end(skb, vf_ports); | ||
740 | |||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev) | ||
745 | { | ||
746 | struct nlattr *port_self; | ||
747 | int err; | ||
748 | |||
749 | port_self = nla_nest_start(skb, IFLA_PORT_SELF); | ||
750 | if (!port_self) | ||
751 | return -EMSGSIZE; | ||
752 | |||
753 | err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb); | ||
754 | if (err) { | ||
755 | nla_nest_cancel(skb, port_self); | ||
756 | return err; | ||
757 | } | ||
758 | |||
759 | nla_nest_end(skb, port_self); | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev) | ||
765 | { | ||
766 | int err; | ||
767 | |||
768 | if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent) | ||
769 | return 0; | ||
770 | |||
771 | err = rtnl_port_self_fill(skb, dev); | ||
772 | if (err) | ||
773 | return err; | ||
774 | |||
775 | if (dev_num_vf(dev->dev.parent)) { | ||
776 | err = rtnl_vf_ports_fill(skb, dev); | ||
777 | if (err) | ||
778 | return err; | ||
779 | } | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
643 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | 784 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, |
644 | int type, u32 pid, u32 seq, u32 change, | 785 | int type, u32 pid, u32 seq, u32 change, |
645 | unsigned int flags) | 786 | unsigned int flags) |
@@ -705,13 +846,21 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
705 | stats = dev_get_stats(dev); | 846 | stats = dev_get_stats(dev); |
706 | copy_rtnl_link_stats(nla_data(attr), stats); | 847 | copy_rtnl_link_stats(nla_data(attr), stats); |
707 | 848 | ||
849 | attr = nla_reserve(skb, IFLA_STATS64, | ||
850 | sizeof(struct rtnl_link_stats64)); | ||
851 | if (attr == NULL) | ||
852 | goto nla_put_failure; | ||
853 | copy_rtnl_link_stats64(nla_data(attr), stats); | ||
854 | |||
855 | if (dev->dev.parent) | ||
856 | NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); | ||
857 | |||
708 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { | 858 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { |
709 | int i; | 859 | int i; |
710 | 860 | ||
711 | struct nlattr *vfinfo, *vf; | 861 | struct nlattr *vfinfo, *vf; |
712 | int num_vfs = dev_num_vf(dev->dev.parent); | 862 | int num_vfs = dev_num_vf(dev->dev.parent); |
713 | 863 | ||
714 | NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs); | ||
715 | vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); | 864 | vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); |
716 | if (!vfinfo) | 865 | if (!vfinfo) |
717 | goto nla_put_failure; | 866 | goto nla_put_failure; |
@@ -739,6 +888,10 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
739 | } | 888 | } |
740 | nla_nest_end(skb, vfinfo); | 889 | nla_nest_end(skb, vfinfo); |
741 | } | 890 | } |
891 | |||
892 | if (rtnl_port_fill(skb, dev)) | ||
893 | goto nla_put_failure; | ||
894 | |||
742 | if (dev->rtnl_link_ops) { | 895 | if (dev->rtnl_link_ops) { |
743 | if (rtnl_link_fill(skb, dev) < 0) | 896 | if (rtnl_link_fill(skb, dev) < 0) |
744 | goto nla_put_failure; | 897 | goto nla_put_failure; |
@@ -800,6 +953,8 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
800 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 953 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
801 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | 954 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, |
802 | [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, | 955 | [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, |
956 | [IFLA_VF_PORTS] = { .type = NLA_NESTED }, | ||
957 | [IFLA_PORT_SELF] = { .type = NLA_NESTED }, | ||
803 | }; | 958 | }; |
804 | EXPORT_SYMBOL(ifla_policy); | 959 | EXPORT_SYMBOL(ifla_policy); |
805 | 960 | ||
@@ -821,6 +976,20 @@ static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { | |||
821 | .len = sizeof(struct ifla_vf_tx_rate) }, | 976 | .len = sizeof(struct ifla_vf_tx_rate) }, |
822 | }; | 977 | }; |
823 | 978 | ||
979 | static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { | ||
980 | [IFLA_PORT_VF] = { .type = NLA_U32 }, | ||
981 | [IFLA_PORT_PROFILE] = { .type = NLA_STRING, | ||
982 | .len = PORT_PROFILE_MAX }, | ||
983 | [IFLA_PORT_VSI_TYPE] = { .type = NLA_BINARY, | ||
984 | .len = sizeof(struct ifla_port_vsi)}, | ||
985 | [IFLA_PORT_INSTANCE_UUID] = { .type = NLA_BINARY, | ||
986 | .len = PORT_UUID_MAX }, | ||
987 | [IFLA_PORT_HOST_UUID] = { .type = NLA_STRING, | ||
988 | .len = PORT_UUID_MAX }, | ||
989 | [IFLA_PORT_REQUEST] = { .type = NLA_U8, }, | ||
990 | [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, | ||
991 | }; | ||
992 | |||
824 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | 993 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) |
825 | { | 994 | { |
826 | struct net *net; | 995 | struct net *net; |
@@ -1040,6 +1209,53 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
1040 | } | 1209 | } |
1041 | err = 0; | 1210 | err = 0; |
1042 | 1211 | ||
1212 | if (tb[IFLA_VF_PORTS]) { | ||
1213 | struct nlattr *port[IFLA_PORT_MAX+1]; | ||
1214 | struct nlattr *attr; | ||
1215 | int vf; | ||
1216 | int rem; | ||
1217 | |||
1218 | err = -EOPNOTSUPP; | ||
1219 | if (!ops->ndo_set_vf_port) | ||
1220 | goto errout; | ||
1221 | |||
1222 | nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { | ||
1223 | if (nla_type(attr) != IFLA_VF_PORT) | ||
1224 | continue; | ||
1225 | err = nla_parse_nested(port, IFLA_PORT_MAX, | ||
1226 | attr, ifla_port_policy); | ||
1227 | if (err < 0) | ||
1228 | goto errout; | ||
1229 | if (!port[IFLA_PORT_VF]) { | ||
1230 | err = -EOPNOTSUPP; | ||
1231 | goto errout; | ||
1232 | } | ||
1233 | vf = nla_get_u32(port[IFLA_PORT_VF]); | ||
1234 | err = ops->ndo_set_vf_port(dev, vf, port); | ||
1235 | if (err < 0) | ||
1236 | goto errout; | ||
1237 | modified = 1; | ||
1238 | } | ||
1239 | } | ||
1240 | err = 0; | ||
1241 | |||
1242 | if (tb[IFLA_PORT_SELF]) { | ||
1243 | struct nlattr *port[IFLA_PORT_MAX+1]; | ||
1244 | |||
1245 | err = nla_parse_nested(port, IFLA_PORT_MAX, | ||
1246 | tb[IFLA_PORT_SELF], ifla_port_policy); | ||
1247 | if (err < 0) | ||
1248 | goto errout; | ||
1249 | |||
1250 | err = -EOPNOTSUPP; | ||
1251 | if (ops->ndo_set_vf_port) | ||
1252 | err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port); | ||
1253 | if (err < 0) | ||
1254 | goto errout; | ||
1255 | modified = 1; | ||
1256 | } | ||
1257 | err = 0; | ||
1258 | |||
1043 | errout: | 1259 | errout: |
1044 | if (err < 0 && modified && net_ratelimit()) | 1260 | if (err < 0 && modified && net_ratelimit()) |
1045 | printk(KERN_WARNING "A link change request failed with " | 1261 | printk(KERN_WARNING "A link change request failed with " |
@@ -1397,7 +1613,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | |||
1397 | 1613 | ||
1398 | if (s_idx == 0) | 1614 | if (s_idx == 0) |
1399 | s_idx = 1; | 1615 | s_idx = 1; |
1400 | for (idx = 1; idx < NPROTO; idx++) { | 1616 | for (idx = 1; idx <= RTNL_FAMILY_MAX; idx++) { |
1401 | int type = cb->nlh->nlmsg_type-RTM_BASE; | 1617 | int type = cb->nlh->nlmsg_type-RTM_BASE; |
1402 | if (idx < s_idx || idx == PF_PACKET) | 1618 | if (idx < s_idx || idx == PF_PACKET) |
1403 | continue; | 1619 | continue; |
@@ -1465,9 +1681,6 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1465 | return 0; | 1681 | return 0; |
1466 | 1682 | ||
1467 | family = ((struct rtgenmsg *)NLMSG_DATA(nlh))->rtgen_family; | 1683 | family = ((struct rtgenmsg *)NLMSG_DATA(nlh))->rtgen_family; |
1468 | if (family >= NPROTO) | ||
1469 | return -EAFNOSUPPORT; | ||
1470 | |||
1471 | sz_idx = type>>2; | 1684 | sz_idx = type>>2; |
1472 | kind = type&3; | 1685 | kind = type&3; |
1473 | 1686 | ||
@@ -1535,6 +1748,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi | |||
1535 | case NETDEV_POST_INIT: | 1748 | case NETDEV_POST_INIT: |
1536 | case NETDEV_REGISTER: | 1749 | case NETDEV_REGISTER: |
1537 | case NETDEV_CHANGE: | 1750 | case NETDEV_CHANGE: |
1751 | case NETDEV_PRE_TYPE_CHANGE: | ||
1538 | case NETDEV_GOING_DOWN: | 1752 | case NETDEV_GOING_DOWN: |
1539 | case NETDEV_UNREGISTER: | 1753 | case NETDEV_UNREGISTER: |
1540 | case NETDEV_UNREGISTER_BATCH: | 1754 | case NETDEV_UNREGISTER_BATCH: |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 93c4e060c91e..c543dd252433 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -117,7 +117,7 @@ static const struct pipe_buf_operations sock_pipe_buf_ops = { | |||
117 | * | 117 | * |
118 | * Out of line support code for skb_put(). Not user callable. | 118 | * Out of line support code for skb_put(). Not user callable. |
119 | */ | 119 | */ |
120 | void skb_over_panic(struct sk_buff *skb, int sz, void *here) | 120 | static void skb_over_panic(struct sk_buff *skb, int sz, void *here) |
121 | { | 121 | { |
122 | printk(KERN_EMERG "skb_over_panic: text:%p len:%d put:%d head:%p " | 122 | printk(KERN_EMERG "skb_over_panic: text:%p len:%d put:%d head:%p " |
123 | "data:%p tail:%#lx end:%#lx dev:%s\n", | 123 | "data:%p tail:%#lx end:%#lx dev:%s\n", |
@@ -126,7 +126,6 @@ void skb_over_panic(struct sk_buff *skb, int sz, void *here) | |||
126 | skb->dev ? skb->dev->name : "<NULL>"); | 126 | skb->dev ? skb->dev->name : "<NULL>"); |
127 | BUG(); | 127 | BUG(); |
128 | } | 128 | } |
129 | EXPORT_SYMBOL(skb_over_panic); | ||
130 | 129 | ||
131 | /** | 130 | /** |
132 | * skb_under_panic - private function | 131 | * skb_under_panic - private function |
@@ -137,7 +136,7 @@ EXPORT_SYMBOL(skb_over_panic); | |||
137 | * Out of line support code for skb_push(). Not user callable. | 136 | * Out of line support code for skb_push(). Not user callable. |
138 | */ | 137 | */ |
139 | 138 | ||
140 | void skb_under_panic(struct sk_buff *skb, int sz, void *here) | 139 | static void skb_under_panic(struct sk_buff *skb, int sz, void *here) |
141 | { | 140 | { |
142 | printk(KERN_EMERG "skb_under_panic: text:%p len:%d put:%d head:%p " | 141 | printk(KERN_EMERG "skb_under_panic: text:%p len:%d put:%d head:%p " |
143 | "data:%p tail:%#lx end:%#lx dev:%s\n", | 142 | "data:%p tail:%#lx end:%#lx dev:%s\n", |
@@ -146,7 +145,6 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) | |||
146 | skb->dev ? skb->dev->name : "<NULL>"); | 145 | skb->dev ? skb->dev->name : "<NULL>"); |
147 | BUG(); | 146 | BUG(); |
148 | } | 147 | } |
149 | EXPORT_SYMBOL(skb_under_panic); | ||
150 | 148 | ||
151 | /* Allocate a new skbuff. We do this ourselves so we can fill in a few | 149 | /* Allocate a new skbuff. We do this ourselves so we can fill in a few |
152 | * 'private' fields and also do memory statistics to find all the | 150 | * 'private' fields and also do memory statistics to find all the |
@@ -183,12 +181,14 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, | |||
183 | skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node); | 181 | skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node); |
184 | if (!skb) | 182 | if (!skb) |
185 | goto out; | 183 | goto out; |
184 | prefetchw(skb); | ||
186 | 185 | ||
187 | size = SKB_DATA_ALIGN(size); | 186 | size = SKB_DATA_ALIGN(size); |
188 | data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info), | 187 | data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info), |
189 | gfp_mask, node); | 188 | gfp_mask, node); |
190 | if (!data) | 189 | if (!data) |
191 | goto nodata; | 190 | goto nodata; |
191 | prefetchw(data + size); | ||
192 | 192 | ||
193 | /* | 193 | /* |
194 | * Only clear those fields we need to clear, not those that we will | 194 | * Only clear those fields we need to clear, not those that we will |
@@ -210,15 +210,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, | |||
210 | 210 | ||
211 | /* make sure we initialize shinfo sequentially */ | 211 | /* make sure we initialize shinfo sequentially */ |
212 | shinfo = skb_shinfo(skb); | 212 | shinfo = skb_shinfo(skb); |
213 | memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); | ||
213 | atomic_set(&shinfo->dataref, 1); | 214 | atomic_set(&shinfo->dataref, 1); |
214 | shinfo->nr_frags = 0; | ||
215 | shinfo->gso_size = 0; | ||
216 | shinfo->gso_segs = 0; | ||
217 | shinfo->gso_type = 0; | ||
218 | shinfo->ip6_frag_id = 0; | ||
219 | shinfo->tx_flags.flags = 0; | ||
220 | skb_frag_list_init(skb); | ||
221 | memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps)); | ||
222 | 215 | ||
223 | if (fclone) { | 216 | if (fclone) { |
224 | struct sk_buff *child = skb + 1; | 217 | struct sk_buff *child = skb + 1; |
@@ -507,16 +500,10 @@ int skb_recycle_check(struct sk_buff *skb, int skb_size) | |||
507 | return 0; | 500 | return 0; |
508 | 501 | ||
509 | skb_release_head_state(skb); | 502 | skb_release_head_state(skb); |
503 | |||
510 | shinfo = skb_shinfo(skb); | 504 | shinfo = skb_shinfo(skb); |
505 | memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); | ||
511 | atomic_set(&shinfo->dataref, 1); | 506 | atomic_set(&shinfo->dataref, 1); |
512 | shinfo->nr_frags = 0; | ||
513 | shinfo->gso_size = 0; | ||
514 | shinfo->gso_segs = 0; | ||
515 | shinfo->gso_type = 0; | ||
516 | shinfo->ip6_frag_id = 0; | ||
517 | shinfo->tx_flags.flags = 0; | ||
518 | skb_frag_list_init(skb); | ||
519 | memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps)); | ||
520 | 507 | ||
521 | memset(skb, 0, offsetof(struct sk_buff, tail)); | 508 | memset(skb, 0, offsetof(struct sk_buff, tail)); |
522 | skb->data = skb->head + NET_SKB_PAD; | 509 | skb->data = skb->head + NET_SKB_PAD; |
@@ -533,7 +520,8 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
533 | new->transport_header = old->transport_header; | 520 | new->transport_header = old->transport_header; |
534 | new->network_header = old->network_header; | 521 | new->network_header = old->network_header; |
535 | new->mac_header = old->mac_header; | 522 | new->mac_header = old->mac_header; |
536 | skb_dst_set(new, dst_clone(skb_dst(old))); | 523 | skb_dst_copy(new, old); |
524 | new->rxhash = old->rxhash; | ||
537 | #ifdef CONFIG_XFRM | 525 | #ifdef CONFIG_XFRM |
538 | new->sp = secpath_get(old->sp); | 526 | new->sp = secpath_get(old->sp); |
539 | #endif | 527 | #endif |
@@ -581,6 +569,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) | |||
581 | C(len); | 569 | C(len); |
582 | C(data_len); | 570 | C(data_len); |
583 | C(mac_len); | 571 | C(mac_len); |
572 | C(rxhash); | ||
584 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; | 573 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; |
585 | n->cloned = 1; | 574 | n->cloned = 1; |
586 | n->nohdr = 0; | 575 | n->nohdr = 0; |
@@ -1051,7 +1040,7 @@ EXPORT_SYMBOL(skb_push); | |||
1051 | */ | 1040 | */ |
1052 | unsigned char *skb_pull(struct sk_buff *skb, unsigned int len) | 1041 | unsigned char *skb_pull(struct sk_buff *skb, unsigned int len) |
1053 | { | 1042 | { |
1054 | return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); | 1043 | return skb_pull_inline(skb, len); |
1055 | } | 1044 | } |
1056 | EXPORT_SYMBOL(skb_pull); | 1045 | EXPORT_SYMBOL(skb_pull); |
1057 | 1046 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index c5812bbc2cc9..bf88a167c8f2 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -307,6 +307,11 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
307 | */ | 307 | */ |
308 | skb_len = skb->len; | 308 | skb_len = skb->len; |
309 | 309 | ||
310 | /* we escape from rcu protected region, make sure we dont leak | ||
311 | * a norefcounted dst | ||
312 | */ | ||
313 | skb_dst_force(skb); | ||
314 | |||
310 | spin_lock_irqsave(&list->lock, flags); | 315 | spin_lock_irqsave(&list->lock, flags); |
311 | skb->dropcount = atomic_read(&sk->sk_drops); | 316 | skb->dropcount = atomic_read(&sk->sk_drops); |
312 | __skb_queue_tail(list, skb); | 317 | __skb_queue_tail(list, skb); |
@@ -327,6 +332,10 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) | |||
327 | 332 | ||
328 | skb->dev = NULL; | 333 | skb->dev = NULL; |
329 | 334 | ||
335 | if (sk_rcvqueues_full(sk, skb)) { | ||
336 | atomic_inc(&sk->sk_drops); | ||
337 | goto discard_and_relse; | ||
338 | } | ||
330 | if (nested) | 339 | if (nested) |
331 | bh_lock_sock_nested(sk); | 340 | bh_lock_sock_nested(sk); |
332 | else | 341 | else |
@@ -364,11 +373,11 @@ EXPORT_SYMBOL(sk_reset_txq); | |||
364 | 373 | ||
365 | struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) | 374 | struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) |
366 | { | 375 | { |
367 | struct dst_entry *dst = sk->sk_dst_cache; | 376 | struct dst_entry *dst = __sk_dst_get(sk); |
368 | 377 | ||
369 | if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) { | 378 | if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) { |
370 | sk_tx_queue_clear(sk); | 379 | sk_tx_queue_clear(sk); |
371 | sk->sk_dst_cache = NULL; | 380 | rcu_assign_pointer(sk->sk_dst_cache, NULL); |
372 | dst_release(dst); | 381 | dst_release(dst); |
373 | return NULL; | 382 | return NULL; |
374 | } | 383 | } |
@@ -1157,7 +1166,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1157 | skb_queue_head_init(&newsk->sk_async_wait_queue); | 1166 | skb_queue_head_init(&newsk->sk_async_wait_queue); |
1158 | #endif | 1167 | #endif |
1159 | 1168 | ||
1160 | rwlock_init(&newsk->sk_dst_lock); | 1169 | spin_lock_init(&newsk->sk_dst_lock); |
1161 | rwlock_init(&newsk->sk_callback_lock); | 1170 | rwlock_init(&newsk->sk_callback_lock); |
1162 | lockdep_set_class_and_name(&newsk->sk_callback_lock, | 1171 | lockdep_set_class_and_name(&newsk->sk_callback_lock, |
1163 | af_callback_keys + newsk->sk_family, | 1172 | af_callback_keys + newsk->sk_family, |
@@ -1207,7 +1216,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1207 | */ | 1216 | */ |
1208 | sk_refcnt_debug_inc(newsk); | 1217 | sk_refcnt_debug_inc(newsk); |
1209 | sk_set_socket(newsk, NULL); | 1218 | sk_set_socket(newsk, NULL); |
1210 | newsk->sk_sleep = NULL; | 1219 | newsk->sk_wq = NULL; |
1211 | 1220 | ||
1212 | if (newsk->sk_prot->sockets_allocated) | 1221 | if (newsk->sk_prot->sockets_allocated) |
1213 | percpu_counter_inc(newsk->sk_prot->sockets_allocated); | 1222 | percpu_counter_inc(newsk->sk_prot->sockets_allocated); |
@@ -1227,6 +1236,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) | |||
1227 | sk->sk_route_caps = dst->dev->features; | 1236 | sk->sk_route_caps = dst->dev->features; |
1228 | if (sk->sk_route_caps & NETIF_F_GSO) | 1237 | if (sk->sk_route_caps & NETIF_F_GSO) |
1229 | sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE; | 1238 | sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE; |
1239 | sk->sk_route_caps &= ~sk->sk_route_nocaps; | ||
1230 | if (sk_can_gso(sk)) { | 1240 | if (sk_can_gso(sk)) { |
1231 | if (dst->header_len) { | 1241 | if (dst->header_len) { |
1232 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1242 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
@@ -1395,7 +1405,7 @@ static long sock_wait_for_wmem(struct sock *sk, long timeo) | |||
1395 | if (signal_pending(current)) | 1405 | if (signal_pending(current)) |
1396 | break; | 1406 | break; |
1397 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | 1407 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
1398 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1408 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1399 | if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) | 1409 | if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) |
1400 | break; | 1410 | break; |
1401 | if (sk->sk_shutdown & SEND_SHUTDOWN) | 1411 | if (sk->sk_shutdown & SEND_SHUTDOWN) |
@@ -1404,7 +1414,7 @@ static long sock_wait_for_wmem(struct sock *sk, long timeo) | |||
1404 | break; | 1414 | break; |
1405 | timeo = schedule_timeout(timeo); | 1415 | timeo = schedule_timeout(timeo); |
1406 | } | 1416 | } |
1407 | finish_wait(sk->sk_sleep, &wait); | 1417 | finish_wait(sk_sleep(sk), &wait); |
1408 | return timeo; | 1418 | return timeo; |
1409 | } | 1419 | } |
1410 | 1420 | ||
@@ -1531,6 +1541,7 @@ static void __release_sock(struct sock *sk) | |||
1531 | do { | 1541 | do { |
1532 | struct sk_buff *next = skb->next; | 1542 | struct sk_buff *next = skb->next; |
1533 | 1543 | ||
1544 | WARN_ON_ONCE(skb_dst_is_noref(skb)); | ||
1534 | skb->next = NULL; | 1545 | skb->next = NULL; |
1535 | sk_backlog_rcv(sk, skb); | 1546 | sk_backlog_rcv(sk, skb); |
1536 | 1547 | ||
@@ -1570,11 +1581,11 @@ int sk_wait_data(struct sock *sk, long *timeo) | |||
1570 | int rc; | 1581 | int rc; |
1571 | DEFINE_WAIT(wait); | 1582 | DEFINE_WAIT(wait); |
1572 | 1583 | ||
1573 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1584 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1574 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1585 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
1575 | rc = sk_wait_event(sk, timeo, !skb_queue_empty(&sk->sk_receive_queue)); | 1586 | rc = sk_wait_event(sk, timeo, !skb_queue_empty(&sk->sk_receive_queue)); |
1576 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1587 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
1577 | finish_wait(sk->sk_sleep, &wait); | 1588 | finish_wait(sk_sleep(sk), &wait); |
1578 | return rc; | 1589 | return rc; |
1579 | } | 1590 | } |
1580 | EXPORT_SYMBOL(sk_wait_data); | 1591 | EXPORT_SYMBOL(sk_wait_data); |
@@ -1796,41 +1807,53 @@ EXPORT_SYMBOL(sock_no_sendpage); | |||
1796 | 1807 | ||
1797 | static void sock_def_wakeup(struct sock *sk) | 1808 | static void sock_def_wakeup(struct sock *sk) |
1798 | { | 1809 | { |
1799 | read_lock(&sk->sk_callback_lock); | 1810 | struct socket_wq *wq; |
1800 | if (sk_has_sleeper(sk)) | 1811 | |
1801 | wake_up_interruptible_all(sk->sk_sleep); | 1812 | rcu_read_lock(); |
1802 | read_unlock(&sk->sk_callback_lock); | 1813 | wq = rcu_dereference(sk->sk_wq); |
1814 | if (wq_has_sleeper(wq)) | ||
1815 | wake_up_interruptible_all(&wq->wait); | ||
1816 | rcu_read_unlock(); | ||
1803 | } | 1817 | } |
1804 | 1818 | ||
1805 | static void sock_def_error_report(struct sock *sk) | 1819 | static void sock_def_error_report(struct sock *sk) |
1806 | { | 1820 | { |
1807 | read_lock(&sk->sk_callback_lock); | 1821 | struct socket_wq *wq; |
1808 | if (sk_has_sleeper(sk)) | 1822 | |
1809 | wake_up_interruptible_poll(sk->sk_sleep, POLLERR); | 1823 | rcu_read_lock(); |
1824 | wq = rcu_dereference(sk->sk_wq); | ||
1825 | if (wq_has_sleeper(wq)) | ||
1826 | wake_up_interruptible_poll(&wq->wait, POLLERR); | ||
1810 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); | 1827 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); |
1811 | read_unlock(&sk->sk_callback_lock); | 1828 | rcu_read_unlock(); |
1812 | } | 1829 | } |
1813 | 1830 | ||
1814 | static void sock_def_readable(struct sock *sk, int len) | 1831 | static void sock_def_readable(struct sock *sk, int len) |
1815 | { | 1832 | { |
1816 | read_lock(&sk->sk_callback_lock); | 1833 | struct socket_wq *wq; |
1817 | if (sk_has_sleeper(sk)) | 1834 | |
1818 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | | 1835 | rcu_read_lock(); |
1836 | wq = rcu_dereference(sk->sk_wq); | ||
1837 | if (wq_has_sleeper(wq)) | ||
1838 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | | ||
1819 | POLLRDNORM | POLLRDBAND); | 1839 | POLLRDNORM | POLLRDBAND); |
1820 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 1840 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
1821 | read_unlock(&sk->sk_callback_lock); | 1841 | rcu_read_unlock(); |
1822 | } | 1842 | } |
1823 | 1843 | ||
1824 | static void sock_def_write_space(struct sock *sk) | 1844 | static void sock_def_write_space(struct sock *sk) |
1825 | { | 1845 | { |
1826 | read_lock(&sk->sk_callback_lock); | 1846 | struct socket_wq *wq; |
1847 | |||
1848 | rcu_read_lock(); | ||
1827 | 1849 | ||
1828 | /* Do not wake up a writer until he can make "significant" | 1850 | /* Do not wake up a writer until he can make "significant" |
1829 | * progress. --DaveM | 1851 | * progress. --DaveM |
1830 | */ | 1852 | */ |
1831 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { | 1853 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { |
1832 | if (sk_has_sleeper(sk)) | 1854 | wq = rcu_dereference(sk->sk_wq); |
1833 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | | 1855 | if (wq_has_sleeper(wq)) |
1856 | wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | | ||
1834 | POLLWRNORM | POLLWRBAND); | 1857 | POLLWRNORM | POLLWRBAND); |
1835 | 1858 | ||
1836 | /* Should agree with poll, otherwise some programs break */ | 1859 | /* Should agree with poll, otherwise some programs break */ |
@@ -1838,7 +1861,7 @@ static void sock_def_write_space(struct sock *sk) | |||
1838 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 1861 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
1839 | } | 1862 | } |
1840 | 1863 | ||
1841 | read_unlock(&sk->sk_callback_lock); | 1864 | rcu_read_unlock(); |
1842 | } | 1865 | } |
1843 | 1866 | ||
1844 | static void sock_def_destruct(struct sock *sk) | 1867 | static void sock_def_destruct(struct sock *sk) |
@@ -1885,7 +1908,6 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1885 | sk->sk_allocation = GFP_KERNEL; | 1908 | sk->sk_allocation = GFP_KERNEL; |
1886 | sk->sk_rcvbuf = sysctl_rmem_default; | 1909 | sk->sk_rcvbuf = sysctl_rmem_default; |
1887 | sk->sk_sndbuf = sysctl_wmem_default; | 1910 | sk->sk_sndbuf = sysctl_wmem_default; |
1888 | sk->sk_backlog.limit = sk->sk_rcvbuf << 1; | ||
1889 | sk->sk_state = TCP_CLOSE; | 1911 | sk->sk_state = TCP_CLOSE; |
1890 | sk_set_socket(sk, sock); | 1912 | sk_set_socket(sk, sock); |
1891 | 1913 | ||
@@ -1893,12 +1915,12 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1893 | 1915 | ||
1894 | if (sock) { | 1916 | if (sock) { |
1895 | sk->sk_type = sock->type; | 1917 | sk->sk_type = sock->type; |
1896 | sk->sk_sleep = &sock->wait; | 1918 | sk->sk_wq = sock->wq; |
1897 | sock->sk = sk; | 1919 | sock->sk = sk; |
1898 | } else | 1920 | } else |
1899 | sk->sk_sleep = NULL; | 1921 | sk->sk_wq = NULL; |
1900 | 1922 | ||
1901 | rwlock_init(&sk->sk_dst_lock); | 1923 | spin_lock_init(&sk->sk_dst_lock); |
1902 | rwlock_init(&sk->sk_callback_lock); | 1924 | rwlock_init(&sk->sk_callback_lock); |
1903 | lockdep_set_class_and_name(&sk->sk_callback_lock, | 1925 | lockdep_set_class_and_name(&sk->sk_callback_lock, |
1904 | af_callback_keys + sk->sk_family, | 1926 | af_callback_keys + sk->sk_family, |
diff --git a/net/core/stream.c b/net/core/stream.c index a37debfeb1b2..cc196f42b8d8 100644 --- a/net/core/stream.c +++ b/net/core/stream.c | |||
@@ -28,15 +28,19 @@ | |||
28 | void sk_stream_write_space(struct sock *sk) | 28 | void sk_stream_write_space(struct sock *sk) |
29 | { | 29 | { |
30 | struct socket *sock = sk->sk_socket; | 30 | struct socket *sock = sk->sk_socket; |
31 | struct socket_wq *wq; | ||
31 | 32 | ||
32 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) { | 33 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) { |
33 | clear_bit(SOCK_NOSPACE, &sock->flags); | 34 | clear_bit(SOCK_NOSPACE, &sock->flags); |
34 | 35 | ||
35 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 36 | rcu_read_lock(); |
36 | wake_up_interruptible_poll(sk->sk_sleep, POLLOUT | | 37 | wq = rcu_dereference(sk->sk_wq); |
38 | if (wq_has_sleeper(wq)) | ||
39 | wake_up_interruptible_poll(&wq->wait, POLLOUT | | ||
37 | POLLWRNORM | POLLWRBAND); | 40 | POLLWRNORM | POLLWRBAND); |
38 | if (sock->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) | 41 | if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) |
39 | sock_wake_async(sock, SOCK_WAKE_SPACE, POLL_OUT); | 42 | sock_wake_async(sock, SOCK_WAKE_SPACE, POLL_OUT); |
43 | rcu_read_unlock(); | ||
40 | } | 44 | } |
41 | } | 45 | } |
42 | 46 | ||
@@ -66,13 +70,13 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p) | |||
66 | if (signal_pending(tsk)) | 70 | if (signal_pending(tsk)) |
67 | return sock_intr_errno(*timeo_p); | 71 | return sock_intr_errno(*timeo_p); |
68 | 72 | ||
69 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 73 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
70 | sk->sk_write_pending++; | 74 | sk->sk_write_pending++; |
71 | done = sk_wait_event(sk, timeo_p, | 75 | done = sk_wait_event(sk, timeo_p, |
72 | !sk->sk_err && | 76 | !sk->sk_err && |
73 | !((1 << sk->sk_state) & | 77 | !((1 << sk->sk_state) & |
74 | ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))); | 78 | ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))); |
75 | finish_wait(sk->sk_sleep, &wait); | 79 | finish_wait(sk_sleep(sk), &wait); |
76 | sk->sk_write_pending--; | 80 | sk->sk_write_pending--; |
77 | } while (!done); | 81 | } while (!done); |
78 | return 0; | 82 | return 0; |
@@ -96,13 +100,13 @@ void sk_stream_wait_close(struct sock *sk, long timeout) | |||
96 | DEFINE_WAIT(wait); | 100 | DEFINE_WAIT(wait); |
97 | 101 | ||
98 | do { | 102 | do { |
99 | prepare_to_wait(sk->sk_sleep, &wait, | 103 | prepare_to_wait(sk_sleep(sk), &wait, |
100 | TASK_INTERRUPTIBLE); | 104 | TASK_INTERRUPTIBLE); |
101 | if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk))) | 105 | if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk))) |
102 | break; | 106 | break; |
103 | } while (!signal_pending(current) && timeout); | 107 | } while (!signal_pending(current) && timeout); |
104 | 108 | ||
105 | finish_wait(sk->sk_sleep, &wait); | 109 | finish_wait(sk_sleep(sk), &wait); |
106 | } | 110 | } |
107 | } | 111 | } |
108 | 112 | ||
@@ -126,7 +130,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) | |||
126 | while (1) { | 130 | while (1) { |
127 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 131 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); |
128 | 132 | ||
129 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 133 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
130 | 134 | ||
131 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 135 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
132 | goto do_error; | 136 | goto do_error; |
@@ -157,7 +161,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) | |||
157 | *timeo_p = current_timeo; | 161 | *timeo_p = current_timeo; |
158 | } | 162 | } |
159 | out: | 163 | out: |
160 | finish_wait(sk->sk_sleep, &wait); | 164 | finish_wait(sk_sleep(sk), &wait); |
161 | return err; | 165 | return err; |
162 | 166 | ||
163 | do_error: | 167 | do_error: |
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index b7b6b8208f75..01eee5d984be 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
@@ -11,12 +11,72 @@ | |||
11 | #include <linux/socket.h> | 11 | #include <linux/socket.h> |
12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
13 | #include <linux/ratelimit.h> | 13 | #include <linux/ratelimit.h> |
14 | #include <linux/vmalloc.h> | ||
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
16 | 17 | ||
17 | #include <net/ip.h> | 18 | #include <net/ip.h> |
18 | #include <net/sock.h> | 19 | #include <net/sock.h> |
19 | 20 | ||
21 | #ifdef CONFIG_RPS | ||
22 | static int rps_sock_flow_sysctl(ctl_table *table, int write, | ||
23 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
24 | { | ||
25 | unsigned int orig_size, size; | ||
26 | int ret, i; | ||
27 | ctl_table tmp = { | ||
28 | .data = &size, | ||
29 | .maxlen = sizeof(size), | ||
30 | .mode = table->mode | ||
31 | }; | ||
32 | struct rps_sock_flow_table *orig_sock_table, *sock_table; | ||
33 | static DEFINE_MUTEX(sock_flow_mutex); | ||
34 | |||
35 | mutex_lock(&sock_flow_mutex); | ||
36 | |||
37 | orig_sock_table = rps_sock_flow_table; | ||
38 | size = orig_size = orig_sock_table ? orig_sock_table->mask + 1 : 0; | ||
39 | |||
40 | ret = proc_dointvec(&tmp, write, buffer, lenp, ppos); | ||
41 | |||
42 | if (write) { | ||
43 | if (size) { | ||
44 | if (size > 1<<30) { | ||
45 | /* Enforce limit to prevent overflow */ | ||
46 | mutex_unlock(&sock_flow_mutex); | ||
47 | return -EINVAL; | ||
48 | } | ||
49 | size = roundup_pow_of_two(size); | ||
50 | if (size != orig_size) { | ||
51 | sock_table = | ||
52 | vmalloc(RPS_SOCK_FLOW_TABLE_SIZE(size)); | ||
53 | if (!sock_table) { | ||
54 | mutex_unlock(&sock_flow_mutex); | ||
55 | return -ENOMEM; | ||
56 | } | ||
57 | |||
58 | sock_table->mask = size - 1; | ||
59 | } else | ||
60 | sock_table = orig_sock_table; | ||
61 | |||
62 | for (i = 0; i < size; i++) | ||
63 | sock_table->ents[i] = RPS_NO_CPU; | ||
64 | } else | ||
65 | sock_table = NULL; | ||
66 | |||
67 | if (sock_table != orig_sock_table) { | ||
68 | rcu_assign_pointer(rps_sock_flow_table, sock_table); | ||
69 | synchronize_rcu(); | ||
70 | vfree(orig_sock_table); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | mutex_unlock(&sock_flow_mutex); | ||
75 | |||
76 | return ret; | ||
77 | } | ||
78 | #endif /* CONFIG_RPS */ | ||
79 | |||
20 | static struct ctl_table net_core_table[] = { | 80 | static struct ctl_table net_core_table[] = { |
21 | #ifdef CONFIG_NET | 81 | #ifdef CONFIG_NET |
22 | { | 82 | { |
@@ -62,6 +122,13 @@ static struct ctl_table net_core_table[] = { | |||
62 | .proc_handler = proc_dointvec | 122 | .proc_handler = proc_dointvec |
63 | }, | 123 | }, |
64 | { | 124 | { |
125 | .procname = "netdev_tstamp_prequeue", | ||
126 | .data = &netdev_tstamp_prequeue, | ||
127 | .maxlen = sizeof(int), | ||
128 | .mode = 0644, | ||
129 | .proc_handler = proc_dointvec | ||
130 | }, | ||
131 | { | ||
65 | .procname = "message_cost", | 132 | .procname = "message_cost", |
66 | .data = &net_ratelimit_state.interval, | 133 | .data = &net_ratelimit_state.interval, |
67 | .maxlen = sizeof(int), | 134 | .maxlen = sizeof(int), |
@@ -82,6 +149,14 @@ static struct ctl_table net_core_table[] = { | |||
82 | .mode = 0644, | 149 | .mode = 0644, |
83 | .proc_handler = proc_dointvec | 150 | .proc_handler = proc_dointvec |
84 | }, | 151 | }, |
152 | #ifdef CONFIG_RPS | ||
153 | { | ||
154 | .procname = "rps_sock_flow_entries", | ||
155 | .maxlen = sizeof(int), | ||
156 | .mode = 0644, | ||
157 | .proc_handler = rps_sock_flow_sysctl | ||
158 | }, | ||
159 | #endif | ||
85 | #endif /* CONFIG_NET */ | 160 | #endif /* CONFIG_NET */ |
86 | { | 161 | { |
87 | .procname = "netdev_budget", | 162 | .procname = "netdev_budget", |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index bcd7632299f5..d3235899c7e3 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -208,7 +208,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
208 | goto restart_timer; | 208 | goto restart_timer; |
209 | } | 209 | } |
210 | 210 | ||
211 | ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk, | 211 | ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk, |
212 | ccid3_tx_state_name(hc->tx_state)); | 212 | ccid3_tx_state_name(hc->tx_state)); |
213 | 213 | ||
214 | if (hc->tx_state == TFRC_SSTATE_FBACK) | 214 | if (hc->tx_state == TFRC_SSTATE_FBACK) |
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 5ef32c2f0d6a..a10a61a1ded2 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -189,7 +189,7 @@ enum { | |||
189 | #define DCCP_MIB_MAX __DCCP_MIB_MAX | 189 | #define DCCP_MIB_MAX __DCCP_MIB_MAX |
190 | struct dccp_mib { | 190 | struct dccp_mib { |
191 | unsigned long mibs[DCCP_MIB_MAX]; | 191 | unsigned long mibs[DCCP_MIB_MAX]; |
192 | } __SNMP_MIB_ALIGN__; | 192 | }; |
193 | 193 | ||
194 | DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics); | 194 | DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics); |
195 | #define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field) | 195 | #define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field) |
@@ -223,7 +223,7 @@ static inline void dccp_csum_outgoing(struct sk_buff *skb) | |||
223 | skb->csum = skb_checksum(skb, 0, (cov > skb->len)? skb->len : cov, 0); | 223 | skb->csum = skb_checksum(skb, 0, (cov > skb->len)? skb->len : cov, 0); |
224 | } | 224 | } |
225 | 225 | ||
226 | extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); | 226 | extern void dccp_v4_send_check(struct sock *sk, struct sk_buff *skb); |
227 | 227 | ||
228 | extern int dccp_retransmit_skb(struct sock *sk); | 228 | extern int dccp_retransmit_skb(struct sock *sk); |
229 | 229 | ||
diff --git a/net/dccp/input.c b/net/dccp/input.c index 9ec717426024..58f7bc156850 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
@@ -415,7 +415,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, | |||
415 | if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, | 415 | if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, |
416 | dp->dccps_awl, dp->dccps_awh)) { | 416 | dp->dccps_awl, dp->dccps_awh)) { |
417 | dccp_pr_debug("invalid ackno: S.AWL=%llu, " | 417 | dccp_pr_debug("invalid ackno: S.AWL=%llu, " |
418 | "P.ackno=%llu, S.AWH=%llu \n", | 418 | "P.ackno=%llu, S.AWH=%llu\n", |
419 | (unsigned long long)dp->dccps_awl, | 419 | (unsigned long long)dp->dccps_awl, |
420 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, | 420 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, |
421 | (unsigned long long)dp->dccps_awh); | 421 | (unsigned long long)dp->dccps_awh); |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 52ffa1cde15a..d9b11ef8694c 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -349,7 +349,7 @@ static inline __sum16 dccp_v4_csum_finish(struct sk_buff *skb, | |||
349 | return csum_tcpudp_magic(src, dst, skb->len, IPPROTO_DCCP, skb->csum); | 349 | return csum_tcpudp_magic(src, dst, skb->len, IPPROTO_DCCP, skb->csum); |
350 | } | 350 | } |
351 | 351 | ||
352 | void dccp_v4_send_check(struct sock *sk, int unused, struct sk_buff *skb) | 352 | void dccp_v4_send_check(struct sock *sk, struct sk_buff *skb) |
353 | { | 353 | { |
354 | const struct inet_sock *inet = inet_sk(sk); | 354 | const struct inet_sock *inet = inet_sk(sk); |
355 | struct dccp_hdr *dh = dccp_hdr(skb); | 355 | struct dccp_hdr *dh = dccp_hdr(skb); |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 3b11e41a2929..091698899594 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -60,8 +60,7 @@ static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb, | |||
60 | return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum); | 60 | return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum); |
61 | } | 61 | } |
62 | 62 | ||
63 | static inline void dccp_v6_send_check(struct sock *sk, int unused_value, | 63 | static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb) |
64 | struct sk_buff *skb) | ||
65 | { | 64 | { |
66 | struct ipv6_pinfo *np = inet6_sk(sk); | 65 | struct ipv6_pinfo *np = inet6_sk(sk); |
67 | struct dccp_hdr *dh = dccp_hdr(skb); | 66 | struct dccp_hdr *dh = dccp_hdr(skb); |
@@ -293,7 +292,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | |||
293 | &ireq6->loc_addr, | 292 | &ireq6->loc_addr, |
294 | &ireq6->rmt_addr); | 293 | &ireq6->rmt_addr); |
295 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | 294 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); |
296 | err = ip6_xmit(sk, skb, &fl, opt, 0); | 295 | err = ip6_xmit(sk, skb, &fl, opt); |
297 | err = net_xmit_eval(err); | 296 | err = net_xmit_eval(err); |
298 | } | 297 | } |
299 | 298 | ||
@@ -348,7 +347,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) | |||
348 | if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { | 347 | if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { |
349 | if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { | 348 | if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { |
350 | skb_dst_set(skb, dst); | 349 | skb_dst_set(skb, dst); |
351 | ip6_xmit(ctl_sk, skb, &fl, NULL, 0); | 350 | ip6_xmit(ctl_sk, skb, &fl, NULL); |
352 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); | 351 | DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); |
353 | DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); | 352 | DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); |
354 | return; | 353 | return; |
diff --git a/net/dccp/output.c b/net/dccp/output.c index fc3f436440b4..aadbdb58758b 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -129,14 +129,14 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | |||
129 | break; | 129 | break; |
130 | } | 130 | } |
131 | 131 | ||
132 | icsk->icsk_af_ops->send_check(sk, 0, skb); | 132 | icsk->icsk_af_ops->send_check(sk, skb); |
133 | 133 | ||
134 | if (set_ack) | 134 | if (set_ack) |
135 | dccp_event_ack_sent(sk); | 135 | dccp_event_ack_sent(sk); |
136 | 136 | ||
137 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); | 137 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); |
138 | 138 | ||
139 | err = icsk->icsk_af_ops->queue_xmit(skb, 0); | 139 | err = icsk->icsk_af_ops->queue_xmit(skb); |
140 | return net_xmit_eval(err); | 140 | return net_xmit_eval(err); |
141 | } | 141 | } |
142 | return -ENOBUFS; | 142 | return -ENOBUFS; |
@@ -195,15 +195,17 @@ EXPORT_SYMBOL_GPL(dccp_sync_mss); | |||
195 | 195 | ||
196 | void dccp_write_space(struct sock *sk) | 196 | void dccp_write_space(struct sock *sk) |
197 | { | 197 | { |
198 | read_lock(&sk->sk_callback_lock); | 198 | struct socket_wq *wq; |
199 | 199 | ||
200 | if (sk_has_sleeper(sk)) | 200 | rcu_read_lock(); |
201 | wake_up_interruptible(sk->sk_sleep); | 201 | wq = rcu_dereference(sk->sk_wq); |
202 | if (wq_has_sleeper(wq)) | ||
203 | wake_up_interruptible(&wq->wait); | ||
202 | /* Should agree with poll, otherwise some programs break */ | 204 | /* Should agree with poll, otherwise some programs break */ |
203 | if (sock_writeable(sk)) | 205 | if (sock_writeable(sk)) |
204 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 206 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
205 | 207 | ||
206 | read_unlock(&sk->sk_callback_lock); | 208 | rcu_read_unlock(); |
207 | } | 209 | } |
208 | 210 | ||
209 | /** | 211 | /** |
@@ -225,7 +227,7 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, int delay) | |||
225 | dccp_pr_debug("delayed send by %d msec\n", delay); | 227 | dccp_pr_debug("delayed send by %d msec\n", delay); |
226 | jiffdelay = msecs_to_jiffies(delay); | 228 | jiffdelay = msecs_to_jiffies(delay); |
227 | 229 | ||
228 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 230 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
229 | 231 | ||
230 | sk->sk_write_pending++; | 232 | sk->sk_write_pending++; |
231 | release_sock(sk); | 233 | release_sock(sk); |
@@ -241,7 +243,7 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, int delay) | |||
241 | rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); | 243 | rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); |
242 | } while ((delay = rc) > 0); | 244 | } while ((delay = rc) > 0); |
243 | out: | 245 | out: |
244 | finish_wait(sk->sk_sleep, &wait); | 246 | finish_wait(sk_sleep(sk), &wait); |
245 | return rc; | 247 | return rc; |
246 | 248 | ||
247 | do_error: | 249 | do_error: |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index a0e38d8018f5..b03ecf6b2bb0 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -312,7 +312,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock, | |||
312 | unsigned int mask; | 312 | unsigned int mask; |
313 | struct sock *sk = sock->sk; | 313 | struct sock *sk = sock->sk; |
314 | 314 | ||
315 | sock_poll_wait(file, sk->sk_sleep, wait); | 315 | sock_poll_wait(file, sk_sleep(sk), wait); |
316 | if (sk->sk_state == DCCP_LISTEN) | 316 | if (sk->sk_state == DCCP_LISTEN) |
317 | return inet_csk_listen_poll(sk); | 317 | return inet_csk_listen_poll(sk); |
318 | 318 | ||
diff --git a/net/dccp/timer.c b/net/dccp/timer.c index bbfeb5eae46a..1a9aa05d4dc4 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c | |||
@@ -38,7 +38,7 @@ static int dccp_write_timeout(struct sock *sk) | |||
38 | 38 | ||
39 | if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) { | 39 | if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) { |
40 | if (icsk->icsk_retransmits != 0) | 40 | if (icsk->icsk_retransmits != 0) |
41 | dst_negative_advice(&sk->sk_dst_cache, sk); | 41 | dst_negative_advice(sk); |
42 | retry_until = icsk->icsk_syn_retries ? | 42 | retry_until = icsk->icsk_syn_retries ? |
43 | : sysctl_dccp_request_retries; | 43 | : sysctl_dccp_request_retries; |
44 | } else { | 44 | } else { |
@@ -63,7 +63,7 @@ static int dccp_write_timeout(struct sock *sk) | |||
63 | Golden words :-). | 63 | Golden words :-). |
64 | */ | 64 | */ |
65 | 65 | ||
66 | dst_negative_advice(&sk->sk_dst_cache, sk); | 66 | dst_negative_advice(sk); |
67 | } | 67 | } |
68 | 68 | ||
69 | retry_until = sysctl_dccp_retries2; | 69 | retry_until = sysctl_dccp_retries2; |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 2b494fac9468..d6b93d19790f 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -446,7 +446,7 @@ static void dn_destruct(struct sock *sk) | |||
446 | skb_queue_purge(&scp->other_xmit_queue); | 446 | skb_queue_purge(&scp->other_xmit_queue); |
447 | skb_queue_purge(&scp->other_receive_queue); | 447 | skb_queue_purge(&scp->other_receive_queue); |
448 | 448 | ||
449 | dst_release(xchg(&sk->sk_dst_cache, NULL)); | 449 | dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); |
450 | } | 450 | } |
451 | 451 | ||
452 | static int dn_memory_pressure; | 452 | static int dn_memory_pressure; |
@@ -832,7 +832,7 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) | |||
832 | scp->segsize_loc = dst_metric(__sk_dst_get(sk), RTAX_ADVMSS); | 832 | scp->segsize_loc = dst_metric(__sk_dst_get(sk), RTAX_ADVMSS); |
833 | dn_send_conn_conf(sk, allocation); | 833 | dn_send_conn_conf(sk, allocation); |
834 | 834 | ||
835 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 835 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
836 | for(;;) { | 836 | for(;;) { |
837 | release_sock(sk); | 837 | release_sock(sk); |
838 | if (scp->state == DN_CC) | 838 | if (scp->state == DN_CC) |
@@ -850,9 +850,9 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) | |||
850 | err = -EAGAIN; | 850 | err = -EAGAIN; |
851 | if (!*timeo) | 851 | if (!*timeo) |
852 | break; | 852 | break; |
853 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 853 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
854 | } | 854 | } |
855 | finish_wait(sk->sk_sleep, &wait); | 855 | finish_wait(sk_sleep(sk), &wait); |
856 | if (err == 0) { | 856 | if (err == 0) { |
857 | sk->sk_socket->state = SS_CONNECTED; | 857 | sk->sk_socket->state = SS_CONNECTED; |
858 | } else if (scp->state != DN_CC) { | 858 | } else if (scp->state != DN_CC) { |
@@ -873,7 +873,7 @@ static int dn_wait_run(struct sock *sk, long *timeo) | |||
873 | if (!*timeo) | 873 | if (!*timeo) |
874 | return -EALREADY; | 874 | return -EALREADY; |
875 | 875 | ||
876 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 876 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
877 | for(;;) { | 877 | for(;;) { |
878 | release_sock(sk); | 878 | release_sock(sk); |
879 | if (scp->state == DN_CI || scp->state == DN_CC) | 879 | if (scp->state == DN_CI || scp->state == DN_CC) |
@@ -891,9 +891,9 @@ static int dn_wait_run(struct sock *sk, long *timeo) | |||
891 | err = -ETIMEDOUT; | 891 | err = -ETIMEDOUT; |
892 | if (!*timeo) | 892 | if (!*timeo) |
893 | break; | 893 | break; |
894 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 894 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
895 | } | 895 | } |
896 | finish_wait(sk->sk_sleep, &wait); | 896 | finish_wait(sk_sleep(sk), &wait); |
897 | out: | 897 | out: |
898 | if (err == 0) { | 898 | if (err == 0) { |
899 | sk->sk_socket->state = SS_CONNECTED; | 899 | sk->sk_socket->state = SS_CONNECTED; |
@@ -1040,7 +1040,7 @@ static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo) | |||
1040 | struct sk_buff *skb = NULL; | 1040 | struct sk_buff *skb = NULL; |
1041 | int err = 0; | 1041 | int err = 0; |
1042 | 1042 | ||
1043 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1043 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1044 | for(;;) { | 1044 | for(;;) { |
1045 | release_sock(sk); | 1045 | release_sock(sk); |
1046 | skb = skb_dequeue(&sk->sk_receive_queue); | 1046 | skb = skb_dequeue(&sk->sk_receive_queue); |
@@ -1060,9 +1060,9 @@ static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo) | |||
1060 | err = -EAGAIN; | 1060 | err = -EAGAIN; |
1061 | if (!*timeo) | 1061 | if (!*timeo) |
1062 | break; | 1062 | break; |
1063 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1063 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1064 | } | 1064 | } |
1065 | finish_wait(sk->sk_sleep, &wait); | 1065 | finish_wait(sk_sleep(sk), &wait); |
1066 | 1066 | ||
1067 | return skb == NULL ? ERR_PTR(err) : skb; | 1067 | return skb == NULL ? ERR_PTR(err) : skb; |
1068 | } | 1068 | } |
@@ -1105,7 +1105,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) | |||
1105 | release_sock(sk); | 1105 | release_sock(sk); |
1106 | 1106 | ||
1107 | dst = skb_dst(skb); | 1107 | dst = skb_dst(skb); |
1108 | dst_release(xchg(&newsk->sk_dst_cache, dst)); | 1108 | sk_dst_set(newsk, dst); |
1109 | skb_dst_set(skb, NULL); | 1109 | skb_dst_set(skb, NULL); |
1110 | 1110 | ||
1111 | DN_SK(newsk)->state = DN_CR; | 1111 | DN_SK(newsk)->state = DN_CR; |
@@ -1746,11 +1746,11 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1746 | goto out; | 1746 | goto out; |
1747 | } | 1747 | } |
1748 | 1748 | ||
1749 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1749 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1750 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1750 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
1751 | sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target)); | 1751 | sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target)); |
1752 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1752 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
1753 | finish_wait(sk->sk_sleep, &wait); | 1753 | finish_wait(sk_sleep(sk), &wait); |
1754 | } | 1754 | } |
1755 | 1755 | ||
1756 | skb_queue_walk_safe(queue, skb, n) { | 1756 | skb_queue_walk_safe(queue, skb, n) { |
@@ -1956,7 +1956,7 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1956 | } | 1956 | } |
1957 | 1957 | ||
1958 | if ((flags & MSG_TRYHARD) && sk->sk_dst_cache) | 1958 | if ((flags & MSG_TRYHARD) && sk->sk_dst_cache) |
1959 | dst_negative_advice(&sk->sk_dst_cache, sk); | 1959 | dst_negative_advice(sk); |
1960 | 1960 | ||
1961 | mss = scp->segsize_rem; | 1961 | mss = scp->segsize_rem; |
1962 | fctype = scp->services_rem & NSP_FC_MASK; | 1962 | fctype = scp->services_rem & NSP_FC_MASK; |
@@ -2003,12 +2003,12 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
2003 | goto out; | 2003 | goto out; |
2004 | } | 2004 | } |
2005 | 2005 | ||
2006 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 2006 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
2007 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2007 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
2008 | sk_wait_event(sk, &timeo, | 2008 | sk_wait_event(sk, &timeo, |
2009 | !dn_queue_too_long(scp, queue, flags)); | 2009 | !dn_queue_too_long(scp, queue, flags)); |
2010 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2010 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
2011 | finish_wait(sk->sk_sleep, &wait); | 2011 | finish_wait(sk_sleep(sk), &wait); |
2012 | continue; | 2012 | continue; |
2013 | } | 2013 | } |
2014 | 2014 | ||
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index cead68eb254c..4c409b46aa35 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
@@ -350,7 +350,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de | |||
350 | if (dn_db->dev->type == ARPHRD_ETHER) { | 350 | if (dn_db->dev->type == ARPHRD_ETHER) { |
351 | if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) { | 351 | if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) { |
352 | dn_dn2eth(mac_addr, ifa1->ifa_local); | 352 | dn_dn2eth(mac_addr, ifa1->ifa_local); |
353 | dev_mc_delete(dev, mac_addr, ETH_ALEN, 0); | 353 | dev_mc_del(dev, mac_addr); |
354 | } | 354 | } |
355 | } | 355 | } |
356 | 356 | ||
@@ -381,7 +381,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) | |||
381 | if (dev->type == ARPHRD_ETHER) { | 381 | if (dev->type == ARPHRD_ETHER) { |
382 | if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) { | 382 | if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) { |
383 | dn_dn2eth(mac_addr, ifa->ifa_local); | 383 | dn_dn2eth(mac_addr, ifa->ifa_local); |
384 | dev_mc_add(dev, mac_addr, ETH_ALEN, 0); | 384 | dev_mc_add(dev, mac_addr); |
385 | } | 385 | } |
386 | } | 386 | } |
387 | 387 | ||
@@ -1001,9 +1001,9 @@ static int dn_eth_up(struct net_device *dev) | |||
1001 | struct dn_dev *dn_db = dev->dn_ptr; | 1001 | struct dn_dev *dn_db = dev->dn_ptr; |
1002 | 1002 | ||
1003 | if (dn_db->parms.forwarding == 0) | 1003 | if (dn_db->parms.forwarding == 0) |
1004 | dev_mc_add(dev, dn_rt_all_end_mcast, ETH_ALEN, 0); | 1004 | dev_mc_add(dev, dn_rt_all_end_mcast); |
1005 | else | 1005 | else |
1006 | dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); | 1006 | dev_mc_add(dev, dn_rt_all_rt_mcast); |
1007 | 1007 | ||
1008 | dn_db->use_long = 1; | 1008 | dn_db->use_long = 1; |
1009 | 1009 | ||
@@ -1015,9 +1015,9 @@ static void dn_eth_down(struct net_device *dev) | |||
1015 | struct dn_dev *dn_db = dev->dn_ptr; | 1015 | struct dn_dev *dn_db = dev->dn_ptr; |
1016 | 1016 | ||
1017 | if (dn_db->parms.forwarding == 0) | 1017 | if (dn_db->parms.forwarding == 0) |
1018 | dev_mc_delete(dev, dn_rt_all_end_mcast, ETH_ALEN, 0); | 1018 | dev_mc_del(dev, dn_rt_all_end_mcast); |
1019 | else | 1019 | else |
1020 | dev_mc_delete(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); | 1020 | dev_mc_del(dev, dn_rt_all_rt_mcast); |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | static void dn_dev_set_timer(struct net_device *dev); | 1023 | static void dn_dev_set_timer(struct net_device *dev); |
@@ -1220,17 +1220,14 @@ void dn_dev_down(struct net_device *dev) | |||
1220 | 1220 | ||
1221 | void dn_dev_init_pkt(struct sk_buff *skb) | 1221 | void dn_dev_init_pkt(struct sk_buff *skb) |
1222 | { | 1222 | { |
1223 | return; | ||
1224 | } | 1223 | } |
1225 | 1224 | ||
1226 | void dn_dev_veri_pkt(struct sk_buff *skb) | 1225 | void dn_dev_veri_pkt(struct sk_buff *skb) |
1227 | { | 1226 | { |
1228 | return; | ||
1229 | } | 1227 | } |
1230 | 1228 | ||
1231 | void dn_dev_hello(struct sk_buff *skb) | 1229 | void dn_dev_hello(struct sk_buff *skb) |
1232 | { | 1230 | { |
1233 | return; | ||
1234 | } | 1231 | } |
1235 | 1232 | ||
1236 | void dn_dev_devices_off(void) | 1233 | void dn_dev_devices_off(void) |
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index deb723dba44b..0363bb95cc7d 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c | |||
@@ -266,7 +266,8 @@ static int dn_long_output(struct sk_buff *skb) | |||
266 | 266 | ||
267 | skb_reset_network_header(skb); | 267 | skb_reset_network_header(skb); |
268 | 268 | ||
269 | return NF_HOOK(PF_DECnet, NF_DN_POST_ROUTING, skb, NULL, neigh->dev, dn_neigh_output_packet); | 269 | return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, skb, NULL, |
270 | neigh->dev, dn_neigh_output_packet); | ||
270 | } | 271 | } |
271 | 272 | ||
272 | static int dn_short_output(struct sk_buff *skb) | 273 | static int dn_short_output(struct sk_buff *skb) |
@@ -305,7 +306,8 @@ static int dn_short_output(struct sk_buff *skb) | |||
305 | 306 | ||
306 | skb_reset_network_header(skb); | 307 | skb_reset_network_header(skb); |
307 | 308 | ||
308 | return NF_HOOK(PF_DECnet, NF_DN_POST_ROUTING, skb, NULL, neigh->dev, dn_neigh_output_packet); | 309 | return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, skb, NULL, |
310 | neigh->dev, dn_neigh_output_packet); | ||
309 | } | 311 | } |
310 | 312 | ||
311 | /* | 313 | /* |
@@ -347,7 +349,8 @@ static int dn_phase3_output(struct sk_buff *skb) | |||
347 | 349 | ||
348 | skb_reset_network_header(skb); | 350 | skb_reset_network_header(skb); |
349 | 351 | ||
350 | return NF_HOOK(PF_DECnet, NF_DN_POST_ROUTING, skb, NULL, neigh->dev, dn_neigh_output_packet); | 352 | return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING, skb, NULL, |
353 | neigh->dev, dn_neigh_output_packet); | ||
351 | } | 354 | } |
352 | 355 | ||
353 | /* | 356 | /* |
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 25a37299bc65..b430549e2b91 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c | |||
@@ -810,7 +810,8 @@ free_out: | |||
810 | 810 | ||
811 | int dn_nsp_rx(struct sk_buff *skb) | 811 | int dn_nsp_rx(struct sk_buff *skb) |
812 | { | 812 | { |
813 | return NF_HOOK(PF_DECnet, NF_DN_LOCAL_IN, skb, skb->dev, NULL, dn_nsp_rx_packet); | 813 | return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_IN, skb, skb->dev, NULL, |
814 | dn_nsp_rx_packet); | ||
814 | } | 815 | } |
815 | 816 | ||
816 | /* | 817 | /* |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 70ebe74027d5..812e6dff6067 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -264,7 +264,6 @@ static struct dst_entry *dn_dst_negative_advice(struct dst_entry *dst) | |||
264 | 264 | ||
265 | static void dn_dst_link_failure(struct sk_buff *skb) | 265 | static void dn_dst_link_failure(struct sk_buff *skb) |
266 | { | 266 | { |
267 | return; | ||
268 | } | 267 | } |
269 | 268 | ||
270 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) | 269 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) |
@@ -518,7 +517,8 @@ static int dn_route_rx_long(struct sk_buff *skb) | |||
518 | ptr++; | 517 | ptr++; |
519 | cb->hops = *ptr++; /* Visit Count */ | 518 | cb->hops = *ptr++; /* Visit Count */ |
520 | 519 | ||
521 | return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet); | 520 | return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, |
521 | dn_route_rx_packet); | ||
522 | 522 | ||
523 | drop_it: | 523 | drop_it: |
524 | kfree_skb(skb); | 524 | kfree_skb(skb); |
@@ -544,7 +544,8 @@ static int dn_route_rx_short(struct sk_buff *skb) | |||
544 | ptr += 2; | 544 | ptr += 2; |
545 | cb->hops = *ptr & 0x3f; | 545 | cb->hops = *ptr & 0x3f; |
546 | 546 | ||
547 | return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet); | 547 | return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, |
548 | dn_route_rx_packet); | ||
548 | 549 | ||
549 | drop_it: | 550 | drop_it: |
550 | kfree_skb(skb); | 551 | kfree_skb(skb); |
@@ -646,16 +647,24 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type | |||
646 | 647 | ||
647 | switch(flags & DN_RT_CNTL_MSK) { | 648 | switch(flags & DN_RT_CNTL_MSK) { |
648 | case DN_RT_PKT_HELO: | 649 | case DN_RT_PKT_HELO: |
649 | return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_route_ptp_hello); | 650 | return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, |
651 | skb, skb->dev, NULL, | ||
652 | dn_route_ptp_hello); | ||
650 | 653 | ||
651 | case DN_RT_PKT_L1RT: | 654 | case DN_RT_PKT_L1RT: |
652 | case DN_RT_PKT_L2RT: | 655 | case DN_RT_PKT_L2RT: |
653 | return NF_HOOK(PF_DECnet, NF_DN_ROUTE, skb, skb->dev, NULL, dn_route_discard); | 656 | return NF_HOOK(NFPROTO_DECNET, NF_DN_ROUTE, |
657 | skb, skb->dev, NULL, | ||
658 | dn_route_discard); | ||
654 | case DN_RT_PKT_ERTH: | 659 | case DN_RT_PKT_ERTH: |
655 | return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_router_hello); | 660 | return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, |
661 | skb, skb->dev, NULL, | ||
662 | dn_neigh_router_hello); | ||
656 | 663 | ||
657 | case DN_RT_PKT_EEDH: | 664 | case DN_RT_PKT_EEDH: |
658 | return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_endnode_hello); | 665 | return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO, |
666 | skb, skb->dev, NULL, | ||
667 | dn_neigh_endnode_hello); | ||
659 | } | 668 | } |
660 | } else { | 669 | } else { |
661 | if (dn->parms.state != DN_DEV_S_RU) | 670 | if (dn->parms.state != DN_DEV_S_RU) |
@@ -704,7 +713,8 @@ static int dn_output(struct sk_buff *skb) | |||
704 | cb->rt_flags |= DN_RT_F_IE; | 713 | cb->rt_flags |= DN_RT_F_IE; |
705 | cb->hops = 0; | 714 | cb->hops = 0; |
706 | 715 | ||
707 | return NF_HOOK(PF_DECnet, NF_DN_LOCAL_OUT, skb, NULL, dev, neigh->output); | 716 | return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, skb, NULL, dev, |
717 | neigh->output); | ||
708 | 718 | ||
709 | error: | 719 | error: |
710 | if (net_ratelimit()) | 720 | if (net_ratelimit()) |
@@ -753,7 +763,8 @@ static int dn_forward(struct sk_buff *skb) | |||
753 | if (rt->rt_flags & RTCF_DOREDIRECT) | 763 | if (rt->rt_flags & RTCF_DOREDIRECT) |
754 | cb->rt_flags |= DN_RT_F_IE; | 764 | cb->rt_flags |= DN_RT_F_IE; |
755 | 765 | ||
756 | return NF_HOOK(PF_DECnet, NF_DN_FORWARD, skb, dev, skb->dev, neigh->output); | 766 | return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, skb, dev, skb->dev, |
767 | neigh->output); | ||
757 | 768 | ||
758 | drop: | 769 | drop: |
759 | kfree_skb(skb); | 770 | kfree_skb(skb); |
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 7466c546f286..48fdf10be7a1 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c | |||
@@ -196,7 +196,6 @@ static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | |||
196 | { | 196 | { |
197 | struct dn_fib_rule *r = (struct dn_fib_rule *)rule; | 197 | struct dn_fib_rule *r = (struct dn_fib_rule *)rule; |
198 | 198 | ||
199 | frh->family = AF_DECnet; | ||
200 | frh->dst_len = r->dst_len; | 199 | frh->dst_len = r->dst_len; |
201 | frh->src_len = r->src_len; | 200 | frh->src_len = r->src_len; |
202 | frh->tos = 0; | 201 | frh->tos = 0; |
@@ -212,29 +211,12 @@ nla_put_failure: | |||
212 | return -ENOBUFS; | 211 | return -ENOBUFS; |
213 | } | 212 | } |
214 | 213 | ||
215 | static u32 dn_fib_rule_default_pref(struct fib_rules_ops *ops) | ||
216 | { | ||
217 | struct list_head *pos; | ||
218 | struct fib_rule *rule; | ||
219 | |||
220 | if (!list_empty(&dn_fib_rules_ops->rules_list)) { | ||
221 | pos = dn_fib_rules_ops->rules_list.next; | ||
222 | if (pos->next != &dn_fib_rules_ops->rules_list) { | ||
223 | rule = list_entry(pos->next, struct fib_rule, list); | ||
224 | if (rule->pref) | ||
225 | return rule->pref - 1; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops) | 214 | static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops) |
233 | { | 215 | { |
234 | dn_rt_cache_flush(-1); | 216 | dn_rt_cache_flush(-1); |
235 | } | 217 | } |
236 | 218 | ||
237 | static struct fib_rules_ops dn_fib_rules_ops_template = { | 219 | static const struct fib_rules_ops __net_initdata dn_fib_rules_ops_template = { |
238 | .family = AF_DECnet, | 220 | .family = AF_DECnet, |
239 | .rule_size = sizeof(struct dn_fib_rule), | 221 | .rule_size = sizeof(struct dn_fib_rule), |
240 | .addr_size = sizeof(u16), | 222 | .addr_size = sizeof(u16), |
@@ -243,7 +225,7 @@ static struct fib_rules_ops dn_fib_rules_ops_template = { | |||
243 | .configure = dn_fib_rule_configure, | 225 | .configure = dn_fib_rule_configure, |
244 | .compare = dn_fib_rule_compare, | 226 | .compare = dn_fib_rule_compare, |
245 | .fill = dn_fib_rule_fill, | 227 | .fill = dn_fib_rule_fill, |
246 | .default_pref = dn_fib_rule_default_pref, | 228 | .default_pref = fib_default_rule_pref, |
247 | .flush_cache = dn_fib_rule_flush_cache, | 229 | .flush_cache = dn_fib_rule_flush_cache, |
248 | .nlgroup = RTNLGRP_DECnet_RULE, | 230 | .nlgroup = RTNLGRP_DECnet_RULE, |
249 | .policy = dn_fib_rule_policy, | 231 | .policy = dn_fib_rule_policy, |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 2175e6d5cc8d..8fdca56bb08f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -67,7 +67,7 @@ static int dsa_slave_open(struct net_device *dev) | |||
67 | return -ENETDOWN; | 67 | return -ENETDOWN; |
68 | 68 | ||
69 | if (compare_ether_addr(dev->dev_addr, master->dev_addr)) { | 69 | if (compare_ether_addr(dev->dev_addr, master->dev_addr)) { |
70 | err = dev_unicast_add(master, dev->dev_addr); | 70 | err = dev_uc_add(master, dev->dev_addr); |
71 | if (err < 0) | 71 | if (err < 0) |
72 | goto out; | 72 | goto out; |
73 | } | 73 | } |
@@ -90,7 +90,7 @@ clear_allmulti: | |||
90 | dev_set_allmulti(master, -1); | 90 | dev_set_allmulti(master, -1); |
91 | del_unicast: | 91 | del_unicast: |
92 | if (compare_ether_addr(dev->dev_addr, master->dev_addr)) | 92 | if (compare_ether_addr(dev->dev_addr, master->dev_addr)) |
93 | dev_unicast_delete(master, dev->dev_addr); | 93 | dev_uc_del(master, dev->dev_addr); |
94 | out: | 94 | out: |
95 | return err; | 95 | return err; |
96 | } | 96 | } |
@@ -101,14 +101,14 @@ static int dsa_slave_close(struct net_device *dev) | |||
101 | struct net_device *master = p->parent->dst->master_netdev; | 101 | struct net_device *master = p->parent->dst->master_netdev; |
102 | 102 | ||
103 | dev_mc_unsync(master, dev); | 103 | dev_mc_unsync(master, dev); |
104 | dev_unicast_unsync(master, dev); | 104 | dev_uc_unsync(master, dev); |
105 | if (dev->flags & IFF_ALLMULTI) | 105 | if (dev->flags & IFF_ALLMULTI) |
106 | dev_set_allmulti(master, -1); | 106 | dev_set_allmulti(master, -1); |
107 | if (dev->flags & IFF_PROMISC) | 107 | if (dev->flags & IFF_PROMISC) |
108 | dev_set_promiscuity(master, -1); | 108 | dev_set_promiscuity(master, -1); |
109 | 109 | ||
110 | if (compare_ether_addr(dev->dev_addr, master->dev_addr)) | 110 | if (compare_ether_addr(dev->dev_addr, master->dev_addr)) |
111 | dev_unicast_delete(master, dev->dev_addr); | 111 | dev_uc_del(master, dev->dev_addr); |
112 | 112 | ||
113 | return 0; | 113 | return 0; |
114 | } | 114 | } |
@@ -130,7 +130,7 @@ static void dsa_slave_set_rx_mode(struct net_device *dev) | |||
130 | struct net_device *master = p->parent->dst->master_netdev; | 130 | struct net_device *master = p->parent->dst->master_netdev; |
131 | 131 | ||
132 | dev_mc_sync(master, dev); | 132 | dev_mc_sync(master, dev); |
133 | dev_unicast_sync(master, dev); | 133 | dev_uc_sync(master, dev); |
134 | } | 134 | } |
135 | 135 | ||
136 | static int dsa_slave_set_mac_address(struct net_device *dev, void *a) | 136 | static int dsa_slave_set_mac_address(struct net_device *dev, void *a) |
@@ -147,13 +147,13 @@ static int dsa_slave_set_mac_address(struct net_device *dev, void *a) | |||
147 | goto out; | 147 | goto out; |
148 | 148 | ||
149 | if (compare_ether_addr(addr->sa_data, master->dev_addr)) { | 149 | if (compare_ether_addr(addr->sa_data, master->dev_addr)) { |
150 | err = dev_unicast_add(master, addr->sa_data); | 150 | err = dev_uc_add(master, addr->sa_data); |
151 | if (err < 0) | 151 | if (err < 0) |
152 | return err; | 152 | return err; |
153 | } | 153 | } |
154 | 154 | ||
155 | if (compare_ether_addr(dev->dev_addr, master->dev_addr)) | 155 | if (compare_ether_addr(dev->dev_addr, master->dev_addr)) |
156 | dev_unicast_delete(master, dev->dev_addr); | 156 | dev_uc_del(master, dev->dev_addr); |
157 | 157 | ||
158 | out: | 158 | out: |
159 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 159 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 205a1c12f3c0..61ec0329316c 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -136,7 +136,7 @@ int eth_rebuild_header(struct sk_buff *skb) | |||
136 | default: | 136 | default: |
137 | printk(KERN_DEBUG | 137 | printk(KERN_DEBUG |
138 | "%s: unable to resolve type %X addresses.\n", | 138 | "%s: unable to resolve type %X addresses.\n", |
139 | dev->name, (int)eth->h_proto); | 139 | dev->name, ntohs(eth->h_proto)); |
140 | 140 | ||
141 | memcpy(eth->h_source, dev->dev_addr, ETH_ALEN); | 141 | memcpy(eth->h_source, dev->dev_addr, ETH_ALEN); |
142 | break; | 142 | break; |
@@ -162,7 +162,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
162 | 162 | ||
163 | skb->dev = dev; | 163 | skb->dev = dev; |
164 | skb_reset_mac_header(skb); | 164 | skb_reset_mac_header(skb); |
165 | skb_pull(skb, ETH_HLEN); | 165 | skb_pull_inline(skb, ETH_HLEN); |
166 | eth = eth_hdr(skb); | 166 | eth = eth_hdr(skb); |
167 | 167 | ||
168 | if (unlikely(is_multicast_ether_addr(eth->h_dest))) { | 168 | if (unlikely(is_multicast_ether_addr(eth->h_dest))) { |
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 0c94a1ac2946..8e3a1fd938ab 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -250,6 +250,20 @@ config IP_MROUTE | |||
250 | <file:Documentation/networking/multicast.txt>. If you haven't heard | 250 | <file:Documentation/networking/multicast.txt>. If you haven't heard |
251 | about it, you don't need it. | 251 | about it, you don't need it. |
252 | 252 | ||
253 | config IP_MROUTE_MULTIPLE_TABLES | ||
254 | bool "IP: multicast policy routing" | ||
255 | depends on IP_MROUTE && IP_ADVANCED_ROUTER | ||
256 | select FIB_RULES | ||
257 | help | ||
258 | Normally, a multicast router runs a userspace daemon and decides | ||
259 | what to do with a multicast packet based on the source and | ||
260 | destination addresses. If you say Y here, the multicast router | ||
261 | will also be able to take interfaces and packet marks into | ||
262 | account and run multiple instances of userspace daemons | ||
263 | simultaneously, each one handling a single table. | ||
264 | |||
265 | If unsure, say N. | ||
266 | |||
253 | config IP_PIMSM_V1 | 267 | config IP_PIMSM_V1 |
254 | bool "IP: PIM-SM version 1 support" | 268 | bool "IP: PIM-SM version 1 support" |
255 | depends on IP_MROUTE | 269 | depends on IP_MROUTE |
@@ -587,9 +601,15 @@ choice | |||
587 | config DEFAULT_HTCP | 601 | config DEFAULT_HTCP |
588 | bool "Htcp" if TCP_CONG_HTCP=y | 602 | bool "Htcp" if TCP_CONG_HTCP=y |
589 | 603 | ||
604 | config DEFAULT_HYBLA | ||
605 | bool "Hybla" if TCP_CONG_HYBLA=y | ||
606 | |||
590 | config DEFAULT_VEGAS | 607 | config DEFAULT_VEGAS |
591 | bool "Vegas" if TCP_CONG_VEGAS=y | 608 | bool "Vegas" if TCP_CONG_VEGAS=y |
592 | 609 | ||
610 | config DEFAULT_VENO | ||
611 | bool "Veno" if TCP_CONG_VENO=y | ||
612 | |||
593 | config DEFAULT_WESTWOOD | 613 | config DEFAULT_WESTWOOD |
594 | bool "Westwood" if TCP_CONG_WESTWOOD=y | 614 | bool "Westwood" if TCP_CONG_WESTWOOD=y |
595 | 615 | ||
@@ -610,8 +630,10 @@ config DEFAULT_TCP_CONG | |||
610 | default "bic" if DEFAULT_BIC | 630 | default "bic" if DEFAULT_BIC |
611 | default "cubic" if DEFAULT_CUBIC | 631 | default "cubic" if DEFAULT_CUBIC |
612 | default "htcp" if DEFAULT_HTCP | 632 | default "htcp" if DEFAULT_HTCP |
633 | default "hybla" if DEFAULT_HYBLA | ||
613 | default "vegas" if DEFAULT_VEGAS | 634 | default "vegas" if DEFAULT_VEGAS |
614 | default "westwood" if DEFAULT_WESTWOOD | 635 | default "westwood" if DEFAULT_WESTWOOD |
636 | default "veno" if DEFAULT_VENO | ||
615 | default "reno" if DEFAULT_RENO | 637 | default "reno" if DEFAULT_RENO |
616 | default "cubic" | 638 | default "cubic" |
617 | 639 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index f71357422380..551ce564b035 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -154,7 +154,7 @@ void inet_sock_destruct(struct sock *sk) | |||
154 | WARN_ON(sk->sk_forward_alloc); | 154 | WARN_ON(sk->sk_forward_alloc); |
155 | 155 | ||
156 | kfree(inet->opt); | 156 | kfree(inet->opt); |
157 | dst_release(sk->sk_dst_cache); | 157 | dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); |
158 | sk_refcnt_debug_dec(sk); | 158 | sk_refcnt_debug_dec(sk); |
159 | } | 159 | } |
160 | EXPORT_SYMBOL(inet_sock_destruct); | 160 | EXPORT_SYMBOL(inet_sock_destruct); |
@@ -419,6 +419,8 @@ int inet_release(struct socket *sock) | |||
419 | if (sk) { | 419 | if (sk) { |
420 | long timeout; | 420 | long timeout; |
421 | 421 | ||
422 | sock_rps_reset_flow(sk); | ||
423 | |||
422 | /* Applications forget to leave groups before exiting */ | 424 | /* Applications forget to leave groups before exiting */ |
423 | ip_mc_drop_socket(sk); | 425 | ip_mc_drop_socket(sk); |
424 | 426 | ||
@@ -546,7 +548,7 @@ static long inet_wait_for_connect(struct sock *sk, long timeo) | |||
546 | { | 548 | { |
547 | DEFINE_WAIT(wait); | 549 | DEFINE_WAIT(wait); |
548 | 550 | ||
549 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 551 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
550 | 552 | ||
551 | /* Basic assumption: if someone sets sk->sk_err, he _must_ | 553 | /* Basic assumption: if someone sets sk->sk_err, he _must_ |
552 | * change state of the socket from TCP_SYN_*. | 554 | * change state of the socket from TCP_SYN_*. |
@@ -559,9 +561,9 @@ static long inet_wait_for_connect(struct sock *sk, long timeo) | |||
559 | lock_sock(sk); | 561 | lock_sock(sk); |
560 | if (signal_pending(current) || !timeo) | 562 | if (signal_pending(current) || !timeo) |
561 | break; | 563 | break; |
562 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 564 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
563 | } | 565 | } |
564 | finish_wait(sk->sk_sleep, &wait); | 566 | finish_wait(sk_sleep(sk), &wait); |
565 | return timeo; | 567 | return timeo; |
566 | } | 568 | } |
567 | 569 | ||
@@ -720,6 +722,8 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
720 | { | 722 | { |
721 | struct sock *sk = sock->sk; | 723 | struct sock *sk = sock->sk; |
722 | 724 | ||
725 | sock_rps_record_flow(sk); | ||
726 | |||
723 | /* We may need to bind the socket. */ | 727 | /* We may need to bind the socket. */ |
724 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 728 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) |
725 | return -EAGAIN; | 729 | return -EAGAIN; |
@@ -728,12 +732,13 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
728 | } | 732 | } |
729 | EXPORT_SYMBOL(inet_sendmsg); | 733 | EXPORT_SYMBOL(inet_sendmsg); |
730 | 734 | ||
731 | |||
732 | static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, | 735 | static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, |
733 | size_t size, int flags) | 736 | size_t size, int flags) |
734 | { | 737 | { |
735 | struct sock *sk = sock->sk; | 738 | struct sock *sk = sock->sk; |
736 | 739 | ||
740 | sock_rps_record_flow(sk); | ||
741 | |||
737 | /* We may need to bind the socket. */ | 742 | /* We may need to bind the socket. */ |
738 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 743 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) |
739 | return -EAGAIN; | 744 | return -EAGAIN; |
@@ -743,6 +748,22 @@ static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, | |||
743 | return sock_no_sendpage(sock, page, offset, size, flags); | 748 | return sock_no_sendpage(sock, page, offset, size, flags); |
744 | } | 749 | } |
745 | 750 | ||
751 | int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | ||
752 | size_t size, int flags) | ||
753 | { | ||
754 | struct sock *sk = sock->sk; | ||
755 | int addr_len = 0; | ||
756 | int err; | ||
757 | |||
758 | sock_rps_record_flow(sk); | ||
759 | |||
760 | err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, | ||
761 | flags & ~MSG_DONTWAIT, &addr_len); | ||
762 | if (err >= 0) | ||
763 | msg->msg_namelen = addr_len; | ||
764 | return err; | ||
765 | } | ||
766 | EXPORT_SYMBOL(inet_recvmsg); | ||
746 | 767 | ||
747 | int inet_shutdown(struct socket *sock, int how) | 768 | int inet_shutdown(struct socket *sock, int how) |
748 | { | 769 | { |
@@ -872,7 +893,7 @@ const struct proto_ops inet_stream_ops = { | |||
872 | .setsockopt = sock_common_setsockopt, | 893 | .setsockopt = sock_common_setsockopt, |
873 | .getsockopt = sock_common_getsockopt, | 894 | .getsockopt = sock_common_getsockopt, |
874 | .sendmsg = tcp_sendmsg, | 895 | .sendmsg = tcp_sendmsg, |
875 | .recvmsg = sock_common_recvmsg, | 896 | .recvmsg = inet_recvmsg, |
876 | .mmap = sock_no_mmap, | 897 | .mmap = sock_no_mmap, |
877 | .sendpage = tcp_sendpage, | 898 | .sendpage = tcp_sendpage, |
878 | .splice_read = tcp_splice_read, | 899 | .splice_read = tcp_splice_read, |
@@ -899,7 +920,7 @@ const struct proto_ops inet_dgram_ops = { | |||
899 | .setsockopt = sock_common_setsockopt, | 920 | .setsockopt = sock_common_setsockopt, |
900 | .getsockopt = sock_common_getsockopt, | 921 | .getsockopt = sock_common_getsockopt, |
901 | .sendmsg = inet_sendmsg, | 922 | .sendmsg = inet_sendmsg, |
902 | .recvmsg = sock_common_recvmsg, | 923 | .recvmsg = inet_recvmsg, |
903 | .mmap = sock_no_mmap, | 924 | .mmap = sock_no_mmap, |
904 | .sendpage = inet_sendpage, | 925 | .sendpage = inet_sendpage, |
905 | #ifdef CONFIG_COMPAT | 926 | #ifdef CONFIG_COMPAT |
@@ -929,7 +950,7 @@ static const struct proto_ops inet_sockraw_ops = { | |||
929 | .setsockopt = sock_common_setsockopt, | 950 | .setsockopt = sock_common_setsockopt, |
930 | .getsockopt = sock_common_getsockopt, | 951 | .getsockopt = sock_common_getsockopt, |
931 | .sendmsg = inet_sendmsg, | 952 | .sendmsg = inet_sendmsg, |
932 | .recvmsg = sock_common_recvmsg, | 953 | .recvmsg = inet_recvmsg, |
933 | .mmap = sock_no_mmap, | 954 | .mmap = sock_no_mmap, |
934 | .sendpage = inet_sendpage, | 955 | .sendpage = inet_sendpage, |
935 | #ifdef CONFIG_COMPAT | 956 | #ifdef CONFIG_COMPAT |
@@ -1302,8 +1323,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1302 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) | 1323 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) |
1303 | goto out_unlock; | 1324 | goto out_unlock; |
1304 | 1325 | ||
1305 | id = ntohl(*(u32 *)&iph->id); | 1326 | id = ntohl(*(__be32 *)&iph->id); |
1306 | flush = (u16)((ntohl(*(u32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF)); | 1327 | flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF)); |
1307 | id >>= 16; | 1328 | id >>= 16; |
1308 | 1329 | ||
1309 | for (p = *head; p; p = p->next) { | 1330 | for (p = *head; p; p = p->next) { |
@@ -1316,8 +1337,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1316 | 1337 | ||
1317 | if ((iph->protocol ^ iph2->protocol) | | 1338 | if ((iph->protocol ^ iph2->protocol) | |
1318 | (iph->tos ^ iph2->tos) | | 1339 | (iph->tos ^ iph2->tos) | |
1319 | (iph->saddr ^ iph2->saddr) | | 1340 | ((__force u32)iph->saddr ^ (__force u32)iph2->saddr) | |
1320 | (iph->daddr ^ iph2->daddr)) { | 1341 | ((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) { |
1321 | NAPI_GRO_CB(p)->same_flow = 0; | 1342 | NAPI_GRO_CB(p)->same_flow = 0; |
1322 | continue; | 1343 | continue; |
1323 | } | 1344 | } |
@@ -1407,10 +1428,10 @@ EXPORT_SYMBOL_GPL(snmp_fold_field); | |||
1407 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) | 1428 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) |
1408 | { | 1429 | { |
1409 | BUG_ON(ptr == NULL); | 1430 | BUG_ON(ptr == NULL); |
1410 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); | 1431 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long)); |
1411 | if (!ptr[0]) | 1432 | if (!ptr[0]) |
1412 | goto err0; | 1433 | goto err0; |
1413 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); | 1434 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long)); |
1414 | if (!ptr[1]) | 1435 | if (!ptr[1]) |
1415 | goto err1; | 1436 | goto err1; |
1416 | return 0; | 1437 | return 0; |
@@ -1552,9 +1573,13 @@ static int __init inet_init(void) | |||
1552 | 1573 | ||
1553 | BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)); | 1574 | BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)); |
1554 | 1575 | ||
1576 | sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL); | ||
1577 | if (!sysctl_local_reserved_ports) | ||
1578 | goto out; | ||
1579 | |||
1555 | rc = proto_register(&tcp_prot, 1); | 1580 | rc = proto_register(&tcp_prot, 1); |
1556 | if (rc) | 1581 | if (rc) |
1557 | goto out; | 1582 | goto out_free_reserved_ports; |
1558 | 1583 | ||
1559 | rc = proto_register(&udp_prot, 1); | 1584 | rc = proto_register(&udp_prot, 1); |
1560 | if (rc) | 1585 | if (rc) |
@@ -1653,6 +1678,8 @@ out_unregister_udp_proto: | |||
1653 | proto_unregister(&udp_prot); | 1678 | proto_unregister(&udp_prot); |
1654 | out_unregister_tcp_proto: | 1679 | out_unregister_tcp_proto: |
1655 | proto_unregister(&tcp_prot); | 1680 | proto_unregister(&tcp_prot); |
1681 | out_free_reserved_ports: | ||
1682 | kfree(sysctl_local_reserved_ports); | ||
1656 | goto out; | 1683 | goto out; |
1657 | } | 1684 | } |
1658 | 1685 | ||
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 80769f1f9fab..f094b75810db 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -854,7 +854,7 @@ static int arp_process(struct sk_buff *skb) | |||
854 | } | 854 | } |
855 | 855 | ||
856 | if (arp->ar_op == htons(ARPOP_REQUEST) && | 856 | if (arp->ar_op == htons(ARPOP_REQUEST) && |
857 | ip_route_input(skb, tip, sip, 0, dev) == 0) { | 857 | ip_route_input_noref(skb, tip, sip, 0, dev) == 0) { |
858 | 858 | ||
859 | rt = skb_rtable(skb); | 859 | rt = skb_rtable(skb); |
860 | addr_type = rt->rt_type; | 860 | addr_type = rt->rt_type; |
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index c97cd9ff697e..3a92a76ae41d 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -290,8 +290,6 @@ void cipso_v4_cache_invalidate(void) | |||
290 | cipso_v4_cache[iter].size = 0; | 290 | cipso_v4_cache[iter].size = 0; |
291 | spin_unlock_bh(&cipso_v4_cache[iter].lock); | 291 | spin_unlock_bh(&cipso_v4_cache[iter].lock); |
292 | } | 292 | } |
293 | |||
294 | return; | ||
295 | } | 293 | } |
296 | 294 | ||
297 | /** | 295 | /** |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 90e3d6379a42..382bc768ed56 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -1096,10 +1096,10 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, | |||
1096 | case NETDEV_DOWN: | 1096 | case NETDEV_DOWN: |
1097 | ip_mc_down(in_dev); | 1097 | ip_mc_down(in_dev); |
1098 | break; | 1098 | break; |
1099 | case NETDEV_BONDING_OLDTYPE: | 1099 | case NETDEV_PRE_TYPE_CHANGE: |
1100 | ip_mc_unmap(in_dev); | 1100 | ip_mc_unmap(in_dev); |
1101 | break; | 1101 | break; |
1102 | case NETDEV_BONDING_NEWTYPE: | 1102 | case NETDEV_POST_TYPE_CHANGE: |
1103 | ip_mc_remap(in_dev); | 1103 | ip_mc_remap(in_dev); |
1104 | break; | 1104 | break; |
1105 | case NETDEV_CHANGEMTU: | 1105 | case NETDEV_CHANGEMTU: |
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index ca2d07b1c706..76daeb5ff564 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
@@ -213,7 +213,6 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | |||
213 | { | 213 | { |
214 | struct fib4_rule *rule4 = (struct fib4_rule *) rule; | 214 | struct fib4_rule *rule4 = (struct fib4_rule *) rule; |
215 | 215 | ||
216 | frh->family = AF_INET; | ||
217 | frh->dst_len = rule4->dst_len; | 216 | frh->dst_len = rule4->dst_len; |
218 | frh->src_len = rule4->src_len; | 217 | frh->src_len = rule4->src_len; |
219 | frh->tos = rule4->tos; | 218 | frh->tos = rule4->tos; |
@@ -234,23 +233,6 @@ nla_put_failure: | |||
234 | return -ENOBUFS; | 233 | return -ENOBUFS; |
235 | } | 234 | } |
236 | 235 | ||
237 | static u32 fib4_rule_default_pref(struct fib_rules_ops *ops) | ||
238 | { | ||
239 | struct list_head *pos; | ||
240 | struct fib_rule *rule; | ||
241 | |||
242 | if (!list_empty(&ops->rules_list)) { | ||
243 | pos = ops->rules_list.next; | ||
244 | if (pos->next != &ops->rules_list) { | ||
245 | rule = list_entry(pos->next, struct fib_rule, list); | ||
246 | if (rule->pref) | ||
247 | return rule->pref - 1; | ||
248 | } | ||
249 | } | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule) | 236 | static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule) |
255 | { | 237 | { |
256 | return nla_total_size(4) /* dst */ | 238 | return nla_total_size(4) /* dst */ |
@@ -263,7 +245,7 @@ static void fib4_rule_flush_cache(struct fib_rules_ops *ops) | |||
263 | rt_cache_flush(ops->fro_net, -1); | 245 | rt_cache_flush(ops->fro_net, -1); |
264 | } | 246 | } |
265 | 247 | ||
266 | static struct fib_rules_ops fib4_rules_ops_template = { | 248 | static const struct fib_rules_ops __net_initdata fib4_rules_ops_template = { |
267 | .family = AF_INET, | 249 | .family = AF_INET, |
268 | .rule_size = sizeof(struct fib4_rule), | 250 | .rule_size = sizeof(struct fib4_rule), |
269 | .addr_size = sizeof(u32), | 251 | .addr_size = sizeof(u32), |
@@ -272,7 +254,7 @@ static struct fib_rules_ops fib4_rules_ops_template = { | |||
272 | .configure = fib4_rule_configure, | 254 | .configure = fib4_rule_configure, |
273 | .compare = fib4_rule_compare, | 255 | .compare = fib4_rule_compare, |
274 | .fill = fib4_rule_fill, | 256 | .fill = fib4_rule_fill, |
275 | .default_pref = fib4_rule_default_pref, | 257 | .default_pref = fib_default_rule_pref, |
276 | .nlmsg_payload = fib4_rule_nlmsg_payload, | 258 | .nlmsg_payload = fib4_rule_nlmsg_payload, |
277 | .flush_cache = fib4_rule_flush_cache, | 259 | .flush_cache = fib4_rule_flush_cache, |
278 | .nlgroup = RTNLGRP_IPV4_RULE, | 260 | .nlgroup = RTNLGRP_IPV4_RULE, |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index c98f115fb0fd..79d057a939ba 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1022,8 +1022,6 @@ static void trie_rebalance(struct trie *t, struct tnode *tn) | |||
1022 | 1022 | ||
1023 | rcu_assign_pointer(t->trie, (struct node *)tn); | 1023 | rcu_assign_pointer(t->trie, (struct node *)tn); |
1024 | tnode_free_flush(); | 1024 | tnode_free_flush(); |
1025 | |||
1026 | return; | ||
1027 | } | 1025 | } |
1028 | 1026 | ||
1029 | /* only used from updater-side */ | 1027 | /* only used from updater-side */ |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index ac4dec132735..d65e9215bcd7 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -331,9 +331,10 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, | |||
331 | if (ip_append_data(sk, icmp_glue_bits, icmp_param, | 331 | if (ip_append_data(sk, icmp_glue_bits, icmp_param, |
332 | icmp_param->data_len+icmp_param->head_len, | 332 | icmp_param->data_len+icmp_param->head_len, |
333 | icmp_param->head_len, | 333 | icmp_param->head_len, |
334 | ipc, rt, MSG_DONTWAIT) < 0) | 334 | ipc, rt, MSG_DONTWAIT) < 0) { |
335 | ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_OUTERRORS); | ||
335 | ip_flush_pending_frames(sk); | 336 | ip_flush_pending_frames(sk); |
336 | else if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { | 337 | } else if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { |
337 | struct icmphdr *icmph = icmp_hdr(skb); | 338 | struct icmphdr *icmph = icmp_hdr(skb); |
338 | __wsum csum = 0; | 339 | __wsum csum = 0; |
339 | struct sk_buff *skb1; | 340 | struct sk_buff *skb1; |
@@ -586,20 +587,20 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
586 | err = __ip_route_output_key(net, &rt2, &fl); | 587 | err = __ip_route_output_key(net, &rt2, &fl); |
587 | else { | 588 | else { |
588 | struct flowi fl2 = {}; | 589 | struct flowi fl2 = {}; |
589 | struct dst_entry *odst; | 590 | unsigned long orefdst; |
590 | 591 | ||
591 | fl2.fl4_dst = fl.fl4_src; | 592 | fl2.fl4_dst = fl.fl4_src; |
592 | if (ip_route_output_key(net, &rt2, &fl2)) | 593 | if (ip_route_output_key(net, &rt2, &fl2)) |
593 | goto relookup_failed; | 594 | goto relookup_failed; |
594 | 595 | ||
595 | /* Ugh! */ | 596 | /* Ugh! */ |
596 | odst = skb_dst(skb_in); | 597 | orefdst = skb_in->_skb_refdst; /* save old refdst */ |
597 | err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src, | 598 | err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src, |
598 | RT_TOS(tos), rt2->u.dst.dev); | 599 | RT_TOS(tos), rt2->u.dst.dev); |
599 | 600 | ||
600 | dst_release(&rt2->u.dst); | 601 | dst_release(&rt2->u.dst); |
601 | rt2 = skb_rtable(skb_in); | 602 | rt2 = skb_rtable(skb_in); |
602 | skb_dst_set(skb_in, odst); | 603 | skb_in->_skb_refdst = orefdst; /* restore old refdst */ |
603 | } | 604 | } |
604 | 605 | ||
605 | if (err) | 606 | if (err) |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 15d3eeda92f5..5fff865a4fa7 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -998,7 +998,7 @@ static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr) | |||
998 | --ANK | 998 | --ANK |
999 | */ | 999 | */ |
1000 | if (arp_mc_map(addr, buf, dev, 0) == 0) | 1000 | if (arp_mc_map(addr, buf, dev, 0) == 0) |
1001 | dev_mc_add(dev, buf, dev->addr_len, 0); | 1001 | dev_mc_add(dev, buf); |
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | /* | 1004 | /* |
@@ -1011,7 +1011,7 @@ static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr) | |||
1011 | struct net_device *dev = in_dev->dev; | 1011 | struct net_device *dev = in_dev->dev; |
1012 | 1012 | ||
1013 | if (arp_mc_map(addr, buf, dev, 0) == 0) | 1013 | if (arp_mc_map(addr, buf, dev, 0) == 0) |
1014 | dev_mc_delete(dev, buf, dev->addr_len, 0); | 1014 | dev_mc_del(dev, buf); |
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | #ifdef CONFIG_IP_MULTICAST | 1017 | #ifdef CONFIG_IP_MULTICAST |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 8da6429269dd..70eb3507c406 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -37,6 +37,9 @@ struct local_ports sysctl_local_ports __read_mostly = { | |||
37 | .range = { 32768, 61000 }, | 37 | .range = { 32768, 61000 }, |
38 | }; | 38 | }; |
39 | 39 | ||
40 | unsigned long *sysctl_local_reserved_ports; | ||
41 | EXPORT_SYMBOL(sysctl_local_reserved_ports); | ||
42 | |||
40 | void inet_get_local_port_range(int *low, int *high) | 43 | void inet_get_local_port_range(int *low, int *high) |
41 | { | 44 | { |
42 | unsigned seq; | 45 | unsigned seq; |
@@ -108,6 +111,8 @@ again: | |||
108 | 111 | ||
109 | smallest_size = -1; | 112 | smallest_size = -1; |
110 | do { | 113 | do { |
114 | if (inet_is_reserved_local_port(rover)) | ||
115 | goto next_nolock; | ||
111 | head = &hashinfo->bhash[inet_bhashfn(net, rover, | 116 | head = &hashinfo->bhash[inet_bhashfn(net, rover, |
112 | hashinfo->bhash_size)]; | 117 | hashinfo->bhash_size)]; |
113 | spin_lock(&head->lock); | 118 | spin_lock(&head->lock); |
@@ -130,6 +135,7 @@ again: | |||
130 | break; | 135 | break; |
131 | next: | 136 | next: |
132 | spin_unlock(&head->lock); | 137 | spin_unlock(&head->lock); |
138 | next_nolock: | ||
133 | if (++rover > high) | 139 | if (++rover > high) |
134 | rover = low; | 140 | rover = low; |
135 | } while (--remaining > 0); | 141 | } while (--remaining > 0); |
@@ -234,7 +240,7 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo) | |||
234 | * having to remove and re-insert us on the wait queue. | 240 | * having to remove and re-insert us on the wait queue. |
235 | */ | 241 | */ |
236 | for (;;) { | 242 | for (;;) { |
237 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, | 243 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
238 | TASK_INTERRUPTIBLE); | 244 | TASK_INTERRUPTIBLE); |
239 | release_sock(sk); | 245 | release_sock(sk); |
240 | if (reqsk_queue_empty(&icsk->icsk_accept_queue)) | 246 | if (reqsk_queue_empty(&icsk->icsk_accept_queue)) |
@@ -253,7 +259,7 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo) | |||
253 | if (!timeo) | 259 | if (!timeo) |
254 | break; | 260 | break; |
255 | } | 261 | } |
256 | finish_wait(sk->sk_sleep, &wait); | 262 | finish_wait(sk_sleep(sk), &wait); |
257 | return err; | 263 | return err; |
258 | } | 264 | } |
259 | 265 | ||
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 2b79377b468d..d3e160a88219 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -456,6 +456,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, | |||
456 | local_bh_disable(); | 456 | local_bh_disable(); |
457 | for (i = 1; i <= remaining; i++) { | 457 | for (i = 1; i <= remaining; i++) { |
458 | port = low + (i + offset) % remaining; | 458 | port = low + (i + offset) % remaining; |
459 | if (inet_is_reserved_local_port(port)) | ||
460 | continue; | ||
459 | head = &hinfo->bhash[inet_bhashfn(net, port, | 461 | head = &hinfo->bhash[inet_bhashfn(net, port, |
460 | hinfo->bhash_size)]; | 462 | hinfo->bhash_size)]; |
461 | spin_lock(&head->lock); | 463 | spin_lock(&head->lock); |
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index af10942b326c..56cdf68a074c 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
@@ -112,8 +112,8 @@ int ip_forward(struct sk_buff *skb) | |||
112 | 112 | ||
113 | skb->priority = rt_tos2priority(iph->tos); | 113 | skb->priority = rt_tos2priority(iph->tos); |
114 | 114 | ||
115 | return NF_HOOK(PF_INET, NF_INET_FORWARD, skb, skb->dev, rt->u.dst.dev, | 115 | return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev, |
116 | ip_forward_finish); | 116 | rt->u.dst.dev, ip_forward_finish); |
117 | 117 | ||
118 | sr_failed: | 118 | sr_failed: |
119 | /* | 119 | /* |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index fe381d12ecdd..32618e11076d 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -502,7 +502,6 @@ static void ipgre_err(struct sk_buff *skb, u32 info) | |||
502 | t->err_time = jiffies; | 502 | t->err_time = jiffies; |
503 | out: | 503 | out: |
504 | rcu_read_unlock(); | 504 | rcu_read_unlock(); |
505 | return; | ||
506 | } | 505 | } |
507 | 506 | ||
508 | static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | 507 | static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) |
@@ -538,7 +537,6 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
538 | struct ip_tunnel *tunnel; | 537 | struct ip_tunnel *tunnel; |
539 | int offset = 4; | 538 | int offset = 4; |
540 | __be16 gre_proto; | 539 | __be16 gre_proto; |
541 | unsigned int len; | ||
542 | 540 | ||
543 | if (!pskb_may_pull(skb, 16)) | 541 | if (!pskb_may_pull(skb, 16)) |
544 | goto drop_nolock; | 542 | goto drop_nolock; |
@@ -629,8 +627,6 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
629 | tunnel->i_seqno = seqno + 1; | 627 | tunnel->i_seqno = seqno + 1; |
630 | } | 628 | } |
631 | 629 | ||
632 | len = skb->len; | ||
633 | |||
634 | /* Warning: All skb pointers will be invalidated! */ | 630 | /* Warning: All skb pointers will be invalidated! */ |
635 | if (tunnel->dev->type == ARPHRD_ETHER) { | 631 | if (tunnel->dev->type == ARPHRD_ETHER) { |
636 | if (!pskb_may_pull(skb, ETH_HLEN)) { | 632 | if (!pskb_may_pull(skb, ETH_HLEN)) { |
@@ -644,11 +640,7 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
644 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); | 640 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); |
645 | } | 641 | } |
646 | 642 | ||
647 | stats->rx_packets++; | 643 | skb_tunnel_rx(skb, tunnel->dev); |
648 | stats->rx_bytes += len; | ||
649 | skb->dev = tunnel->dev; | ||
650 | skb_dst_drop(skb); | ||
651 | nf_reset(skb); | ||
652 | 644 | ||
653 | skb_reset_network_header(skb); | 645 | skb_reset_network_header(skb); |
654 | ipgre_ecn_decapsulate(iph, skb); | 646 | ipgre_ecn_decapsulate(iph, skb); |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index f8ab7a380d4a..d930dc5e4d85 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -266,7 +266,7 @@ int ip_local_deliver(struct sk_buff *skb) | |||
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | 268 | ||
269 | return NF_HOOK(PF_INET, NF_INET_LOCAL_IN, skb, skb->dev, NULL, | 269 | return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, skb, skb->dev, NULL, |
270 | ip_local_deliver_finish); | 270 | ip_local_deliver_finish); |
271 | } | 271 | } |
272 | 272 | ||
@@ -331,8 +331,8 @@ static int ip_rcv_finish(struct sk_buff *skb) | |||
331 | * how the packet travels inside Linux networking. | 331 | * how the packet travels inside Linux networking. |
332 | */ | 332 | */ |
333 | if (skb_dst(skb) == NULL) { | 333 | if (skb_dst(skb) == NULL) { |
334 | int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, | 334 | int err = ip_route_input_noref(skb, iph->daddr, iph->saddr, |
335 | skb->dev); | 335 | iph->tos, skb->dev); |
336 | if (unlikely(err)) { | 336 | if (unlikely(err)) { |
337 | if (err == -EHOSTUNREACH) | 337 | if (err == -EHOSTUNREACH) |
338 | IP_INC_STATS_BH(dev_net(skb->dev), | 338 | IP_INC_STATS_BH(dev_net(skb->dev), |
@@ -444,7 +444,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, | |||
444 | /* Must drop socket now because of tproxy. */ | 444 | /* Must drop socket now because of tproxy. */ |
445 | skb_orphan(skb); | 445 | skb_orphan(skb); |
446 | 446 | ||
447 | return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, | 447 | return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL, |
448 | ip_rcv_finish); | 448 | ip_rcv_finish); |
449 | 449 | ||
450 | inhdr_error: | 450 | inhdr_error: |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 4c09a31fd140..ba9836c488ed 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
@@ -238,7 +238,6 @@ void ip_options_fragment(struct sk_buff * skb) | |||
238 | opt->rr_needaddr = 0; | 238 | opt->rr_needaddr = 0; |
239 | opt->ts_needaddr = 0; | 239 | opt->ts_needaddr = 0; |
240 | opt->ts_needtime = 0; | 240 | opt->ts_needtime = 0; |
241 | return; | ||
242 | } | 241 | } |
243 | 242 | ||
244 | /* | 243 | /* |
@@ -601,6 +600,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) | |||
601 | unsigned char *optptr = skb_network_header(skb) + opt->srr; | 600 | unsigned char *optptr = skb_network_header(skb) + opt->srr; |
602 | struct rtable *rt = skb_rtable(skb); | 601 | struct rtable *rt = skb_rtable(skb); |
603 | struct rtable *rt2; | 602 | struct rtable *rt2; |
603 | unsigned long orefdst; | ||
604 | int err; | 604 | int err; |
605 | 605 | ||
606 | if (!opt->srr) | 606 | if (!opt->srr) |
@@ -624,16 +624,16 @@ int ip_options_rcv_srr(struct sk_buff *skb) | |||
624 | } | 624 | } |
625 | memcpy(&nexthop, &optptr[srrptr-1], 4); | 625 | memcpy(&nexthop, &optptr[srrptr-1], 4); |
626 | 626 | ||
627 | rt = skb_rtable(skb); | 627 | orefdst = skb->_skb_refdst; |
628 | skb_dst_set(skb, NULL); | 628 | skb_dst_set(skb, NULL); |
629 | err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev); | 629 | err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev); |
630 | rt2 = skb_rtable(skb); | 630 | rt2 = skb_rtable(skb); |
631 | if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) { | 631 | if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) { |
632 | ip_rt_put(rt2); | 632 | skb_dst_drop(skb); |
633 | skb_dst_set(skb, &rt->u.dst); | 633 | skb->_skb_refdst = orefdst; |
634 | return -EINVAL; | 634 | return -EINVAL; |
635 | } | 635 | } |
636 | ip_rt_put(rt); | 636 | refdst_drop(orefdst); |
637 | if (rt2->rt_type != RTN_LOCAL) | 637 | if (rt2->rt_type != RTN_LOCAL) |
638 | break; | 638 | break; |
639 | /* Superfast 8) loopback forward */ | 639 | /* Superfast 8) loopback forward */ |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index d1bcc9f21d4f..9a4a6c96cb0d 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -96,8 +96,8 @@ int __ip_local_out(struct sk_buff *skb) | |||
96 | 96 | ||
97 | iph->tot_len = htons(skb->len); | 97 | iph->tot_len = htons(skb->len); |
98 | ip_send_check(iph); | 98 | ip_send_check(iph); |
99 | return nf_hook(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, skb_dst(skb)->dev, | 99 | return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL, |
100 | dst_output); | 100 | skb_dst(skb)->dev, dst_output); |
101 | } | 101 | } |
102 | 102 | ||
103 | int ip_local_out(struct sk_buff *skb) | 103 | int ip_local_out(struct sk_buff *skb) |
@@ -272,8 +272,8 @@ int ip_mc_output(struct sk_buff *skb) | |||
272 | ) { | 272 | ) { |
273 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); | 273 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
274 | if (newskb) | 274 | if (newskb) |
275 | NF_HOOK(PF_INET, NF_INET_POST_ROUTING, newskb, | 275 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, |
276 | NULL, newskb->dev, | 276 | newskb, NULL, newskb->dev, |
277 | ip_dev_loopback_xmit); | 277 | ip_dev_loopback_xmit); |
278 | } | 278 | } |
279 | 279 | ||
@@ -288,12 +288,12 @@ int ip_mc_output(struct sk_buff *skb) | |||
288 | if (rt->rt_flags&RTCF_BROADCAST) { | 288 | if (rt->rt_flags&RTCF_BROADCAST) { |
289 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); | 289 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
290 | if (newskb) | 290 | if (newskb) |
291 | NF_HOOK(PF_INET, NF_INET_POST_ROUTING, newskb, NULL, | 291 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, newskb, |
292 | newskb->dev, ip_dev_loopback_xmit); | 292 | NULL, newskb->dev, ip_dev_loopback_xmit); |
293 | } | 293 | } |
294 | 294 | ||
295 | return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, skb->dev, | 295 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, |
296 | ip_finish_output, | 296 | skb->dev, ip_finish_output, |
297 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 297 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
298 | } | 298 | } |
299 | 299 | ||
@@ -306,22 +306,24 @@ int ip_output(struct sk_buff *skb) | |||
306 | skb->dev = dev; | 306 | skb->dev = dev; |
307 | skb->protocol = htons(ETH_P_IP); | 307 | skb->protocol = htons(ETH_P_IP); |
308 | 308 | ||
309 | return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, dev, | 309 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, dev, |
310 | ip_finish_output, | 310 | ip_finish_output, |
311 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 311 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
312 | } | 312 | } |
313 | 313 | ||
314 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) | 314 | int ip_queue_xmit(struct sk_buff *skb) |
315 | { | 315 | { |
316 | struct sock *sk = skb->sk; | 316 | struct sock *sk = skb->sk; |
317 | struct inet_sock *inet = inet_sk(sk); | 317 | struct inet_sock *inet = inet_sk(sk); |
318 | struct ip_options *opt = inet->opt; | 318 | struct ip_options *opt = inet->opt; |
319 | struct rtable *rt; | 319 | struct rtable *rt; |
320 | struct iphdr *iph; | 320 | struct iphdr *iph; |
321 | int res; | ||
321 | 322 | ||
322 | /* Skip all of this if the packet is already routed, | 323 | /* Skip all of this if the packet is already routed, |
323 | * f.e. by something like SCTP. | 324 | * f.e. by something like SCTP. |
324 | */ | 325 | */ |
326 | rcu_read_lock(); | ||
325 | rt = skb_rtable(skb); | 327 | rt = skb_rtable(skb); |
326 | if (rt != NULL) | 328 | if (rt != NULL) |
327 | goto packet_routed; | 329 | goto packet_routed; |
@@ -359,7 +361,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) | |||
359 | } | 361 | } |
360 | sk_setup_caps(sk, &rt->u.dst); | 362 | sk_setup_caps(sk, &rt->u.dst); |
361 | } | 363 | } |
362 | skb_dst_set(skb, dst_clone(&rt->u.dst)); | 364 | skb_dst_set_noref(skb, &rt->u.dst); |
363 | 365 | ||
364 | packet_routed: | 366 | packet_routed: |
365 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) | 367 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) |
@@ -370,7 +372,7 @@ packet_routed: | |||
370 | skb_reset_network_header(skb); | 372 | skb_reset_network_header(skb); |
371 | iph = ip_hdr(skb); | 373 | iph = ip_hdr(skb); |
372 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); | 374 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); |
373 | if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok) | 375 | if (ip_dont_fragment(sk, &rt->u.dst) && !skb->local_df) |
374 | iph->frag_off = htons(IP_DF); | 376 | iph->frag_off = htons(IP_DF); |
375 | else | 377 | else |
376 | iph->frag_off = 0; | 378 | iph->frag_off = 0; |
@@ -391,9 +393,12 @@ packet_routed: | |||
391 | skb->priority = sk->sk_priority; | 393 | skb->priority = sk->sk_priority; |
392 | skb->mark = sk->sk_mark; | 394 | skb->mark = sk->sk_mark; |
393 | 395 | ||
394 | return ip_local_out(skb); | 396 | res = ip_local_out(skb); |
397 | rcu_read_unlock(); | ||
398 | return res; | ||
395 | 399 | ||
396 | no_route: | 400 | no_route: |
401 | rcu_read_unlock(); | ||
397 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); | 402 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); |
398 | kfree_skb(skb); | 403 | kfree_skb(skb); |
399 | return -EHOSTUNREACH; | 404 | return -EHOSTUNREACH; |
@@ -469,6 +474,10 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
469 | 474 | ||
470 | hlen = iph->ihl * 4; | 475 | hlen = iph->ihl * 4; |
471 | mtu = dst_mtu(&rt->u.dst) - hlen; /* Size of data space */ | 476 | mtu = dst_mtu(&rt->u.dst) - hlen; /* Size of data space */ |
477 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
478 | if (skb->nf_bridge) | ||
479 | mtu -= nf_bridge_mtu_reduction(skb); | ||
480 | #endif | ||
472 | IPCB(skb)->flags |= IPSKB_FRAG_COMPLETE; | 481 | IPCB(skb)->flags |= IPSKB_FRAG_COMPLETE; |
473 | 482 | ||
474 | /* When frag_list is given, use it. First, check its validity: | 483 | /* When frag_list is given, use it. First, check its validity: |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 1e64dabbd232..ce231780a2b1 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -287,12 +287,8 @@ int ip_ra_control(struct sock *sk, unsigned char on, | |||
287 | void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, | 287 | void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, |
288 | __be16 port, u32 info, u8 *payload) | 288 | __be16 port, u32 info, u8 *payload) |
289 | { | 289 | { |
290 | struct inet_sock *inet = inet_sk(sk); | ||
291 | struct sock_exterr_skb *serr; | 290 | struct sock_exterr_skb *serr; |
292 | 291 | ||
293 | if (!inet->recverr) | ||
294 | return; | ||
295 | |||
296 | skb = skb_clone(skb, GFP_ATOMIC); | 292 | skb = skb_clone(skb, GFP_ATOMIC); |
297 | if (!skb) | 293 | if (!skb) |
298 | return; | 294 | return; |
@@ -958,6 +954,22 @@ e_inval: | |||
958 | return -EINVAL; | 954 | return -EINVAL; |
959 | } | 955 | } |
960 | 956 | ||
957 | /** | ||
958 | * ip_queue_rcv_skb - Queue an skb into sock receive queue | ||
959 | * @sk: socket | ||
960 | * @skb: buffer | ||
961 | * | ||
962 | * Queues an skb into socket receive queue. If IP_CMSG_PKTINFO option | ||
963 | * is not set, we drop skb dst entry now, while dst cache line is hot. | ||
964 | */ | ||
965 | int ip_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | ||
966 | { | ||
967 | if (!(inet_sk(sk)->cmsg_flags & IP_CMSG_PKTINFO)) | ||
968 | skb_dst_drop(skb); | ||
969 | return sock_queue_rcv_skb(sk, skb); | ||
970 | } | ||
971 | EXPORT_SYMBOL(ip_queue_rcv_skb); | ||
972 | |||
961 | int ip_setsockopt(struct sock *sk, int level, | 973 | int ip_setsockopt(struct sock *sk, int level, |
962 | int optname, char __user *optval, unsigned int optlen) | 974 | int optname, char __user *optval, unsigned int optlen) |
963 | { | 975 | { |
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 067ce9e043dc..b9d84e800cf4 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -976,7 +976,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str | |||
976 | /* Is it a reply for the device we are configuring? */ | 976 | /* Is it a reply for the device we are configuring? */ |
977 | if (b->xid != ic_dev_xid) { | 977 | if (b->xid != ic_dev_xid) { |
978 | if (net_ratelimit()) | 978 | if (net_ratelimit()) |
979 | printk(KERN_ERR "DHCP/BOOTP: Ignoring delayed packet \n"); | 979 | printk(KERN_ERR "DHCP/BOOTP: Ignoring delayed packet\n"); |
980 | goto drop_unlock; | 980 | goto drop_unlock; |
981 | } | 981 | } |
982 | 982 | ||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 0b27b14dcc9d..7fd636711037 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -374,11 +374,8 @@ static int ipip_rcv(struct sk_buff *skb) | |||
374 | skb->protocol = htons(ETH_P_IP); | 374 | skb->protocol = htons(ETH_P_IP); |
375 | skb->pkt_type = PACKET_HOST; | 375 | skb->pkt_type = PACKET_HOST; |
376 | 376 | ||
377 | tunnel->dev->stats.rx_packets++; | 377 | skb_tunnel_rx(skb, tunnel->dev); |
378 | tunnel->dev->stats.rx_bytes += skb->len; | 378 | |
379 | skb->dev = tunnel->dev; | ||
380 | skb_dst_drop(skb); | ||
381 | nf_reset(skb); | ||
382 | ipip_ecn_decapsulate(iph, skb); | 379 | ipip_ecn_decapsulate(iph, skb); |
383 | netif_rx(skb); | 380 | netif_rx(skb); |
384 | rcu_read_unlock(); | 381 | rcu_read_unlock(); |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 82aa9c9e4edb..45889103b3e2 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -63,11 +63,40 @@ | |||
63 | #include <net/ipip.h> | 63 | #include <net/ipip.h> |
64 | #include <net/checksum.h> | 64 | #include <net/checksum.h> |
65 | #include <net/netlink.h> | 65 | #include <net/netlink.h> |
66 | #include <net/fib_rules.h> | ||
66 | 67 | ||
67 | #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2) | 68 | #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2) |
68 | #define CONFIG_IP_PIMSM 1 | 69 | #define CONFIG_IP_PIMSM 1 |
69 | #endif | 70 | #endif |
70 | 71 | ||
72 | struct mr_table { | ||
73 | struct list_head list; | ||
74 | #ifdef CONFIG_NET_NS | ||
75 | struct net *net; | ||
76 | #endif | ||
77 | u32 id; | ||
78 | struct sock *mroute_sk; | ||
79 | struct timer_list ipmr_expire_timer; | ||
80 | struct list_head mfc_unres_queue; | ||
81 | struct list_head mfc_cache_array[MFC_LINES]; | ||
82 | struct vif_device vif_table[MAXVIFS]; | ||
83 | int maxvif; | ||
84 | atomic_t cache_resolve_queue_len; | ||
85 | int mroute_do_assert; | ||
86 | int mroute_do_pim; | ||
87 | #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2) | ||
88 | int mroute_reg_vif_num; | ||
89 | #endif | ||
90 | }; | ||
91 | |||
92 | struct ipmr_rule { | ||
93 | struct fib_rule common; | ||
94 | }; | ||
95 | |||
96 | struct ipmr_result { | ||
97 | struct mr_table *mrt; | ||
98 | }; | ||
99 | |||
71 | /* Big lock, protecting vif table, mrt cache and mroute socket state. | 100 | /* Big lock, protecting vif table, mrt cache and mroute socket state. |
72 | Note that the changes are semaphored via rtnl_lock. | 101 | Note that the changes are semaphored via rtnl_lock. |
73 | */ | 102 | */ |
@@ -78,9 +107,7 @@ static DEFINE_RWLOCK(mrt_lock); | |||
78 | * Multicast router control variables | 107 | * Multicast router control variables |
79 | */ | 108 | */ |
80 | 109 | ||
81 | #define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL) | 110 | #define VIF_EXISTS(_mrt, _idx) ((_mrt)->vif_table[_idx].dev != NULL) |
82 | |||
83 | static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ | ||
84 | 111 | ||
85 | /* Special spinlock for queue of unresolved entries */ | 112 | /* Special spinlock for queue of unresolved entries */ |
86 | static DEFINE_SPINLOCK(mfc_unres_lock); | 113 | static DEFINE_SPINLOCK(mfc_unres_lock); |
@@ -95,12 +122,215 @@ static DEFINE_SPINLOCK(mfc_unres_lock); | |||
95 | 122 | ||
96 | static struct kmem_cache *mrt_cachep __read_mostly; | 123 | static struct kmem_cache *mrt_cachep __read_mostly; |
97 | 124 | ||
98 | static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local); | 125 | static struct mr_table *ipmr_new_table(struct net *net, u32 id); |
99 | static int ipmr_cache_report(struct net *net, | 126 | static int ip_mr_forward(struct net *net, struct mr_table *mrt, |
127 | struct sk_buff *skb, struct mfc_cache *cache, | ||
128 | int local); | ||
129 | static int ipmr_cache_report(struct mr_table *mrt, | ||
100 | struct sk_buff *pkt, vifi_t vifi, int assert); | 130 | struct sk_buff *pkt, vifi_t vifi, int assert); |
101 | static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); | 131 | static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, |
132 | struct mfc_cache *c, struct rtmsg *rtm); | ||
133 | static void ipmr_expire_process(unsigned long arg); | ||
134 | |||
135 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES | ||
136 | #define ipmr_for_each_table(mrt, net) \ | ||
137 | list_for_each_entry_rcu(mrt, &net->ipv4.mr_tables, list) | ||
138 | |||
139 | static struct mr_table *ipmr_get_table(struct net *net, u32 id) | ||
140 | { | ||
141 | struct mr_table *mrt; | ||
142 | |||
143 | ipmr_for_each_table(mrt, net) { | ||
144 | if (mrt->id == id) | ||
145 | return mrt; | ||
146 | } | ||
147 | return NULL; | ||
148 | } | ||
149 | |||
150 | static int ipmr_fib_lookup(struct net *net, struct flowi *flp, | ||
151 | struct mr_table **mrt) | ||
152 | { | ||
153 | struct ipmr_result res; | ||
154 | struct fib_lookup_arg arg = { .result = &res, }; | ||
155 | int err; | ||
156 | |||
157 | err = fib_rules_lookup(net->ipv4.mr_rules_ops, flp, 0, &arg); | ||
158 | if (err < 0) | ||
159 | return err; | ||
160 | *mrt = res.mrt; | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp, | ||
165 | int flags, struct fib_lookup_arg *arg) | ||
166 | { | ||
167 | struct ipmr_result *res = arg->result; | ||
168 | struct mr_table *mrt; | ||
102 | 169 | ||
103 | static struct timer_list ipmr_expire_timer; | 170 | switch (rule->action) { |
171 | case FR_ACT_TO_TBL: | ||
172 | break; | ||
173 | case FR_ACT_UNREACHABLE: | ||
174 | return -ENETUNREACH; | ||
175 | case FR_ACT_PROHIBIT: | ||
176 | return -EACCES; | ||
177 | case FR_ACT_BLACKHOLE: | ||
178 | default: | ||
179 | return -EINVAL; | ||
180 | } | ||
181 | |||
182 | mrt = ipmr_get_table(rule->fr_net, rule->table); | ||
183 | if (mrt == NULL) | ||
184 | return -EAGAIN; | ||
185 | res->mrt = mrt; | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int ipmr_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | ||
190 | { | ||
191 | return 1; | ||
192 | } | ||
193 | |||
194 | static const struct nla_policy ipmr_rule_policy[FRA_MAX + 1] = { | ||
195 | FRA_GENERIC_POLICY, | ||
196 | }; | ||
197 | |||
198 | static int ipmr_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | ||
199 | struct fib_rule_hdr *frh, struct nlattr **tb) | ||
200 | { | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int ipmr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | ||
205 | struct nlattr **tb) | ||
206 | { | ||
207 | return 1; | ||
208 | } | ||
209 | |||
210 | static int ipmr_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | ||
211 | struct fib_rule_hdr *frh) | ||
212 | { | ||
213 | frh->dst_len = 0; | ||
214 | frh->src_len = 0; | ||
215 | frh->tos = 0; | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static const struct fib_rules_ops __net_initdata ipmr_rules_ops_template = { | ||
220 | .family = RTNL_FAMILY_IPMR, | ||
221 | .rule_size = sizeof(struct ipmr_rule), | ||
222 | .addr_size = sizeof(u32), | ||
223 | .action = ipmr_rule_action, | ||
224 | .match = ipmr_rule_match, | ||
225 | .configure = ipmr_rule_configure, | ||
226 | .compare = ipmr_rule_compare, | ||
227 | .default_pref = fib_default_rule_pref, | ||
228 | .fill = ipmr_rule_fill, | ||
229 | .nlgroup = RTNLGRP_IPV4_RULE, | ||
230 | .policy = ipmr_rule_policy, | ||
231 | .owner = THIS_MODULE, | ||
232 | }; | ||
233 | |||
234 | static int __net_init ipmr_rules_init(struct net *net) | ||
235 | { | ||
236 | struct fib_rules_ops *ops; | ||
237 | struct mr_table *mrt; | ||
238 | int err; | ||
239 | |||
240 | ops = fib_rules_register(&ipmr_rules_ops_template, net); | ||
241 | if (IS_ERR(ops)) | ||
242 | return PTR_ERR(ops); | ||
243 | |||
244 | INIT_LIST_HEAD(&net->ipv4.mr_tables); | ||
245 | |||
246 | mrt = ipmr_new_table(net, RT_TABLE_DEFAULT); | ||
247 | if (mrt == NULL) { | ||
248 | err = -ENOMEM; | ||
249 | goto err1; | ||
250 | } | ||
251 | |||
252 | err = fib_default_rule_add(ops, 0x7fff, RT_TABLE_DEFAULT, 0); | ||
253 | if (err < 0) | ||
254 | goto err2; | ||
255 | |||
256 | net->ipv4.mr_rules_ops = ops; | ||
257 | return 0; | ||
258 | |||
259 | err2: | ||
260 | kfree(mrt); | ||
261 | err1: | ||
262 | fib_rules_unregister(ops); | ||
263 | return err; | ||
264 | } | ||
265 | |||
266 | static void __net_exit ipmr_rules_exit(struct net *net) | ||
267 | { | ||
268 | struct mr_table *mrt, *next; | ||
269 | |||
270 | list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) | ||
271 | kfree(mrt); | ||
272 | fib_rules_unregister(net->ipv4.mr_rules_ops); | ||
273 | } | ||
274 | #else | ||
275 | #define ipmr_for_each_table(mrt, net) \ | ||
276 | for (mrt = net->ipv4.mrt; mrt; mrt = NULL) | ||
277 | |||
278 | static struct mr_table *ipmr_get_table(struct net *net, u32 id) | ||
279 | { | ||
280 | return net->ipv4.mrt; | ||
281 | } | ||
282 | |||
283 | static int ipmr_fib_lookup(struct net *net, struct flowi *flp, | ||
284 | struct mr_table **mrt) | ||
285 | { | ||
286 | *mrt = net->ipv4.mrt; | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int __net_init ipmr_rules_init(struct net *net) | ||
291 | { | ||
292 | net->ipv4.mrt = ipmr_new_table(net, RT_TABLE_DEFAULT); | ||
293 | return net->ipv4.mrt ? 0 : -ENOMEM; | ||
294 | } | ||
295 | |||
296 | static void __net_exit ipmr_rules_exit(struct net *net) | ||
297 | { | ||
298 | kfree(net->ipv4.mrt); | ||
299 | } | ||
300 | #endif | ||
301 | |||
302 | static struct mr_table *ipmr_new_table(struct net *net, u32 id) | ||
303 | { | ||
304 | struct mr_table *mrt; | ||
305 | unsigned int i; | ||
306 | |||
307 | mrt = ipmr_get_table(net, id); | ||
308 | if (mrt != NULL) | ||
309 | return mrt; | ||
310 | |||
311 | mrt = kzalloc(sizeof(*mrt), GFP_KERNEL); | ||
312 | if (mrt == NULL) | ||
313 | return NULL; | ||
314 | write_pnet(&mrt->net, net); | ||
315 | mrt->id = id; | ||
316 | |||
317 | /* Forwarding cache */ | ||
318 | for (i = 0; i < MFC_LINES; i++) | ||
319 | INIT_LIST_HEAD(&mrt->mfc_cache_array[i]); | ||
320 | |||
321 | INIT_LIST_HEAD(&mrt->mfc_unres_queue); | ||
322 | |||
323 | setup_timer(&mrt->ipmr_expire_timer, ipmr_expire_process, | ||
324 | (unsigned long)mrt); | ||
325 | |||
326 | #ifdef CONFIG_IP_PIMSM | ||
327 | mrt->mroute_reg_vif_num = -1; | ||
328 | #endif | ||
329 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES | ||
330 | list_add_tail_rcu(&mrt->list, &net->ipv4.mr_tables); | ||
331 | #endif | ||
332 | return mrt; | ||
333 | } | ||
104 | 334 | ||
105 | /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ | 335 | /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ |
106 | 336 | ||
@@ -201,12 +431,22 @@ failure: | |||
201 | static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | 431 | static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) |
202 | { | 432 | { |
203 | struct net *net = dev_net(dev); | 433 | struct net *net = dev_net(dev); |
434 | struct mr_table *mrt; | ||
435 | struct flowi fl = { | ||
436 | .oif = dev->ifindex, | ||
437 | .iif = skb->skb_iif, | ||
438 | .mark = skb->mark, | ||
439 | }; | ||
440 | int err; | ||
441 | |||
442 | err = ipmr_fib_lookup(net, &fl, &mrt); | ||
443 | if (err < 0) | ||
444 | return err; | ||
204 | 445 | ||
205 | read_lock(&mrt_lock); | 446 | read_lock(&mrt_lock); |
206 | dev->stats.tx_bytes += skb->len; | 447 | dev->stats.tx_bytes += skb->len; |
207 | dev->stats.tx_packets++; | 448 | dev->stats.tx_packets++; |
208 | ipmr_cache_report(net, skb, net->ipv4.mroute_reg_vif_num, | 449 | ipmr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, IGMPMSG_WHOLEPKT); |
209 | IGMPMSG_WHOLEPKT); | ||
210 | read_unlock(&mrt_lock); | 450 | read_unlock(&mrt_lock); |
211 | kfree_skb(skb); | 451 | kfree_skb(skb); |
212 | return NETDEV_TX_OK; | 452 | return NETDEV_TX_OK; |
@@ -226,12 +466,18 @@ static void reg_vif_setup(struct net_device *dev) | |||
226 | dev->features |= NETIF_F_NETNS_LOCAL; | 466 | dev->features |= NETIF_F_NETNS_LOCAL; |
227 | } | 467 | } |
228 | 468 | ||
229 | static struct net_device *ipmr_reg_vif(struct net *net) | 469 | static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt) |
230 | { | 470 | { |
231 | struct net_device *dev; | 471 | struct net_device *dev; |
232 | struct in_device *in_dev; | 472 | struct in_device *in_dev; |
473 | char name[IFNAMSIZ]; | ||
474 | |||
475 | if (mrt->id == RT_TABLE_DEFAULT) | ||
476 | sprintf(name, "pimreg"); | ||
477 | else | ||
478 | sprintf(name, "pimreg%u", mrt->id); | ||
233 | 479 | ||
234 | dev = alloc_netdev(0, "pimreg", reg_vif_setup); | 480 | dev = alloc_netdev(0, name, reg_vif_setup); |
235 | 481 | ||
236 | if (dev == NULL) | 482 | if (dev == NULL) |
237 | return NULL; | 483 | return NULL; |
@@ -276,17 +522,17 @@ failure: | |||
276 | * @notify: Set to 1, if the caller is a notifier_call | 522 | * @notify: Set to 1, if the caller is a notifier_call |
277 | */ | 523 | */ |
278 | 524 | ||
279 | static int vif_delete(struct net *net, int vifi, int notify, | 525 | static int vif_delete(struct mr_table *mrt, int vifi, int notify, |
280 | struct list_head *head) | 526 | struct list_head *head) |
281 | { | 527 | { |
282 | struct vif_device *v; | 528 | struct vif_device *v; |
283 | struct net_device *dev; | 529 | struct net_device *dev; |
284 | struct in_device *in_dev; | 530 | struct in_device *in_dev; |
285 | 531 | ||
286 | if (vifi < 0 || vifi >= net->ipv4.maxvif) | 532 | if (vifi < 0 || vifi >= mrt->maxvif) |
287 | return -EADDRNOTAVAIL; | 533 | return -EADDRNOTAVAIL; |
288 | 534 | ||
289 | v = &net->ipv4.vif_table[vifi]; | 535 | v = &mrt->vif_table[vifi]; |
290 | 536 | ||
291 | write_lock_bh(&mrt_lock); | 537 | write_lock_bh(&mrt_lock); |
292 | dev = v->dev; | 538 | dev = v->dev; |
@@ -298,17 +544,17 @@ static int vif_delete(struct net *net, int vifi, int notify, | |||
298 | } | 544 | } |
299 | 545 | ||
300 | #ifdef CONFIG_IP_PIMSM | 546 | #ifdef CONFIG_IP_PIMSM |
301 | if (vifi == net->ipv4.mroute_reg_vif_num) | 547 | if (vifi == mrt->mroute_reg_vif_num) |
302 | net->ipv4.mroute_reg_vif_num = -1; | 548 | mrt->mroute_reg_vif_num = -1; |
303 | #endif | 549 | #endif |
304 | 550 | ||
305 | if (vifi+1 == net->ipv4.maxvif) { | 551 | if (vifi+1 == mrt->maxvif) { |
306 | int tmp; | 552 | int tmp; |
307 | for (tmp=vifi-1; tmp>=0; tmp--) { | 553 | for (tmp=vifi-1; tmp>=0; tmp--) { |
308 | if (VIF_EXISTS(net, tmp)) | 554 | if (VIF_EXISTS(mrt, tmp)) |
309 | break; | 555 | break; |
310 | } | 556 | } |
311 | net->ipv4.maxvif = tmp+1; | 557 | mrt->maxvif = tmp+1; |
312 | } | 558 | } |
313 | 559 | ||
314 | write_unlock_bh(&mrt_lock); | 560 | write_unlock_bh(&mrt_lock); |
@@ -329,7 +575,6 @@ static int vif_delete(struct net *net, int vifi, int notify, | |||
329 | 575 | ||
330 | static inline void ipmr_cache_free(struct mfc_cache *c) | 576 | static inline void ipmr_cache_free(struct mfc_cache *c) |
331 | { | 577 | { |
332 | release_net(mfc_net(c)); | ||
333 | kmem_cache_free(mrt_cachep, c); | 578 | kmem_cache_free(mrt_cachep, c); |
334 | } | 579 | } |
335 | 580 | ||
@@ -337,13 +582,13 @@ static inline void ipmr_cache_free(struct mfc_cache *c) | |||
337 | and reporting error to netlink readers. | 582 | and reporting error to netlink readers. |
338 | */ | 583 | */ |
339 | 584 | ||
340 | static void ipmr_destroy_unres(struct mfc_cache *c) | 585 | static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c) |
341 | { | 586 | { |
587 | struct net *net = read_pnet(&mrt->net); | ||
342 | struct sk_buff *skb; | 588 | struct sk_buff *skb; |
343 | struct nlmsgerr *e; | 589 | struct nlmsgerr *e; |
344 | struct net *net = mfc_net(c); | ||
345 | 590 | ||
346 | atomic_dec(&net->ipv4.cache_resolve_queue_len); | 591 | atomic_dec(&mrt->cache_resolve_queue_len); |
347 | 592 | ||
348 | while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) { | 593 | while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) { |
349 | if (ip_hdr(skb)->version == 0) { | 594 | if (ip_hdr(skb)->version == 0) { |
@@ -364,42 +609,40 @@ static void ipmr_destroy_unres(struct mfc_cache *c) | |||
364 | } | 609 | } |
365 | 610 | ||
366 | 611 | ||
367 | /* Single timer process for all the unresolved queue. */ | 612 | /* Timer process for the unresolved queue. */ |
368 | 613 | ||
369 | static void ipmr_expire_process(unsigned long dummy) | 614 | static void ipmr_expire_process(unsigned long arg) |
370 | { | 615 | { |
616 | struct mr_table *mrt = (struct mr_table *)arg; | ||
371 | unsigned long now; | 617 | unsigned long now; |
372 | unsigned long expires; | 618 | unsigned long expires; |
373 | struct mfc_cache *c, **cp; | 619 | struct mfc_cache *c, *next; |
374 | 620 | ||
375 | if (!spin_trylock(&mfc_unres_lock)) { | 621 | if (!spin_trylock(&mfc_unres_lock)) { |
376 | mod_timer(&ipmr_expire_timer, jiffies+HZ/10); | 622 | mod_timer(&mrt->ipmr_expire_timer, jiffies+HZ/10); |
377 | return; | 623 | return; |
378 | } | 624 | } |
379 | 625 | ||
380 | if (mfc_unres_queue == NULL) | 626 | if (list_empty(&mrt->mfc_unres_queue)) |
381 | goto out; | 627 | goto out; |
382 | 628 | ||
383 | now = jiffies; | 629 | now = jiffies; |
384 | expires = 10*HZ; | 630 | expires = 10*HZ; |
385 | cp = &mfc_unres_queue; | ||
386 | 631 | ||
387 | while ((c=*cp) != NULL) { | 632 | list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) { |
388 | if (time_after(c->mfc_un.unres.expires, now)) { | 633 | if (time_after(c->mfc_un.unres.expires, now)) { |
389 | unsigned long interval = c->mfc_un.unres.expires - now; | 634 | unsigned long interval = c->mfc_un.unres.expires - now; |
390 | if (interval < expires) | 635 | if (interval < expires) |
391 | expires = interval; | 636 | expires = interval; |
392 | cp = &c->next; | ||
393 | continue; | 637 | continue; |
394 | } | 638 | } |
395 | 639 | ||
396 | *cp = c->next; | 640 | list_del(&c->list); |
397 | 641 | ipmr_destroy_unres(mrt, c); | |
398 | ipmr_destroy_unres(c); | ||
399 | } | 642 | } |
400 | 643 | ||
401 | if (mfc_unres_queue != NULL) | 644 | if (!list_empty(&mrt->mfc_unres_queue)) |
402 | mod_timer(&ipmr_expire_timer, jiffies + expires); | 645 | mod_timer(&mrt->ipmr_expire_timer, jiffies + expires); |
403 | 646 | ||
404 | out: | 647 | out: |
405 | spin_unlock(&mfc_unres_lock); | 648 | spin_unlock(&mfc_unres_lock); |
@@ -407,17 +650,17 @@ out: | |||
407 | 650 | ||
408 | /* Fill oifs list. It is called under write locked mrt_lock. */ | 651 | /* Fill oifs list. It is called under write locked mrt_lock. */ |
409 | 652 | ||
410 | static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) | 653 | static void ipmr_update_thresholds(struct mr_table *mrt, struct mfc_cache *cache, |
654 | unsigned char *ttls) | ||
411 | { | 655 | { |
412 | int vifi; | 656 | int vifi; |
413 | struct net *net = mfc_net(cache); | ||
414 | 657 | ||
415 | cache->mfc_un.res.minvif = MAXVIFS; | 658 | cache->mfc_un.res.minvif = MAXVIFS; |
416 | cache->mfc_un.res.maxvif = 0; | 659 | cache->mfc_un.res.maxvif = 0; |
417 | memset(cache->mfc_un.res.ttls, 255, MAXVIFS); | 660 | memset(cache->mfc_un.res.ttls, 255, MAXVIFS); |
418 | 661 | ||
419 | for (vifi = 0; vifi < net->ipv4.maxvif; vifi++) { | 662 | for (vifi = 0; vifi < mrt->maxvif; vifi++) { |
420 | if (VIF_EXISTS(net, vifi) && | 663 | if (VIF_EXISTS(mrt, vifi) && |
421 | ttls[vifi] && ttls[vifi] < 255) { | 664 | ttls[vifi] && ttls[vifi] < 255) { |
422 | cache->mfc_un.res.ttls[vifi] = ttls[vifi]; | 665 | cache->mfc_un.res.ttls[vifi] = ttls[vifi]; |
423 | if (cache->mfc_un.res.minvif > vifi) | 666 | if (cache->mfc_un.res.minvif > vifi) |
@@ -428,16 +671,17 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) | |||
428 | } | 671 | } |
429 | } | 672 | } |
430 | 673 | ||
431 | static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock) | 674 | static int vif_add(struct net *net, struct mr_table *mrt, |
675 | struct vifctl *vifc, int mrtsock) | ||
432 | { | 676 | { |
433 | int vifi = vifc->vifc_vifi; | 677 | int vifi = vifc->vifc_vifi; |
434 | struct vif_device *v = &net->ipv4.vif_table[vifi]; | 678 | struct vif_device *v = &mrt->vif_table[vifi]; |
435 | struct net_device *dev; | 679 | struct net_device *dev; |
436 | struct in_device *in_dev; | 680 | struct in_device *in_dev; |
437 | int err; | 681 | int err; |
438 | 682 | ||
439 | /* Is vif busy ? */ | 683 | /* Is vif busy ? */ |
440 | if (VIF_EXISTS(net, vifi)) | 684 | if (VIF_EXISTS(mrt, vifi)) |
441 | return -EADDRINUSE; | 685 | return -EADDRINUSE; |
442 | 686 | ||
443 | switch (vifc->vifc_flags) { | 687 | switch (vifc->vifc_flags) { |
@@ -447,9 +691,9 @@ static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock) | |||
447 | * Special Purpose VIF in PIM | 691 | * Special Purpose VIF in PIM |
448 | * All the packets will be sent to the daemon | 692 | * All the packets will be sent to the daemon |
449 | */ | 693 | */ |
450 | if (net->ipv4.mroute_reg_vif_num >= 0) | 694 | if (mrt->mroute_reg_vif_num >= 0) |
451 | return -EADDRINUSE; | 695 | return -EADDRINUSE; |
452 | dev = ipmr_reg_vif(net); | 696 | dev = ipmr_reg_vif(net, mrt); |
453 | if (!dev) | 697 | if (!dev) |
454 | return -ENOBUFS; | 698 | return -ENOBUFS; |
455 | err = dev_set_allmulti(dev, 1); | 699 | err = dev_set_allmulti(dev, 1); |
@@ -525,49 +769,47 @@ static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock) | |||
525 | v->dev = dev; | 769 | v->dev = dev; |
526 | #ifdef CONFIG_IP_PIMSM | 770 | #ifdef CONFIG_IP_PIMSM |
527 | if (v->flags&VIFF_REGISTER) | 771 | if (v->flags&VIFF_REGISTER) |
528 | net->ipv4.mroute_reg_vif_num = vifi; | 772 | mrt->mroute_reg_vif_num = vifi; |
529 | #endif | 773 | #endif |
530 | if (vifi+1 > net->ipv4.maxvif) | 774 | if (vifi+1 > mrt->maxvif) |
531 | net->ipv4.maxvif = vifi+1; | 775 | mrt->maxvif = vifi+1; |
532 | write_unlock_bh(&mrt_lock); | 776 | write_unlock_bh(&mrt_lock); |
533 | return 0; | 777 | return 0; |
534 | } | 778 | } |
535 | 779 | ||
536 | static struct mfc_cache *ipmr_cache_find(struct net *net, | 780 | static struct mfc_cache *ipmr_cache_find(struct mr_table *mrt, |
537 | __be32 origin, | 781 | __be32 origin, |
538 | __be32 mcastgrp) | 782 | __be32 mcastgrp) |
539 | { | 783 | { |
540 | int line = MFC_HASH(mcastgrp, origin); | 784 | int line = MFC_HASH(mcastgrp, origin); |
541 | struct mfc_cache *c; | 785 | struct mfc_cache *c; |
542 | 786 | ||
543 | for (c = net->ipv4.mfc_cache_array[line]; c; c = c->next) { | 787 | list_for_each_entry(c, &mrt->mfc_cache_array[line], list) { |
544 | if (c->mfc_origin==origin && c->mfc_mcastgrp==mcastgrp) | 788 | if (c->mfc_origin == origin && c->mfc_mcastgrp == mcastgrp) |
545 | break; | 789 | return c; |
546 | } | 790 | } |
547 | return c; | 791 | return NULL; |
548 | } | 792 | } |
549 | 793 | ||
550 | /* | 794 | /* |
551 | * Allocate a multicast cache entry | 795 | * Allocate a multicast cache entry |
552 | */ | 796 | */ |
553 | static struct mfc_cache *ipmr_cache_alloc(struct net *net) | 797 | static struct mfc_cache *ipmr_cache_alloc(void) |
554 | { | 798 | { |
555 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); | 799 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); |
556 | if (c == NULL) | 800 | if (c == NULL) |
557 | return NULL; | 801 | return NULL; |
558 | c->mfc_un.res.minvif = MAXVIFS; | 802 | c->mfc_un.res.minvif = MAXVIFS; |
559 | mfc_net_set(c, net); | ||
560 | return c; | 803 | return c; |
561 | } | 804 | } |
562 | 805 | ||
563 | static struct mfc_cache *ipmr_cache_alloc_unres(struct net *net) | 806 | static struct mfc_cache *ipmr_cache_alloc_unres(void) |
564 | { | 807 | { |
565 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); | 808 | struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); |
566 | if (c == NULL) | 809 | if (c == NULL) |
567 | return NULL; | 810 | return NULL; |
568 | skb_queue_head_init(&c->mfc_un.unres.unresolved); | 811 | skb_queue_head_init(&c->mfc_un.unres.unresolved); |
569 | c->mfc_un.unres.expires = jiffies + 10*HZ; | 812 | c->mfc_un.unres.expires = jiffies + 10*HZ; |
570 | mfc_net_set(c, net); | ||
571 | return c; | 813 | return c; |
572 | } | 814 | } |
573 | 815 | ||
@@ -575,7 +817,8 @@ static struct mfc_cache *ipmr_cache_alloc_unres(struct net *net) | |||
575 | * A cache entry has gone into a resolved state from queued | 817 | * A cache entry has gone into a resolved state from queued |
576 | */ | 818 | */ |
577 | 819 | ||
578 | static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) | 820 | static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, |
821 | struct mfc_cache *uc, struct mfc_cache *c) | ||
579 | { | 822 | { |
580 | struct sk_buff *skb; | 823 | struct sk_buff *skb; |
581 | struct nlmsgerr *e; | 824 | struct nlmsgerr *e; |
@@ -588,7 +831,7 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) | |||
588 | if (ip_hdr(skb)->version == 0) { | 831 | if (ip_hdr(skb)->version == 0) { |
589 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); | 832 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); |
590 | 833 | ||
591 | if (ipmr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) { | 834 | if (__ipmr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { |
592 | nlh->nlmsg_len = (skb_tail_pointer(skb) - | 835 | nlh->nlmsg_len = (skb_tail_pointer(skb) - |
593 | (u8 *)nlh); | 836 | (u8 *)nlh); |
594 | } else { | 837 | } else { |
@@ -600,9 +843,9 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) | |||
600 | memset(&e->msg, 0, sizeof(e->msg)); | 843 | memset(&e->msg, 0, sizeof(e->msg)); |
601 | } | 844 | } |
602 | 845 | ||
603 | rtnl_unicast(skb, mfc_net(c), NETLINK_CB(skb).pid); | 846 | rtnl_unicast(skb, net, NETLINK_CB(skb).pid); |
604 | } else | 847 | } else |
605 | ip_mr_forward(skb, c, 0); | 848 | ip_mr_forward(net, mrt, skb, c, 0); |
606 | } | 849 | } |
607 | } | 850 | } |
608 | 851 | ||
@@ -613,7 +856,7 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) | |||
613 | * Called under mrt_lock. | 856 | * Called under mrt_lock. |
614 | */ | 857 | */ |
615 | 858 | ||
616 | static int ipmr_cache_report(struct net *net, | 859 | static int ipmr_cache_report(struct mr_table *mrt, |
617 | struct sk_buff *pkt, vifi_t vifi, int assert) | 860 | struct sk_buff *pkt, vifi_t vifi, int assert) |
618 | { | 861 | { |
619 | struct sk_buff *skb; | 862 | struct sk_buff *skb; |
@@ -646,7 +889,7 @@ static int ipmr_cache_report(struct net *net, | |||
646 | memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr)); | 889 | memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr)); |
647 | msg->im_msgtype = IGMPMSG_WHOLEPKT; | 890 | msg->im_msgtype = IGMPMSG_WHOLEPKT; |
648 | msg->im_mbz = 0; | 891 | msg->im_mbz = 0; |
649 | msg->im_vif = net->ipv4.mroute_reg_vif_num; | 892 | msg->im_vif = mrt->mroute_reg_vif_num; |
650 | ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; | 893 | ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; |
651 | ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + | 894 | ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + |
652 | sizeof(struct iphdr)); | 895 | sizeof(struct iphdr)); |
@@ -678,7 +921,7 @@ static int ipmr_cache_report(struct net *net, | |||
678 | skb->transport_header = skb->network_header; | 921 | skb->transport_header = skb->network_header; |
679 | } | 922 | } |
680 | 923 | ||
681 | if (net->ipv4.mroute_sk == NULL) { | 924 | if (mrt->mroute_sk == NULL) { |
682 | kfree_skb(skb); | 925 | kfree_skb(skb); |
683 | return -EINVAL; | 926 | return -EINVAL; |
684 | } | 927 | } |
@@ -686,7 +929,7 @@ static int ipmr_cache_report(struct net *net, | |||
686 | /* | 929 | /* |
687 | * Deliver to mrouted | 930 | * Deliver to mrouted |
688 | */ | 931 | */ |
689 | ret = sock_queue_rcv_skb(net->ipv4.mroute_sk, skb); | 932 | ret = sock_queue_rcv_skb(mrt->mroute_sk, skb); |
690 | if (ret < 0) { | 933 | if (ret < 0) { |
691 | if (net_ratelimit()) | 934 | if (net_ratelimit()) |
692 | printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n"); | 935 | printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n"); |
@@ -701,27 +944,29 @@ static int ipmr_cache_report(struct net *net, | |||
701 | */ | 944 | */ |
702 | 945 | ||
703 | static int | 946 | static int |
704 | ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb) | 947 | ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb) |
705 | { | 948 | { |
949 | bool found = false; | ||
706 | int err; | 950 | int err; |
707 | struct mfc_cache *c; | 951 | struct mfc_cache *c; |
708 | const struct iphdr *iph = ip_hdr(skb); | 952 | const struct iphdr *iph = ip_hdr(skb); |
709 | 953 | ||
710 | spin_lock_bh(&mfc_unres_lock); | 954 | spin_lock_bh(&mfc_unres_lock); |
711 | for (c=mfc_unres_queue; c; c=c->next) { | 955 | list_for_each_entry(c, &mrt->mfc_unres_queue, list) { |
712 | if (net_eq(mfc_net(c), net) && | 956 | if (c->mfc_mcastgrp == iph->daddr && |
713 | c->mfc_mcastgrp == iph->daddr && | 957 | c->mfc_origin == iph->saddr) { |
714 | c->mfc_origin == iph->saddr) | 958 | found = true; |
715 | break; | 959 | break; |
960 | } | ||
716 | } | 961 | } |
717 | 962 | ||
718 | if (c == NULL) { | 963 | if (!found) { |
719 | /* | 964 | /* |
720 | * Create a new entry if allowable | 965 | * Create a new entry if allowable |
721 | */ | 966 | */ |
722 | 967 | ||
723 | if (atomic_read(&net->ipv4.cache_resolve_queue_len) >= 10 || | 968 | if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 || |
724 | (c = ipmr_cache_alloc_unres(net)) == NULL) { | 969 | (c = ipmr_cache_alloc_unres()) == NULL) { |
725 | spin_unlock_bh(&mfc_unres_lock); | 970 | spin_unlock_bh(&mfc_unres_lock); |
726 | 971 | ||
727 | kfree_skb(skb); | 972 | kfree_skb(skb); |
@@ -738,7 +983,7 @@ ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb) | |||
738 | /* | 983 | /* |
739 | * Reflect first query at mrouted. | 984 | * Reflect first query at mrouted. |
740 | */ | 985 | */ |
741 | err = ipmr_cache_report(net, skb, vifi, IGMPMSG_NOCACHE); | 986 | err = ipmr_cache_report(mrt, skb, vifi, IGMPMSG_NOCACHE); |
742 | if (err < 0) { | 987 | if (err < 0) { |
743 | /* If the report failed throw the cache entry | 988 | /* If the report failed throw the cache entry |
744 | out - Brad Parker | 989 | out - Brad Parker |
@@ -750,12 +995,11 @@ ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb) | |||
750 | return err; | 995 | return err; |
751 | } | 996 | } |
752 | 997 | ||
753 | atomic_inc(&net->ipv4.cache_resolve_queue_len); | 998 | atomic_inc(&mrt->cache_resolve_queue_len); |
754 | c->next = mfc_unres_queue; | 999 | list_add(&c->list, &mrt->mfc_unres_queue); |
755 | mfc_unres_queue = c; | ||
756 | 1000 | ||
757 | if (atomic_read(&net->ipv4.cache_resolve_queue_len) == 1) | 1001 | if (atomic_read(&mrt->cache_resolve_queue_len) == 1) |
758 | mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires); | 1002 | mod_timer(&mrt->ipmr_expire_timer, c->mfc_un.unres.expires); |
759 | } | 1003 | } |
760 | 1004 | ||
761 | /* | 1005 | /* |
@@ -777,19 +1021,18 @@ ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb) | |||
777 | * MFC cache manipulation by user space mroute daemon | 1021 | * MFC cache manipulation by user space mroute daemon |
778 | */ | 1022 | */ |
779 | 1023 | ||
780 | static int ipmr_mfc_delete(struct net *net, struct mfcctl *mfc) | 1024 | static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc) |
781 | { | 1025 | { |
782 | int line; | 1026 | int line; |
783 | struct mfc_cache *c, **cp; | 1027 | struct mfc_cache *c, *next; |
784 | 1028 | ||
785 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); | 1029 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); |
786 | 1030 | ||
787 | for (cp = &net->ipv4.mfc_cache_array[line]; | 1031 | list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[line], list) { |
788 | (c = *cp) != NULL; cp = &c->next) { | ||
789 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && | 1032 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && |
790 | c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { | 1033 | c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { |
791 | write_lock_bh(&mrt_lock); | 1034 | write_lock_bh(&mrt_lock); |
792 | *cp = c->next; | 1035 | list_del(&c->list); |
793 | write_unlock_bh(&mrt_lock); | 1036 | write_unlock_bh(&mrt_lock); |
794 | 1037 | ||
795 | ipmr_cache_free(c); | 1038 | ipmr_cache_free(c); |
@@ -799,27 +1042,30 @@ static int ipmr_mfc_delete(struct net *net, struct mfcctl *mfc) | |||
799 | return -ENOENT; | 1042 | return -ENOENT; |
800 | } | 1043 | } |
801 | 1044 | ||
802 | static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock) | 1045 | static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, |
1046 | struct mfcctl *mfc, int mrtsock) | ||
803 | { | 1047 | { |
1048 | bool found = false; | ||
804 | int line; | 1049 | int line; |
805 | struct mfc_cache *uc, *c, **cp; | 1050 | struct mfc_cache *uc, *c; |
806 | 1051 | ||
807 | if (mfc->mfcc_parent >= MAXVIFS) | 1052 | if (mfc->mfcc_parent >= MAXVIFS) |
808 | return -ENFILE; | 1053 | return -ENFILE; |
809 | 1054 | ||
810 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); | 1055 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); |
811 | 1056 | ||
812 | for (cp = &net->ipv4.mfc_cache_array[line]; | 1057 | list_for_each_entry(c, &mrt->mfc_cache_array[line], list) { |
813 | (c = *cp) != NULL; cp = &c->next) { | ||
814 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && | 1058 | if (c->mfc_origin == mfc->mfcc_origin.s_addr && |
815 | c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) | 1059 | c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { |
1060 | found = true; | ||
816 | break; | 1061 | break; |
1062 | } | ||
817 | } | 1063 | } |
818 | 1064 | ||
819 | if (c != NULL) { | 1065 | if (found) { |
820 | write_lock_bh(&mrt_lock); | 1066 | write_lock_bh(&mrt_lock); |
821 | c->mfc_parent = mfc->mfcc_parent; | 1067 | c->mfc_parent = mfc->mfcc_parent; |
822 | ipmr_update_thresholds(c, mfc->mfcc_ttls); | 1068 | ipmr_update_thresholds(mrt, c, mfc->mfcc_ttls); |
823 | if (!mrtsock) | 1069 | if (!mrtsock) |
824 | c->mfc_flags |= MFC_STATIC; | 1070 | c->mfc_flags |= MFC_STATIC; |
825 | write_unlock_bh(&mrt_lock); | 1071 | write_unlock_bh(&mrt_lock); |
@@ -829,43 +1075,42 @@ static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock) | |||
829 | if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) | 1075 | if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) |
830 | return -EINVAL; | 1076 | return -EINVAL; |
831 | 1077 | ||
832 | c = ipmr_cache_alloc(net); | 1078 | c = ipmr_cache_alloc(); |
833 | if (c == NULL) | 1079 | if (c == NULL) |
834 | return -ENOMEM; | 1080 | return -ENOMEM; |
835 | 1081 | ||
836 | c->mfc_origin = mfc->mfcc_origin.s_addr; | 1082 | c->mfc_origin = mfc->mfcc_origin.s_addr; |
837 | c->mfc_mcastgrp = mfc->mfcc_mcastgrp.s_addr; | 1083 | c->mfc_mcastgrp = mfc->mfcc_mcastgrp.s_addr; |
838 | c->mfc_parent = mfc->mfcc_parent; | 1084 | c->mfc_parent = mfc->mfcc_parent; |
839 | ipmr_update_thresholds(c, mfc->mfcc_ttls); | 1085 | ipmr_update_thresholds(mrt, c, mfc->mfcc_ttls); |
840 | if (!mrtsock) | 1086 | if (!mrtsock) |
841 | c->mfc_flags |= MFC_STATIC; | 1087 | c->mfc_flags |= MFC_STATIC; |
842 | 1088 | ||
843 | write_lock_bh(&mrt_lock); | 1089 | write_lock_bh(&mrt_lock); |
844 | c->next = net->ipv4.mfc_cache_array[line]; | 1090 | list_add(&c->list, &mrt->mfc_cache_array[line]); |
845 | net->ipv4.mfc_cache_array[line] = c; | ||
846 | write_unlock_bh(&mrt_lock); | 1091 | write_unlock_bh(&mrt_lock); |
847 | 1092 | ||
848 | /* | 1093 | /* |
849 | * Check to see if we resolved a queued list. If so we | 1094 | * Check to see if we resolved a queued list. If so we |
850 | * need to send on the frames and tidy up. | 1095 | * need to send on the frames and tidy up. |
851 | */ | 1096 | */ |
1097 | found = false; | ||
852 | spin_lock_bh(&mfc_unres_lock); | 1098 | spin_lock_bh(&mfc_unres_lock); |
853 | for (cp = &mfc_unres_queue; (uc=*cp) != NULL; | 1099 | list_for_each_entry(uc, &mrt->mfc_unres_queue, list) { |
854 | cp = &uc->next) { | 1100 | if (uc->mfc_origin == c->mfc_origin && |
855 | if (net_eq(mfc_net(uc), net) && | ||
856 | uc->mfc_origin == c->mfc_origin && | ||
857 | uc->mfc_mcastgrp == c->mfc_mcastgrp) { | 1101 | uc->mfc_mcastgrp == c->mfc_mcastgrp) { |
858 | *cp = uc->next; | 1102 | list_del(&uc->list); |
859 | atomic_dec(&net->ipv4.cache_resolve_queue_len); | 1103 | atomic_dec(&mrt->cache_resolve_queue_len); |
1104 | found = true; | ||
860 | break; | 1105 | break; |
861 | } | 1106 | } |
862 | } | 1107 | } |
863 | if (mfc_unres_queue == NULL) | 1108 | if (list_empty(&mrt->mfc_unres_queue)) |
864 | del_timer(&ipmr_expire_timer); | 1109 | del_timer(&mrt->ipmr_expire_timer); |
865 | spin_unlock_bh(&mfc_unres_lock); | 1110 | spin_unlock_bh(&mfc_unres_lock); |
866 | 1111 | ||
867 | if (uc) { | 1112 | if (found) { |
868 | ipmr_cache_resolve(uc, c); | 1113 | ipmr_cache_resolve(net, mrt, uc, c); |
869 | ipmr_cache_free(uc); | 1114 | ipmr_cache_free(uc); |
870 | } | 1115 | } |
871 | return 0; | 1116 | return 0; |
@@ -875,53 +1120,41 @@ static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock) | |||
875 | * Close the multicast socket, and clear the vif tables etc | 1120 | * Close the multicast socket, and clear the vif tables etc |
876 | */ | 1121 | */ |
877 | 1122 | ||
878 | static void mroute_clean_tables(struct net *net) | 1123 | static void mroute_clean_tables(struct mr_table *mrt) |
879 | { | 1124 | { |
880 | int i; | 1125 | int i; |
881 | LIST_HEAD(list); | 1126 | LIST_HEAD(list); |
1127 | struct mfc_cache *c, *next; | ||
882 | 1128 | ||
883 | /* | 1129 | /* |
884 | * Shut down all active vif entries | 1130 | * Shut down all active vif entries |
885 | */ | 1131 | */ |
886 | for (i = 0; i < net->ipv4.maxvif; i++) { | 1132 | for (i = 0; i < mrt->maxvif; i++) { |
887 | if (!(net->ipv4.vif_table[i].flags&VIFF_STATIC)) | 1133 | if (!(mrt->vif_table[i].flags&VIFF_STATIC)) |
888 | vif_delete(net, i, 0, &list); | 1134 | vif_delete(mrt, i, 0, &list); |
889 | } | 1135 | } |
890 | unregister_netdevice_many(&list); | 1136 | unregister_netdevice_many(&list); |
891 | 1137 | ||
892 | /* | 1138 | /* |
893 | * Wipe the cache | 1139 | * Wipe the cache |
894 | */ | 1140 | */ |
895 | for (i=0; i<MFC_LINES; i++) { | 1141 | for (i = 0; i < MFC_LINES; i++) { |
896 | struct mfc_cache *c, **cp; | 1142 | list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[i], list) { |
897 | 1143 | if (c->mfc_flags&MFC_STATIC) | |
898 | cp = &net->ipv4.mfc_cache_array[i]; | ||
899 | while ((c = *cp) != NULL) { | ||
900 | if (c->mfc_flags&MFC_STATIC) { | ||
901 | cp = &c->next; | ||
902 | continue; | 1144 | continue; |
903 | } | ||
904 | write_lock_bh(&mrt_lock); | 1145 | write_lock_bh(&mrt_lock); |
905 | *cp = c->next; | 1146 | list_del(&c->list); |
906 | write_unlock_bh(&mrt_lock); | 1147 | write_unlock_bh(&mrt_lock); |
907 | 1148 | ||
908 | ipmr_cache_free(c); | 1149 | ipmr_cache_free(c); |
909 | } | 1150 | } |
910 | } | 1151 | } |
911 | 1152 | ||
912 | if (atomic_read(&net->ipv4.cache_resolve_queue_len) != 0) { | 1153 | if (atomic_read(&mrt->cache_resolve_queue_len) != 0) { |
913 | struct mfc_cache *c, **cp; | ||
914 | |||
915 | spin_lock_bh(&mfc_unres_lock); | 1154 | spin_lock_bh(&mfc_unres_lock); |
916 | cp = &mfc_unres_queue; | 1155 | list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) { |
917 | while ((c = *cp) != NULL) { | 1156 | list_del(&c->list); |
918 | if (!net_eq(mfc_net(c), net)) { | 1157 | ipmr_destroy_unres(mrt, c); |
919 | cp = &c->next; | ||
920 | continue; | ||
921 | } | ||
922 | *cp = c->next; | ||
923 | |||
924 | ipmr_destroy_unres(c); | ||
925 | } | 1158 | } |
926 | spin_unlock_bh(&mfc_unres_lock); | 1159 | spin_unlock_bh(&mfc_unres_lock); |
927 | } | 1160 | } |
@@ -930,16 +1163,19 @@ static void mroute_clean_tables(struct net *net) | |||
930 | static void mrtsock_destruct(struct sock *sk) | 1163 | static void mrtsock_destruct(struct sock *sk) |
931 | { | 1164 | { |
932 | struct net *net = sock_net(sk); | 1165 | struct net *net = sock_net(sk); |
1166 | struct mr_table *mrt; | ||
933 | 1167 | ||
934 | rtnl_lock(); | 1168 | rtnl_lock(); |
935 | if (sk == net->ipv4.mroute_sk) { | 1169 | ipmr_for_each_table(mrt, net) { |
936 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)--; | 1170 | if (sk == mrt->mroute_sk) { |
1171 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)--; | ||
937 | 1172 | ||
938 | write_lock_bh(&mrt_lock); | 1173 | write_lock_bh(&mrt_lock); |
939 | net->ipv4.mroute_sk = NULL; | 1174 | mrt->mroute_sk = NULL; |
940 | write_unlock_bh(&mrt_lock); | 1175 | write_unlock_bh(&mrt_lock); |
941 | 1176 | ||
942 | mroute_clean_tables(net); | 1177 | mroute_clean_tables(mrt); |
1178 | } | ||
943 | } | 1179 | } |
944 | rtnl_unlock(); | 1180 | rtnl_unlock(); |
945 | } | 1181 | } |
@@ -957,9 +1193,14 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
957 | struct vifctl vif; | 1193 | struct vifctl vif; |
958 | struct mfcctl mfc; | 1194 | struct mfcctl mfc; |
959 | struct net *net = sock_net(sk); | 1195 | struct net *net = sock_net(sk); |
1196 | struct mr_table *mrt; | ||
1197 | |||
1198 | mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); | ||
1199 | if (mrt == NULL) | ||
1200 | return -ENOENT; | ||
960 | 1201 | ||
961 | if (optname != MRT_INIT) { | 1202 | if (optname != MRT_INIT) { |
962 | if (sk != net->ipv4.mroute_sk && !capable(CAP_NET_ADMIN)) | 1203 | if (sk != mrt->mroute_sk && !capable(CAP_NET_ADMIN)) |
963 | return -EACCES; | 1204 | return -EACCES; |
964 | } | 1205 | } |
965 | 1206 | ||
@@ -972,7 +1213,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
972 | return -ENOPROTOOPT; | 1213 | return -ENOPROTOOPT; |
973 | 1214 | ||
974 | rtnl_lock(); | 1215 | rtnl_lock(); |
975 | if (net->ipv4.mroute_sk) { | 1216 | if (mrt->mroute_sk) { |
976 | rtnl_unlock(); | 1217 | rtnl_unlock(); |
977 | return -EADDRINUSE; | 1218 | return -EADDRINUSE; |
978 | } | 1219 | } |
@@ -980,7 +1221,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
980 | ret = ip_ra_control(sk, 1, mrtsock_destruct); | 1221 | ret = ip_ra_control(sk, 1, mrtsock_destruct); |
981 | if (ret == 0) { | 1222 | if (ret == 0) { |
982 | write_lock_bh(&mrt_lock); | 1223 | write_lock_bh(&mrt_lock); |
983 | net->ipv4.mroute_sk = sk; | 1224 | mrt->mroute_sk = sk; |
984 | write_unlock_bh(&mrt_lock); | 1225 | write_unlock_bh(&mrt_lock); |
985 | 1226 | ||
986 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)++; | 1227 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)++; |
@@ -988,7 +1229,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
988 | rtnl_unlock(); | 1229 | rtnl_unlock(); |
989 | return ret; | 1230 | return ret; |
990 | case MRT_DONE: | 1231 | case MRT_DONE: |
991 | if (sk != net->ipv4.mroute_sk) | 1232 | if (sk != mrt->mroute_sk) |
992 | return -EACCES; | 1233 | return -EACCES; |
993 | return ip_ra_control(sk, 0, NULL); | 1234 | return ip_ra_control(sk, 0, NULL); |
994 | case MRT_ADD_VIF: | 1235 | case MRT_ADD_VIF: |
@@ -1001,9 +1242,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
1001 | return -ENFILE; | 1242 | return -ENFILE; |
1002 | rtnl_lock(); | 1243 | rtnl_lock(); |
1003 | if (optname == MRT_ADD_VIF) { | 1244 | if (optname == MRT_ADD_VIF) { |
1004 | ret = vif_add(net, &vif, sk == net->ipv4.mroute_sk); | 1245 | ret = vif_add(net, mrt, &vif, sk == mrt->mroute_sk); |
1005 | } else { | 1246 | } else { |
1006 | ret = vif_delete(net, vif.vifc_vifi, 0, NULL); | 1247 | ret = vif_delete(mrt, vif.vifc_vifi, 0, NULL); |
1007 | } | 1248 | } |
1008 | rtnl_unlock(); | 1249 | rtnl_unlock(); |
1009 | return ret; | 1250 | return ret; |
@@ -1020,9 +1261,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
1020 | return -EFAULT; | 1261 | return -EFAULT; |
1021 | rtnl_lock(); | 1262 | rtnl_lock(); |
1022 | if (optname == MRT_DEL_MFC) | 1263 | if (optname == MRT_DEL_MFC) |
1023 | ret = ipmr_mfc_delete(net, &mfc); | 1264 | ret = ipmr_mfc_delete(mrt, &mfc); |
1024 | else | 1265 | else |
1025 | ret = ipmr_mfc_add(net, &mfc, sk == net->ipv4.mroute_sk); | 1266 | ret = ipmr_mfc_add(net, mrt, &mfc, sk == mrt->mroute_sk); |
1026 | rtnl_unlock(); | 1267 | rtnl_unlock(); |
1027 | return ret; | 1268 | return ret; |
1028 | /* | 1269 | /* |
@@ -1033,7 +1274,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
1033 | int v; | 1274 | int v; |
1034 | if (get_user(v,(int __user *)optval)) | 1275 | if (get_user(v,(int __user *)optval)) |
1035 | return -EFAULT; | 1276 | return -EFAULT; |
1036 | net->ipv4.mroute_do_assert = (v) ? 1 : 0; | 1277 | mrt->mroute_do_assert = (v) ? 1 : 0; |
1037 | return 0; | 1278 | return 0; |
1038 | } | 1279 | } |
1039 | #ifdef CONFIG_IP_PIMSM | 1280 | #ifdef CONFIG_IP_PIMSM |
@@ -1047,14 +1288,35 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
1047 | 1288 | ||
1048 | rtnl_lock(); | 1289 | rtnl_lock(); |
1049 | ret = 0; | 1290 | ret = 0; |
1050 | if (v != net->ipv4.mroute_do_pim) { | 1291 | if (v != mrt->mroute_do_pim) { |
1051 | net->ipv4.mroute_do_pim = v; | 1292 | mrt->mroute_do_pim = v; |
1052 | net->ipv4.mroute_do_assert = v; | 1293 | mrt->mroute_do_assert = v; |
1053 | } | 1294 | } |
1054 | rtnl_unlock(); | 1295 | rtnl_unlock(); |
1055 | return ret; | 1296 | return ret; |
1056 | } | 1297 | } |
1057 | #endif | 1298 | #endif |
1299 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES | ||
1300 | case MRT_TABLE: | ||
1301 | { | ||
1302 | u32 v; | ||
1303 | |||
1304 | if (optlen != sizeof(u32)) | ||
1305 | return -EINVAL; | ||
1306 | if (get_user(v, (u32 __user *)optval)) | ||
1307 | return -EFAULT; | ||
1308 | if (sk == mrt->mroute_sk) | ||
1309 | return -EBUSY; | ||
1310 | |||
1311 | rtnl_lock(); | ||
1312 | ret = 0; | ||
1313 | if (!ipmr_new_table(net, v)) | ||
1314 | ret = -ENOMEM; | ||
1315 | raw_sk(sk)->ipmr_table = v; | ||
1316 | rtnl_unlock(); | ||
1317 | return ret; | ||
1318 | } | ||
1319 | #endif | ||
1058 | /* | 1320 | /* |
1059 | * Spurious command, or MRT_VERSION which you cannot | 1321 | * Spurious command, or MRT_VERSION which you cannot |
1060 | * set. | 1322 | * set. |
@@ -1073,6 +1335,11 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int | |||
1073 | int olr; | 1335 | int olr; |
1074 | int val; | 1336 | int val; |
1075 | struct net *net = sock_net(sk); | 1337 | struct net *net = sock_net(sk); |
1338 | struct mr_table *mrt; | ||
1339 | |||
1340 | mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); | ||
1341 | if (mrt == NULL) | ||
1342 | return -ENOENT; | ||
1076 | 1343 | ||
1077 | if (optname != MRT_VERSION && | 1344 | if (optname != MRT_VERSION && |
1078 | #ifdef CONFIG_IP_PIMSM | 1345 | #ifdef CONFIG_IP_PIMSM |
@@ -1094,10 +1361,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int | |||
1094 | val = 0x0305; | 1361 | val = 0x0305; |
1095 | #ifdef CONFIG_IP_PIMSM | 1362 | #ifdef CONFIG_IP_PIMSM |
1096 | else if (optname == MRT_PIM) | 1363 | else if (optname == MRT_PIM) |
1097 | val = net->ipv4.mroute_do_pim; | 1364 | val = mrt->mroute_do_pim; |
1098 | #endif | 1365 | #endif |
1099 | else | 1366 | else |
1100 | val = net->ipv4.mroute_do_assert; | 1367 | val = mrt->mroute_do_assert; |
1101 | if (copy_to_user(optval, &val, olr)) | 1368 | if (copy_to_user(optval, &val, olr)) |
1102 | return -EFAULT; | 1369 | return -EFAULT; |
1103 | return 0; | 1370 | return 0; |
@@ -1114,16 +1381,21 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1114 | struct vif_device *vif; | 1381 | struct vif_device *vif; |
1115 | struct mfc_cache *c; | 1382 | struct mfc_cache *c; |
1116 | struct net *net = sock_net(sk); | 1383 | struct net *net = sock_net(sk); |
1384 | struct mr_table *mrt; | ||
1385 | |||
1386 | mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); | ||
1387 | if (mrt == NULL) | ||
1388 | return -ENOENT; | ||
1117 | 1389 | ||
1118 | switch (cmd) { | 1390 | switch (cmd) { |
1119 | case SIOCGETVIFCNT: | 1391 | case SIOCGETVIFCNT: |
1120 | if (copy_from_user(&vr, arg, sizeof(vr))) | 1392 | if (copy_from_user(&vr, arg, sizeof(vr))) |
1121 | return -EFAULT; | 1393 | return -EFAULT; |
1122 | if (vr.vifi >= net->ipv4.maxvif) | 1394 | if (vr.vifi >= mrt->maxvif) |
1123 | return -EINVAL; | 1395 | return -EINVAL; |
1124 | read_lock(&mrt_lock); | 1396 | read_lock(&mrt_lock); |
1125 | vif = &net->ipv4.vif_table[vr.vifi]; | 1397 | vif = &mrt->vif_table[vr.vifi]; |
1126 | if (VIF_EXISTS(net, vr.vifi)) { | 1398 | if (VIF_EXISTS(mrt, vr.vifi)) { |
1127 | vr.icount = vif->pkt_in; | 1399 | vr.icount = vif->pkt_in; |
1128 | vr.ocount = vif->pkt_out; | 1400 | vr.ocount = vif->pkt_out; |
1129 | vr.ibytes = vif->bytes_in; | 1401 | vr.ibytes = vif->bytes_in; |
@@ -1141,7 +1413,7 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1141 | return -EFAULT; | 1413 | return -EFAULT; |
1142 | 1414 | ||
1143 | read_lock(&mrt_lock); | 1415 | read_lock(&mrt_lock); |
1144 | c = ipmr_cache_find(net, sr.src.s_addr, sr.grp.s_addr); | 1416 | c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr); |
1145 | if (c) { | 1417 | if (c) { |
1146 | sr.pktcnt = c->mfc_un.res.pkt; | 1418 | sr.pktcnt = c->mfc_un.res.pkt; |
1147 | sr.bytecnt = c->mfc_un.res.bytes; | 1419 | sr.bytecnt = c->mfc_un.res.bytes; |
@@ -1164,16 +1436,20 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v | |||
1164 | { | 1436 | { |
1165 | struct net_device *dev = ptr; | 1437 | struct net_device *dev = ptr; |
1166 | struct net *net = dev_net(dev); | 1438 | struct net *net = dev_net(dev); |
1439 | struct mr_table *mrt; | ||
1167 | struct vif_device *v; | 1440 | struct vif_device *v; |
1168 | int ct; | 1441 | int ct; |
1169 | LIST_HEAD(list); | 1442 | LIST_HEAD(list); |
1170 | 1443 | ||
1171 | if (event != NETDEV_UNREGISTER) | 1444 | if (event != NETDEV_UNREGISTER) |
1172 | return NOTIFY_DONE; | 1445 | return NOTIFY_DONE; |
1173 | v = &net->ipv4.vif_table[0]; | 1446 | |
1174 | for (ct = 0; ct < net->ipv4.maxvif; ct++, v++) { | 1447 | ipmr_for_each_table(mrt, net) { |
1175 | if (v->dev == dev) | 1448 | v = &mrt->vif_table[0]; |
1176 | vif_delete(net, ct, 1, &list); | 1449 | for (ct = 0; ct < mrt->maxvif; ct++, v++) { |
1450 | if (v->dev == dev) | ||
1451 | vif_delete(mrt, ct, 1, &list); | ||
1452 | } | ||
1177 | } | 1453 | } |
1178 | unregister_netdevice_many(&list); | 1454 | unregister_netdevice_many(&list); |
1179 | return NOTIFY_DONE; | 1455 | return NOTIFY_DONE; |
@@ -1232,11 +1508,11 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) | |||
1232 | * Processing handlers for ipmr_forward | 1508 | * Processing handlers for ipmr_forward |
1233 | */ | 1509 | */ |
1234 | 1510 | ||
1235 | static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | 1511 | static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, |
1512 | struct sk_buff *skb, struct mfc_cache *c, int vifi) | ||
1236 | { | 1513 | { |
1237 | struct net *net = mfc_net(c); | ||
1238 | const struct iphdr *iph = ip_hdr(skb); | 1514 | const struct iphdr *iph = ip_hdr(skb); |
1239 | struct vif_device *vif = &net->ipv4.vif_table[vifi]; | 1515 | struct vif_device *vif = &mrt->vif_table[vifi]; |
1240 | struct net_device *dev; | 1516 | struct net_device *dev; |
1241 | struct rtable *rt; | 1517 | struct rtable *rt; |
1242 | int encap = 0; | 1518 | int encap = 0; |
@@ -1250,7 +1526,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | |||
1250 | vif->bytes_out += skb->len; | 1526 | vif->bytes_out += skb->len; |
1251 | vif->dev->stats.tx_bytes += skb->len; | 1527 | vif->dev->stats.tx_bytes += skb->len; |
1252 | vif->dev->stats.tx_packets++; | 1528 | vif->dev->stats.tx_packets++; |
1253 | ipmr_cache_report(net, skb, vifi, IGMPMSG_WHOLEPKT); | 1529 | ipmr_cache_report(mrt, skb, vifi, IGMPMSG_WHOLEPKT); |
1254 | goto out_free; | 1530 | goto out_free; |
1255 | } | 1531 | } |
1256 | #endif | 1532 | #endif |
@@ -1324,21 +1600,20 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) | |||
1324 | * not mrouter) cannot join to more than one interface - it will | 1600 | * not mrouter) cannot join to more than one interface - it will |
1325 | * result in receiving multiple packets. | 1601 | * result in receiving multiple packets. |
1326 | */ | 1602 | */ |
1327 | NF_HOOK(PF_INET, NF_INET_FORWARD, skb, skb->dev, dev, | 1603 | NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev, dev, |
1328 | ipmr_forward_finish); | 1604 | ipmr_forward_finish); |
1329 | return; | 1605 | return; |
1330 | 1606 | ||
1331 | out_free: | 1607 | out_free: |
1332 | kfree_skb(skb); | 1608 | kfree_skb(skb); |
1333 | return; | ||
1334 | } | 1609 | } |
1335 | 1610 | ||
1336 | static int ipmr_find_vif(struct net_device *dev) | 1611 | static int ipmr_find_vif(struct mr_table *mrt, struct net_device *dev) |
1337 | { | 1612 | { |
1338 | struct net *net = dev_net(dev); | ||
1339 | int ct; | 1613 | int ct; |
1340 | for (ct = net->ipv4.maxvif-1; ct >= 0; ct--) { | 1614 | |
1341 | if (net->ipv4.vif_table[ct].dev == dev) | 1615 | for (ct = mrt->maxvif-1; ct >= 0; ct--) { |
1616 | if (mrt->vif_table[ct].dev == dev) | ||
1342 | break; | 1617 | break; |
1343 | } | 1618 | } |
1344 | return ct; | 1619 | return ct; |
@@ -1346,11 +1621,12 @@ static int ipmr_find_vif(struct net_device *dev) | |||
1346 | 1621 | ||
1347 | /* "local" means that we should preserve one skb (for local delivery) */ | 1622 | /* "local" means that we should preserve one skb (for local delivery) */ |
1348 | 1623 | ||
1349 | static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local) | 1624 | static int ip_mr_forward(struct net *net, struct mr_table *mrt, |
1625 | struct sk_buff *skb, struct mfc_cache *cache, | ||
1626 | int local) | ||
1350 | { | 1627 | { |
1351 | int psend = -1; | 1628 | int psend = -1; |
1352 | int vif, ct; | 1629 | int vif, ct; |
1353 | struct net *net = mfc_net(cache); | ||
1354 | 1630 | ||
1355 | vif = cache->mfc_parent; | 1631 | vif = cache->mfc_parent; |
1356 | cache->mfc_un.res.pkt++; | 1632 | cache->mfc_un.res.pkt++; |
@@ -1359,7 +1635,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local | |||
1359 | /* | 1635 | /* |
1360 | * Wrong interface: drop packet and (maybe) send PIM assert. | 1636 | * Wrong interface: drop packet and (maybe) send PIM assert. |
1361 | */ | 1637 | */ |
1362 | if (net->ipv4.vif_table[vif].dev != skb->dev) { | 1638 | if (mrt->vif_table[vif].dev != skb->dev) { |
1363 | int true_vifi; | 1639 | int true_vifi; |
1364 | 1640 | ||
1365 | if (skb_rtable(skb)->fl.iif == 0) { | 1641 | if (skb_rtable(skb)->fl.iif == 0) { |
@@ -1378,26 +1654,26 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local | |||
1378 | } | 1654 | } |
1379 | 1655 | ||
1380 | cache->mfc_un.res.wrong_if++; | 1656 | cache->mfc_un.res.wrong_if++; |
1381 | true_vifi = ipmr_find_vif(skb->dev); | 1657 | true_vifi = ipmr_find_vif(mrt, skb->dev); |
1382 | 1658 | ||
1383 | if (true_vifi >= 0 && net->ipv4.mroute_do_assert && | 1659 | if (true_vifi >= 0 && mrt->mroute_do_assert && |
1384 | /* pimsm uses asserts, when switching from RPT to SPT, | 1660 | /* pimsm uses asserts, when switching from RPT to SPT, |
1385 | so that we cannot check that packet arrived on an oif. | 1661 | so that we cannot check that packet arrived on an oif. |
1386 | It is bad, but otherwise we would need to move pretty | 1662 | It is bad, but otherwise we would need to move pretty |
1387 | large chunk of pimd to kernel. Ough... --ANK | 1663 | large chunk of pimd to kernel. Ough... --ANK |
1388 | */ | 1664 | */ |
1389 | (net->ipv4.mroute_do_pim || | 1665 | (mrt->mroute_do_pim || |
1390 | cache->mfc_un.res.ttls[true_vifi] < 255) && | 1666 | cache->mfc_un.res.ttls[true_vifi] < 255) && |
1391 | time_after(jiffies, | 1667 | time_after(jiffies, |
1392 | cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { | 1668 | cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { |
1393 | cache->mfc_un.res.last_assert = jiffies; | 1669 | cache->mfc_un.res.last_assert = jiffies; |
1394 | ipmr_cache_report(net, skb, true_vifi, IGMPMSG_WRONGVIF); | 1670 | ipmr_cache_report(mrt, skb, true_vifi, IGMPMSG_WRONGVIF); |
1395 | } | 1671 | } |
1396 | goto dont_forward; | 1672 | goto dont_forward; |
1397 | } | 1673 | } |
1398 | 1674 | ||
1399 | net->ipv4.vif_table[vif].pkt_in++; | 1675 | mrt->vif_table[vif].pkt_in++; |
1400 | net->ipv4.vif_table[vif].bytes_in += skb->len; | 1676 | mrt->vif_table[vif].bytes_in += skb->len; |
1401 | 1677 | ||
1402 | /* | 1678 | /* |
1403 | * Forward the frame | 1679 | * Forward the frame |
@@ -1407,7 +1683,8 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local | |||
1407 | if (psend != -1) { | 1683 | if (psend != -1) { |
1408 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 1684 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
1409 | if (skb2) | 1685 | if (skb2) |
1410 | ipmr_queue_xmit(skb2, cache, psend); | 1686 | ipmr_queue_xmit(net, mrt, skb2, cache, |
1687 | psend); | ||
1411 | } | 1688 | } |
1412 | psend = ct; | 1689 | psend = ct; |
1413 | } | 1690 | } |
@@ -1416,9 +1693,9 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local | |||
1416 | if (local) { | 1693 | if (local) { |
1417 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 1694 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
1418 | if (skb2) | 1695 | if (skb2) |
1419 | ipmr_queue_xmit(skb2, cache, psend); | 1696 | ipmr_queue_xmit(net, mrt, skb2, cache, psend); |
1420 | } else { | 1697 | } else { |
1421 | ipmr_queue_xmit(skb, cache, psend); | 1698 | ipmr_queue_xmit(net, mrt, skb, cache, psend); |
1422 | return 0; | 1699 | return 0; |
1423 | } | 1700 | } |
1424 | } | 1701 | } |
@@ -1439,6 +1716,8 @@ int ip_mr_input(struct sk_buff *skb) | |||
1439 | struct mfc_cache *cache; | 1716 | struct mfc_cache *cache; |
1440 | struct net *net = dev_net(skb->dev); | 1717 | struct net *net = dev_net(skb->dev); |
1441 | int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL; | 1718 | int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL; |
1719 | struct mr_table *mrt; | ||
1720 | int err; | ||
1442 | 1721 | ||
1443 | /* Packet is looped back after forward, it should not be | 1722 | /* Packet is looped back after forward, it should not be |
1444 | forwarded second time, but still can be delivered locally. | 1723 | forwarded second time, but still can be delivered locally. |
@@ -1446,6 +1725,10 @@ int ip_mr_input(struct sk_buff *skb) | |||
1446 | if (IPCB(skb)->flags&IPSKB_FORWARDED) | 1725 | if (IPCB(skb)->flags&IPSKB_FORWARDED) |
1447 | goto dont_forward; | 1726 | goto dont_forward; |
1448 | 1727 | ||
1728 | err = ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt); | ||
1729 | if (err < 0) | ||
1730 | return err; | ||
1731 | |||
1449 | if (!local) { | 1732 | if (!local) { |
1450 | if (IPCB(skb)->opt.router_alert) { | 1733 | if (IPCB(skb)->opt.router_alert) { |
1451 | if (ip_call_ra_chain(skb)) | 1734 | if (ip_call_ra_chain(skb)) |
@@ -1458,9 +1741,9 @@ int ip_mr_input(struct sk_buff *skb) | |||
1458 | that we can forward NO IGMP messages. | 1741 | that we can forward NO IGMP messages. |
1459 | */ | 1742 | */ |
1460 | read_lock(&mrt_lock); | 1743 | read_lock(&mrt_lock); |
1461 | if (net->ipv4.mroute_sk) { | 1744 | if (mrt->mroute_sk) { |
1462 | nf_reset(skb); | 1745 | nf_reset(skb); |
1463 | raw_rcv(net->ipv4.mroute_sk, skb); | 1746 | raw_rcv(mrt->mroute_sk, skb); |
1464 | read_unlock(&mrt_lock); | 1747 | read_unlock(&mrt_lock); |
1465 | return 0; | 1748 | return 0; |
1466 | } | 1749 | } |
@@ -1469,7 +1752,7 @@ int ip_mr_input(struct sk_buff *skb) | |||
1469 | } | 1752 | } |
1470 | 1753 | ||
1471 | read_lock(&mrt_lock); | 1754 | read_lock(&mrt_lock); |
1472 | cache = ipmr_cache_find(net, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); | 1755 | cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); |
1473 | 1756 | ||
1474 | /* | 1757 | /* |
1475 | * No usable cache entry | 1758 | * No usable cache entry |
@@ -1487,19 +1770,19 @@ int ip_mr_input(struct sk_buff *skb) | |||
1487 | skb = skb2; | 1770 | skb = skb2; |
1488 | } | 1771 | } |
1489 | 1772 | ||
1490 | vif = ipmr_find_vif(skb->dev); | 1773 | vif = ipmr_find_vif(mrt, skb->dev); |
1491 | if (vif >= 0) { | 1774 | if (vif >= 0) { |
1492 | int err = ipmr_cache_unresolved(net, vif, skb); | 1775 | int err2 = ipmr_cache_unresolved(mrt, vif, skb); |
1493 | read_unlock(&mrt_lock); | 1776 | read_unlock(&mrt_lock); |
1494 | 1777 | ||
1495 | return err; | 1778 | return err2; |
1496 | } | 1779 | } |
1497 | read_unlock(&mrt_lock); | 1780 | read_unlock(&mrt_lock); |
1498 | kfree_skb(skb); | 1781 | kfree_skb(skb); |
1499 | return -ENODEV; | 1782 | return -ENODEV; |
1500 | } | 1783 | } |
1501 | 1784 | ||
1502 | ip_mr_forward(skb, cache, local); | 1785 | ip_mr_forward(net, mrt, skb, cache, local); |
1503 | 1786 | ||
1504 | read_unlock(&mrt_lock); | 1787 | read_unlock(&mrt_lock); |
1505 | 1788 | ||
@@ -1516,11 +1799,11 @@ dont_forward: | |||
1516 | } | 1799 | } |
1517 | 1800 | ||
1518 | #ifdef CONFIG_IP_PIMSM | 1801 | #ifdef CONFIG_IP_PIMSM |
1519 | static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) | 1802 | static int __pim_rcv(struct mr_table *mrt, struct sk_buff *skb, |
1803 | unsigned int pimlen) | ||
1520 | { | 1804 | { |
1521 | struct net_device *reg_dev = NULL; | 1805 | struct net_device *reg_dev = NULL; |
1522 | struct iphdr *encap; | 1806 | struct iphdr *encap; |
1523 | struct net *net = dev_net(skb->dev); | ||
1524 | 1807 | ||
1525 | encap = (struct iphdr *)(skb_transport_header(skb) + pimlen); | 1808 | encap = (struct iphdr *)(skb_transport_header(skb) + pimlen); |
1526 | /* | 1809 | /* |
@@ -1535,8 +1818,8 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) | |||
1535 | return 1; | 1818 | return 1; |
1536 | 1819 | ||
1537 | read_lock(&mrt_lock); | 1820 | read_lock(&mrt_lock); |
1538 | if (net->ipv4.mroute_reg_vif_num >= 0) | 1821 | if (mrt->mroute_reg_vif_num >= 0) |
1539 | reg_dev = net->ipv4.vif_table[net->ipv4.mroute_reg_vif_num].dev; | 1822 | reg_dev = mrt->vif_table[mrt->mroute_reg_vif_num].dev; |
1540 | if (reg_dev) | 1823 | if (reg_dev) |
1541 | dev_hold(reg_dev); | 1824 | dev_hold(reg_dev); |
1542 | read_unlock(&mrt_lock); | 1825 | read_unlock(&mrt_lock); |
@@ -1547,14 +1830,12 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) | |||
1547 | skb->mac_header = skb->network_header; | 1830 | skb->mac_header = skb->network_header; |
1548 | skb_pull(skb, (u8*)encap - skb->data); | 1831 | skb_pull(skb, (u8*)encap - skb->data); |
1549 | skb_reset_network_header(skb); | 1832 | skb_reset_network_header(skb); |
1550 | skb->dev = reg_dev; | ||
1551 | skb->protocol = htons(ETH_P_IP); | 1833 | skb->protocol = htons(ETH_P_IP); |
1552 | skb->ip_summed = 0; | 1834 | skb->ip_summed = 0; |
1553 | skb->pkt_type = PACKET_HOST; | 1835 | skb->pkt_type = PACKET_HOST; |
1554 | skb_dst_drop(skb); | 1836 | |
1555 | reg_dev->stats.rx_bytes += skb->len; | 1837 | skb_tunnel_rx(skb, reg_dev); |
1556 | reg_dev->stats.rx_packets++; | 1838 | |
1557 | nf_reset(skb); | ||
1558 | netif_rx(skb); | 1839 | netif_rx(skb); |
1559 | dev_put(reg_dev); | 1840 | dev_put(reg_dev); |
1560 | 1841 | ||
@@ -1571,17 +1852,21 @@ int pim_rcv_v1(struct sk_buff * skb) | |||
1571 | { | 1852 | { |
1572 | struct igmphdr *pim; | 1853 | struct igmphdr *pim; |
1573 | struct net *net = dev_net(skb->dev); | 1854 | struct net *net = dev_net(skb->dev); |
1855 | struct mr_table *mrt; | ||
1574 | 1856 | ||
1575 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr))) | 1857 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr))) |
1576 | goto drop; | 1858 | goto drop; |
1577 | 1859 | ||
1578 | pim = igmp_hdr(skb); | 1860 | pim = igmp_hdr(skb); |
1579 | 1861 | ||
1580 | if (!net->ipv4.mroute_do_pim || | 1862 | if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0) |
1863 | goto drop; | ||
1864 | |||
1865 | if (!mrt->mroute_do_pim || | ||
1581 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) | 1866 | pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) |
1582 | goto drop; | 1867 | goto drop; |
1583 | 1868 | ||
1584 | if (__pim_rcv(skb, sizeof(*pim))) { | 1869 | if (__pim_rcv(mrt, skb, sizeof(*pim))) { |
1585 | drop: | 1870 | drop: |
1586 | kfree_skb(skb); | 1871 | kfree_skb(skb); |
1587 | } | 1872 | } |
@@ -1593,6 +1878,8 @@ drop: | |||
1593 | static int pim_rcv(struct sk_buff * skb) | 1878 | static int pim_rcv(struct sk_buff * skb) |
1594 | { | 1879 | { |
1595 | struct pimreghdr *pim; | 1880 | struct pimreghdr *pim; |
1881 | struct net *net = dev_net(skb->dev); | ||
1882 | struct mr_table *mrt; | ||
1596 | 1883 | ||
1597 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr))) | 1884 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(struct iphdr))) |
1598 | goto drop; | 1885 | goto drop; |
@@ -1604,7 +1891,10 @@ static int pim_rcv(struct sk_buff * skb) | |||
1604 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) | 1891 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) |
1605 | goto drop; | 1892 | goto drop; |
1606 | 1893 | ||
1607 | if (__pim_rcv(skb, sizeof(*pim))) { | 1894 | if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0) |
1895 | goto drop; | ||
1896 | |||
1897 | if (__pim_rcv(mrt, skb, sizeof(*pim))) { | ||
1608 | drop: | 1898 | drop: |
1609 | kfree_skb(skb); | 1899 | kfree_skb(skb); |
1610 | } | 1900 | } |
@@ -1612,12 +1902,11 @@ drop: | |||
1612 | } | 1902 | } |
1613 | #endif | 1903 | #endif |
1614 | 1904 | ||
1615 | static int | 1905 | static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, |
1616 | ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) | 1906 | struct mfc_cache *c, struct rtmsg *rtm) |
1617 | { | 1907 | { |
1618 | int ct; | 1908 | int ct; |
1619 | struct rtnexthop *nhp; | 1909 | struct rtnexthop *nhp; |
1620 | struct net *net = mfc_net(c); | ||
1621 | u8 *b = skb_tail_pointer(skb); | 1910 | u8 *b = skb_tail_pointer(skb); |
1622 | struct rtattr *mp_head; | 1911 | struct rtattr *mp_head; |
1623 | 1912 | ||
@@ -1625,19 +1914,19 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) | |||
1625 | if (c->mfc_parent > MAXVIFS) | 1914 | if (c->mfc_parent > MAXVIFS) |
1626 | return -ENOENT; | 1915 | return -ENOENT; |
1627 | 1916 | ||
1628 | if (VIF_EXISTS(net, c->mfc_parent)) | 1917 | if (VIF_EXISTS(mrt, c->mfc_parent)) |
1629 | RTA_PUT(skb, RTA_IIF, 4, &net->ipv4.vif_table[c->mfc_parent].dev->ifindex); | 1918 | RTA_PUT(skb, RTA_IIF, 4, &mrt->vif_table[c->mfc_parent].dev->ifindex); |
1630 | 1919 | ||
1631 | mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); | 1920 | mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); |
1632 | 1921 | ||
1633 | for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { | 1922 | for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { |
1634 | if (VIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) { | 1923 | if (VIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) { |
1635 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) | 1924 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) |
1636 | goto rtattr_failure; | 1925 | goto rtattr_failure; |
1637 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); | 1926 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); |
1638 | nhp->rtnh_flags = 0; | 1927 | nhp->rtnh_flags = 0; |
1639 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; | 1928 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; |
1640 | nhp->rtnh_ifindex = net->ipv4.vif_table[ct].dev->ifindex; | 1929 | nhp->rtnh_ifindex = mrt->vif_table[ct].dev->ifindex; |
1641 | nhp->rtnh_len = sizeof(*nhp); | 1930 | nhp->rtnh_len = sizeof(*nhp); |
1642 | } | 1931 | } |
1643 | } | 1932 | } |
@@ -1655,11 +1944,16 @@ int ipmr_get_route(struct net *net, | |||
1655 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) | 1944 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) |
1656 | { | 1945 | { |
1657 | int err; | 1946 | int err; |
1947 | struct mr_table *mrt; | ||
1658 | struct mfc_cache *cache; | 1948 | struct mfc_cache *cache; |
1659 | struct rtable *rt = skb_rtable(skb); | 1949 | struct rtable *rt = skb_rtable(skb); |
1660 | 1950 | ||
1951 | mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); | ||
1952 | if (mrt == NULL) | ||
1953 | return -ENOENT; | ||
1954 | |||
1661 | read_lock(&mrt_lock); | 1955 | read_lock(&mrt_lock); |
1662 | cache = ipmr_cache_find(net, rt->rt_src, rt->rt_dst); | 1956 | cache = ipmr_cache_find(mrt, rt->rt_src, rt->rt_dst); |
1663 | 1957 | ||
1664 | if (cache == NULL) { | 1958 | if (cache == NULL) { |
1665 | struct sk_buff *skb2; | 1959 | struct sk_buff *skb2; |
@@ -1673,7 +1967,7 @@ int ipmr_get_route(struct net *net, | |||
1673 | } | 1967 | } |
1674 | 1968 | ||
1675 | dev = skb->dev; | 1969 | dev = skb->dev; |
1676 | if (dev == NULL || (vif = ipmr_find_vif(dev)) < 0) { | 1970 | if (dev == NULL || (vif = ipmr_find_vif(mrt, dev)) < 0) { |
1677 | read_unlock(&mrt_lock); | 1971 | read_unlock(&mrt_lock); |
1678 | return -ENODEV; | 1972 | return -ENODEV; |
1679 | } | 1973 | } |
@@ -1690,24 +1984,107 @@ int ipmr_get_route(struct net *net, | |||
1690 | iph->saddr = rt->rt_src; | 1984 | iph->saddr = rt->rt_src; |
1691 | iph->daddr = rt->rt_dst; | 1985 | iph->daddr = rt->rt_dst; |
1692 | iph->version = 0; | 1986 | iph->version = 0; |
1693 | err = ipmr_cache_unresolved(net, vif, skb2); | 1987 | err = ipmr_cache_unresolved(mrt, vif, skb2); |
1694 | read_unlock(&mrt_lock); | 1988 | read_unlock(&mrt_lock); |
1695 | return err; | 1989 | return err; |
1696 | } | 1990 | } |
1697 | 1991 | ||
1698 | if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) | 1992 | if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) |
1699 | cache->mfc_flags |= MFC_NOTIFY; | 1993 | cache->mfc_flags |= MFC_NOTIFY; |
1700 | err = ipmr_fill_mroute(skb, cache, rtm); | 1994 | err = __ipmr_fill_mroute(mrt, skb, cache, rtm); |
1701 | read_unlock(&mrt_lock); | 1995 | read_unlock(&mrt_lock); |
1702 | return err; | 1996 | return err; |
1703 | } | 1997 | } |
1704 | 1998 | ||
1999 | static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, | ||
2000 | u32 pid, u32 seq, struct mfc_cache *c) | ||
2001 | { | ||
2002 | struct nlmsghdr *nlh; | ||
2003 | struct rtmsg *rtm; | ||
2004 | |||
2005 | nlh = nlmsg_put(skb, pid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI); | ||
2006 | if (nlh == NULL) | ||
2007 | return -EMSGSIZE; | ||
2008 | |||
2009 | rtm = nlmsg_data(nlh); | ||
2010 | rtm->rtm_family = RTNL_FAMILY_IPMR; | ||
2011 | rtm->rtm_dst_len = 32; | ||
2012 | rtm->rtm_src_len = 32; | ||
2013 | rtm->rtm_tos = 0; | ||
2014 | rtm->rtm_table = mrt->id; | ||
2015 | NLA_PUT_U32(skb, RTA_TABLE, mrt->id); | ||
2016 | rtm->rtm_type = RTN_MULTICAST; | ||
2017 | rtm->rtm_scope = RT_SCOPE_UNIVERSE; | ||
2018 | rtm->rtm_protocol = RTPROT_UNSPEC; | ||
2019 | rtm->rtm_flags = 0; | ||
2020 | |||
2021 | NLA_PUT_BE32(skb, RTA_SRC, c->mfc_origin); | ||
2022 | NLA_PUT_BE32(skb, RTA_DST, c->mfc_mcastgrp); | ||
2023 | |||
2024 | if (__ipmr_fill_mroute(mrt, skb, c, rtm) < 0) | ||
2025 | goto nla_put_failure; | ||
2026 | |||
2027 | return nlmsg_end(skb, nlh); | ||
2028 | |||
2029 | nla_put_failure: | ||
2030 | nlmsg_cancel(skb, nlh); | ||
2031 | return -EMSGSIZE; | ||
2032 | } | ||
2033 | |||
2034 | static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) | ||
2035 | { | ||
2036 | struct net *net = sock_net(skb->sk); | ||
2037 | struct mr_table *mrt; | ||
2038 | struct mfc_cache *mfc; | ||
2039 | unsigned int t = 0, s_t; | ||
2040 | unsigned int h = 0, s_h; | ||
2041 | unsigned int e = 0, s_e; | ||
2042 | |||
2043 | s_t = cb->args[0]; | ||
2044 | s_h = cb->args[1]; | ||
2045 | s_e = cb->args[2]; | ||
2046 | |||
2047 | read_lock(&mrt_lock); | ||
2048 | ipmr_for_each_table(mrt, net) { | ||
2049 | if (t < s_t) | ||
2050 | goto next_table; | ||
2051 | if (t > s_t) | ||
2052 | s_h = 0; | ||
2053 | for (h = s_h; h < MFC_LINES; h++) { | ||
2054 | list_for_each_entry(mfc, &mrt->mfc_cache_array[h], list) { | ||
2055 | if (e < s_e) | ||
2056 | goto next_entry; | ||
2057 | if (ipmr_fill_mroute(mrt, skb, | ||
2058 | NETLINK_CB(cb->skb).pid, | ||
2059 | cb->nlh->nlmsg_seq, | ||
2060 | mfc) < 0) | ||
2061 | goto done; | ||
2062 | next_entry: | ||
2063 | e++; | ||
2064 | } | ||
2065 | e = s_e = 0; | ||
2066 | } | ||
2067 | s_h = 0; | ||
2068 | next_table: | ||
2069 | t++; | ||
2070 | } | ||
2071 | done: | ||
2072 | read_unlock(&mrt_lock); | ||
2073 | |||
2074 | cb->args[2] = e; | ||
2075 | cb->args[1] = h; | ||
2076 | cb->args[0] = t; | ||
2077 | |||
2078 | return skb->len; | ||
2079 | } | ||
2080 | |||
1705 | #ifdef CONFIG_PROC_FS | 2081 | #ifdef CONFIG_PROC_FS |
1706 | /* | 2082 | /* |
1707 | * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif | 2083 | * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif |
1708 | */ | 2084 | */ |
1709 | struct ipmr_vif_iter { | 2085 | struct ipmr_vif_iter { |
1710 | struct seq_net_private p; | 2086 | struct seq_net_private p; |
2087 | struct mr_table *mrt; | ||
1711 | int ct; | 2088 | int ct; |
1712 | }; | 2089 | }; |
1713 | 2090 | ||
@@ -1715,11 +2092,13 @@ static struct vif_device *ipmr_vif_seq_idx(struct net *net, | |||
1715 | struct ipmr_vif_iter *iter, | 2092 | struct ipmr_vif_iter *iter, |
1716 | loff_t pos) | 2093 | loff_t pos) |
1717 | { | 2094 | { |
1718 | for (iter->ct = 0; iter->ct < net->ipv4.maxvif; ++iter->ct) { | 2095 | struct mr_table *mrt = iter->mrt; |
1719 | if (!VIF_EXISTS(net, iter->ct)) | 2096 | |
2097 | for (iter->ct = 0; iter->ct < mrt->maxvif; ++iter->ct) { | ||
2098 | if (!VIF_EXISTS(mrt, iter->ct)) | ||
1720 | continue; | 2099 | continue; |
1721 | if (pos-- == 0) | 2100 | if (pos-- == 0) |
1722 | return &net->ipv4.vif_table[iter->ct]; | 2101 | return &mrt->vif_table[iter->ct]; |
1723 | } | 2102 | } |
1724 | return NULL; | 2103 | return NULL; |
1725 | } | 2104 | } |
@@ -1727,7 +2106,15 @@ static struct vif_device *ipmr_vif_seq_idx(struct net *net, | |||
1727 | static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos) | 2106 | static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos) |
1728 | __acquires(mrt_lock) | 2107 | __acquires(mrt_lock) |
1729 | { | 2108 | { |
2109 | struct ipmr_vif_iter *iter = seq->private; | ||
1730 | struct net *net = seq_file_net(seq); | 2110 | struct net *net = seq_file_net(seq); |
2111 | struct mr_table *mrt; | ||
2112 | |||
2113 | mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); | ||
2114 | if (mrt == NULL) | ||
2115 | return ERR_PTR(-ENOENT); | ||
2116 | |||
2117 | iter->mrt = mrt; | ||
1731 | 2118 | ||
1732 | read_lock(&mrt_lock); | 2119 | read_lock(&mrt_lock); |
1733 | return *pos ? ipmr_vif_seq_idx(net, seq->private, *pos - 1) | 2120 | return *pos ? ipmr_vif_seq_idx(net, seq->private, *pos - 1) |
@@ -1738,15 +2125,16 @@ static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1738 | { | 2125 | { |
1739 | struct ipmr_vif_iter *iter = seq->private; | 2126 | struct ipmr_vif_iter *iter = seq->private; |
1740 | struct net *net = seq_file_net(seq); | 2127 | struct net *net = seq_file_net(seq); |
2128 | struct mr_table *mrt = iter->mrt; | ||
1741 | 2129 | ||
1742 | ++*pos; | 2130 | ++*pos; |
1743 | if (v == SEQ_START_TOKEN) | 2131 | if (v == SEQ_START_TOKEN) |
1744 | return ipmr_vif_seq_idx(net, iter, 0); | 2132 | return ipmr_vif_seq_idx(net, iter, 0); |
1745 | 2133 | ||
1746 | while (++iter->ct < net->ipv4.maxvif) { | 2134 | while (++iter->ct < mrt->maxvif) { |
1747 | if (!VIF_EXISTS(net, iter->ct)) | 2135 | if (!VIF_EXISTS(mrt, iter->ct)) |
1748 | continue; | 2136 | continue; |
1749 | return &net->ipv4.vif_table[iter->ct]; | 2137 | return &mrt->vif_table[iter->ct]; |
1750 | } | 2138 | } |
1751 | return NULL; | 2139 | return NULL; |
1752 | } | 2140 | } |
@@ -1759,7 +2147,8 @@ static void ipmr_vif_seq_stop(struct seq_file *seq, void *v) | |||
1759 | 2147 | ||
1760 | static int ipmr_vif_seq_show(struct seq_file *seq, void *v) | 2148 | static int ipmr_vif_seq_show(struct seq_file *seq, void *v) |
1761 | { | 2149 | { |
1762 | struct net *net = seq_file_net(seq); | 2150 | struct ipmr_vif_iter *iter = seq->private; |
2151 | struct mr_table *mrt = iter->mrt; | ||
1763 | 2152 | ||
1764 | if (v == SEQ_START_TOKEN) { | 2153 | if (v == SEQ_START_TOKEN) { |
1765 | seq_puts(seq, | 2154 | seq_puts(seq, |
@@ -1770,7 +2159,7 @@ static int ipmr_vif_seq_show(struct seq_file *seq, void *v) | |||
1770 | 2159 | ||
1771 | seq_printf(seq, | 2160 | seq_printf(seq, |
1772 | "%2Zd %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n", | 2161 | "%2Zd %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n", |
1773 | vif - net->ipv4.vif_table, | 2162 | vif - mrt->vif_table, |
1774 | name, vif->bytes_in, vif->pkt_in, | 2163 | name, vif->bytes_in, vif->pkt_in, |
1775 | vif->bytes_out, vif->pkt_out, | 2164 | vif->bytes_out, vif->pkt_out, |
1776 | vif->flags, vif->local, vif->remote); | 2165 | vif->flags, vif->local, vif->remote); |
@@ -1801,7 +2190,8 @@ static const struct file_operations ipmr_vif_fops = { | |||
1801 | 2190 | ||
1802 | struct ipmr_mfc_iter { | 2191 | struct ipmr_mfc_iter { |
1803 | struct seq_net_private p; | 2192 | struct seq_net_private p; |
1804 | struct mfc_cache **cache; | 2193 | struct mr_table *mrt; |
2194 | struct list_head *cache; | ||
1805 | int ct; | 2195 | int ct; |
1806 | }; | 2196 | }; |
1807 | 2197 | ||
@@ -1809,22 +2199,22 @@ struct ipmr_mfc_iter { | |||
1809 | static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net, | 2199 | static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net, |
1810 | struct ipmr_mfc_iter *it, loff_t pos) | 2200 | struct ipmr_mfc_iter *it, loff_t pos) |
1811 | { | 2201 | { |
2202 | struct mr_table *mrt = it->mrt; | ||
1812 | struct mfc_cache *mfc; | 2203 | struct mfc_cache *mfc; |
1813 | 2204 | ||
1814 | it->cache = net->ipv4.mfc_cache_array; | ||
1815 | read_lock(&mrt_lock); | 2205 | read_lock(&mrt_lock); |
1816 | for (it->ct = 0; it->ct < MFC_LINES; it->ct++) | 2206 | for (it->ct = 0; it->ct < MFC_LINES; it->ct++) { |
1817 | for (mfc = net->ipv4.mfc_cache_array[it->ct]; | 2207 | it->cache = &mrt->mfc_cache_array[it->ct]; |
1818 | mfc; mfc = mfc->next) | 2208 | list_for_each_entry(mfc, it->cache, list) |
1819 | if (pos-- == 0) | 2209 | if (pos-- == 0) |
1820 | return mfc; | 2210 | return mfc; |
2211 | } | ||
1821 | read_unlock(&mrt_lock); | 2212 | read_unlock(&mrt_lock); |
1822 | 2213 | ||
1823 | it->cache = &mfc_unres_queue; | ||
1824 | spin_lock_bh(&mfc_unres_lock); | 2214 | spin_lock_bh(&mfc_unres_lock); |
1825 | for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) | 2215 | it->cache = &mrt->mfc_unres_queue; |
1826 | if (net_eq(mfc_net(mfc), net) && | 2216 | list_for_each_entry(mfc, it->cache, list) |
1827 | pos-- == 0) | 2217 | if (pos-- == 0) |
1828 | return mfc; | 2218 | return mfc; |
1829 | spin_unlock_bh(&mfc_unres_lock); | 2219 | spin_unlock_bh(&mfc_unres_lock); |
1830 | 2220 | ||
@@ -1837,7 +2227,13 @@ static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) | |||
1837 | { | 2227 | { |
1838 | struct ipmr_mfc_iter *it = seq->private; | 2228 | struct ipmr_mfc_iter *it = seq->private; |
1839 | struct net *net = seq_file_net(seq); | 2229 | struct net *net = seq_file_net(seq); |
2230 | struct mr_table *mrt; | ||
1840 | 2231 | ||
2232 | mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); | ||
2233 | if (mrt == NULL) | ||
2234 | return ERR_PTR(-ENOENT); | ||
2235 | |||
2236 | it->mrt = mrt; | ||
1841 | it->cache = NULL; | 2237 | it->cache = NULL; |
1842 | it->ct = 0; | 2238 | it->ct = 0; |
1843 | return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) | 2239 | return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) |
@@ -1849,37 +2245,36 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1849 | struct mfc_cache *mfc = v; | 2245 | struct mfc_cache *mfc = v; |
1850 | struct ipmr_mfc_iter *it = seq->private; | 2246 | struct ipmr_mfc_iter *it = seq->private; |
1851 | struct net *net = seq_file_net(seq); | 2247 | struct net *net = seq_file_net(seq); |
2248 | struct mr_table *mrt = it->mrt; | ||
1852 | 2249 | ||
1853 | ++*pos; | 2250 | ++*pos; |
1854 | 2251 | ||
1855 | if (v == SEQ_START_TOKEN) | 2252 | if (v == SEQ_START_TOKEN) |
1856 | return ipmr_mfc_seq_idx(net, seq->private, 0); | 2253 | return ipmr_mfc_seq_idx(net, seq->private, 0); |
1857 | 2254 | ||
1858 | if (mfc->next) | 2255 | if (mfc->list.next != it->cache) |
1859 | return mfc->next; | 2256 | return list_entry(mfc->list.next, struct mfc_cache, list); |
1860 | 2257 | ||
1861 | if (it->cache == &mfc_unres_queue) | 2258 | if (it->cache == &mrt->mfc_unres_queue) |
1862 | goto end_of_list; | 2259 | goto end_of_list; |
1863 | 2260 | ||
1864 | BUG_ON(it->cache != net->ipv4.mfc_cache_array); | 2261 | BUG_ON(it->cache != &mrt->mfc_cache_array[it->ct]); |
1865 | 2262 | ||
1866 | while (++it->ct < MFC_LINES) { | 2263 | while (++it->ct < MFC_LINES) { |
1867 | mfc = net->ipv4.mfc_cache_array[it->ct]; | 2264 | it->cache = &mrt->mfc_cache_array[it->ct]; |
1868 | if (mfc) | 2265 | if (list_empty(it->cache)) |
1869 | return mfc; | 2266 | continue; |
2267 | return list_first_entry(it->cache, struct mfc_cache, list); | ||
1870 | } | 2268 | } |
1871 | 2269 | ||
1872 | /* exhausted cache_array, show unresolved */ | 2270 | /* exhausted cache_array, show unresolved */ |
1873 | read_unlock(&mrt_lock); | 2271 | read_unlock(&mrt_lock); |
1874 | it->cache = &mfc_unres_queue; | 2272 | it->cache = &mrt->mfc_unres_queue; |
1875 | it->ct = 0; | 2273 | it->ct = 0; |
1876 | 2274 | ||
1877 | spin_lock_bh(&mfc_unres_lock); | 2275 | spin_lock_bh(&mfc_unres_lock); |
1878 | mfc = mfc_unres_queue; | 2276 | if (!list_empty(it->cache)) |
1879 | while (mfc && !net_eq(mfc_net(mfc), net)) | 2277 | return list_first_entry(it->cache, struct mfc_cache, list); |
1880 | mfc = mfc->next; | ||
1881 | if (mfc) | ||
1882 | return mfc; | ||
1883 | 2278 | ||
1884 | end_of_list: | 2279 | end_of_list: |
1885 | spin_unlock_bh(&mfc_unres_lock); | 2280 | spin_unlock_bh(&mfc_unres_lock); |
@@ -1891,18 +2286,17 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1891 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) | 2286 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) |
1892 | { | 2287 | { |
1893 | struct ipmr_mfc_iter *it = seq->private; | 2288 | struct ipmr_mfc_iter *it = seq->private; |
1894 | struct net *net = seq_file_net(seq); | 2289 | struct mr_table *mrt = it->mrt; |
1895 | 2290 | ||
1896 | if (it->cache == &mfc_unres_queue) | 2291 | if (it->cache == &mrt->mfc_unres_queue) |
1897 | spin_unlock_bh(&mfc_unres_lock); | 2292 | spin_unlock_bh(&mfc_unres_lock); |
1898 | else if (it->cache == net->ipv4.mfc_cache_array) | 2293 | else if (it->cache == &mrt->mfc_cache_array[it->ct]) |
1899 | read_unlock(&mrt_lock); | 2294 | read_unlock(&mrt_lock); |
1900 | } | 2295 | } |
1901 | 2296 | ||
1902 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | 2297 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) |
1903 | { | 2298 | { |
1904 | int n; | 2299 | int n; |
1905 | struct net *net = seq_file_net(seq); | ||
1906 | 2300 | ||
1907 | if (v == SEQ_START_TOKEN) { | 2301 | if (v == SEQ_START_TOKEN) { |
1908 | seq_puts(seq, | 2302 | seq_puts(seq, |
@@ -1910,20 +2304,21 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | |||
1910 | } else { | 2304 | } else { |
1911 | const struct mfc_cache *mfc = v; | 2305 | const struct mfc_cache *mfc = v; |
1912 | const struct ipmr_mfc_iter *it = seq->private; | 2306 | const struct ipmr_mfc_iter *it = seq->private; |
2307 | const struct mr_table *mrt = it->mrt; | ||
1913 | 2308 | ||
1914 | seq_printf(seq, "%08lX %08lX %-3hd", | 2309 | seq_printf(seq, "%08X %08X %-3hd", |
1915 | (unsigned long) mfc->mfc_mcastgrp, | 2310 | (__force u32) mfc->mfc_mcastgrp, |
1916 | (unsigned long) mfc->mfc_origin, | 2311 | (__force u32) mfc->mfc_origin, |
1917 | mfc->mfc_parent); | 2312 | mfc->mfc_parent); |
1918 | 2313 | ||
1919 | if (it->cache != &mfc_unres_queue) { | 2314 | if (it->cache != &mrt->mfc_unres_queue) { |
1920 | seq_printf(seq, " %8lu %8lu %8lu", | 2315 | seq_printf(seq, " %8lu %8lu %8lu", |
1921 | mfc->mfc_un.res.pkt, | 2316 | mfc->mfc_un.res.pkt, |
1922 | mfc->mfc_un.res.bytes, | 2317 | mfc->mfc_un.res.bytes, |
1923 | mfc->mfc_un.res.wrong_if); | 2318 | mfc->mfc_un.res.wrong_if); |
1924 | for (n = mfc->mfc_un.res.minvif; | 2319 | for (n = mfc->mfc_un.res.minvif; |
1925 | n < mfc->mfc_un.res.maxvif; n++ ) { | 2320 | n < mfc->mfc_un.res.maxvif; n++ ) { |
1926 | if (VIF_EXISTS(net, n) && | 2321 | if (VIF_EXISTS(mrt, n) && |
1927 | mfc->mfc_un.res.ttls[n] < 255) | 2322 | mfc->mfc_un.res.ttls[n] < 255) |
1928 | seq_printf(seq, | 2323 | seq_printf(seq, |
1929 | " %2d:%-3d", | 2324 | " %2d:%-3d", |
@@ -1975,27 +2370,11 @@ static const struct net_protocol pim_protocol = { | |||
1975 | */ | 2370 | */ |
1976 | static int __net_init ipmr_net_init(struct net *net) | 2371 | static int __net_init ipmr_net_init(struct net *net) |
1977 | { | 2372 | { |
1978 | int err = 0; | 2373 | int err; |
1979 | 2374 | ||
1980 | net->ipv4.vif_table = kcalloc(MAXVIFS, sizeof(struct vif_device), | 2375 | err = ipmr_rules_init(net); |
1981 | GFP_KERNEL); | 2376 | if (err < 0) |
1982 | if (!net->ipv4.vif_table) { | ||
1983 | err = -ENOMEM; | ||
1984 | goto fail; | 2377 | goto fail; |
1985 | } | ||
1986 | |||
1987 | /* Forwarding cache */ | ||
1988 | net->ipv4.mfc_cache_array = kcalloc(MFC_LINES, | ||
1989 | sizeof(struct mfc_cache *), | ||
1990 | GFP_KERNEL); | ||
1991 | if (!net->ipv4.mfc_cache_array) { | ||
1992 | err = -ENOMEM; | ||
1993 | goto fail_mfc_cache; | ||
1994 | } | ||
1995 | |||
1996 | #ifdef CONFIG_IP_PIMSM | ||
1997 | net->ipv4.mroute_reg_vif_num = -1; | ||
1998 | #endif | ||
1999 | 2378 | ||
2000 | #ifdef CONFIG_PROC_FS | 2379 | #ifdef CONFIG_PROC_FS |
2001 | err = -ENOMEM; | 2380 | err = -ENOMEM; |
@@ -2010,10 +2389,8 @@ static int __net_init ipmr_net_init(struct net *net) | |||
2010 | proc_cache_fail: | 2389 | proc_cache_fail: |
2011 | proc_net_remove(net, "ip_mr_vif"); | 2390 | proc_net_remove(net, "ip_mr_vif"); |
2012 | proc_vif_fail: | 2391 | proc_vif_fail: |
2013 | kfree(net->ipv4.mfc_cache_array); | 2392 | ipmr_rules_exit(net); |
2014 | #endif | 2393 | #endif |
2015 | fail_mfc_cache: | ||
2016 | kfree(net->ipv4.vif_table); | ||
2017 | fail: | 2394 | fail: |
2018 | return err; | 2395 | return err; |
2019 | } | 2396 | } |
@@ -2024,8 +2401,7 @@ static void __net_exit ipmr_net_exit(struct net *net) | |||
2024 | proc_net_remove(net, "ip_mr_cache"); | 2401 | proc_net_remove(net, "ip_mr_cache"); |
2025 | proc_net_remove(net, "ip_mr_vif"); | 2402 | proc_net_remove(net, "ip_mr_vif"); |
2026 | #endif | 2403 | #endif |
2027 | kfree(net->ipv4.mfc_cache_array); | 2404 | ipmr_rules_exit(net); |
2028 | kfree(net->ipv4.vif_table); | ||
2029 | } | 2405 | } |
2030 | 2406 | ||
2031 | static struct pernet_operations ipmr_net_ops = { | 2407 | static struct pernet_operations ipmr_net_ops = { |
@@ -2048,7 +2424,6 @@ int __init ip_mr_init(void) | |||
2048 | if (err) | 2424 | if (err) |
2049 | goto reg_pernet_fail; | 2425 | goto reg_pernet_fail; |
2050 | 2426 | ||
2051 | setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); | ||
2052 | err = register_netdevice_notifier(&ip_mr_notifier); | 2427 | err = register_netdevice_notifier(&ip_mr_notifier); |
2053 | if (err) | 2428 | if (err) |
2054 | goto reg_notif_fail; | 2429 | goto reg_notif_fail; |
@@ -2059,6 +2434,7 @@ int __init ip_mr_init(void) | |||
2059 | goto add_proto_fail; | 2434 | goto add_proto_fail; |
2060 | } | 2435 | } |
2061 | #endif | 2436 | #endif |
2437 | rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE, NULL, ipmr_rtm_dumproute); | ||
2062 | return 0; | 2438 | return 0; |
2063 | 2439 | ||
2064 | #ifdef CONFIG_IP_PIMSM_V2 | 2440 | #ifdef CONFIG_IP_PIMSM_V2 |
@@ -2066,7 +2442,6 @@ add_proto_fail: | |||
2066 | unregister_netdevice_notifier(&ip_mr_notifier); | 2442 | unregister_netdevice_notifier(&ip_mr_notifier); |
2067 | #endif | 2443 | #endif |
2068 | reg_notif_fail: | 2444 | reg_notif_fail: |
2069 | del_timer(&ipmr_expire_timer); | ||
2070 | unregister_pernet_subsys(&ipmr_net_ops); | 2445 | unregister_pernet_subsys(&ipmr_net_ops); |
2071 | reg_pernet_fail: | 2446 | reg_pernet_fail: |
2072 | kmem_cache_destroy(mrt_cachep); | 2447 | kmem_cache_destroy(mrt_cachep); |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 82fb43c5c59e..07de855e2175 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -17,7 +17,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) | |||
17 | const struct iphdr *iph = ip_hdr(skb); | 17 | const struct iphdr *iph = ip_hdr(skb); |
18 | struct rtable *rt; | 18 | struct rtable *rt; |
19 | struct flowi fl = {}; | 19 | struct flowi fl = {}; |
20 | struct dst_entry *odst; | 20 | unsigned long orefdst; |
21 | unsigned int hh_len; | 21 | unsigned int hh_len; |
22 | unsigned int type; | 22 | unsigned int type; |
23 | 23 | ||
@@ -51,14 +51,14 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) | |||
51 | if (ip_route_output_key(net, &rt, &fl) != 0) | 51 | if (ip_route_output_key(net, &rt, &fl) != 0) |
52 | return -1; | 52 | return -1; |
53 | 53 | ||
54 | odst = skb_dst(skb); | 54 | orefdst = skb->_skb_refdst; |
55 | if (ip_route_input(skb, iph->daddr, iph->saddr, | 55 | if (ip_route_input(skb, iph->daddr, iph->saddr, |
56 | RT_TOS(iph->tos), rt->u.dst.dev) != 0) { | 56 | RT_TOS(iph->tos), rt->u.dst.dev) != 0) { |
57 | dst_release(&rt->u.dst); | 57 | dst_release(&rt->u.dst); |
58 | return -1; | 58 | return -1; |
59 | } | 59 | } |
60 | dst_release(&rt->u.dst); | 60 | dst_release(&rt->u.dst); |
61 | dst_release(odst); | 61 | refdst_drop(orefdst); |
62 | } | 62 | } |
63 | 63 | ||
64 | if (skb_dst(skb)->error) | 64 | if (skb_dst(skb)->error) |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index f07d77f65751..1ac01b128621 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -49,12 +49,7 @@ MODULE_DESCRIPTION("arptables core"); | |||
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | #ifdef CONFIG_NETFILTER_DEBUG | 51 | #ifdef CONFIG_NETFILTER_DEBUG |
52 | #define ARP_NF_ASSERT(x) \ | 52 | #define ARP_NF_ASSERT(x) WARN_ON(!(x)) |
53 | do { \ | ||
54 | if (!(x)) \ | ||
55 | printk("ARP_NF_ASSERT: %s:%s:%u\n", \ | ||
56 | __func__, __FILE__, __LINE__); \ | ||
57 | } while(0) | ||
58 | #else | 53 | #else |
59 | #define ARP_NF_ASSERT(x) | 54 | #define ARP_NF_ASSERT(x) |
60 | #endif | 55 | #endif |
@@ -224,10 +219,10 @@ static inline int arp_checkentry(const struct arpt_arp *arp) | |||
224 | } | 219 | } |
225 | 220 | ||
226 | static unsigned int | 221 | static unsigned int |
227 | arpt_error(struct sk_buff *skb, const struct xt_target_param *par) | 222 | arpt_error(struct sk_buff *skb, const struct xt_action_param *par) |
228 | { | 223 | { |
229 | if (net_ratelimit()) | 224 | if (net_ratelimit()) |
230 | printk("arp_tables: error: '%s'\n", | 225 | pr_err("arp_tables: error: '%s'\n", |
231 | (const char *)par->targinfo); | 226 | (const char *)par->targinfo); |
232 | 227 | ||
233 | return NF_DROP; | 228 | return NF_DROP; |
@@ -260,12 +255,11 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
260 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 255 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
261 | unsigned int verdict = NF_DROP; | 256 | unsigned int verdict = NF_DROP; |
262 | const struct arphdr *arp; | 257 | const struct arphdr *arp; |
263 | bool hotdrop = false; | ||
264 | struct arpt_entry *e, *back; | 258 | struct arpt_entry *e, *back; |
265 | const char *indev, *outdev; | 259 | const char *indev, *outdev; |
266 | void *table_base; | 260 | void *table_base; |
267 | const struct xt_table_info *private; | 261 | const struct xt_table_info *private; |
268 | struct xt_target_param tgpar; | 262 | struct xt_action_param acpar; |
269 | 263 | ||
270 | if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) | 264 | if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) |
271 | return NF_DROP; | 265 | return NF_DROP; |
@@ -280,10 +274,11 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
280 | e = get_entry(table_base, private->hook_entry[hook]); | 274 | e = get_entry(table_base, private->hook_entry[hook]); |
281 | back = get_entry(table_base, private->underflow[hook]); | 275 | back = get_entry(table_base, private->underflow[hook]); |
282 | 276 | ||
283 | tgpar.in = in; | 277 | acpar.in = in; |
284 | tgpar.out = out; | 278 | acpar.out = out; |
285 | tgpar.hooknum = hook; | 279 | acpar.hooknum = hook; |
286 | tgpar.family = NFPROTO_ARP; | 280 | acpar.family = NFPROTO_ARP; |
281 | acpar.hotdrop = false; | ||
287 | 282 | ||
288 | arp = arp_hdr(skb); | 283 | arp = arp_hdr(skb); |
289 | do { | 284 | do { |
@@ -333,9 +328,9 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
333 | /* Targets which reenter must return | 328 | /* Targets which reenter must return |
334 | * abs. verdicts | 329 | * abs. verdicts |
335 | */ | 330 | */ |
336 | tgpar.target = t->u.kernel.target; | 331 | acpar.target = t->u.kernel.target; |
337 | tgpar.targinfo = t->data; | 332 | acpar.targinfo = t->data; |
338 | verdict = t->u.kernel.target->target(skb, &tgpar); | 333 | verdict = t->u.kernel.target->target(skb, &acpar); |
339 | 334 | ||
340 | /* Target might have changed stuff. */ | 335 | /* Target might have changed stuff. */ |
341 | arp = arp_hdr(skb); | 336 | arp = arp_hdr(skb); |
@@ -345,10 +340,10 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
345 | else | 340 | else |
346 | /* Verdict */ | 341 | /* Verdict */ |
347 | break; | 342 | break; |
348 | } while (!hotdrop); | 343 | } while (!acpar.hotdrop); |
349 | xt_info_rdunlock_bh(); | 344 | xt_info_rdunlock_bh(); |
350 | 345 | ||
351 | if (hotdrop) | 346 | if (acpar.hotdrop) |
352 | return NF_DROP; | 347 | return NF_DROP; |
353 | else | 348 | else |
354 | return verdict; | 349 | return verdict; |
@@ -390,7 +385,7 @@ static int mark_source_chains(const struct xt_table_info *newinfo, | |||
390 | int visited = e->comefrom & (1 << hook); | 385 | int visited = e->comefrom & (1 << hook); |
391 | 386 | ||
392 | if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) { | 387 | if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) { |
393 | printk("arptables: loop hook %u pos %u %08X.\n", | 388 | pr_notice("arptables: loop hook %u pos %u %08X.\n", |
394 | hook, pos, e->comefrom); | 389 | hook, pos, e->comefrom); |
395 | return 0; | 390 | return 0; |
396 | } | 391 | } |
@@ -523,13 +518,11 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size) | |||
523 | return ret; | 518 | return ret; |
524 | 519 | ||
525 | t = arpt_get_target(e); | 520 | t = arpt_get_target(e); |
526 | target = try_then_request_module(xt_find_target(NFPROTO_ARP, | 521 | target = xt_request_find_target(NFPROTO_ARP, t->u.user.name, |
527 | t->u.user.name, | 522 | t->u.user.revision); |
528 | t->u.user.revision), | 523 | if (IS_ERR(target)) { |
529 | "arpt_%s", t->u.user.name); | ||
530 | if (IS_ERR(target) || !target) { | ||
531 | duprintf("find_check_entry: `%s' not found\n", t->u.user.name); | 524 | duprintf("find_check_entry: `%s' not found\n", t->u.user.name); |
532 | ret = target ? PTR_ERR(target) : -ENOENT; | 525 | ret = PTR_ERR(target); |
533 | goto out; | 526 | goto out; |
534 | } | 527 | } |
535 | t->u.kernel.target = target; | 528 | t->u.kernel.target = target; |
@@ -651,6 +644,9 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, | |||
651 | if (ret != 0) | 644 | if (ret != 0) |
652 | break; | 645 | break; |
653 | ++i; | 646 | ++i; |
647 | if (strcmp(arpt_get_target(iter)->u.user.name, | ||
648 | XT_ERROR_TARGET) == 0) | ||
649 | ++newinfo->stacksize; | ||
654 | } | 650 | } |
655 | duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); | 651 | duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); |
656 | if (ret != 0) | 652 | if (ret != 0) |
@@ -1252,14 +1248,12 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, | |||
1252 | entry_offset = (void *)e - (void *)base; | 1248 | entry_offset = (void *)e - (void *)base; |
1253 | 1249 | ||
1254 | t = compat_arpt_get_target(e); | 1250 | t = compat_arpt_get_target(e); |
1255 | target = try_then_request_module(xt_find_target(NFPROTO_ARP, | 1251 | target = xt_request_find_target(NFPROTO_ARP, t->u.user.name, |
1256 | t->u.user.name, | 1252 | t->u.user.revision); |
1257 | t->u.user.revision), | 1253 | if (IS_ERR(target)) { |
1258 | "arpt_%s", t->u.user.name); | ||
1259 | if (IS_ERR(target) || !target) { | ||
1260 | duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", | 1254 | duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", |
1261 | t->u.user.name); | 1255 | t->u.user.name); |
1262 | ret = target ? PTR_ERR(target) : -ENOENT; | 1256 | ret = PTR_ERR(target); |
1263 | goto out; | 1257 | goto out; |
1264 | } | 1258 | } |
1265 | t->u.kernel.target = target; | 1259 | t->u.kernel.target = target; |
@@ -1778,8 +1772,7 @@ struct xt_table *arpt_register_table(struct net *net, | |||
1778 | { | 1772 | { |
1779 | int ret; | 1773 | int ret; |
1780 | struct xt_table_info *newinfo; | 1774 | struct xt_table_info *newinfo; |
1781 | struct xt_table_info bootstrap | 1775 | struct xt_table_info bootstrap = {0}; |
1782 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | ||
1783 | void *loc_cpu_entry; | 1776 | void *loc_cpu_entry; |
1784 | struct xt_table *new_table; | 1777 | struct xt_table *new_table; |
1785 | 1778 | ||
@@ -1830,22 +1823,23 @@ void arpt_unregister_table(struct xt_table *table) | |||
1830 | } | 1823 | } |
1831 | 1824 | ||
1832 | /* The built-in targets: standard (NULL) and error. */ | 1825 | /* The built-in targets: standard (NULL) and error. */ |
1833 | static struct xt_target arpt_standard_target __read_mostly = { | 1826 | static struct xt_target arpt_builtin_tg[] __read_mostly = { |
1834 | .name = ARPT_STANDARD_TARGET, | 1827 | { |
1835 | .targetsize = sizeof(int), | 1828 | .name = ARPT_STANDARD_TARGET, |
1836 | .family = NFPROTO_ARP, | 1829 | .targetsize = sizeof(int), |
1830 | .family = NFPROTO_ARP, | ||
1837 | #ifdef CONFIG_COMPAT | 1831 | #ifdef CONFIG_COMPAT |
1838 | .compatsize = sizeof(compat_int_t), | 1832 | .compatsize = sizeof(compat_int_t), |
1839 | .compat_from_user = compat_standard_from_user, | 1833 | .compat_from_user = compat_standard_from_user, |
1840 | .compat_to_user = compat_standard_to_user, | 1834 | .compat_to_user = compat_standard_to_user, |
1841 | #endif | 1835 | #endif |
1842 | }; | 1836 | }, |
1843 | 1837 | { | |
1844 | static struct xt_target arpt_error_target __read_mostly = { | 1838 | .name = ARPT_ERROR_TARGET, |
1845 | .name = ARPT_ERROR_TARGET, | 1839 | .target = arpt_error, |
1846 | .target = arpt_error, | 1840 | .targetsize = ARPT_FUNCTION_MAXNAMELEN, |
1847 | .targetsize = ARPT_FUNCTION_MAXNAMELEN, | 1841 | .family = NFPROTO_ARP, |
1848 | .family = NFPROTO_ARP, | 1842 | }, |
1849 | }; | 1843 | }; |
1850 | 1844 | ||
1851 | static struct nf_sockopt_ops arpt_sockopts = { | 1845 | static struct nf_sockopt_ops arpt_sockopts = { |
@@ -1889,12 +1883,9 @@ static int __init arp_tables_init(void) | |||
1889 | goto err1; | 1883 | goto err1; |
1890 | 1884 | ||
1891 | /* Noone else will be downing sem now, so we won't sleep */ | 1885 | /* Noone else will be downing sem now, so we won't sleep */ |
1892 | ret = xt_register_target(&arpt_standard_target); | 1886 | ret = xt_register_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); |
1893 | if (ret < 0) | 1887 | if (ret < 0) |
1894 | goto err2; | 1888 | goto err2; |
1895 | ret = xt_register_target(&arpt_error_target); | ||
1896 | if (ret < 0) | ||
1897 | goto err3; | ||
1898 | 1889 | ||
1899 | /* Register setsockopt */ | 1890 | /* Register setsockopt */ |
1900 | ret = nf_register_sockopt(&arpt_sockopts); | 1891 | ret = nf_register_sockopt(&arpt_sockopts); |
@@ -1905,9 +1896,7 @@ static int __init arp_tables_init(void) | |||
1905 | return 0; | 1896 | return 0; |
1906 | 1897 | ||
1907 | err4: | 1898 | err4: |
1908 | xt_unregister_target(&arpt_error_target); | 1899 | xt_unregister_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); |
1909 | err3: | ||
1910 | xt_unregister_target(&arpt_standard_target); | ||
1911 | err2: | 1900 | err2: |
1912 | unregister_pernet_subsys(&arp_tables_net_ops); | 1901 | unregister_pernet_subsys(&arp_tables_net_ops); |
1913 | err1: | 1902 | err1: |
@@ -1917,8 +1906,7 @@ err1: | |||
1917 | static void __exit arp_tables_fini(void) | 1906 | static void __exit arp_tables_fini(void) |
1918 | { | 1907 | { |
1919 | nf_unregister_sockopt(&arpt_sockopts); | 1908 | nf_unregister_sockopt(&arpt_sockopts); |
1920 | xt_unregister_target(&arpt_error_target); | 1909 | xt_unregister_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); |
1921 | xt_unregister_target(&arpt_standard_target); | ||
1922 | unregister_pernet_subsys(&arp_tables_net_ops); | 1910 | unregister_pernet_subsys(&arp_tables_net_ops); |
1923 | } | 1911 | } |
1924 | 1912 | ||
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index b0d5b1d0a769..e1be7dd1171b 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c | |||
@@ -9,7 +9,7 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | |||
9 | MODULE_DESCRIPTION("arptables arp payload mangle target"); | 9 | MODULE_DESCRIPTION("arptables arp payload mangle target"); |
10 | 10 | ||
11 | static unsigned int | 11 | static unsigned int |
12 | target(struct sk_buff *skb, const struct xt_target_param *par) | 12 | target(struct sk_buff *skb, const struct xt_action_param *par) |
13 | { | 13 | { |
14 | const struct arpt_mangle *mangle = par->targinfo; | 14 | const struct arpt_mangle *mangle = par->targinfo; |
15 | const struct arphdr *arp; | 15 | const struct arphdr *arp; |
@@ -54,7 +54,7 @@ target(struct sk_buff *skb, const struct xt_target_param *par) | |||
54 | return mangle->target; | 54 | return mangle->target; |
55 | } | 55 | } |
56 | 56 | ||
57 | static bool checkentry(const struct xt_tgchk_param *par) | 57 | static int checkentry(const struct xt_tgchk_param *par) |
58 | { | 58 | { |
59 | const struct arpt_mangle *mangle = par->targinfo; | 59 | const struct arpt_mangle *mangle = par->targinfo; |
60 | 60 | ||
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index e2787048aa0a..a4e5fc5df4bf 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -161,8 +161,7 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
161 | break; | 161 | break; |
162 | 162 | ||
163 | case IPQ_COPY_PACKET: | 163 | case IPQ_COPY_PACKET: |
164 | if ((entry->skb->ip_summed == CHECKSUM_PARTIAL || | 164 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && |
165 | entry->skb->ip_summed == CHECKSUM_COMPLETE) && | ||
166 | (*errp = skb_checksum_help(entry->skb))) { | 165 | (*errp = skb_checksum_help(entry->skb))) { |
167 | read_unlock_bh(&queue_lock); | 166 | read_unlock_bh(&queue_lock); |
168 | return NULL; | 167 | return NULL; |
@@ -462,7 +461,6 @@ __ipq_rcv_skb(struct sk_buff *skb) | |||
462 | 461 | ||
463 | if (flags & NLM_F_ACK) | 462 | if (flags & NLM_F_ACK) |
464 | netlink_ack(skb, nlh, 0); | 463 | netlink_ack(skb, nlh, 0); |
465 | return; | ||
466 | } | 464 | } |
467 | 465 | ||
468 | static void | 466 | static void |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index b29c66df8d1f..63958f3394a5 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -39,24 +39,19 @@ MODULE_DESCRIPTION("IPv4 packet filter"); | |||
39 | /*#define DEBUG_IP_FIREWALL_USER*/ | 39 | /*#define DEBUG_IP_FIREWALL_USER*/ |
40 | 40 | ||
41 | #ifdef DEBUG_IP_FIREWALL | 41 | #ifdef DEBUG_IP_FIREWALL |
42 | #define dprintf(format, args...) printk(format , ## args) | 42 | #define dprintf(format, args...) pr_info(format , ## args) |
43 | #else | 43 | #else |
44 | #define dprintf(format, args...) | 44 | #define dprintf(format, args...) |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #ifdef DEBUG_IP_FIREWALL_USER | 47 | #ifdef DEBUG_IP_FIREWALL_USER |
48 | #define duprintf(format, args...) printk(format , ## args) | 48 | #define duprintf(format, args...) pr_info(format , ## args) |
49 | #else | 49 | #else |
50 | #define duprintf(format, args...) | 50 | #define duprintf(format, args...) |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | #ifdef CONFIG_NETFILTER_DEBUG | 53 | #ifdef CONFIG_NETFILTER_DEBUG |
54 | #define IP_NF_ASSERT(x) \ | 54 | #define IP_NF_ASSERT(x) WARN_ON(!(x)) |
55 | do { \ | ||
56 | if (!(x)) \ | ||
57 | printk("IP_NF_ASSERT: %s:%s:%u\n", \ | ||
58 | __func__, __FILE__, __LINE__); \ | ||
59 | } while(0) | ||
60 | #else | 55 | #else |
61 | #define IP_NF_ASSERT(x) | 56 | #define IP_NF_ASSERT(x) |
62 | #endif | 57 | #endif |
@@ -165,30 +160,14 @@ ip_checkentry(const struct ipt_ip *ip) | |||
165 | } | 160 | } |
166 | 161 | ||
167 | static unsigned int | 162 | static unsigned int |
168 | ipt_error(struct sk_buff *skb, const struct xt_target_param *par) | 163 | ipt_error(struct sk_buff *skb, const struct xt_action_param *par) |
169 | { | 164 | { |
170 | if (net_ratelimit()) | 165 | if (net_ratelimit()) |
171 | printk("ip_tables: error: `%s'\n", | 166 | pr_info("error: `%s'\n", (const char *)par->targinfo); |
172 | (const char *)par->targinfo); | ||
173 | 167 | ||
174 | return NF_DROP; | 168 | return NF_DROP; |
175 | } | 169 | } |
176 | 170 | ||
177 | /* Performance critical - called for every packet */ | ||
178 | static inline bool | ||
179 | do_match(const struct ipt_entry_match *m, const struct sk_buff *skb, | ||
180 | struct xt_match_param *par) | ||
181 | { | ||
182 | par->match = m->u.kernel.match; | ||
183 | par->matchinfo = m->data; | ||
184 | |||
185 | /* Stop iteration if it doesn't match */ | ||
186 | if (!m->u.kernel.match->match(skb, par)) | ||
187 | return true; | ||
188 | else | ||
189 | return false; | ||
190 | } | ||
191 | |||
192 | /* Performance critical */ | 171 | /* Performance critical */ |
193 | static inline struct ipt_entry * | 172 | static inline struct ipt_entry * |
194 | get_entry(const void *base, unsigned int offset) | 173 | get_entry(const void *base, unsigned int offset) |
@@ -322,19 +301,16 @@ ipt_do_table(struct sk_buff *skb, | |||
322 | const struct net_device *out, | 301 | const struct net_device *out, |
323 | struct xt_table *table) | 302 | struct xt_table *table) |
324 | { | 303 | { |
325 | #define tb_comefrom ((struct ipt_entry *)table_base)->comefrom | ||
326 | |||
327 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 304 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
328 | const struct iphdr *ip; | 305 | const struct iphdr *ip; |
329 | bool hotdrop = false; | ||
330 | /* Initializing verdict to NF_DROP keeps gcc happy. */ | 306 | /* Initializing verdict to NF_DROP keeps gcc happy. */ |
331 | unsigned int verdict = NF_DROP; | 307 | unsigned int verdict = NF_DROP; |
332 | const char *indev, *outdev; | 308 | const char *indev, *outdev; |
333 | const void *table_base; | 309 | const void *table_base; |
334 | struct ipt_entry *e, *back; | 310 | struct ipt_entry *e, **jumpstack; |
311 | unsigned int *stackptr, origptr, cpu; | ||
335 | const struct xt_table_info *private; | 312 | const struct xt_table_info *private; |
336 | struct xt_match_param mtpar; | 313 | struct xt_action_param acpar; |
337 | struct xt_target_param tgpar; | ||
338 | 314 | ||
339 | /* Initialization */ | 315 | /* Initialization */ |
340 | ip = ip_hdr(skb); | 316 | ip = ip_hdr(skb); |
@@ -346,40 +322,47 @@ ipt_do_table(struct sk_buff *skb, | |||
346 | * things we don't know, ie. tcp syn flag or ports). If the | 322 | * things we don't know, ie. tcp syn flag or ports). If the |
347 | * rule is also a fragment-specific rule, non-fragments won't | 323 | * rule is also a fragment-specific rule, non-fragments won't |
348 | * match it. */ | 324 | * match it. */ |
349 | mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; | 325 | acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; |
350 | mtpar.thoff = ip_hdrlen(skb); | 326 | acpar.thoff = ip_hdrlen(skb); |
351 | mtpar.hotdrop = &hotdrop; | 327 | acpar.hotdrop = false; |
352 | mtpar.in = tgpar.in = in; | 328 | acpar.in = in; |
353 | mtpar.out = tgpar.out = out; | 329 | acpar.out = out; |
354 | mtpar.family = tgpar.family = NFPROTO_IPV4; | 330 | acpar.family = NFPROTO_IPV4; |
355 | mtpar.hooknum = tgpar.hooknum = hook; | 331 | acpar.hooknum = hook; |
356 | 332 | ||
357 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 333 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
358 | xt_info_rdlock_bh(); | 334 | xt_info_rdlock_bh(); |
359 | private = table->private; | 335 | private = table->private; |
360 | table_base = private->entries[smp_processor_id()]; | 336 | cpu = smp_processor_id(); |
337 | table_base = private->entries[cpu]; | ||
338 | jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; | ||
339 | stackptr = &private->stackptr[cpu]; | ||
340 | origptr = *stackptr; | ||
361 | 341 | ||
362 | e = get_entry(table_base, private->hook_entry[hook]); | 342 | e = get_entry(table_base, private->hook_entry[hook]); |
363 | 343 | ||
364 | /* For return from builtin chain */ | 344 | pr_debug("Entering %s(hook %u); sp at %u (UF %p)\n", |
365 | back = get_entry(table_base, private->underflow[hook]); | 345 | table->name, hook, origptr, |
346 | get_entry(table_base, private->underflow[hook])); | ||
366 | 347 | ||
367 | do { | 348 | do { |
368 | const struct ipt_entry_target *t; | 349 | const struct ipt_entry_target *t; |
369 | const struct xt_entry_match *ematch; | 350 | const struct xt_entry_match *ematch; |
370 | 351 | ||
371 | IP_NF_ASSERT(e); | 352 | IP_NF_ASSERT(e); |
372 | IP_NF_ASSERT(back); | ||
373 | if (!ip_packet_match(ip, indev, outdev, | 353 | if (!ip_packet_match(ip, indev, outdev, |
374 | &e->ip, mtpar.fragoff)) { | 354 | &e->ip, acpar.fragoff)) { |
375 | no_match: | 355 | no_match: |
376 | e = ipt_next_entry(e); | 356 | e = ipt_next_entry(e); |
377 | continue; | 357 | continue; |
378 | } | 358 | } |
379 | 359 | ||
380 | xt_ematch_foreach(ematch, e) | 360 | xt_ematch_foreach(ematch, e) { |
381 | if (do_match(ematch, skb, &mtpar) != 0) | 361 | acpar.match = ematch->u.kernel.match; |
362 | acpar.matchinfo = ematch->data; | ||
363 | if (!acpar.match->match(skb, &acpar)) | ||
382 | goto no_match; | 364 | goto no_match; |
365 | } | ||
383 | 366 | ||
384 | ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); | 367 | ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); |
385 | 368 | ||
@@ -404,41 +387,38 @@ ipt_do_table(struct sk_buff *skb, | |||
404 | verdict = (unsigned)(-v) - 1; | 387 | verdict = (unsigned)(-v) - 1; |
405 | break; | 388 | break; |
406 | } | 389 | } |
407 | e = back; | 390 | if (*stackptr == 0) { |
408 | back = get_entry(table_base, back->comefrom); | 391 | e = get_entry(table_base, |
392 | private->underflow[hook]); | ||
393 | pr_debug("Underflow (this is normal) " | ||
394 | "to %p\n", e); | ||
395 | } else { | ||
396 | e = jumpstack[--*stackptr]; | ||
397 | pr_debug("Pulled %p out from pos %u\n", | ||
398 | e, *stackptr); | ||
399 | e = ipt_next_entry(e); | ||
400 | } | ||
409 | continue; | 401 | continue; |
410 | } | 402 | } |
411 | if (table_base + v != ipt_next_entry(e) && | 403 | if (table_base + v != ipt_next_entry(e) && |
412 | !(e->ip.flags & IPT_F_GOTO)) { | 404 | !(e->ip.flags & IPT_F_GOTO)) { |
413 | /* Save old back ptr in next entry */ | 405 | if (*stackptr >= private->stacksize) { |
414 | struct ipt_entry *next = ipt_next_entry(e); | 406 | verdict = NF_DROP; |
415 | next->comefrom = (void *)back - table_base; | 407 | break; |
416 | /* set back pointer to next entry */ | 408 | } |
417 | back = next; | 409 | jumpstack[(*stackptr)++] = e; |
410 | pr_debug("Pushed %p into pos %u\n", | ||
411 | e, *stackptr - 1); | ||
418 | } | 412 | } |
419 | 413 | ||
420 | e = get_entry(table_base, v); | 414 | e = get_entry(table_base, v); |
421 | continue; | 415 | continue; |
422 | } | 416 | } |
423 | 417 | ||
424 | /* Targets which reenter must return | 418 | acpar.target = t->u.kernel.target; |
425 | abs. verdicts */ | 419 | acpar.targinfo = t->data; |
426 | tgpar.target = t->u.kernel.target; | ||
427 | tgpar.targinfo = t->data; | ||
428 | |||
429 | 420 | ||
430 | #ifdef CONFIG_NETFILTER_DEBUG | 421 | verdict = t->u.kernel.target->target(skb, &acpar); |
431 | tb_comefrom = 0xeeeeeeec; | ||
432 | #endif | ||
433 | verdict = t->u.kernel.target->target(skb, &tgpar); | ||
434 | #ifdef CONFIG_NETFILTER_DEBUG | ||
435 | if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) { | ||
436 | printk("Target %s reentered!\n", | ||
437 | t->u.kernel.target->name); | ||
438 | verdict = NF_DROP; | ||
439 | } | ||
440 | tb_comefrom = 0x57acc001; | ||
441 | #endif | ||
442 | /* Target might have changed stuff. */ | 422 | /* Target might have changed stuff. */ |
443 | ip = ip_hdr(skb); | 423 | ip = ip_hdr(skb); |
444 | if (verdict == IPT_CONTINUE) | 424 | if (verdict == IPT_CONTINUE) |
@@ -446,18 +426,18 @@ ipt_do_table(struct sk_buff *skb, | |||
446 | else | 426 | else |
447 | /* Verdict */ | 427 | /* Verdict */ |
448 | break; | 428 | break; |
449 | } while (!hotdrop); | 429 | } while (!acpar.hotdrop); |
450 | xt_info_rdunlock_bh(); | 430 | xt_info_rdunlock_bh(); |
451 | 431 | pr_debug("Exiting %s; resetting sp from %u to %u\n", | |
432 | __func__, *stackptr, origptr); | ||
433 | *stackptr = origptr; | ||
452 | #ifdef DEBUG_ALLOW_ALL | 434 | #ifdef DEBUG_ALLOW_ALL |
453 | return NF_ACCEPT; | 435 | return NF_ACCEPT; |
454 | #else | 436 | #else |
455 | if (hotdrop) | 437 | if (acpar.hotdrop) |
456 | return NF_DROP; | 438 | return NF_DROP; |
457 | else return verdict; | 439 | else return verdict; |
458 | #endif | 440 | #endif |
459 | |||
460 | #undef tb_comefrom | ||
461 | } | 441 | } |
462 | 442 | ||
463 | /* Figures out from what hook each rule can be called: returns 0 if | 443 | /* Figures out from what hook each rule can be called: returns 0 if |
@@ -486,7 +466,7 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
486 | int visited = e->comefrom & (1 << hook); | 466 | int visited = e->comefrom & (1 << hook); |
487 | 467 | ||
488 | if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { | 468 | if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { |
489 | printk("iptables: loop hook %u pos %u %08X.\n", | 469 | pr_err("iptables: loop hook %u pos %u %08X.\n", |
490 | hook, pos, e->comefrom); | 470 | hook, pos, e->comefrom); |
491 | return 0; | 471 | return 0; |
492 | } | 472 | } |
@@ -591,7 +571,7 @@ check_entry(const struct ipt_entry *e, const char *name) | |||
591 | const struct ipt_entry_target *t; | 571 | const struct ipt_entry_target *t; |
592 | 572 | ||
593 | if (!ip_checkentry(&e->ip)) { | 573 | if (!ip_checkentry(&e->ip)) { |
594 | duprintf("ip_tables: ip check failed %p %s.\n", e, name); | 574 | duprintf("ip check failed %p %s.\n", e, par->match->name); |
595 | return -EINVAL; | 575 | return -EINVAL; |
596 | } | 576 | } |
597 | 577 | ||
@@ -618,8 +598,7 @@ check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par) | |||
618 | ret = xt_check_match(par, m->u.match_size - sizeof(*m), | 598 | ret = xt_check_match(par, m->u.match_size - sizeof(*m), |
619 | ip->proto, ip->invflags & IPT_INV_PROTO); | 599 | ip->proto, ip->invflags & IPT_INV_PROTO); |
620 | if (ret < 0) { | 600 | if (ret < 0) { |
621 | duprintf("ip_tables: check failed for `%s'.\n", | 601 | duprintf("check failed for `%s'.\n", par->match->name); |
622 | par.match->name); | ||
623 | return ret; | 602 | return ret; |
624 | } | 603 | } |
625 | return 0; | 604 | return 0; |
@@ -631,12 +610,11 @@ find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par) | |||
631 | struct xt_match *match; | 610 | struct xt_match *match; |
632 | int ret; | 611 | int ret; |
633 | 612 | ||
634 | match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, | 613 | match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name, |
635 | m->u.user.revision), | 614 | m->u.user.revision); |
636 | "ipt_%s", m->u.user.name); | 615 | if (IS_ERR(match)) { |
637 | if (IS_ERR(match) || !match) { | ||
638 | duprintf("find_check_match: `%s' not found\n", m->u.user.name); | 616 | duprintf("find_check_match: `%s' not found\n", m->u.user.name); |
639 | return match ? PTR_ERR(match) : -ENOENT; | 617 | return PTR_ERR(match); |
640 | } | 618 | } |
641 | m->u.kernel.match = match; | 619 | m->u.kernel.match = match; |
642 | 620 | ||
@@ -667,7 +645,7 @@ static int check_target(struct ipt_entry *e, struct net *net, const char *name) | |||
667 | ret = xt_check_target(&par, t->u.target_size - sizeof(*t), | 645 | ret = xt_check_target(&par, t->u.target_size - sizeof(*t), |
668 | e->ip.proto, e->ip.invflags & IPT_INV_PROTO); | 646 | e->ip.proto, e->ip.invflags & IPT_INV_PROTO); |
669 | if (ret < 0) { | 647 | if (ret < 0) { |
670 | duprintf("ip_tables: check failed for `%s'.\n", | 648 | duprintf("check failed for `%s'.\n", |
671 | t->u.kernel.target->name); | 649 | t->u.kernel.target->name); |
672 | return ret; | 650 | return ret; |
673 | } | 651 | } |
@@ -703,13 +681,11 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, | |||
703 | } | 681 | } |
704 | 682 | ||
705 | t = ipt_get_target(e); | 683 | t = ipt_get_target(e); |
706 | target = try_then_request_module(xt_find_target(AF_INET, | 684 | target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name, |
707 | t->u.user.name, | 685 | t->u.user.revision); |
708 | t->u.user.revision), | 686 | if (IS_ERR(target)) { |
709 | "ipt_%s", t->u.user.name); | ||
710 | if (IS_ERR(target) || !target) { | ||
711 | duprintf("find_check_entry: `%s' not found\n", t->u.user.name); | 687 | duprintf("find_check_entry: `%s' not found\n", t->u.user.name); |
712 | ret = target ? PTR_ERR(target) : -ENOENT; | 688 | ret = PTR_ERR(target); |
713 | goto cleanup_matches; | 689 | goto cleanup_matches; |
714 | } | 690 | } |
715 | t->u.kernel.target = target; | 691 | t->u.kernel.target = target; |
@@ -843,6 +819,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, | |||
843 | if (ret != 0) | 819 | if (ret != 0) |
844 | return ret; | 820 | return ret; |
845 | ++i; | 821 | ++i; |
822 | if (strcmp(ipt_get_target(iter)->u.user.name, | ||
823 | XT_ERROR_TARGET) == 0) | ||
824 | ++newinfo->stacksize; | ||
846 | } | 825 | } |
847 | 826 | ||
848 | if (i != repl->num_entries) { | 827 | if (i != repl->num_entries) { |
@@ -1311,7 +1290,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) | |||
1311 | if (ret != 0) | 1290 | if (ret != 0) |
1312 | goto free_newinfo; | 1291 | goto free_newinfo; |
1313 | 1292 | ||
1314 | duprintf("ip_tables: Translated table\n"); | 1293 | duprintf("Translated table\n"); |
1315 | 1294 | ||
1316 | ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, | 1295 | ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, |
1317 | tmp.num_counters, tmp.counters); | 1296 | tmp.num_counters, tmp.counters); |
@@ -1476,13 +1455,12 @@ compat_find_calc_match(struct ipt_entry_match *m, | |||
1476 | { | 1455 | { |
1477 | struct xt_match *match; | 1456 | struct xt_match *match; |
1478 | 1457 | ||
1479 | match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, | 1458 | match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name, |
1480 | m->u.user.revision), | 1459 | m->u.user.revision); |
1481 | "ipt_%s", m->u.user.name); | 1460 | if (IS_ERR(match)) { |
1482 | if (IS_ERR(match) || !match) { | ||
1483 | duprintf("compat_check_calc_match: `%s' not found\n", | 1461 | duprintf("compat_check_calc_match: `%s' not found\n", |
1484 | m->u.user.name); | 1462 | m->u.user.name); |
1485 | return match ? PTR_ERR(match) : -ENOENT; | 1463 | return PTR_ERR(match); |
1486 | } | 1464 | } |
1487 | m->u.kernel.match = match; | 1465 | m->u.kernel.match = match; |
1488 | *size += xt_compat_match_offset(match); | 1466 | *size += xt_compat_match_offset(match); |
@@ -1549,14 +1527,12 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, | |||
1549 | } | 1527 | } |
1550 | 1528 | ||
1551 | t = compat_ipt_get_target(e); | 1529 | t = compat_ipt_get_target(e); |
1552 | target = try_then_request_module(xt_find_target(AF_INET, | 1530 | target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name, |
1553 | t->u.user.name, | 1531 | t->u.user.revision); |
1554 | t->u.user.revision), | 1532 | if (IS_ERR(target)) { |
1555 | "ipt_%s", t->u.user.name); | ||
1556 | if (IS_ERR(target) || !target) { | ||
1557 | duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", | 1533 | duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", |
1558 | t->u.user.name); | 1534 | t->u.user.name); |
1559 | ret = target ? PTR_ERR(target) : -ENOENT; | 1535 | ret = PTR_ERR(target); |
1560 | goto release_matches; | 1536 | goto release_matches; |
1561 | } | 1537 | } |
1562 | t->u.kernel.target = target; | 1538 | t->u.kernel.target = target; |
@@ -2094,8 +2070,7 @@ struct xt_table *ipt_register_table(struct net *net, | |||
2094 | { | 2070 | { |
2095 | int ret; | 2071 | int ret; |
2096 | struct xt_table_info *newinfo; | 2072 | struct xt_table_info *newinfo; |
2097 | struct xt_table_info bootstrap | 2073 | struct xt_table_info bootstrap = {0}; |
2098 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | ||
2099 | void *loc_cpu_entry; | 2074 | void *loc_cpu_entry; |
2100 | struct xt_table *new_table; | 2075 | struct xt_table *new_table; |
2101 | 2076 | ||
@@ -2157,7 +2132,7 @@ icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, | |||
2157 | } | 2132 | } |
2158 | 2133 | ||
2159 | static bool | 2134 | static bool |
2160 | icmp_match(const struct sk_buff *skb, const struct xt_match_param *par) | 2135 | icmp_match(const struct sk_buff *skb, struct xt_action_param *par) |
2161 | { | 2136 | { |
2162 | const struct icmphdr *ic; | 2137 | const struct icmphdr *ic; |
2163 | struct icmphdr _icmph; | 2138 | struct icmphdr _icmph; |
@@ -2173,7 +2148,7 @@ icmp_match(const struct sk_buff *skb, const struct xt_match_param *par) | |||
2173 | * can't. Hence, no choice but to drop. | 2148 | * can't. Hence, no choice but to drop. |
2174 | */ | 2149 | */ |
2175 | duprintf("Dropping evil ICMP tinygram.\n"); | 2150 | duprintf("Dropping evil ICMP tinygram.\n"); |
2176 | *par->hotdrop = true; | 2151 | par->hotdrop = true; |
2177 | return false; | 2152 | return false; |
2178 | } | 2153 | } |
2179 | 2154 | ||
@@ -2184,31 +2159,31 @@ icmp_match(const struct sk_buff *skb, const struct xt_match_param *par) | |||
2184 | !!(icmpinfo->invflags&IPT_ICMP_INV)); | 2159 | !!(icmpinfo->invflags&IPT_ICMP_INV)); |
2185 | } | 2160 | } |
2186 | 2161 | ||
2187 | static bool icmp_checkentry(const struct xt_mtchk_param *par) | 2162 | static int icmp_checkentry(const struct xt_mtchk_param *par) |
2188 | { | 2163 | { |
2189 | const struct ipt_icmp *icmpinfo = par->matchinfo; | 2164 | const struct ipt_icmp *icmpinfo = par->matchinfo; |
2190 | 2165 | ||
2191 | /* Must specify no unknown invflags */ | 2166 | /* Must specify no unknown invflags */ |
2192 | return !(icmpinfo->invflags & ~IPT_ICMP_INV); | 2167 | return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0; |
2193 | } | 2168 | } |
2194 | 2169 | ||
2195 | /* The built-in targets: standard (NULL) and error. */ | 2170 | static struct xt_target ipt_builtin_tg[] __read_mostly = { |
2196 | static struct xt_target ipt_standard_target __read_mostly = { | 2171 | { |
2197 | .name = IPT_STANDARD_TARGET, | 2172 | .name = IPT_STANDARD_TARGET, |
2198 | .targetsize = sizeof(int), | 2173 | .targetsize = sizeof(int), |
2199 | .family = NFPROTO_IPV4, | 2174 | .family = NFPROTO_IPV4, |
2200 | #ifdef CONFIG_COMPAT | 2175 | #ifdef CONFIG_COMPAT |
2201 | .compatsize = sizeof(compat_int_t), | 2176 | .compatsize = sizeof(compat_int_t), |
2202 | .compat_from_user = compat_standard_from_user, | 2177 | .compat_from_user = compat_standard_from_user, |
2203 | .compat_to_user = compat_standard_to_user, | 2178 | .compat_to_user = compat_standard_to_user, |
2204 | #endif | 2179 | #endif |
2205 | }; | 2180 | }, |
2206 | 2181 | { | |
2207 | static struct xt_target ipt_error_target __read_mostly = { | 2182 | .name = IPT_ERROR_TARGET, |
2208 | .name = IPT_ERROR_TARGET, | 2183 | .target = ipt_error, |
2209 | .target = ipt_error, | 2184 | .targetsize = IPT_FUNCTION_MAXNAMELEN, |
2210 | .targetsize = IPT_FUNCTION_MAXNAMELEN, | 2185 | .family = NFPROTO_IPV4, |
2211 | .family = NFPROTO_IPV4, | 2186 | }, |
2212 | }; | 2187 | }; |
2213 | 2188 | ||
2214 | static struct nf_sockopt_ops ipt_sockopts = { | 2189 | static struct nf_sockopt_ops ipt_sockopts = { |
@@ -2228,13 +2203,15 @@ static struct nf_sockopt_ops ipt_sockopts = { | |||
2228 | .owner = THIS_MODULE, | 2203 | .owner = THIS_MODULE, |
2229 | }; | 2204 | }; |
2230 | 2205 | ||
2231 | static struct xt_match icmp_matchstruct __read_mostly = { | 2206 | static struct xt_match ipt_builtin_mt[] __read_mostly = { |
2232 | .name = "icmp", | 2207 | { |
2233 | .match = icmp_match, | 2208 | .name = "icmp", |
2234 | .matchsize = sizeof(struct ipt_icmp), | 2209 | .match = icmp_match, |
2235 | .checkentry = icmp_checkentry, | 2210 | .matchsize = sizeof(struct ipt_icmp), |
2236 | .proto = IPPROTO_ICMP, | 2211 | .checkentry = icmp_checkentry, |
2237 | .family = NFPROTO_IPV4, | 2212 | .proto = IPPROTO_ICMP, |
2213 | .family = NFPROTO_IPV4, | ||
2214 | }, | ||
2238 | }; | 2215 | }; |
2239 | 2216 | ||
2240 | static int __net_init ip_tables_net_init(struct net *net) | 2217 | static int __net_init ip_tables_net_init(struct net *net) |
@@ -2261,13 +2238,10 @@ static int __init ip_tables_init(void) | |||
2261 | goto err1; | 2238 | goto err1; |
2262 | 2239 | ||
2263 | /* Noone else will be downing sem now, so we won't sleep */ | 2240 | /* Noone else will be downing sem now, so we won't sleep */ |
2264 | ret = xt_register_target(&ipt_standard_target); | 2241 | ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg)); |
2265 | if (ret < 0) | 2242 | if (ret < 0) |
2266 | goto err2; | 2243 | goto err2; |
2267 | ret = xt_register_target(&ipt_error_target); | 2244 | ret = xt_register_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt)); |
2268 | if (ret < 0) | ||
2269 | goto err3; | ||
2270 | ret = xt_register_match(&icmp_matchstruct); | ||
2271 | if (ret < 0) | 2245 | if (ret < 0) |
2272 | goto err4; | 2246 | goto err4; |
2273 | 2247 | ||
@@ -2276,15 +2250,13 @@ static int __init ip_tables_init(void) | |||
2276 | if (ret < 0) | 2250 | if (ret < 0) |
2277 | goto err5; | 2251 | goto err5; |
2278 | 2252 | ||
2279 | printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n"); | 2253 | pr_info("(C) 2000-2006 Netfilter Core Team\n"); |
2280 | return 0; | 2254 | return 0; |
2281 | 2255 | ||
2282 | err5: | 2256 | err5: |
2283 | xt_unregister_match(&icmp_matchstruct); | 2257 | xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt)); |
2284 | err4: | 2258 | err4: |
2285 | xt_unregister_target(&ipt_error_target); | 2259 | xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg)); |
2286 | err3: | ||
2287 | xt_unregister_target(&ipt_standard_target); | ||
2288 | err2: | 2260 | err2: |
2289 | unregister_pernet_subsys(&ip_tables_net_ops); | 2261 | unregister_pernet_subsys(&ip_tables_net_ops); |
2290 | err1: | 2262 | err1: |
@@ -2295,10 +2267,8 @@ static void __exit ip_tables_fini(void) | |||
2295 | { | 2267 | { |
2296 | nf_unregister_sockopt(&ipt_sockopts); | 2268 | nf_unregister_sockopt(&ipt_sockopts); |
2297 | 2269 | ||
2298 | xt_unregister_match(&icmp_matchstruct); | 2270 | xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt)); |
2299 | xt_unregister_target(&ipt_error_target); | 2271 | xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg)); |
2300 | xt_unregister_target(&ipt_standard_target); | ||
2301 | |||
2302 | unregister_pernet_subsys(&ip_tables_net_ops); | 2272 | unregister_pernet_subsys(&ip_tables_net_ops); |
2303 | } | 2273 | } |
2304 | 2274 | ||
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index ab828400ed71..f91c94b9a790 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/proc_fs.h> | 14 | #include <linux/proc_fs.h> |
14 | #include <linux/jhash.h> | 15 | #include <linux/jhash.h> |
@@ -88,7 +89,7 @@ clusterip_config_entry_put(struct clusterip_config *c) | |||
88 | list_del(&c->list); | 89 | list_del(&c->list); |
89 | write_unlock_bh(&clusterip_lock); | 90 | write_unlock_bh(&clusterip_lock); |
90 | 91 | ||
91 | dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0); | 92 | dev_mc_del(c->dev, c->clustermac); |
92 | dev_put(c->dev); | 93 | dev_put(c->dev); |
93 | 94 | ||
94 | /* In case anyone still accesses the file, the open/close | 95 | /* In case anyone still accesses the file, the open/close |
@@ -239,8 +240,7 @@ clusterip_hashfn(const struct sk_buff *skb, | |||
239 | break; | 240 | break; |
240 | default: | 241 | default: |
241 | if (net_ratelimit()) | 242 | if (net_ratelimit()) |
242 | printk(KERN_NOTICE "CLUSTERIP: unknown protocol `%u'\n", | 243 | pr_info("unknown protocol %u\n", iph->protocol); |
243 | iph->protocol); | ||
244 | sport = dport = 0; | 244 | sport = dport = 0; |
245 | } | 245 | } |
246 | 246 | ||
@@ -262,7 +262,7 @@ clusterip_hashfn(const struct sk_buff *skb, | |||
262 | hashval = 0; | 262 | hashval = 0; |
263 | /* This cannot happen, unless the check function wasn't called | 263 | /* This cannot happen, unless the check function wasn't called |
264 | * at rule load time */ | 264 | * at rule load time */ |
265 | printk("CLUSTERIP: unknown mode `%u'\n", config->hash_mode); | 265 | pr_info("unknown mode %u\n", config->hash_mode); |
266 | BUG(); | 266 | BUG(); |
267 | break; | 267 | break; |
268 | } | 268 | } |
@@ -282,7 +282,7 @@ clusterip_responsible(const struct clusterip_config *config, u_int32_t hash) | |||
282 | ***********************************************************************/ | 282 | ***********************************************************************/ |
283 | 283 | ||
284 | static unsigned int | 284 | static unsigned int |
285 | clusterip_tg(struct sk_buff *skb, const struct xt_target_param *par) | 285 | clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par) |
286 | { | 286 | { |
287 | const struct ipt_clusterip_tgt_info *cipinfo = par->targinfo; | 287 | const struct ipt_clusterip_tgt_info *cipinfo = par->targinfo; |
288 | struct nf_conn *ct; | 288 | struct nf_conn *ct; |
@@ -295,7 +295,7 @@ clusterip_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
295 | 295 | ||
296 | ct = nf_ct_get(skb, &ctinfo); | 296 | ct = nf_ct_get(skb, &ctinfo); |
297 | if (ct == NULL) { | 297 | if (ct == NULL) { |
298 | printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); | 298 | pr_info("no conntrack!\n"); |
299 | /* FIXME: need to drop invalid ones, since replies | 299 | /* FIXME: need to drop invalid ones, since replies |
300 | * to outgoing connections of other nodes will be | 300 | * to outgoing connections of other nodes will be |
301 | * marked as INVALID */ | 301 | * marked as INVALID */ |
@@ -348,25 +348,24 @@ clusterip_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
348 | return XT_CONTINUE; | 348 | return XT_CONTINUE; |
349 | } | 349 | } |
350 | 350 | ||
351 | static bool clusterip_tg_check(const struct xt_tgchk_param *par) | 351 | static int clusterip_tg_check(const struct xt_tgchk_param *par) |
352 | { | 352 | { |
353 | struct ipt_clusterip_tgt_info *cipinfo = par->targinfo; | 353 | struct ipt_clusterip_tgt_info *cipinfo = par->targinfo; |
354 | const struct ipt_entry *e = par->entryinfo; | 354 | const struct ipt_entry *e = par->entryinfo; |
355 | |||
356 | struct clusterip_config *config; | 355 | struct clusterip_config *config; |
356 | int ret; | ||
357 | 357 | ||
358 | if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP && | 358 | if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP && |
359 | cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT && | 359 | cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT && |
360 | cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) { | 360 | cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) { |
361 | printk(KERN_WARNING "CLUSTERIP: unknown mode `%u'\n", | 361 | pr_info("unknown mode %u\n", cipinfo->hash_mode); |
362 | cipinfo->hash_mode); | 362 | return -EINVAL; |
363 | return false; | ||
364 | 363 | ||
365 | } | 364 | } |
366 | if (e->ip.dmsk.s_addr != htonl(0xffffffff) || | 365 | if (e->ip.dmsk.s_addr != htonl(0xffffffff) || |
367 | e->ip.dst.s_addr == 0) { | 366 | e->ip.dst.s_addr == 0) { |
368 | printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n"); | 367 | pr_info("Please specify destination IP\n"); |
369 | return false; | 368 | return -EINVAL; |
370 | } | 369 | } |
371 | 370 | ||
372 | /* FIXME: further sanity checks */ | 371 | /* FIXME: further sanity checks */ |
@@ -374,41 +373,41 @@ static bool clusterip_tg_check(const struct xt_tgchk_param *par) | |||
374 | config = clusterip_config_find_get(e->ip.dst.s_addr, 1); | 373 | config = clusterip_config_find_get(e->ip.dst.s_addr, 1); |
375 | if (!config) { | 374 | if (!config) { |
376 | if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { | 375 | if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { |
377 | printk(KERN_WARNING "CLUSTERIP: no config found for %pI4, need 'new'\n", &e->ip.dst.s_addr); | 376 | pr_info("no config found for %pI4, need 'new'\n", |
378 | return false; | 377 | &e->ip.dst.s_addr); |
378 | return -EINVAL; | ||
379 | } else { | 379 | } else { |
380 | struct net_device *dev; | 380 | struct net_device *dev; |
381 | 381 | ||
382 | if (e->ip.iniface[0] == '\0') { | 382 | if (e->ip.iniface[0] == '\0') { |
383 | printk(KERN_WARNING "CLUSTERIP: Please specify an interface name\n"); | 383 | pr_info("Please specify an interface name\n"); |
384 | return false; | 384 | return -EINVAL; |
385 | } | 385 | } |
386 | 386 | ||
387 | dev = dev_get_by_name(&init_net, e->ip.iniface); | 387 | dev = dev_get_by_name(&init_net, e->ip.iniface); |
388 | if (!dev) { | 388 | if (!dev) { |
389 | printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface); | 389 | pr_info("no such interface %s\n", |
390 | return false; | 390 | e->ip.iniface); |
391 | return -ENOENT; | ||
391 | } | 392 | } |
392 | 393 | ||
393 | config = clusterip_config_init(cipinfo, | 394 | config = clusterip_config_init(cipinfo, |
394 | e->ip.dst.s_addr, dev); | 395 | e->ip.dst.s_addr, dev); |
395 | if (!config) { | 396 | if (!config) { |
396 | printk(KERN_WARNING "CLUSTERIP: cannot allocate config\n"); | 397 | pr_info("cannot allocate config\n"); |
397 | dev_put(dev); | 398 | dev_put(dev); |
398 | return false; | 399 | return -ENOMEM; |
399 | } | 400 | } |
400 | dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); | 401 | dev_mc_add(config->dev, config->clustermac); |
401 | } | 402 | } |
402 | } | 403 | } |
403 | cipinfo->config = config; | 404 | cipinfo->config = config; |
404 | 405 | ||
405 | if (nf_ct_l3proto_try_module_get(par->target->family) < 0) { | 406 | ret = nf_ct_l3proto_try_module_get(par->family); |
406 | printk(KERN_WARNING "can't load conntrack support for " | 407 | if (ret < 0) |
407 | "proto=%u\n", par->target->family); | 408 | pr_info("cannot load conntrack support for proto=%u\n", |
408 | return false; | 409 | par->family); |
409 | } | 410 | return ret; |
410 | |||
411 | return true; | ||
412 | } | 411 | } |
413 | 412 | ||
414 | /* drop reference count of cluster config when rule is deleted */ | 413 | /* drop reference count of cluster config when rule is deleted */ |
@@ -422,7 +421,7 @@ static void clusterip_tg_destroy(const struct xt_tgdtor_param *par) | |||
422 | 421 | ||
423 | clusterip_config_put(cipinfo->config); | 422 | clusterip_config_put(cipinfo->config); |
424 | 423 | ||
425 | nf_ct_l3proto_module_put(par->target->family); | 424 | nf_ct_l3proto_module_put(par->family); |
426 | } | 425 | } |
427 | 426 | ||
428 | #ifdef CONFIG_COMPAT | 427 | #ifdef CONFIG_COMPAT |
@@ -479,8 +478,8 @@ static void arp_print(struct arp_payload *payload) | |||
479 | } | 478 | } |
480 | hbuffer[--k]='\0'; | 479 | hbuffer[--k]='\0'; |
481 | 480 | ||
482 | printk("src %pI4@%s, dst %pI4\n", | 481 | pr_debug("src %pI4@%s, dst %pI4\n", |
483 | &payload->src_ip, hbuffer, &payload->dst_ip); | 482 | &payload->src_ip, hbuffer, &payload->dst_ip); |
484 | } | 483 | } |
485 | #endif | 484 | #endif |
486 | 485 | ||
@@ -519,7 +518,7 @@ arp_mangle(unsigned int hook, | |||
519 | * this wouldn't work, since we didn't subscribe the mcast group on | 518 | * this wouldn't work, since we didn't subscribe the mcast group on |
520 | * other interfaces */ | 519 | * other interfaces */ |
521 | if (c->dev != out) { | 520 | if (c->dev != out) { |
522 | pr_debug("CLUSTERIP: not mangling arp reply on different " | 521 | pr_debug("not mangling arp reply on different " |
523 | "interface: cip'%s'-skb'%s'\n", | 522 | "interface: cip'%s'-skb'%s'\n", |
524 | c->dev->name, out->name); | 523 | c->dev->name, out->name); |
525 | clusterip_config_put(c); | 524 | clusterip_config_put(c); |
@@ -530,7 +529,7 @@ arp_mangle(unsigned int hook, | |||
530 | memcpy(payload->src_hw, c->clustermac, arp->ar_hln); | 529 | memcpy(payload->src_hw, c->clustermac, arp->ar_hln); |
531 | 530 | ||
532 | #ifdef DEBUG | 531 | #ifdef DEBUG |
533 | pr_debug(KERN_DEBUG "CLUSTERIP mangled arp reply: "); | 532 | pr_debug("mangled arp reply: "); |
534 | arp_print(payload); | 533 | arp_print(payload); |
535 | #endif | 534 | #endif |
536 | 535 | ||
@@ -601,7 +600,8 @@ static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos) | |||
601 | 600 | ||
602 | static void clusterip_seq_stop(struct seq_file *s, void *v) | 601 | static void clusterip_seq_stop(struct seq_file *s, void *v) |
603 | { | 602 | { |
604 | kfree(v); | 603 | if (!IS_ERR(v)) |
604 | kfree(v); | ||
605 | } | 605 | } |
606 | 606 | ||
607 | static int clusterip_seq_show(struct seq_file *s, void *v) | 607 | static int clusterip_seq_show(struct seq_file *s, void *v) |
@@ -706,13 +706,13 @@ static int __init clusterip_tg_init(void) | |||
706 | #ifdef CONFIG_PROC_FS | 706 | #ifdef CONFIG_PROC_FS |
707 | clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", init_net.proc_net); | 707 | clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", init_net.proc_net); |
708 | if (!clusterip_procdir) { | 708 | if (!clusterip_procdir) { |
709 | printk(KERN_ERR "CLUSTERIP: Unable to proc dir entry\n"); | 709 | pr_err("Unable to proc dir entry\n"); |
710 | ret = -ENOMEM; | 710 | ret = -ENOMEM; |
711 | goto cleanup_hook; | 711 | goto cleanup_hook; |
712 | } | 712 | } |
713 | #endif /* CONFIG_PROC_FS */ | 713 | #endif /* CONFIG_PROC_FS */ |
714 | 714 | ||
715 | printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n", | 715 | pr_info("ClusterIP Version %s loaded successfully\n", |
716 | CLUSTERIP_VERSION); | 716 | CLUSTERIP_VERSION); |
717 | return 0; | 717 | return 0; |
718 | 718 | ||
@@ -727,8 +727,7 @@ cleanup_target: | |||
727 | 727 | ||
728 | static void __exit clusterip_tg_exit(void) | 728 | static void __exit clusterip_tg_exit(void) |
729 | { | 729 | { |
730 | printk(KERN_NOTICE "ClusterIP Version %s unloading\n", | 730 | pr_info("ClusterIP Version %s unloading\n", CLUSTERIP_VERSION); |
731 | CLUSTERIP_VERSION); | ||
732 | #ifdef CONFIG_PROC_FS | 731 | #ifdef CONFIG_PROC_FS |
733 | remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent); | 732 | remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent); |
734 | #endif | 733 | #endif |
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index ea5cea2415c1..4bf3dc49ad1e 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/in.h> | 10 | #include <linux/in.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
@@ -77,7 +77,7 @@ set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo) | |||
77 | } | 77 | } |
78 | 78 | ||
79 | static unsigned int | 79 | static unsigned int |
80 | ecn_tg(struct sk_buff *skb, const struct xt_target_param *par) | 80 | ecn_tg(struct sk_buff *skb, const struct xt_action_param *par) |
81 | { | 81 | { |
82 | const struct ipt_ECN_info *einfo = par->targinfo; | 82 | const struct ipt_ECN_info *einfo = par->targinfo; |
83 | 83 | ||
@@ -93,28 +93,25 @@ ecn_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
93 | return XT_CONTINUE; | 93 | return XT_CONTINUE; |
94 | } | 94 | } |
95 | 95 | ||
96 | static bool ecn_tg_check(const struct xt_tgchk_param *par) | 96 | static int ecn_tg_check(const struct xt_tgchk_param *par) |
97 | { | 97 | { |
98 | const struct ipt_ECN_info *einfo = par->targinfo; | 98 | const struct ipt_ECN_info *einfo = par->targinfo; |
99 | const struct ipt_entry *e = par->entryinfo; | 99 | const struct ipt_entry *e = par->entryinfo; |
100 | 100 | ||
101 | if (einfo->operation & IPT_ECN_OP_MASK) { | 101 | if (einfo->operation & IPT_ECN_OP_MASK) { |
102 | printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", | 102 | pr_info("unsupported ECN operation %x\n", einfo->operation); |
103 | einfo->operation); | 103 | return -EINVAL; |
104 | return false; | ||
105 | } | 104 | } |
106 | if (einfo->ip_ect & ~IPT_ECN_IP_MASK) { | 105 | if (einfo->ip_ect & ~IPT_ECN_IP_MASK) { |
107 | printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n", | 106 | pr_info("new ECT codepoint %x out of mask\n", einfo->ip_ect); |
108 | einfo->ip_ect); | 107 | return -EINVAL; |
109 | return false; | ||
110 | } | 108 | } |
111 | if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) && | 109 | if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) && |
112 | (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) { | 110 | (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) { |
113 | printk(KERN_WARNING "ECN: cannot use TCP operations on a " | 111 | pr_info("cannot use TCP operations on a non-tcp rule\n"); |
114 | "non-tcp rule\n"); | 112 | return -EINVAL; |
115 | return false; | ||
116 | } | 113 | } |
117 | return true; | 114 | return 0; |
118 | } | 115 | } |
119 | 116 | ||
120 | static struct xt_target ecn_tg_reg __read_mostly = { | 117 | static struct xt_target ecn_tg_reg __read_mostly = { |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index ee128efa1c8d..5234f4f3499a 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/skbuff.h> | 15 | #include <linux/skbuff.h> |
@@ -367,7 +367,7 @@ static struct nf_loginfo default_loginfo = { | |||
367 | .type = NF_LOG_TYPE_LOG, | 367 | .type = NF_LOG_TYPE_LOG, |
368 | .u = { | 368 | .u = { |
369 | .log = { | 369 | .log = { |
370 | .level = 0, | 370 | .level = 5, |
371 | .logflags = NF_LOG_MASK, | 371 | .logflags = NF_LOG_MASK, |
372 | }, | 372 | }, |
373 | }, | 373 | }, |
@@ -425,7 +425,7 @@ ipt_log_packet(u_int8_t pf, | |||
425 | } | 425 | } |
426 | 426 | ||
427 | static unsigned int | 427 | static unsigned int |
428 | log_tg(struct sk_buff *skb, const struct xt_target_param *par) | 428 | log_tg(struct sk_buff *skb, const struct xt_action_param *par) |
429 | { | 429 | { |
430 | const struct ipt_log_info *loginfo = par->targinfo; | 430 | const struct ipt_log_info *loginfo = par->targinfo; |
431 | struct nf_loginfo li; | 431 | struct nf_loginfo li; |
@@ -439,20 +439,19 @@ log_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
439 | return XT_CONTINUE; | 439 | return XT_CONTINUE; |
440 | } | 440 | } |
441 | 441 | ||
442 | static bool log_tg_check(const struct xt_tgchk_param *par) | 442 | static int log_tg_check(const struct xt_tgchk_param *par) |
443 | { | 443 | { |
444 | const struct ipt_log_info *loginfo = par->targinfo; | 444 | const struct ipt_log_info *loginfo = par->targinfo; |
445 | 445 | ||
446 | if (loginfo->level >= 8) { | 446 | if (loginfo->level >= 8) { |
447 | pr_debug("LOG: level %u >= 8\n", loginfo->level); | 447 | pr_debug("level %u >= 8\n", loginfo->level); |
448 | return false; | 448 | return -EINVAL; |
449 | } | 449 | } |
450 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { | 450 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { |
451 | pr_debug("LOG: prefix term %i\n", | 451 | pr_debug("prefix is not null-terminated\n"); |
452 | loginfo->prefix[sizeof(loginfo->prefix)-1]); | 452 | return -EINVAL; |
453 | return false; | ||
454 | } | 453 | } |
455 | return true; | 454 | return 0; |
456 | } | 455 | } |
457 | 456 | ||
458 | static struct xt_target log_tg_reg __read_mostly = { | 457 | static struct xt_target log_tg_reg __read_mostly = { |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 650b54042b01..d2ed9dc74ebc 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/inetdevice.h> | 13 | #include <linux/inetdevice.h> |
14 | #include <linux/ip.h> | 14 | #include <linux/ip.h> |
@@ -28,23 +28,23 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | |||
28 | MODULE_DESCRIPTION("Xtables: automatic-address SNAT"); | 28 | MODULE_DESCRIPTION("Xtables: automatic-address SNAT"); |
29 | 29 | ||
30 | /* FIXME: Multiple targets. --RR */ | 30 | /* FIXME: Multiple targets. --RR */ |
31 | static bool masquerade_tg_check(const struct xt_tgchk_param *par) | 31 | static int masquerade_tg_check(const struct xt_tgchk_param *par) |
32 | { | 32 | { |
33 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 33 | const struct nf_nat_multi_range_compat *mr = par->targinfo; |
34 | 34 | ||
35 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { | 35 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { |
36 | pr_debug("masquerade_check: bad MAP_IPS.\n"); | 36 | pr_debug("bad MAP_IPS.\n"); |
37 | return false; | 37 | return -EINVAL; |
38 | } | 38 | } |
39 | if (mr->rangesize != 1) { | 39 | if (mr->rangesize != 1) { |
40 | pr_debug("masquerade_check: bad rangesize %u\n", mr->rangesize); | 40 | pr_debug("bad rangesize %u\n", mr->rangesize); |
41 | return false; | 41 | return -EINVAL; |
42 | } | 42 | } |
43 | return true; | 43 | return 0; |
44 | } | 44 | } |
45 | 45 | ||
46 | static unsigned int | 46 | static unsigned int |
47 | masquerade_tg(struct sk_buff *skb, const struct xt_target_param *par) | 47 | masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) |
48 | { | 48 | { |
49 | struct nf_conn *ct; | 49 | struct nf_conn *ct; |
50 | struct nf_conn_nat *nat; | 50 | struct nf_conn_nat *nat; |
@@ -72,7 +72,7 @@ masquerade_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
72 | rt = skb_rtable(skb); | 72 | rt = skb_rtable(skb); |
73 | newsrc = inet_select_addr(par->out, rt->rt_gateway, RT_SCOPE_UNIVERSE); | 73 | newsrc = inet_select_addr(par->out, rt->rt_gateway, RT_SCOPE_UNIVERSE); |
74 | if (!newsrc) { | 74 | if (!newsrc) { |
75 | printk("MASQUERADE: %s ate my IP address\n", par->out->name); | 75 | pr_info("%s ate my IP address\n", par->out->name); |
76 | return NF_DROP; | 76 | return NF_DROP; |
77 | } | 77 | } |
78 | 78 | ||
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index 7c29582d4ec8..f43867d1697f 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/ip.h> | 13 | #include <linux/ip.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
@@ -22,23 +22,23 @@ MODULE_LICENSE("GPL"); | |||
22 | MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); | 22 | MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); |
23 | MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets"); | 23 | MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets"); |
24 | 24 | ||
25 | static bool netmap_tg_check(const struct xt_tgchk_param *par) | 25 | static int netmap_tg_check(const struct xt_tgchk_param *par) |
26 | { | 26 | { |
27 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 27 | const struct nf_nat_multi_range_compat *mr = par->targinfo; |
28 | 28 | ||
29 | if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { | 29 | if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { |
30 | pr_debug("NETMAP:check: bad MAP_IPS.\n"); | 30 | pr_debug("bad MAP_IPS.\n"); |
31 | return false; | 31 | return -EINVAL; |
32 | } | 32 | } |
33 | if (mr->rangesize != 1) { | 33 | if (mr->rangesize != 1) { |
34 | pr_debug("NETMAP:check: bad rangesize %u.\n", mr->rangesize); | 34 | pr_debug("bad rangesize %u.\n", mr->rangesize); |
35 | return false; | 35 | return -EINVAL; |
36 | } | 36 | } |
37 | return true; | 37 | return 0; |
38 | } | 38 | } |
39 | 39 | ||
40 | static unsigned int | 40 | static unsigned int |
41 | netmap_tg(struct sk_buff *skb, const struct xt_target_param *par) | 41 | netmap_tg(struct sk_buff *skb, const struct xt_action_param *par) |
42 | { | 42 | { |
43 | struct nf_conn *ct; | 43 | struct nf_conn *ct; |
44 | enum ip_conntrack_info ctinfo; | 44 | enum ip_conntrack_info ctinfo; |
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 698e5e78685b..18a0656505a0 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <linux/ip.h> | 11 | #include <linux/ip.h> |
12 | #include <linux/timer.h> | 12 | #include <linux/timer.h> |
@@ -26,23 +26,23 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | |||
26 | MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); | 26 | MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); |
27 | 27 | ||
28 | /* FIXME: Take multiple ranges --RR */ | 28 | /* FIXME: Take multiple ranges --RR */ |
29 | static bool redirect_tg_check(const struct xt_tgchk_param *par) | 29 | static int redirect_tg_check(const struct xt_tgchk_param *par) |
30 | { | 30 | { |
31 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 31 | const struct nf_nat_multi_range_compat *mr = par->targinfo; |
32 | 32 | ||
33 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { | 33 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { |
34 | pr_debug("redirect_check: bad MAP_IPS.\n"); | 34 | pr_debug("bad MAP_IPS.\n"); |
35 | return false; | 35 | return -EINVAL; |
36 | } | 36 | } |
37 | if (mr->rangesize != 1) { | 37 | if (mr->rangesize != 1) { |
38 | pr_debug("redirect_check: bad rangesize %u.\n", mr->rangesize); | 38 | pr_debug("bad rangesize %u.\n", mr->rangesize); |
39 | return false; | 39 | return -EINVAL; |
40 | } | 40 | } |
41 | return true; | 41 | return 0; |
42 | } | 42 | } |
43 | 43 | ||
44 | static unsigned int | 44 | static unsigned int |
45 | redirect_tg(struct sk_buff *skb, const struct xt_target_param *par) | 45 | redirect_tg(struct sk_buff *skb, const struct xt_action_param *par) |
46 | { | 46 | { |
47 | struct nf_conn *ct; | 47 | struct nf_conn *ct; |
48 | enum ip_conntrack_info ctinfo; | 48 | enum ip_conntrack_info ctinfo; |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index a0e8bcf04159..f5f4a888e4ec 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
@@ -136,13 +136,10 @@ static inline void send_unreach(struct sk_buff *skb_in, int code) | |||
136 | } | 136 | } |
137 | 137 | ||
138 | static unsigned int | 138 | static unsigned int |
139 | reject_tg(struct sk_buff *skb, const struct xt_target_param *par) | 139 | reject_tg(struct sk_buff *skb, const struct xt_action_param *par) |
140 | { | 140 | { |
141 | const struct ipt_reject_info *reject = par->targinfo; | 141 | const struct ipt_reject_info *reject = par->targinfo; |
142 | 142 | ||
143 | /* WARNING: This code causes reentry within iptables. | ||
144 | This means that the iptables jump stack is now crap. We | ||
145 | must return an absolute verdict. --RR */ | ||
146 | switch (reject->with) { | 143 | switch (reject->with) { |
147 | case IPT_ICMP_NET_UNREACHABLE: | 144 | case IPT_ICMP_NET_UNREACHABLE: |
148 | send_unreach(skb, ICMP_NET_UNREACH); | 145 | send_unreach(skb, ICMP_NET_UNREACH); |
@@ -175,23 +172,23 @@ reject_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
175 | return NF_DROP; | 172 | return NF_DROP; |
176 | } | 173 | } |
177 | 174 | ||
178 | static bool reject_tg_check(const struct xt_tgchk_param *par) | 175 | static int reject_tg_check(const struct xt_tgchk_param *par) |
179 | { | 176 | { |
180 | const struct ipt_reject_info *rejinfo = par->targinfo; | 177 | const struct ipt_reject_info *rejinfo = par->targinfo; |
181 | const struct ipt_entry *e = par->entryinfo; | 178 | const struct ipt_entry *e = par->entryinfo; |
182 | 179 | ||
183 | if (rejinfo->with == IPT_ICMP_ECHOREPLY) { | 180 | if (rejinfo->with == IPT_ICMP_ECHOREPLY) { |
184 | printk("ipt_REJECT: ECHOREPLY no longer supported.\n"); | 181 | pr_info("ECHOREPLY no longer supported.\n"); |
185 | return false; | 182 | return -EINVAL; |
186 | } else if (rejinfo->with == IPT_TCP_RESET) { | 183 | } else if (rejinfo->with == IPT_TCP_RESET) { |
187 | /* Must specify that it's a TCP packet */ | 184 | /* Must specify that it's a TCP packet */ |
188 | if (e->ip.proto != IPPROTO_TCP || | 185 | if (e->ip.proto != IPPROTO_TCP || |
189 | (e->ip.invflags & XT_INV_PROTO)) { | 186 | (e->ip.invflags & XT_INV_PROTO)) { |
190 | printk("ipt_REJECT: TCP_RESET invalid for non-tcp\n"); | 187 | pr_info("TCP_RESET invalid for non-tcp\n"); |
191 | return false; | 188 | return -EINVAL; |
192 | } | 189 | } |
193 | } | 190 | } |
194 | return true; | 191 | return 0; |
195 | } | 192 | } |
196 | 193 | ||
197 | static struct xt_target reject_tg_reg __read_mostly = { | 194 | static struct xt_target reject_tg_reg __read_mostly = { |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 0dbe697f164f..446e0f467a17 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -29,7 +29,7 @@ | |||
29 | * Specify, after how many hundredths of a second the queue should be | 29 | * Specify, after how many hundredths of a second the queue should be |
30 | * flushed even if it is not full yet. | 30 | * flushed even if it is not full yet. |
31 | */ | 31 | */ |
32 | 32 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
35 | #include <linux/socket.h> | 35 | #include <linux/socket.h> |
@@ -57,8 +57,6 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG); | |||
57 | #define ULOG_NL_EVENT 111 /* Harald's favorite number */ | 57 | #define ULOG_NL_EVENT 111 /* Harald's favorite number */ |
58 | #define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */ | 58 | #define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */ |
59 | 59 | ||
60 | #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) | ||
61 | |||
62 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; | 60 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; |
63 | module_param(nlbufsiz, uint, 0400); | 61 | module_param(nlbufsiz, uint, 0400); |
64 | MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); | 62 | MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); |
@@ -91,12 +89,12 @@ static void ulog_send(unsigned int nlgroupnum) | |||
91 | ulog_buff_t *ub = &ulog_buffers[nlgroupnum]; | 89 | ulog_buff_t *ub = &ulog_buffers[nlgroupnum]; |
92 | 90 | ||
93 | if (timer_pending(&ub->timer)) { | 91 | if (timer_pending(&ub->timer)) { |
94 | pr_debug("ipt_ULOG: ulog_send: timer was pending, deleting\n"); | 92 | pr_debug("ulog_send: timer was pending, deleting\n"); |
95 | del_timer(&ub->timer); | 93 | del_timer(&ub->timer); |
96 | } | 94 | } |
97 | 95 | ||
98 | if (!ub->skb) { | 96 | if (!ub->skb) { |
99 | pr_debug("ipt_ULOG: ulog_send: nothing to send\n"); | 97 | pr_debug("ulog_send: nothing to send\n"); |
100 | return; | 98 | return; |
101 | } | 99 | } |
102 | 100 | ||
@@ -105,7 +103,7 @@ static void ulog_send(unsigned int nlgroupnum) | |||
105 | ub->lastnlh->nlmsg_type = NLMSG_DONE; | 103 | ub->lastnlh->nlmsg_type = NLMSG_DONE; |
106 | 104 | ||
107 | NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1; | 105 | NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1; |
108 | pr_debug("ipt_ULOG: throwing %d packets to netlink group %u\n", | 106 | pr_debug("throwing %d packets to netlink group %u\n", |
109 | ub->qlen, nlgroupnum + 1); | 107 | ub->qlen, nlgroupnum + 1); |
110 | netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC); | 108 | netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC); |
111 | 109 | ||
@@ -118,7 +116,7 @@ static void ulog_send(unsigned int nlgroupnum) | |||
118 | /* timer function to flush queue in flushtimeout time */ | 116 | /* timer function to flush queue in flushtimeout time */ |
119 | static void ulog_timer(unsigned long data) | 117 | static void ulog_timer(unsigned long data) |
120 | { | 118 | { |
121 | pr_debug("ipt_ULOG: timer function called, calling ulog_send\n"); | 119 | pr_debug("timer function called, calling ulog_send\n"); |
122 | 120 | ||
123 | /* lock to protect against somebody modifying our structure | 121 | /* lock to protect against somebody modifying our structure |
124 | * from ipt_ulog_target at the same time */ | 122 | * from ipt_ulog_target at the same time */ |
@@ -139,7 +137,7 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size) | |||
139 | n = max(size, nlbufsiz); | 137 | n = max(size, nlbufsiz); |
140 | skb = alloc_skb(n, GFP_ATOMIC); | 138 | skb = alloc_skb(n, GFP_ATOMIC); |
141 | if (!skb) { | 139 | if (!skb) { |
142 | PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", n); | 140 | pr_debug("cannot alloc whole buffer %ub!\n", n); |
143 | 141 | ||
144 | if (n > size) { | 142 | if (n > size) { |
145 | /* try to allocate only as much as we need for | 143 | /* try to allocate only as much as we need for |
@@ -147,8 +145,7 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size) | |||
147 | 145 | ||
148 | skb = alloc_skb(size, GFP_ATOMIC); | 146 | skb = alloc_skb(size, GFP_ATOMIC); |
149 | if (!skb) | 147 | if (!skb) |
150 | PRINTR("ipt_ULOG: can't even allocate %ub\n", | 148 | pr_debug("cannot even allocate %ub\n", size); |
151 | size); | ||
152 | } | 149 | } |
153 | } | 150 | } |
154 | 151 | ||
@@ -199,8 +196,7 @@ static void ipt_ulog_packet(unsigned int hooknum, | |||
199 | goto alloc_failure; | 196 | goto alloc_failure; |
200 | } | 197 | } |
201 | 198 | ||
202 | pr_debug("ipt_ULOG: qlen %d, qthreshold %Zu\n", ub->qlen, | 199 | pr_debug("qlen %d, qthreshold %Zu\n", ub->qlen, loginfo->qthreshold); |
203 | loginfo->qthreshold); | ||
204 | 200 | ||
205 | /* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */ | 201 | /* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */ |
206 | nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, | 202 | nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, |
@@ -273,16 +269,14 @@ static void ipt_ulog_packet(unsigned int hooknum, | |||
273 | return; | 269 | return; |
274 | 270 | ||
275 | nlmsg_failure: | 271 | nlmsg_failure: |
276 | PRINTR("ipt_ULOG: error during NLMSG_PUT\n"); | 272 | pr_debug("error during NLMSG_PUT\n"); |
277 | |||
278 | alloc_failure: | 273 | alloc_failure: |
279 | PRINTR("ipt_ULOG: Error building netlink message\n"); | 274 | pr_debug("Error building netlink message\n"); |
280 | |||
281 | spin_unlock_bh(&ulog_lock); | 275 | spin_unlock_bh(&ulog_lock); |
282 | } | 276 | } |
283 | 277 | ||
284 | static unsigned int | 278 | static unsigned int |
285 | ulog_tg(struct sk_buff *skb, const struct xt_target_param *par) | 279 | ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) |
286 | { | 280 | { |
287 | ipt_ulog_packet(par->hooknum, skb, par->in, par->out, | 281 | ipt_ulog_packet(par->hooknum, skb, par->in, par->out, |
288 | par->targinfo, NULL); | 282 | par->targinfo, NULL); |
@@ -314,21 +308,20 @@ static void ipt_logfn(u_int8_t pf, | |||
314 | ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); | 308 | ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); |
315 | } | 309 | } |
316 | 310 | ||
317 | static bool ulog_tg_check(const struct xt_tgchk_param *par) | 311 | static int ulog_tg_check(const struct xt_tgchk_param *par) |
318 | { | 312 | { |
319 | const struct ipt_ulog_info *loginfo = par->targinfo; | 313 | const struct ipt_ulog_info *loginfo = par->targinfo; |
320 | 314 | ||
321 | if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { | 315 | if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { |
322 | pr_debug("ipt_ULOG: prefix term %i\n", | 316 | pr_debug("prefix not null-terminated\n"); |
323 | loginfo->prefix[sizeof(loginfo->prefix) - 1]); | 317 | return -EINVAL; |
324 | return false; | ||
325 | } | 318 | } |
326 | if (loginfo->qthreshold > ULOG_MAX_QLEN) { | 319 | if (loginfo->qthreshold > ULOG_MAX_QLEN) { |
327 | pr_debug("ipt_ULOG: queue threshold %Zu > MAX_QLEN\n", | 320 | pr_debug("queue threshold %Zu > MAX_QLEN\n", |
328 | loginfo->qthreshold); | 321 | loginfo->qthreshold); |
329 | return false; | 322 | return -EINVAL; |
330 | } | 323 | } |
331 | return true; | 324 | return 0; |
332 | } | 325 | } |
333 | 326 | ||
334 | #ifdef CONFIG_COMPAT | 327 | #ifdef CONFIG_COMPAT |
@@ -390,10 +383,10 @@ static int __init ulog_tg_init(void) | |||
390 | { | 383 | { |
391 | int ret, i; | 384 | int ret, i; |
392 | 385 | ||
393 | pr_debug("ipt_ULOG: init module\n"); | 386 | pr_debug("init module\n"); |
394 | 387 | ||
395 | if (nlbufsiz > 128*1024) { | 388 | if (nlbufsiz > 128*1024) { |
396 | printk("Netlink buffer has to be <= 128kB\n"); | 389 | pr_warning("Netlink buffer has to be <= 128kB\n"); |
397 | return -EINVAL; | 390 | return -EINVAL; |
398 | } | 391 | } |
399 | 392 | ||
@@ -423,7 +416,7 @@ static void __exit ulog_tg_exit(void) | |||
423 | ulog_buff_t *ub; | 416 | ulog_buff_t *ub; |
424 | int i; | 417 | int i; |
425 | 418 | ||
426 | pr_debug("ipt_ULOG: cleanup_module\n"); | 419 | pr_debug("cleanup_module\n"); |
427 | 420 | ||
428 | if (nflog) | 421 | if (nflog) |
429 | nf_log_unregister(&ipt_ulog_logger); | 422 | nf_log_unregister(&ipt_ulog_logger); |
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index 3b216be3bc9f..db8bff0fb86d 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
@@ -30,7 +30,7 @@ static inline bool match_type(struct net *net, const struct net_device *dev, | |||
30 | } | 30 | } |
31 | 31 | ||
32 | static bool | 32 | static bool |
33 | addrtype_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) | 33 | addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par) |
34 | { | 34 | { |
35 | struct net *net = dev_net(par->in ? par->in : par->out); | 35 | struct net *net = dev_net(par->in ? par->in : par->out); |
36 | const struct ipt_addrtype_info *info = par->matchinfo; | 36 | const struct ipt_addrtype_info *info = par->matchinfo; |
@@ -48,7 +48,7 @@ addrtype_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) | |||
48 | } | 48 | } |
49 | 49 | ||
50 | static bool | 50 | static bool |
51 | addrtype_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | 51 | addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) |
52 | { | 52 | { |
53 | struct net *net = dev_net(par->in ? par->in : par->out); | 53 | struct net *net = dev_net(par->in ? par->in : par->out); |
54 | const struct ipt_addrtype_info_v1 *info = par->matchinfo; | 54 | const struct ipt_addrtype_info_v1 *info = par->matchinfo; |
@@ -70,34 +70,34 @@ addrtype_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | |||
70 | return ret; | 70 | return ret; |
71 | } | 71 | } |
72 | 72 | ||
73 | static bool addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par) | 73 | static int addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par) |
74 | { | 74 | { |
75 | struct ipt_addrtype_info_v1 *info = par->matchinfo; | 75 | struct ipt_addrtype_info_v1 *info = par->matchinfo; |
76 | 76 | ||
77 | if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN && | 77 | if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN && |
78 | info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { | 78 | info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { |
79 | printk(KERN_ERR "ipt_addrtype: both incoming and outgoing " | 79 | pr_info("both incoming and outgoing " |
80 | "interface limitation cannot be selected\n"); | 80 | "interface limitation cannot be selected\n"); |
81 | return false; | 81 | return -EINVAL; |
82 | } | 82 | } |
83 | 83 | ||
84 | if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) | | 84 | if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) | |
85 | (1 << NF_INET_LOCAL_IN)) && | 85 | (1 << NF_INET_LOCAL_IN)) && |
86 | info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { | 86 | info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) { |
87 | printk(KERN_ERR "ipt_addrtype: output interface limitation " | 87 | pr_info("output interface limitation " |
88 | "not valid in PRE_ROUTING and INPUT\n"); | 88 | "not valid in PREROUTING and INPUT\n"); |
89 | return false; | 89 | return -EINVAL; |
90 | } | 90 | } |
91 | 91 | ||
92 | if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) | | 92 | if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) | |
93 | (1 << NF_INET_LOCAL_OUT)) && | 93 | (1 << NF_INET_LOCAL_OUT)) && |
94 | info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { | 94 | info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) { |
95 | printk(KERN_ERR "ipt_addrtype: input interface limitation " | 95 | pr_info("input interface limitation " |
96 | "not valid in POST_ROUTING and OUTPUT\n"); | 96 | "not valid in POSTROUTING and OUTPUT\n"); |
97 | return false; | 97 | return -EINVAL; |
98 | } | 98 | } |
99 | 99 | ||
100 | return true; | 100 | return 0; |
101 | } | 101 | } |
102 | 102 | ||
103 | static struct xt_match addrtype_mt_reg[] __read_mostly = { | 103 | static struct xt_match addrtype_mt_reg[] __read_mostly = { |
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c index 0104c0b399de..14a2aa8b8a14 100644 --- a/net/ipv4/netfilter/ipt_ah.c +++ b/net/ipv4/netfilter/ipt_ah.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | 8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
9 | #include <linux/in.h> | 9 | #include <linux/in.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
@@ -18,25 +18,19 @@ MODULE_LICENSE("GPL"); | |||
18 | MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>"); | 18 | MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>"); |
19 | MODULE_DESCRIPTION("Xtables: IPv4 IPsec-AH SPI match"); | 19 | MODULE_DESCRIPTION("Xtables: IPv4 IPsec-AH SPI match"); |
20 | 20 | ||
21 | #ifdef DEBUG_CONNTRACK | ||
22 | #define duprintf(format, args...) printk(format , ## args) | ||
23 | #else | ||
24 | #define duprintf(format, args...) | ||
25 | #endif | ||
26 | |||
27 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ | 21 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ |
28 | static inline bool | 22 | static inline bool |
29 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) | 23 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) |
30 | { | 24 | { |
31 | bool r; | 25 | bool r; |
32 | duprintf("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', | 26 | pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n", |
33 | min,spi,max); | 27 | invert ? '!' : ' ', min, spi, max); |
34 | r=(spi >= min && spi <= max) ^ invert; | 28 | r=(spi >= min && spi <= max) ^ invert; |
35 | duprintf(" result %s\n",r? "PASS" : "FAILED"); | 29 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
36 | return r; | 30 | return r; |
37 | } | 31 | } |
38 | 32 | ||
39 | static bool ah_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 33 | static bool ah_mt(const struct sk_buff *skb, struct xt_action_param *par) |
40 | { | 34 | { |
41 | struct ip_auth_hdr _ahdr; | 35 | struct ip_auth_hdr _ahdr; |
42 | const struct ip_auth_hdr *ah; | 36 | const struct ip_auth_hdr *ah; |
@@ -51,8 +45,8 @@ static bool ah_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
51 | /* We've been asked to examine this packet, and we | 45 | /* We've been asked to examine this packet, and we |
52 | * can't. Hence, no choice but to drop. | 46 | * can't. Hence, no choice but to drop. |
53 | */ | 47 | */ |
54 | duprintf("Dropping evil AH tinygram.\n"); | 48 | pr_debug("Dropping evil AH tinygram.\n"); |
55 | *par->hotdrop = true; | 49 | par->hotdrop = true; |
56 | return 0; | 50 | return 0; |
57 | } | 51 | } |
58 | 52 | ||
@@ -61,16 +55,16 @@ static bool ah_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
61 | !!(ahinfo->invflags & IPT_AH_INV_SPI)); | 55 | !!(ahinfo->invflags & IPT_AH_INV_SPI)); |
62 | } | 56 | } |
63 | 57 | ||
64 | static bool ah_mt_check(const struct xt_mtchk_param *par) | 58 | static int ah_mt_check(const struct xt_mtchk_param *par) |
65 | { | 59 | { |
66 | const struct ipt_ah *ahinfo = par->matchinfo; | 60 | const struct ipt_ah *ahinfo = par->matchinfo; |
67 | 61 | ||
68 | /* Must specify no unknown invflags */ | 62 | /* Must specify no unknown invflags */ |
69 | if (ahinfo->invflags & ~IPT_AH_INV_MASK) { | 63 | if (ahinfo->invflags & ~IPT_AH_INV_MASK) { |
70 | duprintf("ipt_ah: unknown flags %X\n", ahinfo->invflags); | 64 | pr_debug("unknown flags %X\n", ahinfo->invflags); |
71 | return false; | 65 | return -EINVAL; |
72 | } | 66 | } |
73 | return true; | 67 | return 0; |
74 | } | 68 | } |
75 | 69 | ||
76 | static struct xt_match ah_mt_reg __read_mostly = { | 70 | static struct xt_match ah_mt_reg __read_mostly = { |
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index 2a1e56b71908..af6e9c778345 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/in.h> | 10 | #include <linux/in.h> |
11 | #include <linux/ip.h> | 11 | #include <linux/ip.h> |
12 | #include <net/ip.h> | 12 | #include <net/ip.h> |
@@ -67,7 +67,7 @@ static inline bool match_tcp(const struct sk_buff *skb, | |||
67 | return true; | 67 | return true; |
68 | } | 68 | } |
69 | 69 | ||
70 | static bool ecn_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 70 | static bool ecn_mt(const struct sk_buff *skb, struct xt_action_param *par) |
71 | { | 71 | { |
72 | const struct ipt_ecn_info *info = par->matchinfo; | 72 | const struct ipt_ecn_info *info = par->matchinfo; |
73 | 73 | ||
@@ -78,32 +78,31 @@ static bool ecn_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
78 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { | 78 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { |
79 | if (ip_hdr(skb)->protocol != IPPROTO_TCP) | 79 | if (ip_hdr(skb)->protocol != IPPROTO_TCP) |
80 | return false; | 80 | return false; |
81 | if (!match_tcp(skb, info, par->hotdrop)) | 81 | if (!match_tcp(skb, info, &par->hotdrop)) |
82 | return false; | 82 | return false; |
83 | } | 83 | } |
84 | 84 | ||
85 | return true; | 85 | return true; |
86 | } | 86 | } |
87 | 87 | ||
88 | static bool ecn_mt_check(const struct xt_mtchk_param *par) | 88 | static int ecn_mt_check(const struct xt_mtchk_param *par) |
89 | { | 89 | { |
90 | const struct ipt_ecn_info *info = par->matchinfo; | 90 | const struct ipt_ecn_info *info = par->matchinfo; |
91 | const struct ipt_ip *ip = par->entryinfo; | 91 | const struct ipt_ip *ip = par->entryinfo; |
92 | 92 | ||
93 | if (info->operation & IPT_ECN_OP_MATCH_MASK) | 93 | if (info->operation & IPT_ECN_OP_MATCH_MASK) |
94 | return false; | 94 | return -EINVAL; |
95 | 95 | ||
96 | if (info->invert & IPT_ECN_OP_MATCH_MASK) | 96 | if (info->invert & IPT_ECN_OP_MATCH_MASK) |
97 | return false; | 97 | return -EINVAL; |
98 | 98 | ||
99 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) && | 99 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) && |
100 | ip->proto != IPPROTO_TCP) { | 100 | ip->proto != IPPROTO_TCP) { |
101 | printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for" | 101 | pr_info("cannot match TCP bits in rule for non-tcp packets\n"); |
102 | " non-tcp packets\n"); | 102 | return -EINVAL; |
103 | return false; | ||
104 | } | 103 | } |
105 | 104 | ||
106 | return true; | 105 | return 0; |
107 | } | 106 | } |
108 | 107 | ||
109 | static struct xt_match ecn_mt_reg __read_mostly = { | 108 | static struct xt_match ecn_mt_reg __read_mostly = { |
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 55392466daa4..c37641e819f2 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -89,7 +89,7 @@ static int __init iptable_filter_init(void) | |||
89 | int ret; | 89 | int ret; |
90 | 90 | ||
91 | if (forward < 0 || forward > NF_MAX_VERDICT) { | 91 | if (forward < 0 || forward > NF_MAX_VERDICT) { |
92 | printk("iptables forward must be 0 or 1\n"); | 92 | pr_err("iptables forward must be 0 or 1\n"); |
93 | return -EINVAL; | 93 | return -EINVAL; |
94 | } | 94 | } |
95 | 95 | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 2bb1f87051c4..5a03c02af999 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -382,32 +382,32 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) | |||
382 | 382 | ||
383 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4); | 383 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4); |
384 | if (ret < 0) { | 384 | if (ret < 0) { |
385 | printk("nf_conntrack_ipv4: can't register tcp.\n"); | 385 | pr_err("nf_conntrack_ipv4: can't register tcp.\n"); |
386 | goto cleanup_sockopt; | 386 | goto cleanup_sockopt; |
387 | } | 387 | } |
388 | 388 | ||
389 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4); | 389 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4); |
390 | if (ret < 0) { | 390 | if (ret < 0) { |
391 | printk("nf_conntrack_ipv4: can't register udp.\n"); | 391 | pr_err("nf_conntrack_ipv4: can't register udp.\n"); |
392 | goto cleanup_tcp; | 392 | goto cleanup_tcp; |
393 | } | 393 | } |
394 | 394 | ||
395 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp); | 395 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp); |
396 | if (ret < 0) { | 396 | if (ret < 0) { |
397 | printk("nf_conntrack_ipv4: can't register icmp.\n"); | 397 | pr_err("nf_conntrack_ipv4: can't register icmp.\n"); |
398 | goto cleanup_udp; | 398 | goto cleanup_udp; |
399 | } | 399 | } |
400 | 400 | ||
401 | ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4); | 401 | ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4); |
402 | if (ret < 0) { | 402 | if (ret < 0) { |
403 | printk("nf_conntrack_ipv4: can't register ipv4\n"); | 403 | pr_err("nf_conntrack_ipv4: can't register ipv4\n"); |
404 | goto cleanup_icmp; | 404 | goto cleanup_icmp; |
405 | } | 405 | } |
406 | 406 | ||
407 | ret = nf_register_hooks(ipv4_conntrack_ops, | 407 | ret = nf_register_hooks(ipv4_conntrack_ops, |
408 | ARRAY_SIZE(ipv4_conntrack_ops)); | 408 | ARRAY_SIZE(ipv4_conntrack_ops)); |
409 | if (ret < 0) { | 409 | if (ret < 0) { |
410 | printk("nf_conntrack_ipv4: can't register hooks.\n"); | 410 | pr_err("nf_conntrack_ipv4: can't register hooks.\n"); |
411 | goto cleanup_ipv4; | 411 | goto cleanup_ipv4; |
412 | } | 412 | } |
413 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) | 413 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 2fb7b76da94f..244f7cb08d68 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | |||
@@ -336,12 +336,12 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v) | |||
336 | const struct ip_conntrack_stat *st = v; | 336 | const struct ip_conntrack_stat *st = v; |
337 | 337 | ||
338 | if (v == SEQ_START_TOKEN) { | 338 | if (v == SEQ_START_TOKEN) { |
339 | seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n"); | 339 | seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete search_restart\n"); |
340 | return 0; | 340 | return 0; |
341 | } | 341 | } |
342 | 342 | ||
343 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x " | 343 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x " |
344 | "%08x %08x %08x %08x %08x %08x %08x %08x \n", | 344 | "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n", |
345 | nr_conntracks, | 345 | nr_conntracks, |
346 | st->searched, | 346 | st->searched, |
347 | st->found, | 347 | st->found, |
@@ -358,7 +358,8 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v) | |||
358 | 358 | ||
359 | st->expect_new, | 359 | st->expect_new, |
360 | st->expect_create, | 360 | st->expect_create, |
361 | st->expect_delete | 361 | st->expect_delete, |
362 | st->search_restart | ||
362 | ); | 363 | ); |
363 | return 0; | 364 | return 0; |
364 | } | 365 | } |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index 7e8e6fc75413..5045196d853c 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
@@ -10,7 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/tcp.h> | 13 | #include <linux/tcp.h> |
15 | #include <net/tcp.h> | 14 | #include <net/tcp.h> |
16 | 15 | ||
@@ -44,7 +43,7 @@ static int set_addr(struct sk_buff *skb, | |||
44 | addroff, sizeof(buf), | 43 | addroff, sizeof(buf), |
45 | (char *) &buf, sizeof(buf))) { | 44 | (char *) &buf, sizeof(buf))) { |
46 | if (net_ratelimit()) | 45 | if (net_ratelimit()) |
47 | printk("nf_nat_h323: nf_nat_mangle_tcp_packet" | 46 | pr_notice("nf_nat_h323: nf_nat_mangle_tcp_packet" |
48 | " error\n"); | 47 | " error\n"); |
49 | return -1; | 48 | return -1; |
50 | } | 49 | } |
@@ -60,7 +59,7 @@ static int set_addr(struct sk_buff *skb, | |||
60 | addroff, sizeof(buf), | 59 | addroff, sizeof(buf), |
61 | (char *) &buf, sizeof(buf))) { | 60 | (char *) &buf, sizeof(buf))) { |
62 | if (net_ratelimit()) | 61 | if (net_ratelimit()) |
63 | printk("nf_nat_h323: nf_nat_mangle_udp_packet" | 62 | pr_notice("nf_nat_h323: nf_nat_mangle_udp_packet" |
64 | " error\n"); | 63 | " error\n"); |
65 | return -1; | 64 | return -1; |
66 | } | 65 | } |
@@ -216,7 +215,7 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | |||
216 | /* Run out of expectations */ | 215 | /* Run out of expectations */ |
217 | if (i >= H323_RTP_CHANNEL_MAX) { | 216 | if (i >= H323_RTP_CHANNEL_MAX) { |
218 | if (net_ratelimit()) | 217 | if (net_ratelimit()) |
219 | printk("nf_nat_h323: out of expectations\n"); | 218 | pr_notice("nf_nat_h323: out of expectations\n"); |
220 | return 0; | 219 | return 0; |
221 | } | 220 | } |
222 | 221 | ||
@@ -235,7 +234,7 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | |||
235 | 234 | ||
236 | if (nated_port == 0) { /* No port available */ | 235 | if (nated_port == 0) { /* No port available */ |
237 | if (net_ratelimit()) | 236 | if (net_ratelimit()) |
238 | printk("nf_nat_h323: out of RTP ports\n"); | 237 | pr_notice("nf_nat_h323: out of RTP ports\n"); |
239 | return 0; | 238 | return 0; |
240 | } | 239 | } |
241 | 240 | ||
@@ -292,7 +291,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, | |||
292 | 291 | ||
293 | if (nated_port == 0) { /* No port available */ | 292 | if (nated_port == 0) { /* No port available */ |
294 | if (net_ratelimit()) | 293 | if (net_ratelimit()) |
295 | printk("nf_nat_h323: out of TCP ports\n"); | 294 | pr_notice("nf_nat_h323: out of TCP ports\n"); |
296 | return 0; | 295 | return 0; |
297 | } | 296 | } |
298 | 297 | ||
@@ -342,7 +341,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, | |||
342 | 341 | ||
343 | if (nated_port == 0) { /* No port available */ | 342 | if (nated_port == 0) { /* No port available */ |
344 | if (net_ratelimit()) | 343 | if (net_ratelimit()) |
345 | printk("nf_nat_q931: out of TCP ports\n"); | 344 | pr_notice("nf_nat_q931: out of TCP ports\n"); |
346 | return 0; | 345 | return 0; |
347 | } | 346 | } |
348 | 347 | ||
@@ -426,7 +425,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
426 | 425 | ||
427 | if (nated_port == 0) { /* No port available */ | 426 | if (nated_port == 0) { /* No port available */ |
428 | if (net_ratelimit()) | 427 | if (net_ratelimit()) |
429 | printk("nf_nat_ras: out of TCP ports\n"); | 428 | pr_notice("nf_nat_ras: out of TCP ports\n"); |
430 | return 0; | 429 | return 0; |
431 | } | 430 | } |
432 | 431 | ||
@@ -508,7 +507,7 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, | |||
508 | 507 | ||
509 | if (nated_port == 0) { /* No port available */ | 508 | if (nated_port == 0) { /* No port available */ |
510 | if (net_ratelimit()) | 509 | if (net_ratelimit()) |
511 | printk("nf_nat_q931: out of TCP ports\n"); | 510 | pr_notice("nf_nat_q931: out of TCP ports\n"); |
512 | return 0; | 511 | return 0; |
513 | } | 512 | } |
514 | 513 | ||
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 26de2c1f7fab..98ed78281aee 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* Everything about the rules for NAT. */ | 9 | /* Everything about the rules for NAT. */ |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
10 | #include <linux/types.h> | 11 | #include <linux/types.h> |
11 | #include <linux/ip.h> | 12 | #include <linux/ip.h> |
12 | #include <linux/netfilter.h> | 13 | #include <linux/netfilter.h> |
@@ -38,7 +39,7 @@ static const struct xt_table nat_table = { | |||
38 | 39 | ||
39 | /* Source NAT */ | 40 | /* Source NAT */ |
40 | static unsigned int | 41 | static unsigned int |
41 | ipt_snat_target(struct sk_buff *skb, const struct xt_target_param *par) | 42 | ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par) |
42 | { | 43 | { |
43 | struct nf_conn *ct; | 44 | struct nf_conn *ct; |
44 | enum ip_conntrack_info ctinfo; | 45 | enum ip_conntrack_info ctinfo; |
@@ -57,7 +58,7 @@ ipt_snat_target(struct sk_buff *skb, const struct xt_target_param *par) | |||
57 | } | 58 | } |
58 | 59 | ||
59 | static unsigned int | 60 | static unsigned int |
60 | ipt_dnat_target(struct sk_buff *skb, const struct xt_target_param *par) | 61 | ipt_dnat_target(struct sk_buff *skb, const struct xt_action_param *par) |
61 | { | 62 | { |
62 | struct nf_conn *ct; | 63 | struct nf_conn *ct; |
63 | enum ip_conntrack_info ctinfo; | 64 | enum ip_conntrack_info ctinfo; |
@@ -74,28 +75,28 @@ ipt_dnat_target(struct sk_buff *skb, const struct xt_target_param *par) | |||
74 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); | 75 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); |
75 | } | 76 | } |
76 | 77 | ||
77 | static bool ipt_snat_checkentry(const struct xt_tgchk_param *par) | 78 | static int ipt_snat_checkentry(const struct xt_tgchk_param *par) |
78 | { | 79 | { |
79 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 80 | const struct nf_nat_multi_range_compat *mr = par->targinfo; |
80 | 81 | ||
81 | /* Must be a valid range */ | 82 | /* Must be a valid range */ |
82 | if (mr->rangesize != 1) { | 83 | if (mr->rangesize != 1) { |
83 | printk("SNAT: multiple ranges no longer supported\n"); | 84 | pr_info("SNAT: multiple ranges no longer supported\n"); |
84 | return false; | 85 | return -EINVAL; |
85 | } | 86 | } |
86 | return true; | 87 | return 0; |
87 | } | 88 | } |
88 | 89 | ||
89 | static bool ipt_dnat_checkentry(const struct xt_tgchk_param *par) | 90 | static int ipt_dnat_checkentry(const struct xt_tgchk_param *par) |
90 | { | 91 | { |
91 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 92 | const struct nf_nat_multi_range_compat *mr = par->targinfo; |
92 | 93 | ||
93 | /* Must be a valid range */ | 94 | /* Must be a valid range */ |
94 | if (mr->rangesize != 1) { | 95 | if (mr->rangesize != 1) { |
95 | printk("DNAT: multiple ranges no longer supported\n"); | 96 | pr_info("DNAT: multiple ranges no longer supported\n"); |
96 | return false; | 97 | return -EINVAL; |
97 | } | 98 | } |
98 | return true; | 99 | return 0; |
99 | } | 100 | } |
100 | 101 | ||
101 | unsigned int | 102 | unsigned int |
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 4d85b6e55f29..1679e2c0963d 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c | |||
@@ -401,7 +401,7 @@ static unsigned char asn1_octets_decode(struct asn1_ctx *ctx, | |||
401 | *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC); | 401 | *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC); |
402 | if (*octets == NULL) { | 402 | if (*octets == NULL) { |
403 | if (net_ratelimit()) | 403 | if (net_ratelimit()) |
404 | printk("OOM in bsalg (%d)\n", __LINE__); | 404 | pr_notice("OOM in bsalg (%d)\n", __LINE__); |
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
407 | 407 | ||
@@ -452,7 +452,7 @@ static unsigned char asn1_oid_decode(struct asn1_ctx *ctx, | |||
452 | *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); | 452 | *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); |
453 | if (*oid == NULL) { | 453 | if (*oid == NULL) { |
454 | if (net_ratelimit()) | 454 | if (net_ratelimit()) |
455 | printk("OOM in bsalg (%d)\n", __LINE__); | 455 | pr_notice("OOM in bsalg (%d)\n", __LINE__); |
456 | return 0; | 456 | return 0; |
457 | } | 457 | } |
458 | 458 | ||
@@ -729,7 +729,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx, | |||
729 | if (*obj == NULL) { | 729 | if (*obj == NULL) { |
730 | kfree(id); | 730 | kfree(id); |
731 | if (net_ratelimit()) | 731 | if (net_ratelimit()) |
732 | printk("OOM in bsalg (%d)\n", __LINE__); | 732 | pr_notice("OOM in bsalg (%d)\n", __LINE__); |
733 | return 0; | 733 | return 0; |
734 | } | 734 | } |
735 | (*obj)->syntax.l[0] = l; | 735 | (*obj)->syntax.l[0] = l; |
@@ -746,7 +746,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx, | |||
746 | kfree(p); | 746 | kfree(p); |
747 | kfree(id); | 747 | kfree(id); |
748 | if (net_ratelimit()) | 748 | if (net_ratelimit()) |
749 | printk("OOM in bsalg (%d)\n", __LINE__); | 749 | pr_notice("OOM in bsalg (%d)\n", __LINE__); |
750 | return 0; | 750 | return 0; |
751 | } | 751 | } |
752 | memcpy((*obj)->syntax.c, p, len); | 752 | memcpy((*obj)->syntax.c, p, len); |
@@ -761,7 +761,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx, | |||
761 | if (*obj == NULL) { | 761 | if (*obj == NULL) { |
762 | kfree(id); | 762 | kfree(id); |
763 | if (net_ratelimit()) | 763 | if (net_ratelimit()) |
764 | printk("OOM in bsalg (%d)\n", __LINE__); | 764 | pr_notice("OOM in bsalg (%d)\n", __LINE__); |
765 | return 0; | 765 | return 0; |
766 | } | 766 | } |
767 | if (!asn1_null_decode(ctx, end)) { | 767 | if (!asn1_null_decode(ctx, end)) { |
@@ -782,7 +782,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx, | |||
782 | kfree(lp); | 782 | kfree(lp); |
783 | kfree(id); | 783 | kfree(id); |
784 | if (net_ratelimit()) | 784 | if (net_ratelimit()) |
785 | printk("OOM in bsalg (%d)\n", __LINE__); | 785 | pr_notice("OOM in bsalg (%d)\n", __LINE__); |
786 | return 0; | 786 | return 0; |
787 | } | 787 | } |
788 | memcpy((*obj)->syntax.ul, lp, len); | 788 | memcpy((*obj)->syntax.ul, lp, len); |
@@ -803,7 +803,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx, | |||
803 | kfree(p); | 803 | kfree(p); |
804 | kfree(id); | 804 | kfree(id); |
805 | if (net_ratelimit()) | 805 | if (net_ratelimit()) |
806 | printk("OOM in bsalg (%d)\n", __LINE__); | 806 | pr_notice("OOM in bsalg (%d)\n", __LINE__); |
807 | return 0; | 807 | return 0; |
808 | } | 808 | } |
809 | memcpy((*obj)->syntax.uc, p, len); | 809 | memcpy((*obj)->syntax.uc, p, len); |
@@ -821,7 +821,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx, | |||
821 | if (*obj == NULL) { | 821 | if (*obj == NULL) { |
822 | kfree(id); | 822 | kfree(id); |
823 | if (net_ratelimit()) | 823 | if (net_ratelimit()) |
824 | printk("OOM in bsalg (%d)\n", __LINE__); | 824 | pr_notice("OOM in bsalg (%d)\n", __LINE__); |
825 | return 0; | 825 | return 0; |
826 | } | 826 | } |
827 | (*obj)->syntax.ul[0] = ul; | 827 | (*obj)->syntax.ul[0] = ul; |
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index c39c9cf6bee6..beb25819c9c9 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
@@ -138,9 +138,8 @@ nf_nat_fn(unsigned int hooknum, | |||
138 | ret = nf_nat_rule_find(skb, hooknum, in, out, | 138 | ret = nf_nat_rule_find(skb, hooknum, in, out, |
139 | ct); | 139 | ct); |
140 | 140 | ||
141 | if (ret != NF_ACCEPT) { | 141 | if (ret != NF_ACCEPT) |
142 | return ret; | 142 | return ret; |
143 | } | ||
144 | } else | 143 | } else |
145 | pr_debug("Already setup manip %s for ct %p\n", | 144 | pr_debug("Already setup manip %s for ct %p\n", |
146 | maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", | 145 | maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", |
@@ -294,12 +293,12 @@ static int __init nf_nat_standalone_init(void) | |||
294 | #endif | 293 | #endif |
295 | ret = nf_nat_rule_init(); | 294 | ret = nf_nat_rule_init(); |
296 | if (ret < 0) { | 295 | if (ret < 0) { |
297 | printk("nf_nat_init: can't setup rules.\n"); | 296 | pr_err("nf_nat_init: can't setup rules.\n"); |
298 | goto cleanup_decode_session; | 297 | goto cleanup_decode_session; |
299 | } | 298 | } |
300 | ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); | 299 | ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); |
301 | if (ret < 0) { | 300 | if (ret < 0) { |
302 | printk("nf_nat_init: can't register hooks.\n"); | 301 | pr_err("nf_nat_init: can't register hooks.\n"); |
303 | goto cleanup_rule_init; | 302 | goto cleanup_rule_init; |
304 | } | 303 | } |
305 | return ret; | 304 | return ret; |
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c index b096e81500ae..7274a43c7a12 100644 --- a/net/ipv4/netfilter/nf_nat_tftp.c +++ b/net/ipv4/netfilter/nf_nat_tftp.c | |||
@@ -6,7 +6,6 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/moduleparam.h> | ||
10 | #include <linux/udp.h> | 9 | #include <linux/udp.h> |
11 | 10 | ||
12 | #include <net/netfilter/nf_nat_helper.h> | 11 | #include <net/netfilter/nf_nat_helper.h> |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 4f1f337f4337..3dc9914c1dce 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -251,6 +251,7 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
251 | SNMP_MIB_ITEM("TCPSackShiftFallback", LINUX_MIB_SACKSHIFTFALLBACK), | 251 | SNMP_MIB_ITEM("TCPSackShiftFallback", LINUX_MIB_SACKSHIFTFALLBACK), |
252 | SNMP_MIB_ITEM("TCPBacklogDrop", LINUX_MIB_TCPBACKLOGDROP), | 252 | SNMP_MIB_ITEM("TCPBacklogDrop", LINUX_MIB_TCPBACKLOGDROP), |
253 | SNMP_MIB_ITEM("TCPMinTTLDrop", LINUX_MIB_TCPMINTTLDROP), | 253 | SNMP_MIB_ITEM("TCPMinTTLDrop", LINUX_MIB_TCPMINTTLDROP), |
254 | SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP), | ||
254 | SNMP_MIB_SENTINEL | 255 | SNMP_MIB_SENTINEL |
255 | }; | 256 | }; |
256 | 257 | ||
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index cc6f097fbd5f..2c7a1639388a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -290,7 +290,7 @@ static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb) | |||
290 | { | 290 | { |
291 | /* Charge it to the socket. */ | 291 | /* Charge it to the socket. */ |
292 | 292 | ||
293 | if (sock_queue_rcv_skb(sk, skb) < 0) { | 293 | if (ip_queue_rcv_skb(sk, skb) < 0) { |
294 | kfree_skb(skb); | 294 | kfree_skb(skb); |
295 | return NET_RX_DROP; | 295 | return NET_RX_DROP; |
296 | } | 296 | } |
@@ -381,8 +381,8 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, | |||
381 | icmp_out_count(net, ((struct icmphdr *) | 381 | icmp_out_count(net, ((struct icmphdr *) |
382 | skb_transport_header(skb))->type); | 382 | skb_transport_header(skb))->type); |
383 | 383 | ||
384 | err = NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, | 384 | err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL, |
385 | dst_output); | 385 | rt->u.dst.dev, dst_output); |
386 | if (err > 0) | 386 | if (err > 0) |
387 | err = net_xmit_errno(err); | 387 | err = net_xmit_errno(err); |
388 | if (err) | 388 | if (err) |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index cb562fdd9b9a..560acc677ce4 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -129,7 +129,6 @@ static int ip_rt_gc_elasticity __read_mostly = 8; | |||
129 | static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; | 129 | static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; |
130 | static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; | 130 | static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; |
131 | static int ip_rt_min_advmss __read_mostly = 256; | 131 | static int ip_rt_min_advmss __read_mostly = 256; |
132 | static int ip_rt_secret_interval __read_mostly = 10 * 60 * HZ; | ||
133 | static int rt_chain_length_max __read_mostly = 20; | 132 | static int rt_chain_length_max __read_mostly = 20; |
134 | 133 | ||
135 | static struct delayed_work expires_work; | 134 | static struct delayed_work expires_work; |
@@ -258,10 +257,9 @@ static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); | |||
258 | (__raw_get_cpu_var(rt_cache_stat).field++) | 257 | (__raw_get_cpu_var(rt_cache_stat).field++) |
259 | 258 | ||
260 | static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx, | 259 | static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx, |
261 | int genid) | 260 | int genid) |
262 | { | 261 | { |
263 | return jhash_3words((__force u32)(__be32)(daddr), | 262 | return jhash_3words((__force u32)daddr, (__force u32)saddr, |
264 | (__force u32)(__be32)(saddr), | ||
265 | idx, genid) | 263 | idx, genid) |
266 | & rt_hash_mask; | 264 | & rt_hash_mask; |
267 | } | 265 | } |
@@ -378,12 +376,13 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) | |||
378 | struct rtable *r = v; | 376 | struct rtable *r = v; |
379 | int len; | 377 | int len; |
380 | 378 | ||
381 | seq_printf(seq, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t" | 379 | seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" |
382 | "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", | 380 | "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", |
383 | r->u.dst.dev ? r->u.dst.dev->name : "*", | 381 | r->u.dst.dev ? r->u.dst.dev->name : "*", |
384 | (unsigned long)r->rt_dst, (unsigned long)r->rt_gateway, | 382 | (__force u32)r->rt_dst, |
383 | (__force u32)r->rt_gateway, | ||
385 | r->rt_flags, atomic_read(&r->u.dst.__refcnt), | 384 | r->rt_flags, atomic_read(&r->u.dst.__refcnt), |
386 | r->u.dst.__use, 0, (unsigned long)r->rt_src, | 385 | r->u.dst.__use, 0, (__force u32)r->rt_src, |
387 | (dst_metric(&r->u.dst, RTAX_ADVMSS) ? | 386 | (dst_metric(&r->u.dst, RTAX_ADVMSS) ? |
388 | (int)dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0), | 387 | (int)dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0), |
389 | dst_metric(&r->u.dst, RTAX_WINDOW), | 388 | dst_metric(&r->u.dst, RTAX_WINDOW), |
@@ -685,18 +684,17 @@ static inline bool rt_caching(const struct net *net) | |||
685 | static inline bool compare_hash_inputs(const struct flowi *fl1, | 684 | static inline bool compare_hash_inputs(const struct flowi *fl1, |
686 | const struct flowi *fl2) | 685 | const struct flowi *fl2) |
687 | { | 686 | { |
688 | return (__force u32)(((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | | 687 | return ((((__force u32)fl1->nl_u.ip4_u.daddr ^ (__force u32)fl2->nl_u.ip4_u.daddr) | |
689 | (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) | | 688 | ((__force u32)fl1->nl_u.ip4_u.saddr ^ (__force u32)fl2->nl_u.ip4_u.saddr) | |
690 | (fl1->iif ^ fl2->iif)) == 0); | 689 | (fl1->iif ^ fl2->iif)) == 0); |
691 | } | 690 | } |
692 | 691 | ||
693 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) | 692 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) |
694 | { | 693 | { |
695 | return ((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | | 694 | return (((__force u32)fl1->nl_u.ip4_u.daddr ^ (__force u32)fl2->nl_u.ip4_u.daddr) | |
696 | (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr)) | | 695 | ((__force u32)fl1->nl_u.ip4_u.saddr ^ (__force u32)fl2->nl_u.ip4_u.saddr) | |
697 | (fl1->mark ^ fl2->mark) | | 696 | (fl1->mark ^ fl2->mark) | |
698 | (*(u16 *)&fl1->nl_u.ip4_u.tos ^ | 697 | (*(u16 *)&fl1->nl_u.ip4_u.tos ^ *(u16 *)&fl2->nl_u.ip4_u.tos) | |
699 | *(u16 *)&fl2->nl_u.ip4_u.tos) | | ||
700 | (fl1->oif ^ fl2->oif) | | 698 | (fl1->oif ^ fl2->oif) | |
701 | (fl1->iif ^ fl2->iif)) == 0; | 699 | (fl1->iif ^ fl2->iif)) == 0; |
702 | } | 700 | } |
@@ -919,32 +917,11 @@ void rt_cache_flush_batch(void) | |||
919 | rt_do_flush(!in_softirq()); | 917 | rt_do_flush(!in_softirq()); |
920 | } | 918 | } |
921 | 919 | ||
922 | /* | ||
923 | * We change rt_genid and let gc do the cleanup | ||
924 | */ | ||
925 | static void rt_secret_rebuild(unsigned long __net) | ||
926 | { | ||
927 | struct net *net = (struct net *)__net; | ||
928 | rt_cache_invalidate(net); | ||
929 | mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval); | ||
930 | } | ||
931 | |||
932 | static void rt_secret_rebuild_oneshot(struct net *net) | ||
933 | { | ||
934 | del_timer_sync(&net->ipv4.rt_secret_timer); | ||
935 | rt_cache_invalidate(net); | ||
936 | if (ip_rt_secret_interval) | ||
937 | mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval); | ||
938 | } | ||
939 | |||
940 | static void rt_emergency_hash_rebuild(struct net *net) | 920 | static void rt_emergency_hash_rebuild(struct net *net) |
941 | { | 921 | { |
942 | if (net_ratelimit()) { | 922 | if (net_ratelimit()) |
943 | printk(KERN_WARNING "Route hash chain too long!\n"); | 923 | printk(KERN_WARNING "Route hash chain too long!\n"); |
944 | printk(KERN_WARNING "Adjust your secret_interval!\n"); | 924 | rt_cache_invalidate(net); |
945 | } | ||
946 | |||
947 | rt_secret_rebuild_oneshot(net); | ||
948 | } | 925 | } |
949 | 926 | ||
950 | /* | 927 | /* |
@@ -2300,8 +2277,8 @@ martian_source: | |||
2300 | goto e_inval; | 2277 | goto e_inval; |
2301 | } | 2278 | } |
2302 | 2279 | ||
2303 | int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, | 2280 | int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, |
2304 | u8 tos, struct net_device *dev) | 2281 | u8 tos, struct net_device *dev, bool noref) |
2305 | { | 2282 | { |
2306 | struct rtable * rth; | 2283 | struct rtable * rth; |
2307 | unsigned hash; | 2284 | unsigned hash; |
@@ -2319,18 +2296,23 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2319 | rcu_read_lock(); | 2296 | rcu_read_lock(); |
2320 | for (rth = rcu_dereference(rt_hash_table[hash].chain); rth; | 2297 | for (rth = rcu_dereference(rt_hash_table[hash].chain); rth; |
2321 | rth = rcu_dereference(rth->u.dst.rt_next)) { | 2298 | rth = rcu_dereference(rth->u.dst.rt_next)) { |
2322 | if (((rth->fl.fl4_dst ^ daddr) | | 2299 | if ((((__force u32)rth->fl.fl4_dst ^ (__force u32)daddr) | |
2323 | (rth->fl.fl4_src ^ saddr) | | 2300 | ((__force u32)rth->fl.fl4_src ^ (__force u32)saddr) | |
2324 | (rth->fl.iif ^ iif) | | 2301 | (rth->fl.iif ^ iif) | |
2325 | rth->fl.oif | | 2302 | rth->fl.oif | |
2326 | (rth->fl.fl4_tos ^ tos)) == 0 && | 2303 | (rth->fl.fl4_tos ^ tos)) == 0 && |
2327 | rth->fl.mark == skb->mark && | 2304 | rth->fl.mark == skb->mark && |
2328 | net_eq(dev_net(rth->u.dst.dev), net) && | 2305 | net_eq(dev_net(rth->u.dst.dev), net) && |
2329 | !rt_is_expired(rth)) { | 2306 | !rt_is_expired(rth)) { |
2330 | dst_use(&rth->u.dst, jiffies); | 2307 | if (noref) { |
2308 | dst_use_noref(&rth->u.dst, jiffies); | ||
2309 | skb_dst_set_noref(skb, &rth->u.dst); | ||
2310 | } else { | ||
2311 | dst_use(&rth->u.dst, jiffies); | ||
2312 | skb_dst_set(skb, &rth->u.dst); | ||
2313 | } | ||
2331 | RT_CACHE_STAT_INC(in_hit); | 2314 | RT_CACHE_STAT_INC(in_hit); |
2332 | rcu_read_unlock(); | 2315 | rcu_read_unlock(); |
2333 | skb_dst_set(skb, &rth->u.dst); | ||
2334 | return 0; | 2316 | return 0; |
2335 | } | 2317 | } |
2336 | RT_CACHE_STAT_INC(in_hlist_search); | 2318 | RT_CACHE_STAT_INC(in_hlist_search); |
@@ -2373,6 +2355,7 @@ skip_cache: | |||
2373 | } | 2355 | } |
2374 | return ip_route_input_slow(skb, daddr, saddr, tos, dev); | 2356 | return ip_route_input_slow(skb, daddr, saddr, tos, dev); |
2375 | } | 2357 | } |
2358 | EXPORT_SYMBOL(ip_route_input_common); | ||
2376 | 2359 | ||
2377 | static int __mkroute_output(struct rtable **result, | 2360 | static int __mkroute_output(struct rtable **result, |
2378 | struct fib_result *res, | 2361 | struct fib_result *res, |
@@ -3056,7 +3039,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
3056 | continue; | 3039 | continue; |
3057 | if (rt_is_expired(rt)) | 3040 | if (rt_is_expired(rt)) |
3058 | continue; | 3041 | continue; |
3059 | skb_dst_set(skb, dst_clone(&rt->u.dst)); | 3042 | skb_dst_set_noref(skb, &rt->u.dst); |
3060 | if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid, | 3043 | if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid, |
3061 | cb->nlh->nlmsg_seq, RTM_NEWROUTE, | 3044 | cb->nlh->nlmsg_seq, RTM_NEWROUTE, |
3062 | 1, NLM_F_MULTI) <= 0) { | 3045 | 1, NLM_F_MULTI) <= 0) { |
@@ -3102,48 +3085,6 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write, | |||
3102 | return -EINVAL; | 3085 | return -EINVAL; |
3103 | } | 3086 | } |
3104 | 3087 | ||
3105 | static void rt_secret_reschedule(int old) | ||
3106 | { | ||
3107 | struct net *net; | ||
3108 | int new = ip_rt_secret_interval; | ||
3109 | int diff = new - old; | ||
3110 | |||
3111 | if (!diff) | ||
3112 | return; | ||
3113 | |||
3114 | rtnl_lock(); | ||
3115 | for_each_net(net) { | ||
3116 | int deleted = del_timer_sync(&net->ipv4.rt_secret_timer); | ||
3117 | long time; | ||
3118 | |||
3119 | if (!new) | ||
3120 | continue; | ||
3121 | |||
3122 | if (deleted) { | ||
3123 | time = net->ipv4.rt_secret_timer.expires - jiffies; | ||
3124 | |||
3125 | if (time <= 0 || (time += diff) <= 0) | ||
3126 | time = 0; | ||
3127 | } else | ||
3128 | time = new; | ||
3129 | |||
3130 | mod_timer(&net->ipv4.rt_secret_timer, jiffies + time); | ||
3131 | } | ||
3132 | rtnl_unlock(); | ||
3133 | } | ||
3134 | |||
3135 | static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write, | ||
3136 | void __user *buffer, size_t *lenp, | ||
3137 | loff_t *ppos) | ||
3138 | { | ||
3139 | int old = ip_rt_secret_interval; | ||
3140 | int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos); | ||
3141 | |||
3142 | rt_secret_reschedule(old); | ||
3143 | |||
3144 | return ret; | ||
3145 | } | ||
3146 | |||
3147 | static ctl_table ipv4_route_table[] = { | 3088 | static ctl_table ipv4_route_table[] = { |
3148 | { | 3089 | { |
3149 | .procname = "gc_thresh", | 3090 | .procname = "gc_thresh", |
@@ -3252,13 +3193,6 @@ static ctl_table ipv4_route_table[] = { | |||
3252 | .mode = 0644, | 3193 | .mode = 0644, |
3253 | .proc_handler = proc_dointvec, | 3194 | .proc_handler = proc_dointvec, |
3254 | }, | 3195 | }, |
3255 | { | ||
3256 | .procname = "secret_interval", | ||
3257 | .data = &ip_rt_secret_interval, | ||
3258 | .maxlen = sizeof(int), | ||
3259 | .mode = 0644, | ||
3260 | .proc_handler = ipv4_sysctl_rt_secret_interval, | ||
3261 | }, | ||
3262 | { } | 3196 | { } |
3263 | }; | 3197 | }; |
3264 | 3198 | ||
@@ -3337,34 +3271,15 @@ static __net_initdata struct pernet_operations sysctl_route_ops = { | |||
3337 | }; | 3271 | }; |
3338 | #endif | 3272 | #endif |
3339 | 3273 | ||
3340 | 3274 | static __net_init int rt_genid_init(struct net *net) | |
3341 | static __net_init int rt_secret_timer_init(struct net *net) | ||
3342 | { | 3275 | { |
3343 | atomic_set(&net->ipv4.rt_genid, | 3276 | get_random_bytes(&net->ipv4.rt_genid, |
3344 | (int) ((num_physpages ^ (num_physpages>>8)) ^ | 3277 | sizeof(net->ipv4.rt_genid)); |
3345 | (jiffies ^ (jiffies >> 7)))); | ||
3346 | |||
3347 | net->ipv4.rt_secret_timer.function = rt_secret_rebuild; | ||
3348 | net->ipv4.rt_secret_timer.data = (unsigned long)net; | ||
3349 | init_timer_deferrable(&net->ipv4.rt_secret_timer); | ||
3350 | |||
3351 | if (ip_rt_secret_interval) { | ||
3352 | net->ipv4.rt_secret_timer.expires = | ||
3353 | jiffies + net_random() % ip_rt_secret_interval + | ||
3354 | ip_rt_secret_interval; | ||
3355 | add_timer(&net->ipv4.rt_secret_timer); | ||
3356 | } | ||
3357 | return 0; | 3278 | return 0; |
3358 | } | 3279 | } |
3359 | 3280 | ||
3360 | static __net_exit void rt_secret_timer_exit(struct net *net) | 3281 | static __net_initdata struct pernet_operations rt_genid_ops = { |
3361 | { | 3282 | .init = rt_genid_init, |
3362 | del_timer_sync(&net->ipv4.rt_secret_timer); | ||
3363 | } | ||
3364 | |||
3365 | static __net_initdata struct pernet_operations rt_secret_timer_ops = { | ||
3366 | .init = rt_secret_timer_init, | ||
3367 | .exit = rt_secret_timer_exit, | ||
3368 | }; | 3283 | }; |
3369 | 3284 | ||
3370 | 3285 | ||
@@ -3425,9 +3340,6 @@ int __init ip_rt_init(void) | |||
3425 | schedule_delayed_work(&expires_work, | 3340 | schedule_delayed_work(&expires_work, |
3426 | net_random() % ip_rt_gc_interval + ip_rt_gc_interval); | 3341 | net_random() % ip_rt_gc_interval + ip_rt_gc_interval); |
3427 | 3342 | ||
3428 | if (register_pernet_subsys(&rt_secret_timer_ops)) | ||
3429 | printk(KERN_ERR "Unable to setup rt_secret_timer\n"); | ||
3430 | |||
3431 | if (ip_rt_proc_init()) | 3343 | if (ip_rt_proc_init()) |
3432 | printk(KERN_ERR "Unable to create route proc files\n"); | 3344 | printk(KERN_ERR "Unable to create route proc files\n"); |
3433 | #ifdef CONFIG_XFRM | 3345 | #ifdef CONFIG_XFRM |
@@ -3439,6 +3351,7 @@ int __init ip_rt_init(void) | |||
3439 | #ifdef CONFIG_SYSCTL | 3351 | #ifdef CONFIG_SYSCTL |
3440 | register_pernet_subsys(&sysctl_route_ops); | 3352 | register_pernet_subsys(&sysctl_route_ops); |
3441 | #endif | 3353 | #endif |
3354 | register_pernet_subsys(&rt_genid_ops); | ||
3442 | return rc; | 3355 | return rc; |
3443 | } | 3356 | } |
3444 | 3357 | ||
@@ -3454,5 +3367,4 @@ void __init ip_static_sysctl_init(void) | |||
3454 | #endif | 3367 | #endif |
3455 | 3368 | ||
3456 | EXPORT_SYMBOL(__ip_select_ident); | 3369 | EXPORT_SYMBOL(__ip_select_ident); |
3457 | EXPORT_SYMBOL(ip_route_input); | ||
3458 | EXPORT_SYMBOL(ip_route_output_key); | 3370 | EXPORT_SYMBOL(ip_route_output_key); |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 1cd5c15174b8..d96c1da4b17c 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -299,6 +299,13 @@ static struct ctl_table ipv4_table[] = { | |||
299 | .mode = 0644, | 299 | .mode = 0644, |
300 | .proc_handler = ipv4_local_port_range, | 300 | .proc_handler = ipv4_local_port_range, |
301 | }, | 301 | }, |
302 | { | ||
303 | .procname = "ip_local_reserved_ports", | ||
304 | .data = NULL, /* initialized in sysctl_ipv4_init */ | ||
305 | .maxlen = 65536, | ||
306 | .mode = 0644, | ||
307 | .proc_handler = proc_do_large_bitmap, | ||
308 | }, | ||
302 | #ifdef CONFIG_IP_MULTICAST | 309 | #ifdef CONFIG_IP_MULTICAST |
303 | { | 310 | { |
304 | .procname = "igmp_max_memberships", | 311 | .procname = "igmp_max_memberships", |
@@ -736,6 +743,16 @@ static __net_initdata struct pernet_operations ipv4_sysctl_ops = { | |||
736 | static __init int sysctl_ipv4_init(void) | 743 | static __init int sysctl_ipv4_init(void) |
737 | { | 744 | { |
738 | struct ctl_table_header *hdr; | 745 | struct ctl_table_header *hdr; |
746 | struct ctl_table *i; | ||
747 | |||
748 | for (i = ipv4_table; i->procname; i++) { | ||
749 | if (strcmp(i->procname, "ip_local_reserved_ports") == 0) { | ||
750 | i->data = sysctl_local_reserved_ports; | ||
751 | break; | ||
752 | } | ||
753 | } | ||
754 | if (!i->procname) | ||
755 | return -EINVAL; | ||
739 | 756 | ||
740 | hdr = register_sysctl_paths(net_ipv4_ctl_path, ipv4_table); | 757 | hdr = register_sysctl_paths(net_ipv4_ctl_path, ipv4_table); |
741 | if (hdr == NULL) | 758 | if (hdr == NULL) |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 296150b2a62f..6596b4feeddc 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -378,7 +378,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
378 | struct sock *sk = sock->sk; | 378 | struct sock *sk = sock->sk; |
379 | struct tcp_sock *tp = tcp_sk(sk); | 379 | struct tcp_sock *tp = tcp_sk(sk); |
380 | 380 | ||
381 | sock_poll_wait(file, sk->sk_sleep, wait); | 381 | sock_poll_wait(file, sk_sleep(sk), wait); |
382 | if (sk->sk_state == TCP_LISTEN) | 382 | if (sk->sk_state == TCP_LISTEN) |
383 | return inet_csk_listen_poll(sk); | 383 | return inet_csk_listen_poll(sk); |
384 | 384 | ||
@@ -2215,7 +2215,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
2215 | default: | 2215 | default: |
2216 | /* fallthru */ | 2216 | /* fallthru */ |
2217 | break; | 2217 | break; |
2218 | }; | 2218 | } |
2219 | 2219 | ||
2220 | if (optlen < sizeof(int)) | 2220 | if (optlen < sizeof(int)) |
2221 | return -EINVAL; | 2221 | return -EINVAL; |
@@ -2298,7 +2298,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
2298 | if (sock_flag(sk, SOCK_KEEPOPEN) && | 2298 | if (sock_flag(sk, SOCK_KEEPOPEN) && |
2299 | !((1 << sk->sk_state) & | 2299 | !((1 << sk->sk_state) & |
2300 | (TCPF_CLOSE | TCPF_LISTEN))) { | 2300 | (TCPF_CLOSE | TCPF_LISTEN))) { |
2301 | __u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; | 2301 | u32 elapsed = keepalive_time_elapsed(tp); |
2302 | if (tp->keepalive_time > elapsed) | 2302 | if (tp->keepalive_time > elapsed) |
2303 | elapsed = tp->keepalive_time - elapsed; | 2303 | elapsed = tp->keepalive_time - elapsed; |
2304 | else | 2304 | else |
@@ -2721,7 +2721,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2721 | struct tcphdr *th2; | 2721 | struct tcphdr *th2; |
2722 | unsigned int len; | 2722 | unsigned int len; |
2723 | unsigned int thlen; | 2723 | unsigned int thlen; |
2724 | unsigned int flags; | 2724 | __be32 flags; |
2725 | unsigned int mss = 1; | 2725 | unsigned int mss = 1; |
2726 | unsigned int hlen; | 2726 | unsigned int hlen; |
2727 | unsigned int off; | 2727 | unsigned int off; |
@@ -2771,10 +2771,10 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2771 | 2771 | ||
2772 | found: | 2772 | found: |
2773 | flush = NAPI_GRO_CB(p)->flush; | 2773 | flush = NAPI_GRO_CB(p)->flush; |
2774 | flush |= flags & TCP_FLAG_CWR; | 2774 | flush |= (__force int)(flags & TCP_FLAG_CWR); |
2775 | flush |= (flags ^ tcp_flag_word(th2)) & | 2775 | flush |= (__force int)((flags ^ tcp_flag_word(th2)) & |
2776 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); | 2776 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); |
2777 | flush |= th->ack_seq ^ th2->ack_seq; | 2777 | flush |= (__force int)(th->ack_seq ^ th2->ack_seq); |
2778 | for (i = sizeof(*th); i < thlen; i += 4) | 2778 | for (i = sizeof(*th); i < thlen; i += 4) |
2779 | flush |= *(u32 *)((u8 *)th + i) ^ | 2779 | flush |= *(u32 *)((u8 *)th + i) ^ |
2780 | *(u32 *)((u8 *)th2 + i); | 2780 | *(u32 *)((u8 *)th2 + i); |
@@ -2795,8 +2795,9 @@ found: | |||
2795 | 2795 | ||
2796 | out_check_final: | 2796 | out_check_final: |
2797 | flush = len < mss; | 2797 | flush = len < mss; |
2798 | flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | | 2798 | flush |= (__force int)(flags & (TCP_FLAG_URG | TCP_FLAG_PSH | |
2799 | TCP_FLAG_SYN | TCP_FLAG_FIN); | 2799 | TCP_FLAG_RST | TCP_FLAG_SYN | |
2800 | TCP_FLAG_FIN)); | ||
2800 | 2801 | ||
2801 | if (p && (!NAPI_GRO_CB(skb)->same_flow || flush)) | 2802 | if (p && (!NAPI_GRO_CB(skb)->same_flow || flush)) |
2802 | pp = head; | 2803 | pp = head; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index f240f57b2199..3e6dafcb1071 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3710,7 +3710,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) | |||
3710 | } | 3710 | } |
3711 | 3711 | ||
3712 | if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) | 3712 | if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) |
3713 | dst_confirm(sk->sk_dst_cache); | 3713 | dst_confirm(__sk_dst_get(sk)); |
3714 | 3714 | ||
3715 | return 1; | 3715 | return 1; |
3716 | 3716 | ||
@@ -3845,12 +3845,13 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, | |||
3845 | /* 16-bit multiple */ | 3845 | /* 16-bit multiple */ |
3846 | opt_rx->cookie_plus = opsize; | 3846 | opt_rx->cookie_plus = opsize; |
3847 | *hvpp = ptr; | 3847 | *hvpp = ptr; |
3848 | break; | ||
3848 | default: | 3849 | default: |
3849 | /* ignore option */ | 3850 | /* ignore option */ |
3850 | break; | 3851 | break; |
3851 | }; | 3852 | } |
3852 | break; | 3853 | break; |
3853 | }; | 3854 | } |
3854 | 3855 | ||
3855 | ptr += opsize-2; | 3856 | ptr += opsize-2; |
3856 | length -= opsize; | 3857 | length -= opsize; |
@@ -4319,7 +4320,7 @@ static void tcp_ofo_queue(struct sock *sk) | |||
4319 | } | 4320 | } |
4320 | 4321 | ||
4321 | if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) { | 4322 | if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) { |
4322 | SOCK_DEBUG(sk, "ofo packet was already received \n"); | 4323 | SOCK_DEBUG(sk, "ofo packet was already received\n"); |
4323 | __skb_unlink(skb, &tp->out_of_order_queue); | 4324 | __skb_unlink(skb, &tp->out_of_order_queue); |
4324 | __kfree_skb(skb); | 4325 | __kfree_skb(skb); |
4325 | continue; | 4326 | continue; |
@@ -4367,6 +4368,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) | |||
4367 | if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) | 4368 | if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) |
4368 | goto drop; | 4369 | goto drop; |
4369 | 4370 | ||
4371 | skb_dst_drop(skb); | ||
4370 | __skb_pull(skb, th->doff * 4); | 4372 | __skb_pull(skb, th->doff * 4); |
4371 | 4373 | ||
4372 | TCP_ECN_accept_cwr(tp, skb); | 4374 | TCP_ECN_accept_cwr(tp, skb); |
@@ -5833,7 +5835,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5833 | if (tp->snd_una == tp->write_seq) { | 5835 | if (tp->snd_una == tp->write_seq) { |
5834 | tcp_set_state(sk, TCP_FIN_WAIT2); | 5836 | tcp_set_state(sk, TCP_FIN_WAIT2); |
5835 | sk->sk_shutdown |= SEND_SHUTDOWN; | 5837 | sk->sk_shutdown |= SEND_SHUTDOWN; |
5836 | dst_confirm(sk->sk_dst_cache); | 5838 | dst_confirm(__sk_dst_get(sk)); |
5837 | 5839 | ||
5838 | if (!sock_flag(sk, SOCK_DEAD)) | 5840 | if (!sock_flag(sk, SOCK_DEAD)) |
5839 | /* Wake up lingering close() */ | 5841 | /* Wake up lingering close() */ |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3c23e70885f4..202cf09c4cd4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -519,26 +519,31 @@ out: | |||
519 | sock_put(sk); | 519 | sock_put(sk); |
520 | } | 520 | } |
521 | 521 | ||
522 | /* This routine computes an IPv4 TCP checksum. */ | 522 | static void __tcp_v4_send_check(struct sk_buff *skb, |
523 | void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) | 523 | __be32 saddr, __be32 daddr) |
524 | { | 524 | { |
525 | struct inet_sock *inet = inet_sk(sk); | ||
526 | struct tcphdr *th = tcp_hdr(skb); | 525 | struct tcphdr *th = tcp_hdr(skb); |
527 | 526 | ||
528 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 527 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
529 | th->check = ~tcp_v4_check(len, inet->inet_saddr, | 528 | th->check = ~tcp_v4_check(skb->len, saddr, daddr, 0); |
530 | inet->inet_daddr, 0); | ||
531 | skb->csum_start = skb_transport_header(skb) - skb->head; | 529 | skb->csum_start = skb_transport_header(skb) - skb->head; |
532 | skb->csum_offset = offsetof(struct tcphdr, check); | 530 | skb->csum_offset = offsetof(struct tcphdr, check); |
533 | } else { | 531 | } else { |
534 | th->check = tcp_v4_check(len, inet->inet_saddr, | 532 | th->check = tcp_v4_check(skb->len, saddr, daddr, |
535 | inet->inet_daddr, | ||
536 | csum_partial(th, | 533 | csum_partial(th, |
537 | th->doff << 2, | 534 | th->doff << 2, |
538 | skb->csum)); | 535 | skb->csum)); |
539 | } | 536 | } |
540 | } | 537 | } |
541 | 538 | ||
539 | /* This routine computes an IPv4 TCP checksum. */ | ||
540 | void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb) | ||
541 | { | ||
542 | struct inet_sock *inet = inet_sk(sk); | ||
543 | |||
544 | __tcp_v4_send_check(skb, inet->inet_saddr, inet->inet_daddr); | ||
545 | } | ||
546 | |||
542 | int tcp_v4_gso_send_check(struct sk_buff *skb) | 547 | int tcp_v4_gso_send_check(struct sk_buff *skb) |
543 | { | 548 | { |
544 | const struct iphdr *iph; | 549 | const struct iphdr *iph; |
@@ -551,10 +556,8 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) | |||
551 | th = tcp_hdr(skb); | 556 | th = tcp_hdr(skb); |
552 | 557 | ||
553 | th->check = 0; | 558 | th->check = 0; |
554 | th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0); | ||
555 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
556 | skb->csum_offset = offsetof(struct tcphdr, check); | ||
557 | skb->ip_summed = CHECKSUM_PARTIAL; | 559 | skb->ip_summed = CHECKSUM_PARTIAL; |
560 | __tcp_v4_send_check(skb, iph->saddr, iph->daddr); | ||
558 | return 0; | 561 | return 0; |
559 | } | 562 | } |
560 | 563 | ||
@@ -763,13 +766,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | |||
763 | skb = tcp_make_synack(sk, dst, req, rvp); | 766 | skb = tcp_make_synack(sk, dst, req, rvp); |
764 | 767 | ||
765 | if (skb) { | 768 | if (skb) { |
766 | struct tcphdr *th = tcp_hdr(skb); | 769 | __tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr); |
767 | |||
768 | th->check = tcp_v4_check(skb->len, | ||
769 | ireq->loc_addr, | ||
770 | ireq->rmt_addr, | ||
771 | csum_partial(th, skb->len, | ||
772 | skb->csum)); | ||
773 | 770 | ||
774 | err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, | 771 | err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, |
775 | ireq->rmt_addr, | 772 | ireq->rmt_addr, |
@@ -894,7 +891,7 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | |||
894 | kfree(newkey); | 891 | kfree(newkey); |
895 | return -ENOMEM; | 892 | return -ENOMEM; |
896 | } | 893 | } |
897 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 894 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
898 | } | 895 | } |
899 | if (tcp_alloc_md5sig_pool(sk) == NULL) { | 896 | if (tcp_alloc_md5sig_pool(sk) == NULL) { |
900 | kfree(newkey); | 897 | kfree(newkey); |
@@ -1024,7 +1021,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1024 | return -EINVAL; | 1021 | return -EINVAL; |
1025 | 1022 | ||
1026 | tp->md5sig_info = p; | 1023 | tp->md5sig_info = p; |
1027 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1024 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
1028 | } | 1025 | } |
1029 | 1026 | ||
1030 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation); | 1027 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation); |
@@ -1289,8 +1286,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1289 | goto drop_and_release; | 1286 | goto drop_and_release; |
1290 | 1287 | ||
1291 | /* Secret recipe starts with IP addresses */ | 1288 | /* Secret recipe starts with IP addresses */ |
1292 | *mess++ ^= daddr; | 1289 | *mess++ ^= (__force u32)daddr; |
1293 | *mess++ ^= saddr; | 1290 | *mess++ ^= (__force u32)saddr; |
1294 | 1291 | ||
1295 | /* plus variable length Initiator Cookie */ | 1292 | /* plus variable length Initiator Cookie */ |
1296 | c = (u8 *)mess; | 1293 | c = (u8 *)mess; |
@@ -1465,7 +1462,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1465 | if (newkey != NULL) | 1462 | if (newkey != NULL) |
1466 | tcp_v4_md5_do_add(newsk, newinet->inet_daddr, | 1463 | tcp_v4_md5_do_add(newsk, newinet->inet_daddr, |
1467 | newkey, key->keylen); | 1464 | newkey, key->keylen); |
1468 | newsk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1465 | sk_nocaps_add(newsk, NETIF_F_GSO_MASK); |
1469 | } | 1466 | } |
1470 | #endif | 1467 | #endif |
1471 | 1468 | ||
@@ -1675,6 +1672,8 @@ process: | |||
1675 | 1672 | ||
1676 | skb->dev = NULL; | 1673 | skb->dev = NULL; |
1677 | 1674 | ||
1675 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
1676 | |||
1678 | bh_lock_sock_nested(sk); | 1677 | bh_lock_sock_nested(sk); |
1679 | ret = 0; | 1678 | ret = 0; |
1680 | if (!sock_owned_by_user(sk)) { | 1679 | if (!sock_owned_by_user(sk)) { |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 5fabff9ac6d6..794c2e122a41 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -672,6 +672,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
672 | if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && | 672 | if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && |
673 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { | 673 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { |
674 | inet_rsk(req)->acked = 1; | 674 | inet_rsk(req)->acked = 1; |
675 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP); | ||
675 | return NULL; | 676 | return NULL; |
676 | } | 677 | } |
677 | 678 | ||
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 0dda86e72ad8..b4ed957f201a 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -350,6 +350,7 @@ static inline void TCP_ECN_send(struct sock *sk, struct sk_buff *skb, | |||
350 | */ | 350 | */ |
351 | static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags) | 351 | static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags) |
352 | { | 352 | { |
353 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
353 | skb->csum = 0; | 354 | skb->csum = 0; |
354 | 355 | ||
355 | TCP_SKB_CB(skb)->flags = flags; | 356 | TCP_SKB_CB(skb)->flags = flags; |
@@ -667,7 +668,6 @@ static unsigned tcp_synack_options(struct sock *sk, | |||
667 | u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ? | 668 | u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ? |
668 | xvp->cookie_plus : | 669 | xvp->cookie_plus : |
669 | 0; | 670 | 0; |
670 | bool doing_ts = ireq->tstamp_ok; | ||
671 | 671 | ||
672 | #ifdef CONFIG_TCP_MD5SIG | 672 | #ifdef CONFIG_TCP_MD5SIG |
673 | *md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req); | 673 | *md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req); |
@@ -680,7 +680,7 @@ static unsigned tcp_synack_options(struct sock *sk, | |||
680 | * rather than TS in order to fit in better with old, | 680 | * rather than TS in order to fit in better with old, |
681 | * buggy kernels, but that was deemed to be unnecessary. | 681 | * buggy kernels, but that was deemed to be unnecessary. |
682 | */ | 682 | */ |
683 | doing_ts &= !ireq->sack_ok; | 683 | ireq->tstamp_ok &= !ireq->sack_ok; |
684 | } | 684 | } |
685 | #else | 685 | #else |
686 | *md5 = NULL; | 686 | *md5 = NULL; |
@@ -695,7 +695,7 @@ static unsigned tcp_synack_options(struct sock *sk, | |||
695 | opts->options |= OPTION_WSCALE; | 695 | opts->options |= OPTION_WSCALE; |
696 | remaining -= TCPOLEN_WSCALE_ALIGNED; | 696 | remaining -= TCPOLEN_WSCALE_ALIGNED; |
697 | } | 697 | } |
698 | if (likely(doing_ts)) { | 698 | if (likely(ireq->tstamp_ok)) { |
699 | opts->options |= OPTION_TS; | 699 | opts->options |= OPTION_TS; |
700 | opts->tsval = TCP_SKB_CB(skb)->when; | 700 | opts->tsval = TCP_SKB_CB(skb)->when; |
701 | opts->tsecr = req->ts_recent; | 701 | opts->tsecr = req->ts_recent; |
@@ -703,7 +703,7 @@ static unsigned tcp_synack_options(struct sock *sk, | |||
703 | } | 703 | } |
704 | if (likely(ireq->sack_ok)) { | 704 | if (likely(ireq->sack_ok)) { |
705 | opts->options |= OPTION_SACK_ADVERTISE; | 705 | opts->options |= OPTION_SACK_ADVERTISE; |
706 | if (unlikely(!doing_ts)) | 706 | if (unlikely(!ireq->tstamp_ok)) |
707 | remaining -= TCPOLEN_SACKPERM_ALIGNED; | 707 | remaining -= TCPOLEN_SACKPERM_ALIGNED; |
708 | } | 708 | } |
709 | 709 | ||
@@ -711,7 +711,7 @@ static unsigned tcp_synack_options(struct sock *sk, | |||
711 | * If the <SYN> options fit, the same options should fit now! | 711 | * If the <SYN> options fit, the same options should fit now! |
712 | */ | 712 | */ |
713 | if (*md5 == NULL && | 713 | if (*md5 == NULL && |
714 | doing_ts && | 714 | ireq->tstamp_ok && |
715 | cookie_plus > TCPOLEN_COOKIE_BASE) { | 715 | cookie_plus > TCPOLEN_COOKIE_BASE) { |
716 | int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */ | 716 | int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */ |
717 | 717 | ||
@@ -860,7 +860,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
860 | th->urg_ptr = htons(tp->snd_up - tcb->seq); | 860 | th->urg_ptr = htons(tp->snd_up - tcb->seq); |
861 | th->urg = 1; | 861 | th->urg = 1; |
862 | } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { | 862 | } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { |
863 | th->urg_ptr = 0xFFFF; | 863 | th->urg_ptr = htons(0xFFFF); |
864 | th->urg = 1; | 864 | th->urg = 1; |
865 | } | 865 | } |
866 | } | 866 | } |
@@ -872,13 +872,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
872 | #ifdef CONFIG_TCP_MD5SIG | 872 | #ifdef CONFIG_TCP_MD5SIG |
873 | /* Calculate the MD5 hash, as we have all we need now */ | 873 | /* Calculate the MD5 hash, as we have all we need now */ |
874 | if (md5) { | 874 | if (md5) { |
875 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 875 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
876 | tp->af_specific->calc_md5_hash(opts.hash_location, | 876 | tp->af_specific->calc_md5_hash(opts.hash_location, |
877 | md5, sk, NULL, skb); | 877 | md5, sk, NULL, skb); |
878 | } | 878 | } |
879 | #endif | 879 | #endif |
880 | 880 | ||
881 | icsk->icsk_af_ops->send_check(sk, skb->len, skb); | 881 | icsk->icsk_af_ops->send_check(sk, skb); |
882 | 882 | ||
883 | if (likely(tcb->flags & TCPCB_FLAG_ACK)) | 883 | if (likely(tcb->flags & TCPCB_FLAG_ACK)) |
884 | tcp_event_ack_sent(sk, tcp_skb_pcount(skb)); | 884 | tcp_event_ack_sent(sk, tcp_skb_pcount(skb)); |
@@ -887,9 +887,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
887 | tcp_event_data_sent(tp, skb, sk); | 887 | tcp_event_data_sent(tp, skb, sk); |
888 | 888 | ||
889 | if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) | 889 | if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) |
890 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); | 890 | TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, |
891 | tcp_skb_pcount(skb)); | ||
891 | 892 | ||
892 | err = icsk->icsk_af_ops->queue_xmit(skb, 0); | 893 | err = icsk->icsk_af_ops->queue_xmit(skb); |
893 | if (likely(err <= 0)) | 894 | if (likely(err <= 0)) |
894 | return err; | 895 | return err; |
895 | 896 | ||
@@ -2484,7 +2485,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2484 | *tail-- ^= TCP_SKB_CB(skb)->seq + 1; | 2485 | *tail-- ^= TCP_SKB_CB(skb)->seq + 1; |
2485 | 2486 | ||
2486 | /* recommended */ | 2487 | /* recommended */ |
2487 | *tail-- ^= ((th->dest << 16) | th->source); | 2488 | *tail-- ^= (((__force u32)th->dest << 16) | (__force u32)th->source); |
2488 | *tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */ | 2489 | *tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */ |
2489 | 2490 | ||
2490 | sha_transform((__u32 *)&xvp->cookie_bakery[0], | 2491 | sha_transform((__u32 *)&xvp->cookie_bakery[0], |
@@ -2502,7 +2503,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2502 | th->window = htons(min(req->rcv_wnd, 65535U)); | 2503 | th->window = htons(min(req->rcv_wnd, 65535U)); |
2503 | tcp_options_write((__be32 *)(th + 1), tp, &opts); | 2504 | tcp_options_write((__be32 *)(th + 1), tp, &opts); |
2504 | th->doff = (tcp_header_size >> 2); | 2505 | th->doff = (tcp_header_size >> 2); |
2505 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); | 2506 | TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, tcp_skb_pcount(skb)); |
2506 | 2507 | ||
2507 | #ifdef CONFIG_TCP_MD5SIG | 2508 | #ifdef CONFIG_TCP_MD5SIG |
2508 | /* Okay, we have all we need - do the md5 hash if needed */ | 2509 | /* Okay, we have all we need - do the md5 hash if needed */ |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 8a0ab2977f1f..440a5c6004f6 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -172,14 +172,14 @@ static int tcp_write_timeout(struct sock *sk) | |||
172 | 172 | ||
173 | if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { | 173 | if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { |
174 | if (icsk->icsk_retransmits) | 174 | if (icsk->icsk_retransmits) |
175 | dst_negative_advice(&sk->sk_dst_cache, sk); | 175 | dst_negative_advice(sk); |
176 | retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; | 176 | retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; |
177 | } else { | 177 | } else { |
178 | if (retransmits_timed_out(sk, sysctl_tcp_retries1)) { | 178 | if (retransmits_timed_out(sk, sysctl_tcp_retries1)) { |
179 | /* Black hole detection */ | 179 | /* Black hole detection */ |
180 | tcp_mtu_probing(icsk, sk); | 180 | tcp_mtu_probing(icsk, sk); |
181 | 181 | ||
182 | dst_negative_advice(&sk->sk_dst_cache, sk); | 182 | dst_negative_advice(sk); |
183 | } | 183 | } |
184 | 184 | ||
185 | retry_until = sysctl_tcp_retries2; | 185 | retry_until = sysctl_tcp_retries2; |
@@ -517,7 +517,7 @@ static void tcp_keepalive_timer (unsigned long data) | |||
517 | struct sock *sk = (struct sock *) data; | 517 | struct sock *sk = (struct sock *) data; |
518 | struct inet_connection_sock *icsk = inet_csk(sk); | 518 | struct inet_connection_sock *icsk = inet_csk(sk); |
519 | struct tcp_sock *tp = tcp_sk(sk); | 519 | struct tcp_sock *tp = tcp_sk(sk); |
520 | __u32 elapsed; | 520 | u32 elapsed; |
521 | 521 | ||
522 | /* Only process if socket is not in use. */ | 522 | /* Only process if socket is not in use. */ |
523 | bh_lock_sock(sk); | 523 | bh_lock_sock(sk); |
@@ -554,7 +554,7 @@ static void tcp_keepalive_timer (unsigned long data) | |||
554 | if (tp->packets_out || tcp_send_head(sk)) | 554 | if (tp->packets_out || tcp_send_head(sk)) |
555 | goto resched; | 555 | goto resched; |
556 | 556 | ||
557 | elapsed = tcp_time_stamp - tp->rcv_tstamp; | 557 | elapsed = keepalive_time_elapsed(tp); |
558 | 558 | ||
559 | if (elapsed >= keepalive_time_when(tp)) { | 559 | if (elapsed >= keepalive_time_when(tp)) { |
560 | if (icsk->icsk_probes_out >= keepalive_probes(tp)) { | 560 | if (icsk->icsk_probes_out >= keepalive_probes(tp)) { |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c36522a0f113..9de6a698f91d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -233,7 +233,8 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
233 | */ | 233 | */ |
234 | do { | 234 | do { |
235 | if (low <= snum && snum <= high && | 235 | if (low <= snum && snum <= high && |
236 | !test_bit(snum >> udptable->log, bitmap)) | 236 | !test_bit(snum >> udptable->log, bitmap) && |
237 | !inet_is_reserved_local_port(snum)) | ||
237 | goto found; | 238 | goto found; |
238 | snum += rand; | 239 | snum += rand; |
239 | } while (snum != first); | 240 | } while (snum != first); |
@@ -307,13 +308,13 @@ static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) | |||
307 | static unsigned int udp4_portaddr_hash(struct net *net, __be32 saddr, | 308 | static unsigned int udp4_portaddr_hash(struct net *net, __be32 saddr, |
308 | unsigned int port) | 309 | unsigned int port) |
309 | { | 310 | { |
310 | return jhash_1word(saddr, net_hash_mix(net)) ^ port; | 311 | return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port; |
311 | } | 312 | } |
312 | 313 | ||
313 | int udp_v4_get_port(struct sock *sk, unsigned short snum) | 314 | int udp_v4_get_port(struct sock *sk, unsigned short snum) |
314 | { | 315 | { |
315 | unsigned int hash2_nulladdr = | 316 | unsigned int hash2_nulladdr = |
316 | udp4_portaddr_hash(sock_net(sk), INADDR_ANY, snum); | 317 | udp4_portaddr_hash(sock_net(sk), htonl(INADDR_ANY), snum); |
317 | unsigned int hash2_partial = | 318 | unsigned int hash2_partial = |
318 | udp4_portaddr_hash(sock_net(sk), inet_sk(sk)->inet_rcv_saddr, 0); | 319 | udp4_portaddr_hash(sock_net(sk), inet_sk(sk)->inet_rcv_saddr, 0); |
319 | 320 | ||
@@ -466,14 +467,14 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
466 | daddr, hnum, dif, | 467 | daddr, hnum, dif, |
467 | hslot2, slot2); | 468 | hslot2, slot2); |
468 | if (!result) { | 469 | if (!result) { |
469 | hash2 = udp4_portaddr_hash(net, INADDR_ANY, hnum); | 470 | hash2 = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum); |
470 | slot2 = hash2 & udptable->mask; | 471 | slot2 = hash2 & udptable->mask; |
471 | hslot2 = &udptable->hash2[slot2]; | 472 | hslot2 = &udptable->hash2[slot2]; |
472 | if (hslot->count < hslot2->count) | 473 | if (hslot->count < hslot2->count) |
473 | goto begin; | 474 | goto begin; |
474 | 475 | ||
475 | result = udp4_lib_lookup2(net, saddr, sport, | 476 | result = udp4_lib_lookup2(net, saddr, sport, |
476 | INADDR_ANY, hnum, dif, | 477 | htonl(INADDR_ANY), hnum, dif, |
477 | hslot2, slot2); | 478 | hslot2, slot2); |
478 | } | 479 | } |
479 | rcu_read_unlock(); | 480 | rcu_read_unlock(); |
@@ -1062,10 +1063,10 @@ static unsigned int first_packet_length(struct sock *sk) | |||
1062 | spin_unlock_bh(&rcvq->lock); | 1063 | spin_unlock_bh(&rcvq->lock); |
1063 | 1064 | ||
1064 | if (!skb_queue_empty(&list_kill)) { | 1065 | if (!skb_queue_empty(&list_kill)) { |
1065 | lock_sock(sk); | 1066 | lock_sock_bh(sk); |
1066 | __skb_queue_purge(&list_kill); | 1067 | __skb_queue_purge(&list_kill); |
1067 | sk_mem_reclaim_partial(sk); | 1068 | sk_mem_reclaim_partial(sk); |
1068 | release_sock(sk); | 1069 | unlock_sock_bh(sk); |
1069 | } | 1070 | } |
1070 | return res; | 1071 | return res; |
1071 | } | 1072 | } |
@@ -1196,10 +1197,10 @@ out: | |||
1196 | return err; | 1197 | return err; |
1197 | 1198 | ||
1198 | csum_copy_err: | 1199 | csum_copy_err: |
1199 | lock_sock(sk); | 1200 | lock_sock_bh(sk); |
1200 | if (!skb_kill_datagram(sk, skb, flags)) | 1201 | if (!skb_kill_datagram(sk, skb, flags)) |
1201 | UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); | 1202 | UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
1202 | release_sock(sk); | 1203 | unlock_sock_bh(sk); |
1203 | 1204 | ||
1204 | if (noblock) | 1205 | if (noblock) |
1205 | return -EAGAIN; | 1206 | return -EAGAIN; |
@@ -1217,6 +1218,7 @@ int udp_disconnect(struct sock *sk, int flags) | |||
1217 | sk->sk_state = TCP_CLOSE; | 1218 | sk->sk_state = TCP_CLOSE; |
1218 | inet->inet_daddr = 0; | 1219 | inet->inet_daddr = 0; |
1219 | inet->inet_dport = 0; | 1220 | inet->inet_dport = 0; |
1221 | sock_rps_save_rxhash(sk, 0); | ||
1220 | sk->sk_bound_dev_if = 0; | 1222 | sk->sk_bound_dev_if = 0; |
1221 | if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) | 1223 | if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) |
1222 | inet_reset_saddr(sk); | 1224 | inet_reset_saddr(sk); |
@@ -1258,8 +1260,12 @@ EXPORT_SYMBOL(udp_lib_unhash); | |||
1258 | 1260 | ||
1259 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | 1261 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
1260 | { | 1262 | { |
1261 | int rc = sock_queue_rcv_skb(sk, skb); | 1263 | int rc; |
1264 | |||
1265 | if (inet_sk(sk)->inet_daddr) | ||
1266 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
1262 | 1267 | ||
1268 | rc = ip_queue_rcv_skb(sk, skb); | ||
1263 | if (rc < 0) { | 1269 | if (rc < 0) { |
1264 | int is_udplite = IS_UDPLITE(sk); | 1270 | int is_udplite = IS_UDPLITE(sk); |
1265 | 1271 | ||
@@ -1367,6 +1373,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1367 | goto drop; | 1373 | goto drop; |
1368 | } | 1374 | } |
1369 | 1375 | ||
1376 | |||
1377 | if (sk_rcvqueues_full(sk, skb)) | ||
1378 | goto drop; | ||
1379 | |||
1370 | rc = 0; | 1380 | rc = 0; |
1371 | 1381 | ||
1372 | bh_lock_sock(sk); | 1382 | bh_lock_sock(sk); |
@@ -1615,9 +1625,9 @@ int udp_rcv(struct sk_buff *skb) | |||
1615 | 1625 | ||
1616 | void udp_destroy_sock(struct sock *sk) | 1626 | void udp_destroy_sock(struct sock *sk) |
1617 | { | 1627 | { |
1618 | lock_sock(sk); | 1628 | lock_sock_bh(sk); |
1619 | udp_flush_pending_frames(sk); | 1629 | udp_flush_pending_frames(sk); |
1620 | release_sock(sk); | 1630 | unlock_sock_bh(sk); |
1621 | } | 1631 | } |
1622 | 1632 | ||
1623 | /* | 1633 | /* |
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index c791bb63203f..ad8fbb871aa0 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
@@ -27,8 +27,8 @@ static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) | |||
27 | if (skb_dst(skb) == NULL) { | 27 | if (skb_dst(skb) == NULL) { |
28 | const struct iphdr *iph = ip_hdr(skb); | 28 | const struct iphdr *iph = ip_hdr(skb); |
29 | 29 | ||
30 | if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, | 30 | if (ip_route_input_noref(skb, iph->daddr, iph->saddr, |
31 | skb->dev)) | 31 | iph->tos, skb->dev)) |
32 | goto drop; | 32 | goto drop; |
33 | } | 33 | } |
34 | return dst_input(skb); | 34 | return dst_input(skb); |
@@ -61,7 +61,7 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async) | |||
61 | iph->tot_len = htons(skb->len); | 61 | iph->tot_len = htons(skb->len); |
62 | ip_send_check(iph); | 62 | ip_send_check(iph); |
63 | 63 | ||
64 | NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, | 64 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, |
65 | xfrm4_rcv_encap_finish); | 65 | xfrm4_rcv_encap_finish); |
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index c908bd99bcba..571aa96a175c 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -86,7 +86,7 @@ static int xfrm4_output_finish(struct sk_buff *skb) | |||
86 | 86 | ||
87 | int xfrm4_output(struct sk_buff *skb) | 87 | int xfrm4_output(struct sk_buff *skb) |
88 | { | 88 | { |
89 | return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, | 89 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, |
90 | NULL, skb_dst(skb)->dev, xfrm4_output_finish, | 90 | NULL, skb_dst(skb)->dev, xfrm4_output_finish, |
91 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 91 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
92 | } | 92 | } |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index e4a1483fba77..1705476670ef 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -59,27 +59,6 @@ static int xfrm4_get_saddr(struct net *net, | |||
59 | return 0; | 59 | return 0; |
60 | } | 60 | } |
61 | 61 | ||
62 | static struct dst_entry * | ||
63 | __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | ||
64 | { | ||
65 | struct dst_entry *dst; | ||
66 | |||
67 | read_lock_bh(&policy->lock); | ||
68 | for (dst = policy->bundles; dst; dst = dst->next) { | ||
69 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | ||
70 | if (xdst->u.rt.fl.oif == fl->oif && /*XXX*/ | ||
71 | xdst->u.rt.fl.fl4_dst == fl->fl4_dst && | ||
72 | xdst->u.rt.fl.fl4_src == fl->fl4_src && | ||
73 | xdst->u.rt.fl.fl4_tos == fl->fl4_tos && | ||
74 | xfrm_bundle_ok(policy, xdst, fl, AF_INET, 0)) { | ||
75 | dst_clone(dst); | ||
76 | break; | ||
77 | } | ||
78 | } | ||
79 | read_unlock_bh(&policy->lock); | ||
80 | return dst; | ||
81 | } | ||
82 | |||
83 | static int xfrm4_get_tos(struct flowi *fl) | 62 | static int xfrm4_get_tos(struct flowi *fl) |
84 | { | 63 | { |
85 | return fl->fl4_tos; | 64 | return fl->fl4_tos; |
@@ -259,7 +238,6 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { | |||
259 | .dst_ops = &xfrm4_dst_ops, | 238 | .dst_ops = &xfrm4_dst_ops, |
260 | .dst_lookup = xfrm4_dst_lookup, | 239 | .dst_lookup = xfrm4_dst_lookup, |
261 | .get_saddr = xfrm4_get_saddr, | 240 | .get_saddr = xfrm4_get_saddr, |
262 | .find_bundle = __xfrm4_find_bundle, | ||
263 | .decode_session = _decode_session4, | 241 | .decode_session = _decode_session4, |
264 | .get_tos = xfrm4_get_tos, | 242 | .get_tos = xfrm4_get_tos, |
265 | .init_path = xfrm4_init_path, | 243 | .init_path = xfrm4_init_path, |
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index a578096152ab..36d7437ac054 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -229,6 +229,20 @@ config IPV6_MROUTE | |||
229 | Experimental support for IPv6 multicast forwarding. | 229 | Experimental support for IPv6 multicast forwarding. |
230 | If unsure, say N. | 230 | If unsure, say N. |
231 | 231 | ||
232 | config IPV6_MROUTE_MULTIPLE_TABLES | ||
233 | bool "IPv6: multicast policy routing" | ||
234 | depends on IPV6_MROUTE | ||
235 | select FIB_RULES | ||
236 | help | ||
237 | Normally, a multicast router runs a userspace daemon and decides | ||
238 | what to do with a multicast packet based on the source and | ||
239 | destination addresses. If you say Y here, the multicast router | ||
240 | will also be able to take interfaces and packet marks into | ||
241 | account and run multiple instances of userspace daemons | ||
242 | simultaneously, each one handling a single table. | ||
243 | |||
244 | If unsure, say N. | ||
245 | |||
232 | config IPV6_PIMSM_V2 | 246 | config IPV6_PIMSM_V2 |
233 | bool "IPv6: PIM-SM version 2 support (EXPERIMENTAL)" | 247 | bool "IPv6: PIM-SM version 2 support (EXPERIMENTAL)" |
234 | depends on IPV6_MROUTE | 248 | depends on IPV6_MROUTE |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 413054f02aab..e1a698df5706 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -82,7 +82,7 @@ | |||
82 | #include <linux/random.h> | 82 | #include <linux/random.h> |
83 | #endif | 83 | #endif |
84 | 84 | ||
85 | #include <asm/uaccess.h> | 85 | #include <linux/uaccess.h> |
86 | #include <asm/unaligned.h> | 86 | #include <asm/unaligned.h> |
87 | 87 | ||
88 | #include <linux/proc_fs.h> | 88 | #include <linux/proc_fs.h> |
@@ -98,7 +98,11 @@ | |||
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | #define INFINITY_LIFE_TIME 0xFFFFFFFF | 100 | #define INFINITY_LIFE_TIME 0xFFFFFFFF |
101 | #define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b))) | 101 | #define TIME_DELTA(a, b) ((unsigned long)((long)(a) - (long)(b))) |
102 | |||
103 | #define ADDRCONF_TIMER_FUZZ_MINUS (HZ > 50 ? HZ/50 : 1) | ||
104 | #define ADDRCONF_TIMER_FUZZ (HZ / 4) | ||
105 | #define ADDRCONF_TIMER_FUZZ_MAX (HZ) | ||
102 | 106 | ||
103 | #ifdef CONFIG_SYSCTL | 107 | #ifdef CONFIG_SYSCTL |
104 | static void addrconf_sysctl_register(struct inet6_dev *idev); | 108 | static void addrconf_sysctl_register(struct inet6_dev *idev); |
@@ -127,8 +131,8 @@ static int ipv6_count_addresses(struct inet6_dev *idev); | |||
127 | /* | 131 | /* |
128 | * Configured unicast address hash table | 132 | * Configured unicast address hash table |
129 | */ | 133 | */ |
130 | static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; | 134 | static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE]; |
131 | static DEFINE_RWLOCK(addrconf_hash_lock); | 135 | static DEFINE_SPINLOCK(addrconf_hash_lock); |
132 | 136 | ||
133 | static void addrconf_verify(unsigned long); | 137 | static void addrconf_verify(unsigned long); |
134 | 138 | ||
@@ -138,8 +142,8 @@ static DEFINE_SPINLOCK(addrconf_verify_lock); | |||
138 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); | 142 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); |
139 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); | 143 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); |
140 | 144 | ||
141 | static void addrconf_bonding_change(struct net_device *dev, | 145 | static void addrconf_type_change(struct net_device *dev, |
142 | unsigned long event); | 146 | unsigned long event); |
143 | static int addrconf_ifdown(struct net_device *dev, int how); | 147 | static int addrconf_ifdown(struct net_device *dev, int how); |
144 | 148 | ||
145 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); | 149 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); |
@@ -152,8 +156,8 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | |||
152 | 156 | ||
153 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, | 157 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, |
154 | struct prefix_info *pinfo); | 158 | struct prefix_info *pinfo); |
155 | static int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 159 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
156 | struct net_device *dev); | 160 | struct net_device *dev); |
157 | 161 | ||
158 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | 162 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); |
159 | 163 | ||
@@ -250,8 +254,7 @@ static void addrconf_del_timer(struct inet6_ifaddr *ifp) | |||
250 | __in6_ifa_put(ifp); | 254 | __in6_ifa_put(ifp); |
251 | } | 255 | } |
252 | 256 | ||
253 | enum addrconf_timer_t | 257 | enum addrconf_timer_t { |
254 | { | ||
255 | AC_NONE, | 258 | AC_NONE, |
256 | AC_DAD, | 259 | AC_DAD, |
257 | AC_RS, | 260 | AC_RS, |
@@ -271,7 +274,8 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
271 | case AC_RS: | 274 | case AC_RS: |
272 | ifp->timer.function = addrconf_rs_timer; | 275 | ifp->timer.function = addrconf_rs_timer; |
273 | break; | 276 | break; |
274 | default:; | 277 | default: |
278 | break; | ||
275 | } | 279 | } |
276 | ifp->timer.expires = jiffies + when; | 280 | ifp->timer.expires = jiffies + when; |
277 | add_timer(&ifp->timer); | 281 | add_timer(&ifp->timer); |
@@ -318,7 +322,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
318 | { | 322 | { |
319 | struct net_device *dev = idev->dev; | 323 | struct net_device *dev = idev->dev; |
320 | 324 | ||
321 | WARN_ON(idev->addr_list != NULL); | 325 | WARN_ON(!list_empty(&idev->addr_list)); |
322 | WARN_ON(idev->mc_list != NULL); | 326 | WARN_ON(idev->mc_list != NULL); |
323 | 327 | ||
324 | #ifdef NET_REFCNT_DEBUG | 328 | #ifdef NET_REFCNT_DEBUG |
@@ -326,7 +330,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
326 | #endif | 330 | #endif |
327 | dev_put(dev); | 331 | dev_put(dev); |
328 | if (!idev->dead) { | 332 | if (!idev->dead) { |
329 | printk("Freeing alive inet6 device %p\n", idev); | 333 | pr_warning("Freeing alive inet6 device %p\n", idev); |
330 | return; | 334 | return; |
331 | } | 335 | } |
332 | snmp6_free_dev(idev); | 336 | snmp6_free_dev(idev); |
@@ -351,6 +355,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
351 | 355 | ||
352 | rwlock_init(&ndev->lock); | 356 | rwlock_init(&ndev->lock); |
353 | ndev->dev = dev; | 357 | ndev->dev = dev; |
358 | INIT_LIST_HEAD(&ndev->addr_list); | ||
359 | |||
354 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); | 360 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); |
355 | ndev->cnf.mtu6 = dev->mtu; | 361 | ndev->cnf.mtu6 = dev->mtu; |
356 | ndev->cnf.sysctl = NULL; | 362 | ndev->cnf.sysctl = NULL; |
@@ -402,6 +408,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
402 | #endif | 408 | #endif |
403 | 409 | ||
404 | #ifdef CONFIG_IPV6_PRIVACY | 410 | #ifdef CONFIG_IPV6_PRIVACY |
411 | INIT_LIST_HEAD(&ndev->tempaddr_list); | ||
405 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); | 412 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); |
406 | if ((dev->flags&IFF_LOOPBACK) || | 413 | if ((dev->flags&IFF_LOOPBACK) || |
407 | dev->type == ARPHRD_TUNNEL || | 414 | dev->type == ARPHRD_TUNNEL || |
@@ -439,8 +446,10 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev) | |||
439 | 446 | ||
440 | ASSERT_RTNL(); | 447 | ASSERT_RTNL(); |
441 | 448 | ||
442 | if ((idev = __in6_dev_get(dev)) == NULL) { | 449 | idev = __in6_dev_get(dev); |
443 | if ((idev = ipv6_add_dev(dev)) == NULL) | 450 | if (!idev) { |
451 | idev = ipv6_add_dev(dev); | ||
452 | if (!idev) | ||
444 | return NULL; | 453 | return NULL; |
445 | } | 454 | } |
446 | 455 | ||
@@ -466,7 +475,8 @@ static void dev_forward_change(struct inet6_dev *idev) | |||
466 | else | 475 | else |
467 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); | 476 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); |
468 | } | 477 | } |
469 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { | 478 | |
479 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
470 | if (ifa->flags&IFA_F_TENTATIVE) | 480 | if (ifa->flags&IFA_F_TENTATIVE) |
471 | continue; | 481 | continue; |
472 | if (idev->cnf.forwarding) | 482 | if (idev->cnf.forwarding) |
@@ -523,12 +533,16 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
523 | } | 533 | } |
524 | #endif | 534 | #endif |
525 | 535 | ||
526 | /* Nobody refers to this ifaddr, destroy it */ | 536 | static void inet6_ifa_finish_destroy_rcu(struct rcu_head *head) |
537 | { | ||
538 | struct inet6_ifaddr *ifp = container_of(head, struct inet6_ifaddr, rcu); | ||
539 | kfree(ifp); | ||
540 | } | ||
527 | 541 | ||
542 | /* Nobody refers to this ifaddr, destroy it */ | ||
528 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | 543 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) |
529 | { | 544 | { |
530 | WARN_ON(ifp->if_next != NULL); | 545 | WARN_ON(!hlist_unhashed(&ifp->addr_lst)); |
531 | WARN_ON(ifp->lst_next != NULL); | ||
532 | 546 | ||
533 | #ifdef NET_REFCNT_DEBUG | 547 | #ifdef NET_REFCNT_DEBUG |
534 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); | 548 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); |
@@ -537,54 +551,46 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
537 | in6_dev_put(ifp->idev); | 551 | in6_dev_put(ifp->idev); |
538 | 552 | ||
539 | if (del_timer(&ifp->timer)) | 553 | if (del_timer(&ifp->timer)) |
540 | printk("Timer is still running, when freeing ifa=%p\n", ifp); | 554 | pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); |
541 | 555 | ||
542 | if (!ifp->dead) { | 556 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { |
543 | printk("Freeing alive inet6 address %p\n", ifp); | 557 | pr_warning("Freeing alive inet6 address %p\n", ifp); |
544 | return; | 558 | return; |
545 | } | 559 | } |
546 | dst_release(&ifp->rt->u.dst); | 560 | dst_release(&ifp->rt->u.dst); |
547 | 561 | ||
548 | kfree(ifp); | 562 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); |
549 | } | 563 | } |
550 | 564 | ||
551 | static void | 565 | static void |
552 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) | 566 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) |
553 | { | 567 | { |
554 | struct inet6_ifaddr *ifa, **ifap; | 568 | struct list_head *p; |
555 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); | 569 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); |
556 | 570 | ||
557 | /* | 571 | /* |
558 | * Each device address list is sorted in order of scope - | 572 | * Each device address list is sorted in order of scope - |
559 | * global before linklocal. | 573 | * global before linklocal. |
560 | */ | 574 | */ |
561 | for (ifap = &idev->addr_list; (ifa = *ifap) != NULL; | 575 | list_for_each(p, &idev->addr_list) { |
562 | ifap = &ifa->if_next) { | 576 | struct inet6_ifaddr *ifa |
577 | = list_entry(p, struct inet6_ifaddr, if_list); | ||
563 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) | 578 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) |
564 | break; | 579 | break; |
565 | } | 580 | } |
566 | 581 | ||
567 | ifp->if_next = *ifap; | 582 | list_add_tail(&ifp->if_list, p); |
568 | *ifap = ifp; | ||
569 | } | 583 | } |
570 | 584 | ||
571 | /* | 585 | static u32 ipv6_addr_hash(const struct in6_addr *addr) |
572 | * Hash function taken from net_alias.c | ||
573 | */ | ||
574 | static u8 ipv6_addr_hash(const struct in6_addr *addr) | ||
575 | { | 586 | { |
576 | __u32 word; | ||
577 | |||
578 | /* | 587 | /* |
579 | * We perform the hash function over the last 64 bits of the address | 588 | * We perform the hash function over the last 64 bits of the address |
580 | * This will include the IEEE address token on links that support it. | 589 | * This will include the IEEE address token on links that support it. |
581 | */ | 590 | */ |
582 | 591 | return jhash_2words((__force u32)addr->s6_addr32[2], | |
583 | word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); | 592 | (__force u32)addr->s6_addr32[3], 0) |
584 | word ^= (word >> 16); | 593 | & (IN6_ADDR_HSIZE - 1); |
585 | word ^= (word >> 8); | ||
586 | |||
587 | return ((word ^ (word >> 4)) & 0x0f); | ||
588 | } | 594 | } |
589 | 595 | ||
590 | /* On success it returns ifp with increased reference count */ | 596 | /* On success it returns ifp with increased reference count */ |
@@ -595,7 +601,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
595 | { | 601 | { |
596 | struct inet6_ifaddr *ifa = NULL; | 602 | struct inet6_ifaddr *ifa = NULL; |
597 | struct rt6_info *rt; | 603 | struct rt6_info *rt; |
598 | int hash; | 604 | unsigned int hash; |
599 | int err = 0; | 605 | int err = 0; |
600 | int addr_type = ipv6_addr_type(addr); | 606 | int addr_type = ipv6_addr_type(addr); |
601 | 607 | ||
@@ -616,7 +622,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
616 | goto out2; | 622 | goto out2; |
617 | } | 623 | } |
618 | 624 | ||
619 | write_lock(&addrconf_hash_lock); | 625 | spin_lock(&addrconf_hash_lock); |
620 | 626 | ||
621 | /* Ignore adding duplicate addresses on an interface */ | 627 | /* Ignore adding duplicate addresses on an interface */ |
622 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { | 628 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { |
@@ -642,7 +648,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
642 | ipv6_addr_copy(&ifa->addr, addr); | 648 | ipv6_addr_copy(&ifa->addr, addr); |
643 | 649 | ||
644 | spin_lock_init(&ifa->lock); | 650 | spin_lock_init(&ifa->lock); |
651 | spin_lock_init(&ifa->state_lock); | ||
645 | init_timer(&ifa->timer); | 652 | init_timer(&ifa->timer); |
653 | INIT_HLIST_NODE(&ifa->addr_lst); | ||
646 | ifa->timer.data = (unsigned long) ifa; | 654 | ifa->timer.data = (unsigned long) ifa; |
647 | ifa->scope = scope; | 655 | ifa->scope = scope; |
648 | ifa->prefix_len = pfxlen; | 656 | ifa->prefix_len = pfxlen; |
@@ -669,10 +677,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
669 | /* Add to big hash table */ | 677 | /* Add to big hash table */ |
670 | hash = ipv6_addr_hash(addr); | 678 | hash = ipv6_addr_hash(addr); |
671 | 679 | ||
672 | ifa->lst_next = inet6_addr_lst[hash]; | 680 | hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]); |
673 | inet6_addr_lst[hash] = ifa; | 681 | spin_unlock(&addrconf_hash_lock); |
674 | in6_ifa_hold(ifa); | ||
675 | write_unlock(&addrconf_hash_lock); | ||
676 | 682 | ||
677 | write_lock(&idev->lock); | 683 | write_lock(&idev->lock); |
678 | /* Add to inet6_dev unicast addr list. */ | 684 | /* Add to inet6_dev unicast addr list. */ |
@@ -680,8 +686,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
680 | 686 | ||
681 | #ifdef CONFIG_IPV6_PRIVACY | 687 | #ifdef CONFIG_IPV6_PRIVACY |
682 | if (ifa->flags&IFA_F_TEMPORARY) { | 688 | if (ifa->flags&IFA_F_TEMPORARY) { |
683 | ifa->tmp_next = idev->tempaddr_list; | 689 | list_add(&ifa->tmp_list, &idev->tempaddr_list); |
684 | idev->tempaddr_list = ifa; | ||
685 | in6_ifa_hold(ifa); | 690 | in6_ifa_hold(ifa); |
686 | } | 691 | } |
687 | #endif | 692 | #endif |
@@ -700,7 +705,7 @@ out2: | |||
700 | 705 | ||
701 | return ifa; | 706 | return ifa; |
702 | out: | 707 | out: |
703 | write_unlock(&addrconf_hash_lock); | 708 | spin_unlock(&addrconf_hash_lock); |
704 | goto out2; | 709 | goto out2; |
705 | } | 710 | } |
706 | 711 | ||
@@ -708,52 +713,44 @@ out: | |||
708 | 713 | ||
709 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) | 714 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) |
710 | { | 715 | { |
711 | struct inet6_ifaddr *ifa, **ifap; | 716 | struct inet6_ifaddr *ifa, *ifn; |
712 | struct inet6_dev *idev = ifp->idev; | 717 | struct inet6_dev *idev = ifp->idev; |
718 | int state; | ||
713 | int hash; | 719 | int hash; |
714 | int deleted = 0, onlink = 0; | 720 | int deleted = 0, onlink = 0; |
715 | unsigned long expires = jiffies; | 721 | unsigned long expires = jiffies; |
716 | 722 | ||
717 | hash = ipv6_addr_hash(&ifp->addr); | 723 | hash = ipv6_addr_hash(&ifp->addr); |
718 | 724 | ||
719 | ifp->dead = 1; | 725 | spin_lock_bh(&ifp->state_lock); |
726 | state = ifp->state; | ||
727 | ifp->state = INET6_IFADDR_STATE_DEAD; | ||
728 | spin_unlock_bh(&ifp->state_lock); | ||
720 | 729 | ||
721 | write_lock_bh(&addrconf_hash_lock); | 730 | if (state == INET6_IFADDR_STATE_DEAD) |
722 | for (ifap = &inet6_addr_lst[hash]; (ifa=*ifap) != NULL; | 731 | goto out; |
723 | ifap = &ifa->lst_next) { | 732 | |
724 | if (ifa == ifp) { | 733 | spin_lock_bh(&addrconf_hash_lock); |
725 | *ifap = ifa->lst_next; | 734 | hlist_del_init_rcu(&ifp->addr_lst); |
726 | __in6_ifa_put(ifp); | 735 | spin_unlock_bh(&addrconf_hash_lock); |
727 | ifa->lst_next = NULL; | ||
728 | break; | ||
729 | } | ||
730 | } | ||
731 | write_unlock_bh(&addrconf_hash_lock); | ||
732 | 736 | ||
733 | write_lock_bh(&idev->lock); | 737 | write_lock_bh(&idev->lock); |
734 | #ifdef CONFIG_IPV6_PRIVACY | 738 | #ifdef CONFIG_IPV6_PRIVACY |
735 | if (ifp->flags&IFA_F_TEMPORARY) { | 739 | if (ifp->flags&IFA_F_TEMPORARY) { |
736 | for (ifap = &idev->tempaddr_list; (ifa=*ifap) != NULL; | 740 | list_del(&ifp->tmp_list); |
737 | ifap = &ifa->tmp_next) { | 741 | if (ifp->ifpub) { |
738 | if (ifa == ifp) { | 742 | in6_ifa_put(ifp->ifpub); |
739 | *ifap = ifa->tmp_next; | 743 | ifp->ifpub = NULL; |
740 | if (ifp->ifpub) { | ||
741 | in6_ifa_put(ifp->ifpub); | ||
742 | ifp->ifpub = NULL; | ||
743 | } | ||
744 | __in6_ifa_put(ifp); | ||
745 | ifa->tmp_next = NULL; | ||
746 | break; | ||
747 | } | ||
748 | } | 744 | } |
745 | __in6_ifa_put(ifp); | ||
749 | } | 746 | } |
750 | #endif | 747 | #endif |
751 | 748 | ||
752 | for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) { | 749 | list_for_each_entry_safe(ifa, ifn, &idev->addr_list, if_list) { |
753 | if (ifa == ifp) { | 750 | if (ifa == ifp) { |
754 | *ifap = ifa->if_next; | 751 | list_del_init(&ifp->if_list); |
755 | __in6_ifa_put(ifp); | 752 | __in6_ifa_put(ifp); |
756 | ifa->if_next = NULL; | 753 | |
757 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) | 754 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) |
758 | break; | 755 | break; |
759 | deleted = 1; | 756 | deleted = 1; |
@@ -786,7 +783,6 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
786 | } | 783 | } |
787 | } | 784 | } |
788 | } | 785 | } |
789 | ifap = &ifa->if_next; | ||
790 | } | 786 | } |
791 | write_unlock_bh(&idev->lock); | 787 | write_unlock_bh(&idev->lock); |
792 | 788 | ||
@@ -830,6 +826,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
830 | dst_release(&rt->u.dst); | 826 | dst_release(&rt->u.dst); |
831 | } | 827 | } |
832 | 828 | ||
829 | out: | ||
833 | in6_ifa_put(ifp); | 830 | in6_ifa_put(ifp); |
834 | } | 831 | } |
835 | 832 | ||
@@ -1165,7 +1162,7 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | |||
1165 | continue; | 1162 | continue; |
1166 | 1163 | ||
1167 | read_lock_bh(&idev->lock); | 1164 | read_lock_bh(&idev->lock); |
1168 | for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { | 1165 | list_for_each_entry(score->ifa, &idev->addr_list, if_list) { |
1169 | int i; | 1166 | int i; |
1170 | 1167 | ||
1171 | /* | 1168 | /* |
@@ -1243,7 +1240,6 @@ try_nextdev: | |||
1243 | in6_ifa_put(hiscore->ifa); | 1240 | in6_ifa_put(hiscore->ifa); |
1244 | return 0; | 1241 | return 0; |
1245 | } | 1242 | } |
1246 | |||
1247 | EXPORT_SYMBOL(ipv6_dev_get_saddr); | 1243 | EXPORT_SYMBOL(ipv6_dev_get_saddr); |
1248 | 1244 | ||
1249 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | 1245 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
@@ -1253,12 +1249,14 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | |||
1253 | int err = -EADDRNOTAVAIL; | 1249 | int err = -EADDRNOTAVAIL; |
1254 | 1250 | ||
1255 | rcu_read_lock(); | 1251 | rcu_read_lock(); |
1256 | if ((idev = __in6_dev_get(dev)) != NULL) { | 1252 | idev = __in6_dev_get(dev); |
1253 | if (idev) { | ||
1257 | struct inet6_ifaddr *ifp; | 1254 | struct inet6_ifaddr *ifp; |
1258 | 1255 | ||
1259 | read_lock_bh(&idev->lock); | 1256 | read_lock_bh(&idev->lock); |
1260 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1257 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
1261 | if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) { | 1258 | if (ifp->scope == IFA_LINK && |
1259 | !(ifp->flags & banned_flags)) { | ||
1262 | ipv6_addr_copy(addr, &ifp->addr); | 1260 | ipv6_addr_copy(addr, &ifp->addr); |
1263 | err = 0; | 1261 | err = 0; |
1264 | break; | 1262 | break; |
@@ -1276,7 +1274,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1276 | struct inet6_ifaddr *ifp; | 1274 | struct inet6_ifaddr *ifp; |
1277 | 1275 | ||
1278 | read_lock_bh(&idev->lock); | 1276 | read_lock_bh(&idev->lock); |
1279 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) | 1277 | list_for_each_entry(ifp, &idev->addr_list, if_list) |
1280 | cnt++; | 1278 | cnt++; |
1281 | read_unlock_bh(&idev->lock); | 1279 | read_unlock_bh(&idev->lock); |
1282 | return cnt; | 1280 | return cnt; |
@@ -1285,41 +1283,44 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1285 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | 1283 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, |
1286 | struct net_device *dev, int strict) | 1284 | struct net_device *dev, int strict) |
1287 | { | 1285 | { |
1288 | struct inet6_ifaddr * ifp; | 1286 | struct inet6_ifaddr *ifp; |
1289 | u8 hash = ipv6_addr_hash(addr); | 1287 | struct hlist_node *node; |
1288 | unsigned int hash = ipv6_addr_hash(addr); | ||
1290 | 1289 | ||
1291 | read_lock_bh(&addrconf_hash_lock); | 1290 | rcu_read_lock_bh(); |
1292 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1291 | hlist_for_each_entry_rcu(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1293 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1292 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1294 | continue; | 1293 | continue; |
1295 | if (ipv6_addr_equal(&ifp->addr, addr) && | 1294 | if (ipv6_addr_equal(&ifp->addr, addr) && |
1296 | !(ifp->flags&IFA_F_TENTATIVE)) { | 1295 | !(ifp->flags&IFA_F_TENTATIVE) && |
1297 | if (dev == NULL || ifp->idev->dev == dev || | 1296 | (dev == NULL || ifp->idev->dev == dev || |
1298 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) | 1297 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))) { |
1299 | break; | 1298 | rcu_read_unlock_bh(); |
1299 | return 1; | ||
1300 | } | 1300 | } |
1301 | } | 1301 | } |
1302 | read_unlock_bh(&addrconf_hash_lock); | 1302 | |
1303 | return ifp != NULL; | 1303 | rcu_read_unlock_bh(); |
1304 | return 0; | ||
1304 | } | 1305 | } |
1305 | EXPORT_SYMBOL(ipv6_chk_addr); | 1306 | EXPORT_SYMBOL(ipv6_chk_addr); |
1306 | 1307 | ||
1307 | static | 1308 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
1308 | int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 1309 | struct net_device *dev) |
1309 | struct net_device *dev) | ||
1310 | { | 1310 | { |
1311 | struct inet6_ifaddr * ifp; | 1311 | unsigned int hash = ipv6_addr_hash(addr); |
1312 | u8 hash = ipv6_addr_hash(addr); | 1312 | struct inet6_ifaddr *ifp; |
1313 | struct hlist_node *node; | ||
1313 | 1314 | ||
1314 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1315 | hlist_for_each_entry(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1315 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1316 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1316 | continue; | 1317 | continue; |
1317 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1318 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1318 | if (dev == NULL || ifp->idev->dev == dev) | 1319 | if (dev == NULL || ifp->idev->dev == dev) |
1319 | break; | 1320 | return true; |
1320 | } | 1321 | } |
1321 | } | 1322 | } |
1322 | return ifp != NULL; | 1323 | return false; |
1323 | } | 1324 | } |
1324 | 1325 | ||
1325 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | 1326 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) |
@@ -1333,7 +1334,7 @@ int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | |||
1333 | idev = __in6_dev_get(dev); | 1334 | idev = __in6_dev_get(dev); |
1334 | if (idev) { | 1335 | if (idev) { |
1335 | read_lock_bh(&idev->lock); | 1336 | read_lock_bh(&idev->lock); |
1336 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { | 1337 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
1337 | onlink = ipv6_prefix_equal(addr, &ifa->addr, | 1338 | onlink = ipv6_prefix_equal(addr, &ifa->addr, |
1338 | ifa->prefix_len); | 1339 | ifa->prefix_len); |
1339 | if (onlink) | 1340 | if (onlink) |
@@ -1350,24 +1351,26 @@ EXPORT_SYMBOL(ipv6_chk_prefix); | |||
1350 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, | 1351 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, |
1351 | struct net_device *dev, int strict) | 1352 | struct net_device *dev, int strict) |
1352 | { | 1353 | { |
1353 | struct inet6_ifaddr * ifp; | 1354 | struct inet6_ifaddr *ifp, *result = NULL; |
1354 | u8 hash = ipv6_addr_hash(addr); | 1355 | unsigned int hash = ipv6_addr_hash(addr); |
1356 | struct hlist_node *node; | ||
1355 | 1357 | ||
1356 | read_lock_bh(&addrconf_hash_lock); | 1358 | rcu_read_lock_bh(); |
1357 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1359 | hlist_for_each_entry_rcu_bh(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1358 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1360 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1359 | continue; | 1361 | continue; |
1360 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1362 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1361 | if (dev == NULL || ifp->idev->dev == dev || | 1363 | if (dev == NULL || ifp->idev->dev == dev || |
1362 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { | 1364 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { |
1365 | result = ifp; | ||
1363 | in6_ifa_hold(ifp); | 1366 | in6_ifa_hold(ifp); |
1364 | break; | 1367 | break; |
1365 | } | 1368 | } |
1366 | } | 1369 | } |
1367 | } | 1370 | } |
1368 | read_unlock_bh(&addrconf_hash_lock); | 1371 | rcu_read_unlock_bh(); |
1369 | 1372 | ||
1370 | return ifp; | 1373 | return result; |
1371 | } | 1374 | } |
1372 | 1375 | ||
1373 | /* Gets referenced address, destroys ifaddr */ | 1376 | /* Gets referenced address, destroys ifaddr */ |
@@ -1403,10 +1406,27 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
1403 | ipv6_del_addr(ifp); | 1406 | ipv6_del_addr(ifp); |
1404 | } | 1407 | } |
1405 | 1408 | ||
1409 | static int addrconf_dad_end(struct inet6_ifaddr *ifp) | ||
1410 | { | ||
1411 | int err = -ENOENT; | ||
1412 | |||
1413 | spin_lock(&ifp->state_lock); | ||
1414 | if (ifp->state == INET6_IFADDR_STATE_DAD) { | ||
1415 | ifp->state = INET6_IFADDR_STATE_POSTDAD; | ||
1416 | err = 0; | ||
1417 | } | ||
1418 | spin_unlock(&ifp->state_lock); | ||
1419 | |||
1420 | return err; | ||
1421 | } | ||
1422 | |||
1406 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | 1423 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) |
1407 | { | 1424 | { |
1408 | struct inet6_dev *idev = ifp->idev; | 1425 | struct inet6_dev *idev = ifp->idev; |
1409 | 1426 | ||
1427 | if (addrconf_dad_end(ifp)) | ||
1428 | return; | ||
1429 | |||
1410 | if (net_ratelimit()) | 1430 | if (net_ratelimit()) |
1411 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", | 1431 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", |
1412 | ifp->idev->dev->name, &ifp->addr); | 1432 | ifp->idev->dev->name, &ifp->addr); |
@@ -1570,7 +1590,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev) | |||
1570 | struct inet6_ifaddr *ifp; | 1590 | struct inet6_ifaddr *ifp; |
1571 | 1591 | ||
1572 | read_lock_bh(&idev->lock); | 1592 | read_lock_bh(&idev->lock); |
1573 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1593 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
1574 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { | 1594 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { |
1575 | memcpy(eui, ifp->addr.s6_addr+8, 8); | 1595 | memcpy(eui, ifp->addr.s6_addr+8, 8); |
1576 | err = 0; | 1596 | err = 0; |
@@ -1738,7 +1758,8 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) | |||
1738 | 1758 | ||
1739 | ASSERT_RTNL(); | 1759 | ASSERT_RTNL(); |
1740 | 1760 | ||
1741 | if ((idev = ipv6_find_idev(dev)) == NULL) | 1761 | idev = ipv6_find_idev(dev); |
1762 | if (!idev) | ||
1742 | return NULL; | 1763 | return NULL; |
1743 | 1764 | ||
1744 | /* Add default multicast route */ | 1765 | /* Add default multicast route */ |
@@ -1971,7 +1992,7 @@ ok: | |||
1971 | #ifdef CONFIG_IPV6_PRIVACY | 1992 | #ifdef CONFIG_IPV6_PRIVACY |
1972 | read_lock_bh(&in6_dev->lock); | 1993 | read_lock_bh(&in6_dev->lock); |
1973 | /* update all temporary addresses in the list */ | 1994 | /* update all temporary addresses in the list */ |
1974 | for (ift=in6_dev->tempaddr_list; ift; ift=ift->tmp_next) { | 1995 | list_for_each_entry(ift, &in6_dev->tempaddr_list, tmp_list) { |
1975 | /* | 1996 | /* |
1976 | * When adjusting the lifetimes of an existing | 1997 | * When adjusting the lifetimes of an existing |
1977 | * temporary address, only lower the lifetimes. | 1998 | * temporary address, only lower the lifetimes. |
@@ -2174,7 +2195,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2174 | return -ENXIO; | 2195 | return -ENXIO; |
2175 | 2196 | ||
2176 | read_lock_bh(&idev->lock); | 2197 | read_lock_bh(&idev->lock); |
2177 | for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) { | 2198 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
2178 | if (ifp->prefix_len == plen && | 2199 | if (ifp->prefix_len == plen && |
2179 | ipv6_addr_equal(pfx, &ifp->addr)) { | 2200 | ipv6_addr_equal(pfx, &ifp->addr)) { |
2180 | in6_ifa_hold(ifp); | 2201 | in6_ifa_hold(ifp); |
@@ -2185,7 +2206,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2185 | /* If the last address is deleted administratively, | 2206 | /* If the last address is deleted administratively, |
2186 | disable IPv6 on this interface. | 2207 | disable IPv6 on this interface. |
2187 | */ | 2208 | */ |
2188 | if (idev->addr_list == NULL) | 2209 | if (list_empty(&idev->addr_list)) |
2189 | addrconf_ifdown(idev->dev, 1); | 2210 | addrconf_ifdown(idev->dev, 1); |
2190 | return 0; | 2211 | return 0; |
2191 | } | 2212 | } |
@@ -2446,7 +2467,8 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) | |||
2446 | 2467 | ||
2447 | ASSERT_RTNL(); | 2468 | ASSERT_RTNL(); |
2448 | 2469 | ||
2449 | if ((idev = addrconf_add_dev(dev)) == NULL) { | 2470 | idev = addrconf_add_dev(dev); |
2471 | if (!idev) { | ||
2450 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); | 2472 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); |
2451 | return; | 2473 | return; |
2452 | } | 2474 | } |
@@ -2461,7 +2483,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2461 | int run_pending = 0; | 2483 | int run_pending = 0; |
2462 | int err; | 2484 | int err; |
2463 | 2485 | ||
2464 | switch(event) { | 2486 | switch (event) { |
2465 | case NETDEV_REGISTER: | 2487 | case NETDEV_REGISTER: |
2466 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2488 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
2467 | idev = ipv6_add_dev(dev); | 2489 | idev = ipv6_add_dev(dev); |
@@ -2469,6 +2491,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2469 | return notifier_from_errno(-ENOMEM); | 2491 | return notifier_from_errno(-ENOMEM); |
2470 | } | 2492 | } |
2471 | break; | 2493 | break; |
2494 | |||
2472 | case NETDEV_UP: | 2495 | case NETDEV_UP: |
2473 | case NETDEV_CHANGE: | 2496 | case NETDEV_CHANGE: |
2474 | if (dev->flags & IFF_SLAVE) | 2497 | if (dev->flags & IFF_SLAVE) |
@@ -2498,10 +2521,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2498 | } | 2521 | } |
2499 | 2522 | ||
2500 | if (idev) { | 2523 | if (idev) { |
2501 | if (idev->if_flags & IF_READY) { | 2524 | if (idev->if_flags & IF_READY) |
2502 | /* device is already configured. */ | 2525 | /* device is already configured. */ |
2503 | break; | 2526 | break; |
2504 | } | ||
2505 | idev->if_flags |= IF_READY; | 2527 | idev->if_flags |= IF_READY; |
2506 | } | 2528 | } |
2507 | 2529 | ||
@@ -2513,7 +2535,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2513 | run_pending = 1; | 2535 | run_pending = 1; |
2514 | } | 2536 | } |
2515 | 2537 | ||
2516 | switch(dev->type) { | 2538 | switch (dev->type) { |
2517 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | 2539 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) |
2518 | case ARPHRD_SIT: | 2540 | case ARPHRD_SIT: |
2519 | addrconf_sit_config(dev); | 2541 | addrconf_sit_config(dev); |
@@ -2530,25 +2552,30 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2530 | addrconf_dev_config(dev); | 2552 | addrconf_dev_config(dev); |
2531 | break; | 2553 | break; |
2532 | } | 2554 | } |
2555 | |||
2533 | if (idev) { | 2556 | if (idev) { |
2534 | if (run_pending) | 2557 | if (run_pending) |
2535 | addrconf_dad_run(idev); | 2558 | addrconf_dad_run(idev); |
2536 | 2559 | ||
2537 | /* If the MTU changed during the interface down, when the | 2560 | /* |
2538 | interface up, the changed MTU must be reflected in the | 2561 | * If the MTU changed during the interface down, |
2539 | idev as well as routers. | 2562 | * when the interface up, the changed MTU must be |
2563 | * reflected in the idev as well as routers. | ||
2540 | */ | 2564 | */ |
2541 | if (idev->cnf.mtu6 != dev->mtu && dev->mtu >= IPV6_MIN_MTU) { | 2565 | if (idev->cnf.mtu6 != dev->mtu && |
2566 | dev->mtu >= IPV6_MIN_MTU) { | ||
2542 | rt6_mtu_change(dev, dev->mtu); | 2567 | rt6_mtu_change(dev, dev->mtu); |
2543 | idev->cnf.mtu6 = dev->mtu; | 2568 | idev->cnf.mtu6 = dev->mtu; |
2544 | } | 2569 | } |
2545 | idev->tstamp = jiffies; | 2570 | idev->tstamp = jiffies; |
2546 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | 2571 | inet6_ifinfo_notify(RTM_NEWLINK, idev); |
2547 | /* If the changed mtu during down is lower than IPV6_MIN_MTU | 2572 | |
2548 | stop IPv6 on this interface. | 2573 | /* |
2574 | * If the changed mtu during down is lower than | ||
2575 | * IPV6_MIN_MTU stop IPv6 on this interface. | ||
2549 | */ | 2576 | */ |
2550 | if (dev->mtu < IPV6_MIN_MTU) | 2577 | if (dev->mtu < IPV6_MIN_MTU) |
2551 | addrconf_ifdown(dev, event != NETDEV_DOWN); | 2578 | addrconf_ifdown(dev, 1); |
2552 | } | 2579 | } |
2553 | break; | 2580 | break; |
2554 | 2581 | ||
@@ -2565,7 +2592,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2565 | break; | 2592 | break; |
2566 | } | 2593 | } |
2567 | 2594 | ||
2568 | /* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */ | 2595 | /* |
2596 | * MTU falled under IPV6_MIN_MTU. | ||
2597 | * Stop IPv6 on this interface. | ||
2598 | */ | ||
2569 | 2599 | ||
2570 | case NETDEV_DOWN: | 2600 | case NETDEV_DOWN: |
2571 | case NETDEV_UNREGISTER: | 2601 | case NETDEV_UNREGISTER: |
@@ -2585,9 +2615,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2585 | return notifier_from_errno(err); | 2615 | return notifier_from_errno(err); |
2586 | } | 2616 | } |
2587 | break; | 2617 | break; |
2588 | case NETDEV_BONDING_OLDTYPE: | 2618 | |
2589 | case NETDEV_BONDING_NEWTYPE: | 2619 | case NETDEV_PRE_TYPE_CHANGE: |
2590 | addrconf_bonding_change(dev, event); | 2620 | case NETDEV_POST_TYPE_CHANGE: |
2621 | addrconf_type_change(dev, event); | ||
2591 | break; | 2622 | break; |
2592 | } | 2623 | } |
2593 | 2624 | ||
@@ -2599,28 +2630,28 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2599 | */ | 2630 | */ |
2600 | static struct notifier_block ipv6_dev_notf = { | 2631 | static struct notifier_block ipv6_dev_notf = { |
2601 | .notifier_call = addrconf_notify, | 2632 | .notifier_call = addrconf_notify, |
2602 | .priority = 0 | ||
2603 | }; | 2633 | }; |
2604 | 2634 | ||
2605 | static void addrconf_bonding_change(struct net_device *dev, unsigned long event) | 2635 | static void addrconf_type_change(struct net_device *dev, unsigned long event) |
2606 | { | 2636 | { |
2607 | struct inet6_dev *idev; | 2637 | struct inet6_dev *idev; |
2608 | ASSERT_RTNL(); | 2638 | ASSERT_RTNL(); |
2609 | 2639 | ||
2610 | idev = __in6_dev_get(dev); | 2640 | idev = __in6_dev_get(dev); |
2611 | 2641 | ||
2612 | if (event == NETDEV_BONDING_NEWTYPE) | 2642 | if (event == NETDEV_POST_TYPE_CHANGE) |
2613 | ipv6_mc_remap(idev); | 2643 | ipv6_mc_remap(idev); |
2614 | else if (event == NETDEV_BONDING_OLDTYPE) | 2644 | else if (event == NETDEV_PRE_TYPE_CHANGE) |
2615 | ipv6_mc_unmap(idev); | 2645 | ipv6_mc_unmap(idev); |
2616 | } | 2646 | } |
2617 | 2647 | ||
2618 | static int addrconf_ifdown(struct net_device *dev, int how) | 2648 | static int addrconf_ifdown(struct net_device *dev, int how) |
2619 | { | 2649 | { |
2620 | struct inet6_dev *idev; | ||
2621 | struct inet6_ifaddr *ifa, *keep_list, **bifa; | ||
2622 | struct net *net = dev_net(dev); | 2650 | struct net *net = dev_net(dev); |
2623 | int i; | 2651 | struct inet6_dev *idev; |
2652 | struct inet6_ifaddr *ifa; | ||
2653 | LIST_HEAD(keep_list); | ||
2654 | int state; | ||
2624 | 2655 | ||
2625 | ASSERT_RTNL(); | 2656 | ASSERT_RTNL(); |
2626 | 2657 | ||
@@ -2631,8 +2662,9 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2631 | if (idev == NULL) | 2662 | if (idev == NULL) |
2632 | return -ENODEV; | 2663 | return -ENODEV; |
2633 | 2664 | ||
2634 | /* Step 1: remove reference to ipv6 device from parent device. | 2665 | /* |
2635 | Do not dev_put! | 2666 | * Step 1: remove reference to ipv6 device from parent device. |
2667 | * Do not dev_put! | ||
2636 | */ | 2668 | */ |
2637 | if (how) { | 2669 | if (how) { |
2638 | idev->dead = 1; | 2670 | idev->dead = 1; |
@@ -2645,41 +2677,21 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2645 | 2677 | ||
2646 | } | 2678 | } |
2647 | 2679 | ||
2648 | /* Step 2: clear hash table */ | ||
2649 | for (i=0; i<IN6_ADDR_HSIZE; i++) { | ||
2650 | bifa = &inet6_addr_lst[i]; | ||
2651 | |||
2652 | write_lock_bh(&addrconf_hash_lock); | ||
2653 | while ((ifa = *bifa) != NULL) { | ||
2654 | if (ifa->idev == idev && | ||
2655 | (how || !(ifa->flags&IFA_F_PERMANENT) || | ||
2656 | ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
2657 | *bifa = ifa->lst_next; | ||
2658 | ifa->lst_next = NULL; | ||
2659 | __in6_ifa_put(ifa); | ||
2660 | continue; | ||
2661 | } | ||
2662 | bifa = &ifa->lst_next; | ||
2663 | } | ||
2664 | write_unlock_bh(&addrconf_hash_lock); | ||
2665 | } | ||
2666 | |||
2667 | write_lock_bh(&idev->lock); | 2680 | write_lock_bh(&idev->lock); |
2668 | 2681 | ||
2669 | /* Step 3: clear flags for stateless addrconf */ | 2682 | /* Step 2: clear flags for stateless addrconf */ |
2670 | if (!how) | 2683 | if (!how) |
2671 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); | 2684 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); |
2672 | 2685 | ||
2673 | /* Step 4: clear address list */ | ||
2674 | #ifdef CONFIG_IPV6_PRIVACY | 2686 | #ifdef CONFIG_IPV6_PRIVACY |
2675 | if (how && del_timer(&idev->regen_timer)) | 2687 | if (how && del_timer(&idev->regen_timer)) |
2676 | in6_dev_put(idev); | 2688 | in6_dev_put(idev); |
2677 | 2689 | ||
2678 | /* clear tempaddr list */ | 2690 | /* Step 3: clear tempaddr list */ |
2679 | while ((ifa = idev->tempaddr_list) != NULL) { | 2691 | while (!list_empty(&idev->tempaddr_list)) { |
2680 | idev->tempaddr_list = ifa->tmp_next; | 2692 | ifa = list_first_entry(&idev->tempaddr_list, |
2681 | ifa->tmp_next = NULL; | 2693 | struct inet6_ifaddr, tmp_list); |
2682 | ifa->dead = 1; | 2694 | list_del(&ifa->tmp_list); |
2683 | write_unlock_bh(&idev->lock); | 2695 | write_unlock_bh(&idev->lock); |
2684 | spin_lock_bh(&ifa->lock); | 2696 | spin_lock_bh(&ifa->lock); |
2685 | 2697 | ||
@@ -2692,23 +2704,18 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2692 | write_lock_bh(&idev->lock); | 2704 | write_lock_bh(&idev->lock); |
2693 | } | 2705 | } |
2694 | #endif | 2706 | #endif |
2695 | keep_list = NULL; | ||
2696 | bifa = &keep_list; | ||
2697 | while ((ifa = idev->addr_list) != NULL) { | ||
2698 | idev->addr_list = ifa->if_next; | ||
2699 | ifa->if_next = NULL; | ||
2700 | 2707 | ||
2708 | while (!list_empty(&idev->addr_list)) { | ||
2709 | ifa = list_first_entry(&idev->addr_list, | ||
2710 | struct inet6_ifaddr, if_list); | ||
2701 | addrconf_del_timer(ifa); | 2711 | addrconf_del_timer(ifa); |
2702 | 2712 | ||
2703 | /* If just doing link down, and address is permanent | 2713 | /* If just doing link down, and address is permanent |
2704 | and not link-local, then retain it. */ | 2714 | and not link-local, then retain it. */ |
2705 | if (how == 0 && | 2715 | if (!how && |
2706 | (ifa->flags&IFA_F_PERMANENT) && | 2716 | (ifa->flags&IFA_F_PERMANENT) && |
2707 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | 2717 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { |
2708 | 2718 | list_move_tail(&ifa->if_list, &keep_list); | |
2709 | /* Move to holding list */ | ||
2710 | *bifa = ifa; | ||
2711 | bifa = &ifa->if_next; | ||
2712 | 2719 | ||
2713 | /* If not doing DAD on this address, just keep it. */ | 2720 | /* If not doing DAD on this address, just keep it. */ |
2714 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | 2721 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || |
@@ -2722,25 +2729,45 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2722 | 2729 | ||
2723 | /* Flag it for later restoration when link comes up */ | 2730 | /* Flag it for later restoration when link comes up */ |
2724 | ifa->flags |= IFA_F_TENTATIVE; | 2731 | ifa->flags |= IFA_F_TENTATIVE; |
2732 | ifa->state = INET6_IFADDR_STATE_DAD; | ||
2733 | |||
2734 | write_unlock_bh(&idev->lock); | ||
2735 | |||
2725 | in6_ifa_hold(ifa); | 2736 | in6_ifa_hold(ifa); |
2726 | } else { | 2737 | } else { |
2727 | ifa->dead = 1; | 2738 | list_del(&ifa->if_list); |
2739 | |||
2740 | /* clear hash table */ | ||
2741 | spin_lock_bh(&addrconf_hash_lock); | ||
2742 | hlist_del_init_rcu(&ifa->addr_lst); | ||
2743 | spin_unlock_bh(&addrconf_hash_lock); | ||
2744 | |||
2745 | write_unlock_bh(&idev->lock); | ||
2746 | spin_lock_bh(&ifa->state_lock); | ||
2747 | state = ifa->state; | ||
2748 | ifa->state = INET6_IFADDR_STATE_DEAD; | ||
2749 | spin_unlock_bh(&ifa->state_lock); | ||
2750 | |||
2751 | if (state == INET6_IFADDR_STATE_DEAD) | ||
2752 | goto put_ifa; | ||
2728 | } | 2753 | } |
2729 | write_unlock_bh(&idev->lock); | ||
2730 | 2754 | ||
2731 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2755 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
2732 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | 2756 | if (ifa->state == INET6_IFADDR_STATE_DEAD) |
2757 | atomic_notifier_call_chain(&inet6addr_chain, | ||
2758 | NETDEV_DOWN, ifa); | ||
2759 | |||
2760 | put_ifa: | ||
2733 | in6_ifa_put(ifa); | 2761 | in6_ifa_put(ifa); |
2734 | 2762 | ||
2735 | write_lock_bh(&idev->lock); | 2763 | write_lock_bh(&idev->lock); |
2736 | } | 2764 | } |
2737 | 2765 | ||
2738 | idev->addr_list = keep_list; | 2766 | list_splice(&keep_list, &idev->addr_list); |
2739 | 2767 | ||
2740 | write_unlock_bh(&idev->lock); | 2768 | write_unlock_bh(&idev->lock); |
2741 | 2769 | ||
2742 | /* Step 5: Discard multicast list */ | 2770 | /* Step 5: Discard multicast list */ |
2743 | |||
2744 | if (how) | 2771 | if (how) |
2745 | ipv6_mc_destroy_dev(idev); | 2772 | ipv6_mc_destroy_dev(idev); |
2746 | else | 2773 | else |
@@ -2748,8 +2775,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2748 | 2775 | ||
2749 | idev->tstamp = jiffies; | 2776 | idev->tstamp = jiffies; |
2750 | 2777 | ||
2751 | /* Shot the device (if unregistered) */ | 2778 | /* Last: Shot the device (if unregistered) */ |
2752 | |||
2753 | if (how) { | 2779 | if (how) { |
2754 | addrconf_sysctl_unregister(idev); | 2780 | addrconf_sysctl_unregister(idev); |
2755 | neigh_parms_release(&nd_tbl, idev->nd_parms); | 2781 | neigh_parms_release(&nd_tbl, idev->nd_parms); |
@@ -2827,10 +2853,10 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2827 | net_srandom(ifp->addr.s6_addr32[3]); | 2853 | net_srandom(ifp->addr.s6_addr32[3]); |
2828 | 2854 | ||
2829 | read_lock_bh(&idev->lock); | 2855 | read_lock_bh(&idev->lock); |
2830 | if (ifp->dead) | 2856 | spin_lock(&ifp->lock); |
2857 | if (ifp->state == INET6_IFADDR_STATE_DEAD) | ||
2831 | goto out; | 2858 | goto out; |
2832 | 2859 | ||
2833 | spin_lock(&ifp->lock); | ||
2834 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || | 2860 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || |
2835 | idev->cnf.accept_dad < 1 || | 2861 | idev->cnf.accept_dad < 1 || |
2836 | !(ifp->flags&IFA_F_TENTATIVE) || | 2862 | !(ifp->flags&IFA_F_TENTATIVE) || |
@@ -2860,12 +2886,12 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2860 | * Optimistic nodes can start receiving | 2886 | * Optimistic nodes can start receiving |
2861 | * Frames right away | 2887 | * Frames right away |
2862 | */ | 2888 | */ |
2863 | if(ifp->flags & IFA_F_OPTIMISTIC) | 2889 | if (ifp->flags & IFA_F_OPTIMISTIC) |
2864 | ip6_ins_rt(ifp->rt); | 2890 | ip6_ins_rt(ifp->rt); |
2865 | 2891 | ||
2866 | addrconf_dad_kick(ifp); | 2892 | addrconf_dad_kick(ifp); |
2867 | spin_unlock(&ifp->lock); | ||
2868 | out: | 2893 | out: |
2894 | spin_unlock(&ifp->lock); | ||
2869 | read_unlock_bh(&idev->lock); | 2895 | read_unlock_bh(&idev->lock); |
2870 | } | 2896 | } |
2871 | 2897 | ||
@@ -2875,6 +2901,9 @@ static void addrconf_dad_timer(unsigned long data) | |||
2875 | struct inet6_dev *idev = ifp->idev; | 2901 | struct inet6_dev *idev = ifp->idev; |
2876 | struct in6_addr mcaddr; | 2902 | struct in6_addr mcaddr; |
2877 | 2903 | ||
2904 | if (!ifp->probes && addrconf_dad_end(ifp)) | ||
2905 | goto out; | ||
2906 | |||
2878 | read_lock(&idev->lock); | 2907 | read_lock(&idev->lock); |
2879 | if (idev->dead || !(idev->if_flags & IF_READY)) { | 2908 | if (idev->dead || !(idev->if_flags & IF_READY)) { |
2880 | read_unlock(&idev->lock); | 2909 | read_unlock(&idev->lock); |
@@ -2882,6 +2911,12 @@ static void addrconf_dad_timer(unsigned long data) | |||
2882 | } | 2911 | } |
2883 | 2912 | ||
2884 | spin_lock(&ifp->lock); | 2913 | spin_lock(&ifp->lock); |
2914 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { | ||
2915 | spin_unlock(&ifp->lock); | ||
2916 | read_unlock(&idev->lock); | ||
2917 | goto out; | ||
2918 | } | ||
2919 | |||
2885 | if (ifp->probes == 0) { | 2920 | if (ifp->probes == 0) { |
2886 | /* | 2921 | /* |
2887 | * DAD was successful | 2922 | * DAD was successful |
@@ -2910,7 +2945,7 @@ out: | |||
2910 | 2945 | ||
2911 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | 2946 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) |
2912 | { | 2947 | { |
2913 | struct net_device * dev = ifp->idev->dev; | 2948 | struct net_device *dev = ifp->idev->dev; |
2914 | 2949 | ||
2915 | /* | 2950 | /* |
2916 | * Configure the address for reception. Now it is valid. | 2951 | * Configure the address for reception. Now it is valid. |
@@ -2941,18 +2976,17 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
2941 | } | 2976 | } |
2942 | } | 2977 | } |
2943 | 2978 | ||
2944 | static void addrconf_dad_run(struct inet6_dev *idev) { | 2979 | static void addrconf_dad_run(struct inet6_dev *idev) |
2980 | { | ||
2945 | struct inet6_ifaddr *ifp; | 2981 | struct inet6_ifaddr *ifp; |
2946 | 2982 | ||
2947 | read_lock_bh(&idev->lock); | 2983 | read_lock_bh(&idev->lock); |
2948 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { | 2984 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
2949 | spin_lock(&ifp->lock); | 2985 | spin_lock(&ifp->lock); |
2950 | if (!(ifp->flags & IFA_F_TENTATIVE)) { | 2986 | if (ifp->flags & IFA_F_TENTATIVE && |
2951 | spin_unlock(&ifp->lock); | 2987 | ifp->state == INET6_IFADDR_STATE_DAD) |
2952 | continue; | 2988 | addrconf_dad_kick(ifp); |
2953 | } | ||
2954 | spin_unlock(&ifp->lock); | 2989 | spin_unlock(&ifp->lock); |
2955 | addrconf_dad_kick(ifp); | ||
2956 | } | 2990 | } |
2957 | read_unlock_bh(&idev->lock); | 2991 | read_unlock_bh(&idev->lock); |
2958 | } | 2992 | } |
@@ -2970,36 +3004,35 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2970 | struct net *net = seq_file_net(seq); | 3004 | struct net *net = seq_file_net(seq); |
2971 | 3005 | ||
2972 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 3006 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { |
2973 | ifa = inet6_addr_lst[state->bucket]; | 3007 | struct hlist_node *n; |
2974 | 3008 | hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], | |
2975 | while (ifa && !net_eq(dev_net(ifa->idev->dev), net)) | 3009 | addr_lst) |
2976 | ifa = ifa->lst_next; | 3010 | if (net_eq(dev_net(ifa->idev->dev), net)) |
2977 | if (ifa) | 3011 | return ifa; |
2978 | break; | ||
2979 | } | 3012 | } |
2980 | return ifa; | 3013 | return NULL; |
2981 | } | 3014 | } |
2982 | 3015 | ||
2983 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) | 3016 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, |
3017 | struct inet6_ifaddr *ifa) | ||
2984 | { | 3018 | { |
2985 | struct if6_iter_state *state = seq->private; | 3019 | struct if6_iter_state *state = seq->private; |
2986 | struct net *net = seq_file_net(seq); | 3020 | struct net *net = seq_file_net(seq); |
3021 | struct hlist_node *n = &ifa->addr_lst; | ||
2987 | 3022 | ||
2988 | ifa = ifa->lst_next; | 3023 | hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) |
2989 | try_again: | 3024 | if (net_eq(dev_net(ifa->idev->dev), net)) |
2990 | if (ifa) { | 3025 | return ifa; |
2991 | if (!net_eq(dev_net(ifa->idev->dev), net)) { | ||
2992 | ifa = ifa->lst_next; | ||
2993 | goto try_again; | ||
2994 | } | ||
2995 | } | ||
2996 | 3026 | ||
2997 | if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) { | 3027 | while (++state->bucket < IN6_ADDR_HSIZE) { |
2998 | ifa = inet6_addr_lst[state->bucket]; | 3028 | hlist_for_each_entry_rcu_bh(ifa, n, |
2999 | goto try_again; | 3029 | &inet6_addr_lst[state->bucket], addr_lst) { |
3030 | if (net_eq(dev_net(ifa->idev->dev), net)) | ||
3031 | return ifa; | ||
3032 | } | ||
3000 | } | 3033 | } |
3001 | 3034 | ||
3002 | return ifa; | 3035 | return NULL; |
3003 | } | 3036 | } |
3004 | 3037 | ||
3005 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | 3038 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) |
@@ -3007,15 +3040,15 @@ static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | |||
3007 | struct inet6_ifaddr *ifa = if6_get_first(seq); | 3040 | struct inet6_ifaddr *ifa = if6_get_first(seq); |
3008 | 3041 | ||
3009 | if (ifa) | 3042 | if (ifa) |
3010 | while(pos && (ifa = if6_get_next(seq, ifa)) != NULL) | 3043 | while (pos && (ifa = if6_get_next(seq, ifa)) != NULL) |
3011 | --pos; | 3044 | --pos; |
3012 | return pos ? NULL : ifa; | 3045 | return pos ? NULL : ifa; |
3013 | } | 3046 | } |
3014 | 3047 | ||
3015 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) | 3048 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) |
3016 | __acquires(addrconf_hash_lock) | 3049 | __acquires(rcu_bh) |
3017 | { | 3050 | { |
3018 | read_lock_bh(&addrconf_hash_lock); | 3051 | rcu_read_lock_bh(); |
3019 | return if6_get_idx(seq, *pos); | 3052 | return if6_get_idx(seq, *pos); |
3020 | } | 3053 | } |
3021 | 3054 | ||
@@ -3029,9 +3062,9 @@ static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
3029 | } | 3062 | } |
3030 | 3063 | ||
3031 | static void if6_seq_stop(struct seq_file *seq, void *v) | 3064 | static void if6_seq_stop(struct seq_file *seq, void *v) |
3032 | __releases(addrconf_hash_lock) | 3065 | __releases(rcu_bh) |
3033 | { | 3066 | { |
3034 | read_unlock_bh(&addrconf_hash_lock); | 3067 | rcu_read_unlock_bh(); |
3035 | } | 3068 | } |
3036 | 3069 | ||
3037 | static int if6_seq_show(struct seq_file *seq, void *v) | 3070 | static int if6_seq_show(struct seq_file *seq, void *v) |
@@ -3101,10 +3134,12 @@ void if6_proc_exit(void) | |||
3101 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | 3134 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) |
3102 | { | 3135 | { |
3103 | int ret = 0; | 3136 | int ret = 0; |
3104 | struct inet6_ifaddr * ifp; | 3137 | struct inet6_ifaddr *ifp = NULL; |
3105 | u8 hash = ipv6_addr_hash(addr); | 3138 | struct hlist_node *n; |
3106 | read_lock_bh(&addrconf_hash_lock); | 3139 | unsigned int hash = ipv6_addr_hash(addr); |
3107 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { | 3140 | |
3141 | rcu_read_lock_bh(); | ||
3142 | hlist_for_each_entry_rcu_bh(ifp, n, &inet6_addr_lst[hash], addr_lst) { | ||
3108 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 3143 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
3109 | continue; | 3144 | continue; |
3110 | if (ipv6_addr_equal(&ifp->addr, addr) && | 3145 | if (ipv6_addr_equal(&ifp->addr, addr) && |
@@ -3113,7 +3148,7 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
3113 | break; | 3148 | break; |
3114 | } | 3149 | } |
3115 | } | 3150 | } |
3116 | read_unlock_bh(&addrconf_hash_lock); | 3151 | rcu_read_unlock_bh(); |
3117 | return ret; | 3152 | return ret; |
3118 | } | 3153 | } |
3119 | #endif | 3154 | #endif |
@@ -3124,43 +3159,35 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
3124 | 3159 | ||
3125 | static void addrconf_verify(unsigned long foo) | 3160 | static void addrconf_verify(unsigned long foo) |
3126 | { | 3161 | { |
3162 | unsigned long now, next, next_sec, next_sched; | ||
3127 | struct inet6_ifaddr *ifp; | 3163 | struct inet6_ifaddr *ifp; |
3128 | unsigned long now, next; | 3164 | struct hlist_node *node; |
3129 | int i; | 3165 | int i; |
3130 | 3166 | ||
3131 | spin_lock_bh(&addrconf_verify_lock); | 3167 | rcu_read_lock_bh(); |
3168 | spin_lock(&addrconf_verify_lock); | ||
3132 | now = jiffies; | 3169 | now = jiffies; |
3133 | next = now + ADDR_CHECK_FREQUENCY; | 3170 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); |
3134 | 3171 | ||
3135 | del_timer(&addr_chk_timer); | 3172 | del_timer(&addr_chk_timer); |
3136 | 3173 | ||
3137 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 3174 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { |
3138 | |||
3139 | restart: | 3175 | restart: |
3140 | read_lock(&addrconf_hash_lock); | 3176 | hlist_for_each_entry_rcu_bh(ifp, node, |
3141 | for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) { | 3177 | &inet6_addr_lst[i], addr_lst) { |
3142 | unsigned long age; | 3178 | unsigned long age; |
3143 | #ifdef CONFIG_IPV6_PRIVACY | ||
3144 | unsigned long regen_advance; | ||
3145 | #endif | ||
3146 | 3179 | ||
3147 | if (ifp->flags & IFA_F_PERMANENT) | 3180 | if (ifp->flags & IFA_F_PERMANENT) |
3148 | continue; | 3181 | continue; |
3149 | 3182 | ||
3150 | spin_lock(&ifp->lock); | 3183 | spin_lock(&ifp->lock); |
3151 | age = (now - ifp->tstamp) / HZ; | 3184 | /* We try to batch several events at once. */ |
3152 | 3185 | age = (now - ifp->tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; | |
3153 | #ifdef CONFIG_IPV6_PRIVACY | ||
3154 | regen_advance = ifp->idev->cnf.regen_max_retry * | ||
3155 | ifp->idev->cnf.dad_transmits * | ||
3156 | ifp->idev->nd_parms->retrans_time / HZ; | ||
3157 | #endif | ||
3158 | 3186 | ||
3159 | if (ifp->valid_lft != INFINITY_LIFE_TIME && | 3187 | if (ifp->valid_lft != INFINITY_LIFE_TIME && |
3160 | age >= ifp->valid_lft) { | 3188 | age >= ifp->valid_lft) { |
3161 | spin_unlock(&ifp->lock); | 3189 | spin_unlock(&ifp->lock); |
3162 | in6_ifa_hold(ifp); | 3190 | in6_ifa_hold(ifp); |
3163 | read_unlock(&addrconf_hash_lock); | ||
3164 | ipv6_del_addr(ifp); | 3191 | ipv6_del_addr(ifp); |
3165 | goto restart; | 3192 | goto restart; |
3166 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { | 3193 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { |
@@ -3182,7 +3209,6 @@ restart: | |||
3182 | 3209 | ||
3183 | if (deprecate) { | 3210 | if (deprecate) { |
3184 | in6_ifa_hold(ifp); | 3211 | in6_ifa_hold(ifp); |
3185 | read_unlock(&addrconf_hash_lock); | ||
3186 | 3212 | ||
3187 | ipv6_ifa_notify(0, ifp); | 3213 | ipv6_ifa_notify(0, ifp); |
3188 | in6_ifa_put(ifp); | 3214 | in6_ifa_put(ifp); |
@@ -3191,6 +3217,10 @@ restart: | |||
3191 | #ifdef CONFIG_IPV6_PRIVACY | 3217 | #ifdef CONFIG_IPV6_PRIVACY |
3192 | } else if ((ifp->flags&IFA_F_TEMPORARY) && | 3218 | } else if ((ifp->flags&IFA_F_TEMPORARY) && |
3193 | !(ifp->flags&IFA_F_TENTATIVE)) { | 3219 | !(ifp->flags&IFA_F_TENTATIVE)) { |
3220 | unsigned long regen_advance = ifp->idev->cnf.regen_max_retry * | ||
3221 | ifp->idev->cnf.dad_transmits * | ||
3222 | ifp->idev->nd_parms->retrans_time / HZ; | ||
3223 | |||
3194 | if (age >= ifp->prefered_lft - regen_advance) { | 3224 | if (age >= ifp->prefered_lft - regen_advance) { |
3195 | struct inet6_ifaddr *ifpub = ifp->ifpub; | 3225 | struct inet6_ifaddr *ifpub = ifp->ifpub; |
3196 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) | 3226 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) |
@@ -3200,7 +3230,7 @@ restart: | |||
3200 | in6_ifa_hold(ifp); | 3230 | in6_ifa_hold(ifp); |
3201 | in6_ifa_hold(ifpub); | 3231 | in6_ifa_hold(ifpub); |
3202 | spin_unlock(&ifp->lock); | 3232 | spin_unlock(&ifp->lock); |
3203 | read_unlock(&addrconf_hash_lock); | 3233 | |
3204 | spin_lock(&ifpub->lock); | 3234 | spin_lock(&ifpub->lock); |
3205 | ifpub->regen_count = 0; | 3235 | ifpub->regen_count = 0; |
3206 | spin_unlock(&ifpub->lock); | 3236 | spin_unlock(&ifpub->lock); |
@@ -3220,12 +3250,26 @@ restart: | |||
3220 | spin_unlock(&ifp->lock); | 3250 | spin_unlock(&ifp->lock); |
3221 | } | 3251 | } |
3222 | } | 3252 | } |
3223 | read_unlock(&addrconf_hash_lock); | ||
3224 | } | 3253 | } |
3225 | 3254 | ||
3226 | addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next; | 3255 | next_sec = round_jiffies_up(next); |
3256 | next_sched = next; | ||
3257 | |||
3258 | /* If rounded timeout is accurate enough, accept it. */ | ||
3259 | if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ)) | ||
3260 | next_sched = next_sec; | ||
3261 | |||
3262 | /* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */ | ||
3263 | if (time_before(next_sched, jiffies + ADDRCONF_TIMER_FUZZ_MAX)) | ||
3264 | next_sched = jiffies + ADDRCONF_TIMER_FUZZ_MAX; | ||
3265 | |||
3266 | ADBG((KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n", | ||
3267 | now, next, next_sec, next_sched)); | ||
3268 | |||
3269 | addr_chk_timer.expires = next_sched; | ||
3227 | add_timer(&addr_chk_timer); | 3270 | add_timer(&addr_chk_timer); |
3228 | spin_unlock_bh(&addrconf_verify_lock); | 3271 | spin_unlock(&addrconf_verify_lock); |
3272 | rcu_read_unlock_bh(); | ||
3229 | } | 3273 | } |
3230 | 3274 | ||
3231 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) | 3275 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) |
@@ -3515,8 +3559,7 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, | |||
3515 | return nlmsg_end(skb, nlh); | 3559 | return nlmsg_end(skb, nlh); |
3516 | } | 3560 | } |
3517 | 3561 | ||
3518 | enum addr_type_t | 3562 | enum addr_type_t { |
3519 | { | ||
3520 | UNICAST_ADDR, | 3563 | UNICAST_ADDR, |
3521 | MULTICAST_ADDR, | 3564 | MULTICAST_ADDR, |
3522 | ANYCAST_ADDR, | 3565 | ANYCAST_ADDR, |
@@ -3527,7 +3570,6 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3527 | struct netlink_callback *cb, enum addr_type_t type, | 3570 | struct netlink_callback *cb, enum addr_type_t type, |
3528 | int s_ip_idx, int *p_ip_idx) | 3571 | int s_ip_idx, int *p_ip_idx) |
3529 | { | 3572 | { |
3530 | struct inet6_ifaddr *ifa; | ||
3531 | struct ifmcaddr6 *ifmca; | 3573 | struct ifmcaddr6 *ifmca; |
3532 | struct ifacaddr6 *ifaca; | 3574 | struct ifacaddr6 *ifaca; |
3533 | int err = 1; | 3575 | int err = 1; |
@@ -3535,11 +3577,12 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3535 | 3577 | ||
3536 | read_lock_bh(&idev->lock); | 3578 | read_lock_bh(&idev->lock); |
3537 | switch (type) { | 3579 | switch (type) { |
3538 | case UNICAST_ADDR: | 3580 | case UNICAST_ADDR: { |
3581 | struct inet6_ifaddr *ifa; | ||
3582 | |||
3539 | /* unicast address incl. temp addr */ | 3583 | /* unicast address incl. temp addr */ |
3540 | for (ifa = idev->addr_list; ifa; | 3584 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
3541 | ifa = ifa->if_next, ip_idx++) { | 3585 | if (++ip_idx < s_ip_idx) |
3542 | if (ip_idx < s_ip_idx) | ||
3543 | continue; | 3586 | continue; |
3544 | err = inet6_fill_ifaddr(skb, ifa, | 3587 | err = inet6_fill_ifaddr(skb, ifa, |
3545 | NETLINK_CB(cb->skb).pid, | 3588 | NETLINK_CB(cb->skb).pid, |
@@ -3550,6 +3593,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3550 | break; | 3593 | break; |
3551 | } | 3594 | } |
3552 | break; | 3595 | break; |
3596 | } | ||
3553 | case MULTICAST_ADDR: | 3597 | case MULTICAST_ADDR: |
3554 | /* multicast address */ | 3598 | /* multicast address */ |
3555 | for (ifmca = idev->mc_list; ifmca; | 3599 | for (ifmca = idev->mc_list; ifmca; |
@@ -3614,7 +3658,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
3614 | if (h > s_h || idx > s_idx) | 3658 | if (h > s_h || idx > s_idx) |
3615 | s_ip_idx = 0; | 3659 | s_ip_idx = 0; |
3616 | ip_idx = 0; | 3660 | ip_idx = 0; |
3617 | if ((idev = __in6_dev_get(dev)) == NULL) | 3661 | idev = __in6_dev_get(dev); |
3662 | if (!idev) | ||
3618 | goto cont; | 3663 | goto cont; |
3619 | 3664 | ||
3620 | if (in6_dump_addrs(idev, skb, cb, type, | 3665 | if (in6_dump_addrs(idev, skb, cb, type, |
@@ -3681,12 +3726,14 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3681 | if (ifm->ifa_index) | 3726 | if (ifm->ifa_index) |
3682 | dev = __dev_get_by_index(net, ifm->ifa_index); | 3727 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3683 | 3728 | ||
3684 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { | 3729 | ifa = ipv6_get_ifaddr(net, addr, dev, 1); |
3730 | if (!ifa) { | ||
3685 | err = -EADDRNOTAVAIL; | 3731 | err = -EADDRNOTAVAIL; |
3686 | goto errout; | 3732 | goto errout; |
3687 | } | 3733 | } |
3688 | 3734 | ||
3689 | if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) { | 3735 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL); |
3736 | if (!skb) { | ||
3690 | err = -ENOBUFS; | 3737 | err = -ENOBUFS; |
3691 | goto errout_ifa; | 3738 | goto errout_ifa; |
3692 | } | 3739 | } |
@@ -3811,7 +3858,7 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | |||
3811 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | 3858 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, |
3812 | int bytes) | 3859 | int bytes) |
3813 | { | 3860 | { |
3814 | switch(attrtype) { | 3861 | switch (attrtype) { |
3815 | case IFLA_INET6_STATS: | 3862 | case IFLA_INET6_STATS: |
3816 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | 3863 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); |
3817 | break; | 3864 | break; |
@@ -4047,7 +4094,9 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4047 | addrconf_leave_anycast(ifp); | 4094 | addrconf_leave_anycast(ifp); |
4048 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4095 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
4049 | dst_hold(&ifp->rt->u.dst); | 4096 | dst_hold(&ifp->rt->u.dst); |
4050 | if (ip6_del_rt(ifp->rt)) | 4097 | |
4098 | if (ifp->state == INET6_IFADDR_STATE_DEAD && | ||
4099 | ip6_del_rt(ifp->rt)) | ||
4051 | dst_free(&ifp->rt->u.dst); | 4100 | dst_free(&ifp->rt->u.dst); |
4052 | break; | 4101 | break; |
4053 | } | 4102 | } |
@@ -4163,211 +4212,211 @@ static struct addrconf_sysctl_table | |||
4163 | .sysctl_header = NULL, | 4212 | .sysctl_header = NULL, |
4164 | .addrconf_vars = { | 4213 | .addrconf_vars = { |
4165 | { | 4214 | { |
4166 | .procname = "forwarding", | 4215 | .procname = "forwarding", |
4167 | .data = &ipv6_devconf.forwarding, | 4216 | .data = &ipv6_devconf.forwarding, |
4168 | .maxlen = sizeof(int), | 4217 | .maxlen = sizeof(int), |
4169 | .mode = 0644, | 4218 | .mode = 0644, |
4170 | .proc_handler = addrconf_sysctl_forward, | 4219 | .proc_handler = addrconf_sysctl_forward, |
4171 | }, | 4220 | }, |
4172 | { | 4221 | { |
4173 | .procname = "hop_limit", | 4222 | .procname = "hop_limit", |
4174 | .data = &ipv6_devconf.hop_limit, | 4223 | .data = &ipv6_devconf.hop_limit, |
4175 | .maxlen = sizeof(int), | 4224 | .maxlen = sizeof(int), |
4176 | .mode = 0644, | 4225 | .mode = 0644, |
4177 | .proc_handler = proc_dointvec, | 4226 | .proc_handler = proc_dointvec, |
4178 | }, | 4227 | }, |
4179 | { | 4228 | { |
4180 | .procname = "mtu", | 4229 | .procname = "mtu", |
4181 | .data = &ipv6_devconf.mtu6, | 4230 | .data = &ipv6_devconf.mtu6, |
4182 | .maxlen = sizeof(int), | 4231 | .maxlen = sizeof(int), |
4183 | .mode = 0644, | 4232 | .mode = 0644, |
4184 | .proc_handler = proc_dointvec, | 4233 | .proc_handler = proc_dointvec, |
4185 | }, | 4234 | }, |
4186 | { | 4235 | { |
4187 | .procname = "accept_ra", | 4236 | .procname = "accept_ra", |
4188 | .data = &ipv6_devconf.accept_ra, | 4237 | .data = &ipv6_devconf.accept_ra, |
4189 | .maxlen = sizeof(int), | 4238 | .maxlen = sizeof(int), |
4190 | .mode = 0644, | 4239 | .mode = 0644, |
4191 | .proc_handler = proc_dointvec, | 4240 | .proc_handler = proc_dointvec, |
4192 | }, | 4241 | }, |
4193 | { | 4242 | { |
4194 | .procname = "accept_redirects", | 4243 | .procname = "accept_redirects", |
4195 | .data = &ipv6_devconf.accept_redirects, | 4244 | .data = &ipv6_devconf.accept_redirects, |
4196 | .maxlen = sizeof(int), | 4245 | .maxlen = sizeof(int), |
4197 | .mode = 0644, | 4246 | .mode = 0644, |
4198 | .proc_handler = proc_dointvec, | 4247 | .proc_handler = proc_dointvec, |
4199 | }, | 4248 | }, |
4200 | { | 4249 | { |
4201 | .procname = "autoconf", | 4250 | .procname = "autoconf", |
4202 | .data = &ipv6_devconf.autoconf, | 4251 | .data = &ipv6_devconf.autoconf, |
4203 | .maxlen = sizeof(int), | 4252 | .maxlen = sizeof(int), |
4204 | .mode = 0644, | 4253 | .mode = 0644, |
4205 | .proc_handler = proc_dointvec, | 4254 | .proc_handler = proc_dointvec, |
4206 | }, | 4255 | }, |
4207 | { | 4256 | { |
4208 | .procname = "dad_transmits", | 4257 | .procname = "dad_transmits", |
4209 | .data = &ipv6_devconf.dad_transmits, | 4258 | .data = &ipv6_devconf.dad_transmits, |
4210 | .maxlen = sizeof(int), | 4259 | .maxlen = sizeof(int), |
4211 | .mode = 0644, | 4260 | .mode = 0644, |
4212 | .proc_handler = proc_dointvec, | 4261 | .proc_handler = proc_dointvec, |
4213 | }, | 4262 | }, |
4214 | { | 4263 | { |
4215 | .procname = "router_solicitations", | 4264 | .procname = "router_solicitations", |
4216 | .data = &ipv6_devconf.rtr_solicits, | 4265 | .data = &ipv6_devconf.rtr_solicits, |
4217 | .maxlen = sizeof(int), | 4266 | .maxlen = sizeof(int), |
4218 | .mode = 0644, | 4267 | .mode = 0644, |
4219 | .proc_handler = proc_dointvec, | 4268 | .proc_handler = proc_dointvec, |
4220 | }, | 4269 | }, |
4221 | { | 4270 | { |
4222 | .procname = "router_solicitation_interval", | 4271 | .procname = "router_solicitation_interval", |
4223 | .data = &ipv6_devconf.rtr_solicit_interval, | 4272 | .data = &ipv6_devconf.rtr_solicit_interval, |
4224 | .maxlen = sizeof(int), | 4273 | .maxlen = sizeof(int), |
4225 | .mode = 0644, | 4274 | .mode = 0644, |
4226 | .proc_handler = proc_dointvec_jiffies, | 4275 | .proc_handler = proc_dointvec_jiffies, |
4227 | }, | 4276 | }, |
4228 | { | 4277 | { |
4229 | .procname = "router_solicitation_delay", | 4278 | .procname = "router_solicitation_delay", |
4230 | .data = &ipv6_devconf.rtr_solicit_delay, | 4279 | .data = &ipv6_devconf.rtr_solicit_delay, |
4231 | .maxlen = sizeof(int), | 4280 | .maxlen = sizeof(int), |
4232 | .mode = 0644, | 4281 | .mode = 0644, |
4233 | .proc_handler = proc_dointvec_jiffies, | 4282 | .proc_handler = proc_dointvec_jiffies, |
4234 | }, | 4283 | }, |
4235 | { | 4284 | { |
4236 | .procname = "force_mld_version", | 4285 | .procname = "force_mld_version", |
4237 | .data = &ipv6_devconf.force_mld_version, | 4286 | .data = &ipv6_devconf.force_mld_version, |
4238 | .maxlen = sizeof(int), | 4287 | .maxlen = sizeof(int), |
4239 | .mode = 0644, | 4288 | .mode = 0644, |
4240 | .proc_handler = proc_dointvec, | 4289 | .proc_handler = proc_dointvec, |
4241 | }, | 4290 | }, |
4242 | #ifdef CONFIG_IPV6_PRIVACY | 4291 | #ifdef CONFIG_IPV6_PRIVACY |
4243 | { | 4292 | { |
4244 | .procname = "use_tempaddr", | 4293 | .procname = "use_tempaddr", |
4245 | .data = &ipv6_devconf.use_tempaddr, | 4294 | .data = &ipv6_devconf.use_tempaddr, |
4246 | .maxlen = sizeof(int), | 4295 | .maxlen = sizeof(int), |
4247 | .mode = 0644, | 4296 | .mode = 0644, |
4248 | .proc_handler = proc_dointvec, | 4297 | .proc_handler = proc_dointvec, |
4249 | }, | 4298 | }, |
4250 | { | 4299 | { |
4251 | .procname = "temp_valid_lft", | 4300 | .procname = "temp_valid_lft", |
4252 | .data = &ipv6_devconf.temp_valid_lft, | 4301 | .data = &ipv6_devconf.temp_valid_lft, |
4253 | .maxlen = sizeof(int), | 4302 | .maxlen = sizeof(int), |
4254 | .mode = 0644, | 4303 | .mode = 0644, |
4255 | .proc_handler = proc_dointvec, | 4304 | .proc_handler = proc_dointvec, |
4256 | }, | 4305 | }, |
4257 | { | 4306 | { |
4258 | .procname = "temp_prefered_lft", | 4307 | .procname = "temp_prefered_lft", |
4259 | .data = &ipv6_devconf.temp_prefered_lft, | 4308 | .data = &ipv6_devconf.temp_prefered_lft, |
4260 | .maxlen = sizeof(int), | 4309 | .maxlen = sizeof(int), |
4261 | .mode = 0644, | 4310 | .mode = 0644, |
4262 | .proc_handler = proc_dointvec, | 4311 | .proc_handler = proc_dointvec, |
4263 | }, | 4312 | }, |
4264 | { | 4313 | { |
4265 | .procname = "regen_max_retry", | 4314 | .procname = "regen_max_retry", |
4266 | .data = &ipv6_devconf.regen_max_retry, | 4315 | .data = &ipv6_devconf.regen_max_retry, |
4267 | .maxlen = sizeof(int), | 4316 | .maxlen = sizeof(int), |
4268 | .mode = 0644, | 4317 | .mode = 0644, |
4269 | .proc_handler = proc_dointvec, | 4318 | .proc_handler = proc_dointvec, |
4270 | }, | 4319 | }, |
4271 | { | 4320 | { |
4272 | .procname = "max_desync_factor", | 4321 | .procname = "max_desync_factor", |
4273 | .data = &ipv6_devconf.max_desync_factor, | 4322 | .data = &ipv6_devconf.max_desync_factor, |
4274 | .maxlen = sizeof(int), | 4323 | .maxlen = sizeof(int), |
4275 | .mode = 0644, | 4324 | .mode = 0644, |
4276 | .proc_handler = proc_dointvec, | 4325 | .proc_handler = proc_dointvec, |
4277 | }, | 4326 | }, |
4278 | #endif | 4327 | #endif |
4279 | { | 4328 | { |
4280 | .procname = "max_addresses", | 4329 | .procname = "max_addresses", |
4281 | .data = &ipv6_devconf.max_addresses, | 4330 | .data = &ipv6_devconf.max_addresses, |
4282 | .maxlen = sizeof(int), | 4331 | .maxlen = sizeof(int), |
4283 | .mode = 0644, | 4332 | .mode = 0644, |
4284 | .proc_handler = proc_dointvec, | 4333 | .proc_handler = proc_dointvec, |
4285 | }, | 4334 | }, |
4286 | { | 4335 | { |
4287 | .procname = "accept_ra_defrtr", | 4336 | .procname = "accept_ra_defrtr", |
4288 | .data = &ipv6_devconf.accept_ra_defrtr, | 4337 | .data = &ipv6_devconf.accept_ra_defrtr, |
4289 | .maxlen = sizeof(int), | 4338 | .maxlen = sizeof(int), |
4290 | .mode = 0644, | 4339 | .mode = 0644, |
4291 | .proc_handler = proc_dointvec, | 4340 | .proc_handler = proc_dointvec, |
4292 | }, | 4341 | }, |
4293 | { | 4342 | { |
4294 | .procname = "accept_ra_pinfo", | 4343 | .procname = "accept_ra_pinfo", |
4295 | .data = &ipv6_devconf.accept_ra_pinfo, | 4344 | .data = &ipv6_devconf.accept_ra_pinfo, |
4296 | .maxlen = sizeof(int), | 4345 | .maxlen = sizeof(int), |
4297 | .mode = 0644, | 4346 | .mode = 0644, |
4298 | .proc_handler = proc_dointvec, | 4347 | .proc_handler = proc_dointvec, |
4299 | }, | 4348 | }, |
4300 | #ifdef CONFIG_IPV6_ROUTER_PREF | 4349 | #ifdef CONFIG_IPV6_ROUTER_PREF |
4301 | { | 4350 | { |
4302 | .procname = "accept_ra_rtr_pref", | 4351 | .procname = "accept_ra_rtr_pref", |
4303 | .data = &ipv6_devconf.accept_ra_rtr_pref, | 4352 | .data = &ipv6_devconf.accept_ra_rtr_pref, |
4304 | .maxlen = sizeof(int), | 4353 | .maxlen = sizeof(int), |
4305 | .mode = 0644, | 4354 | .mode = 0644, |
4306 | .proc_handler = proc_dointvec, | 4355 | .proc_handler = proc_dointvec, |
4307 | }, | 4356 | }, |
4308 | { | 4357 | { |
4309 | .procname = "router_probe_interval", | 4358 | .procname = "router_probe_interval", |
4310 | .data = &ipv6_devconf.rtr_probe_interval, | 4359 | .data = &ipv6_devconf.rtr_probe_interval, |
4311 | .maxlen = sizeof(int), | 4360 | .maxlen = sizeof(int), |
4312 | .mode = 0644, | 4361 | .mode = 0644, |
4313 | .proc_handler = proc_dointvec_jiffies, | 4362 | .proc_handler = proc_dointvec_jiffies, |
4314 | }, | 4363 | }, |
4315 | #ifdef CONFIG_IPV6_ROUTE_INFO | 4364 | #ifdef CONFIG_IPV6_ROUTE_INFO |
4316 | { | 4365 | { |
4317 | .procname = "accept_ra_rt_info_max_plen", | 4366 | .procname = "accept_ra_rt_info_max_plen", |
4318 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, | 4367 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, |
4319 | .maxlen = sizeof(int), | 4368 | .maxlen = sizeof(int), |
4320 | .mode = 0644, | 4369 | .mode = 0644, |
4321 | .proc_handler = proc_dointvec, | 4370 | .proc_handler = proc_dointvec, |
4322 | }, | 4371 | }, |
4323 | #endif | 4372 | #endif |
4324 | #endif | 4373 | #endif |
4325 | { | 4374 | { |
4326 | .procname = "proxy_ndp", | 4375 | .procname = "proxy_ndp", |
4327 | .data = &ipv6_devconf.proxy_ndp, | 4376 | .data = &ipv6_devconf.proxy_ndp, |
4328 | .maxlen = sizeof(int), | 4377 | .maxlen = sizeof(int), |
4329 | .mode = 0644, | 4378 | .mode = 0644, |
4330 | .proc_handler = proc_dointvec, | 4379 | .proc_handler = proc_dointvec, |
4331 | }, | 4380 | }, |
4332 | { | 4381 | { |
4333 | .procname = "accept_source_route", | 4382 | .procname = "accept_source_route", |
4334 | .data = &ipv6_devconf.accept_source_route, | 4383 | .data = &ipv6_devconf.accept_source_route, |
4335 | .maxlen = sizeof(int), | 4384 | .maxlen = sizeof(int), |
4336 | .mode = 0644, | 4385 | .mode = 0644, |
4337 | .proc_handler = proc_dointvec, | 4386 | .proc_handler = proc_dointvec, |
4338 | }, | 4387 | }, |
4339 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 4388 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
4340 | { | 4389 | { |
4341 | .procname = "optimistic_dad", | 4390 | .procname = "optimistic_dad", |
4342 | .data = &ipv6_devconf.optimistic_dad, | 4391 | .data = &ipv6_devconf.optimistic_dad, |
4343 | .maxlen = sizeof(int), | 4392 | .maxlen = sizeof(int), |
4344 | .mode = 0644, | 4393 | .mode = 0644, |
4345 | .proc_handler = proc_dointvec, | 4394 | .proc_handler = proc_dointvec, |
4346 | 4395 | ||
4347 | }, | 4396 | }, |
4348 | #endif | 4397 | #endif |
4349 | #ifdef CONFIG_IPV6_MROUTE | 4398 | #ifdef CONFIG_IPV6_MROUTE |
4350 | { | 4399 | { |
4351 | .procname = "mc_forwarding", | 4400 | .procname = "mc_forwarding", |
4352 | .data = &ipv6_devconf.mc_forwarding, | 4401 | .data = &ipv6_devconf.mc_forwarding, |
4353 | .maxlen = sizeof(int), | 4402 | .maxlen = sizeof(int), |
4354 | .mode = 0444, | 4403 | .mode = 0444, |
4355 | .proc_handler = proc_dointvec, | 4404 | .proc_handler = proc_dointvec, |
4356 | }, | 4405 | }, |
4357 | #endif | 4406 | #endif |
4358 | { | 4407 | { |
4359 | .procname = "disable_ipv6", | 4408 | .procname = "disable_ipv6", |
4360 | .data = &ipv6_devconf.disable_ipv6, | 4409 | .data = &ipv6_devconf.disable_ipv6, |
4361 | .maxlen = sizeof(int), | 4410 | .maxlen = sizeof(int), |
4362 | .mode = 0644, | 4411 | .mode = 0644, |
4363 | .proc_handler = addrconf_sysctl_disable, | 4412 | .proc_handler = addrconf_sysctl_disable, |
4364 | }, | 4413 | }, |
4365 | { | 4414 | { |
4366 | .procname = "accept_dad", | 4415 | .procname = "accept_dad", |
4367 | .data = &ipv6_devconf.accept_dad, | 4416 | .data = &ipv6_devconf.accept_dad, |
4368 | .maxlen = sizeof(int), | 4417 | .maxlen = sizeof(int), |
4369 | .mode = 0644, | 4418 | .mode = 0644, |
4370 | .proc_handler = proc_dointvec, | 4419 | .proc_handler = proc_dointvec, |
4371 | }, | 4420 | }, |
4372 | { | 4421 | { |
4373 | .procname = "force_tllao", | 4422 | .procname = "force_tllao", |
@@ -4403,8 +4452,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, | |||
4403 | if (t == NULL) | 4452 | if (t == NULL) |
4404 | goto out; | 4453 | goto out; |
4405 | 4454 | ||
4406 | for (i=0; t->addrconf_vars[i].data; i++) { | 4455 | for (i = 0; t->addrconf_vars[i].data; i++) { |
4407 | t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf; | 4456 | t->addrconf_vars[i].data += (char *)p - (char *)&ipv6_devconf; |
4408 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ | 4457 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ |
4409 | t->addrconf_vars[i].extra2 = net; | 4458 | t->addrconf_vars[i].extra2 = net; |
4410 | } | 4459 | } |
@@ -4541,14 +4590,12 @@ int register_inet6addr_notifier(struct notifier_block *nb) | |||
4541 | { | 4590 | { |
4542 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | 4591 | return atomic_notifier_chain_register(&inet6addr_chain, nb); |
4543 | } | 4592 | } |
4544 | |||
4545 | EXPORT_SYMBOL(register_inet6addr_notifier); | 4593 | EXPORT_SYMBOL(register_inet6addr_notifier); |
4546 | 4594 | ||
4547 | int unregister_inet6addr_notifier(struct notifier_block *nb) | 4595 | int unregister_inet6addr_notifier(struct notifier_block *nb) |
4548 | { | 4596 | { |
4549 | return atomic_notifier_chain_unregister(&inet6addr_chain,nb); | 4597 | return atomic_notifier_chain_unregister(&inet6addr_chain, nb); |
4550 | } | 4598 | } |
4551 | |||
4552 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4599 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4553 | 4600 | ||
4554 | /* | 4601 | /* |
@@ -4557,11 +4604,12 @@ EXPORT_SYMBOL(unregister_inet6addr_notifier); | |||
4557 | 4604 | ||
4558 | int __init addrconf_init(void) | 4605 | int __init addrconf_init(void) |
4559 | { | 4606 | { |
4560 | int err; | 4607 | int i, err; |
4561 | 4608 | ||
4562 | if ((err = ipv6_addr_label_init()) < 0) { | 4609 | err = ipv6_addr_label_init(); |
4563 | printk(KERN_CRIT "IPv6 Addrconf: cannot initialize default policy table: %d.\n", | 4610 | if (err < 0) { |
4564 | err); | 4611 | printk(KERN_CRIT "IPv6 Addrconf:" |
4612 | " cannot initialize default policy table: %d.\n", err); | ||
4565 | return err; | 4613 | return err; |
4566 | } | 4614 | } |
4567 | 4615 | ||
@@ -4592,6 +4640,9 @@ int __init addrconf_init(void) | |||
4592 | if (err) | 4640 | if (err) |
4593 | goto errlo; | 4641 | goto errlo; |
4594 | 4642 | ||
4643 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | ||
4644 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); | ||
4645 | |||
4595 | register_netdevice_notifier(&ipv6_dev_notf); | 4646 | register_netdevice_notifier(&ipv6_dev_notf); |
4596 | 4647 | ||
4597 | addrconf_verify(0); | 4648 | addrconf_verify(0); |
@@ -4620,7 +4671,6 @@ errlo: | |||
4620 | 4671 | ||
4621 | void addrconf_cleanup(void) | 4672 | void addrconf_cleanup(void) |
4622 | { | 4673 | { |
4623 | struct inet6_ifaddr *ifa; | ||
4624 | struct net_device *dev; | 4674 | struct net_device *dev; |
4625 | int i; | 4675 | int i; |
4626 | 4676 | ||
@@ -4640,20 +4690,10 @@ void addrconf_cleanup(void) | |||
4640 | /* | 4690 | /* |
4641 | * Check hash table. | 4691 | * Check hash table. |
4642 | */ | 4692 | */ |
4643 | write_lock_bh(&addrconf_hash_lock); | 4693 | spin_lock_bh(&addrconf_hash_lock); |
4644 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 4694 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
4645 | for (ifa=inet6_addr_lst[i]; ifa; ) { | 4695 | WARN_ON(!hlist_empty(&inet6_addr_lst[i])); |
4646 | struct inet6_ifaddr *bifa; | 4696 | spin_unlock_bh(&addrconf_hash_lock); |
4647 | |||
4648 | bifa = ifa; | ||
4649 | ifa = ifa->lst_next; | ||
4650 | printk(KERN_DEBUG "bug: IPv6 address leakage detected: ifa=%p\n", bifa); | ||
4651 | /* Do not free it; something is wrong. | ||
4652 | Now we can investigate it with debugger. | ||
4653 | */ | ||
4654 | } | ||
4655 | } | ||
4656 | write_unlock_bh(&addrconf_hash_lock); | ||
4657 | 4697 | ||
4658 | del_timer(&addr_chk_timer); | 4698 | del_timer(&addr_chk_timer); |
4659 | rtnl_unlock(); | 4699 | rtnl_unlock(); |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index ae404c9a746c..8c4348cb1950 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -422,10 +422,6 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
422 | ifal->ifal_prefixlen > 128) | 422 | ifal->ifal_prefixlen > 128) |
423 | return -EINVAL; | 423 | return -EINVAL; |
424 | 424 | ||
425 | if (ifal->ifal_index && | ||
426 | !__dev_get_by_index(net, ifal->ifal_index)) | ||
427 | return -EINVAL; | ||
428 | |||
429 | if (!tb[IFAL_ADDRESS]) | 425 | if (!tb[IFAL_ADDRESS]) |
430 | return -EINVAL; | 426 | return -EINVAL; |
431 | 427 | ||
@@ -441,6 +437,10 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
441 | 437 | ||
442 | switch(nlh->nlmsg_type) { | 438 | switch(nlh->nlmsg_type) { |
443 | case RTM_NEWADDRLABEL: | 439 | case RTM_NEWADDRLABEL: |
440 | if (ifal->ifal_index && | ||
441 | !__dev_get_by_index(net, ifal->ifal_index)) | ||
442 | return -EINVAL; | ||
443 | |||
444 | err = ip6addrlbl_add(net, pfx, ifal->ifal_prefixlen, | 444 | err = ip6addrlbl_add(net, pfx, ifal->ifal_prefixlen, |
445 | ifal->ifal_index, label, | 445 | ifal->ifal_index, label, |
446 | nlh->nlmsg_flags & NLM_F_REPLACE); | 446 | nlh->nlmsg_flags & NLM_F_REPLACE); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3f9e86b15e0d..e733942dafe1 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -417,6 +417,9 @@ void inet6_destroy_sock(struct sock *sk) | |||
417 | if ((skb = xchg(&np->pktoptions, NULL)) != NULL) | 417 | if ((skb = xchg(&np->pktoptions, NULL)) != NULL) |
418 | kfree_skb(skb); | 418 | kfree_skb(skb); |
419 | 419 | ||
420 | if ((skb = xchg(&np->rxpmtu, NULL)) != NULL) | ||
421 | kfree_skb(skb); | ||
422 | |||
420 | /* Free flowlabels */ | 423 | /* Free flowlabels */ |
421 | fl6_free_socklist(sk); | 424 | fl6_free_socklist(sk); |
422 | 425 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 61573885e451..712684687c9a 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -282,6 +282,45 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | |||
282 | kfree_skb(skb); | 282 | kfree_skb(skb); |
283 | } | 283 | } |
284 | 284 | ||
285 | void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu) | ||
286 | { | ||
287 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
288 | struct ipv6hdr *iph; | ||
289 | struct sk_buff *skb; | ||
290 | struct ip6_mtuinfo *mtu_info; | ||
291 | |||
292 | if (!np->rxopt.bits.rxpmtu) | ||
293 | return; | ||
294 | |||
295 | skb = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC); | ||
296 | if (!skb) | ||
297 | return; | ||
298 | |||
299 | skb_put(skb, sizeof(struct ipv6hdr)); | ||
300 | skb_reset_network_header(skb); | ||
301 | iph = ipv6_hdr(skb); | ||
302 | ipv6_addr_copy(&iph->daddr, &fl->fl6_dst); | ||
303 | |||
304 | mtu_info = IP6CBMTU(skb); | ||
305 | if (!mtu_info) { | ||
306 | kfree_skb(skb); | ||
307 | return; | ||
308 | } | ||
309 | |||
310 | mtu_info->ip6m_mtu = mtu; | ||
311 | mtu_info->ip6m_addr.sin6_family = AF_INET6; | ||
312 | mtu_info->ip6m_addr.sin6_port = 0; | ||
313 | mtu_info->ip6m_addr.sin6_flowinfo = 0; | ||
314 | mtu_info->ip6m_addr.sin6_scope_id = fl->oif; | ||
315 | ipv6_addr_copy(&mtu_info->ip6m_addr.sin6_addr, &ipv6_hdr(skb)->daddr); | ||
316 | |||
317 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); | ||
318 | skb_reset_transport_header(skb); | ||
319 | |||
320 | skb = xchg(&np->rxpmtu, skb); | ||
321 | kfree_skb(skb); | ||
322 | } | ||
323 | |||
285 | /* | 324 | /* |
286 | * Handle MSG_ERRQUEUE | 325 | * Handle MSG_ERRQUEUE |
287 | */ | 326 | */ |
@@ -385,6 +424,54 @@ out: | |||
385 | return err; | 424 | return err; |
386 | } | 425 | } |
387 | 426 | ||
427 | /* | ||
428 | * Handle IPV6_RECVPATHMTU | ||
429 | */ | ||
430 | int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) | ||
431 | { | ||
432 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
433 | struct sk_buff *skb; | ||
434 | struct sockaddr_in6 *sin; | ||
435 | struct ip6_mtuinfo mtu_info; | ||
436 | int err; | ||
437 | int copied; | ||
438 | |||
439 | err = -EAGAIN; | ||
440 | skb = xchg(&np->rxpmtu, NULL); | ||
441 | if (skb == NULL) | ||
442 | goto out; | ||
443 | |||
444 | copied = skb->len; | ||
445 | if (copied > len) { | ||
446 | msg->msg_flags |= MSG_TRUNC; | ||
447 | copied = len; | ||
448 | } | ||
449 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | ||
450 | if (err) | ||
451 | goto out_free_skb; | ||
452 | |||
453 | sock_recv_timestamp(msg, sk, skb); | ||
454 | |||
455 | memcpy(&mtu_info, IP6CBMTU(skb), sizeof(mtu_info)); | ||
456 | |||
457 | sin = (struct sockaddr_in6 *)msg->msg_name; | ||
458 | if (sin) { | ||
459 | sin->sin6_family = AF_INET6; | ||
460 | sin->sin6_flowinfo = 0; | ||
461 | sin->sin6_port = 0; | ||
462 | sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; | ||
463 | ipv6_addr_copy(&sin->sin6_addr, &mtu_info.ip6m_addr.sin6_addr); | ||
464 | } | ||
465 | |||
466 | put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); | ||
467 | |||
468 | err = copied; | ||
469 | |||
470 | out_free_skb: | ||
471 | kfree_skb(skb); | ||
472 | out: | ||
473 | return err; | ||
474 | } | ||
388 | 475 | ||
389 | 476 | ||
390 | int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | 477 | int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) |
@@ -501,7 +588,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
501 | int datagram_send_ctl(struct net *net, | 588 | int datagram_send_ctl(struct net *net, |
502 | struct msghdr *msg, struct flowi *fl, | 589 | struct msghdr *msg, struct flowi *fl, |
503 | struct ipv6_txoptions *opt, | 590 | struct ipv6_txoptions *opt, |
504 | int *hlimit, int *tclass) | 591 | int *hlimit, int *tclass, int *dontfrag) |
505 | { | 592 | { |
506 | struct in6_pktinfo *src_info; | 593 | struct in6_pktinfo *src_info; |
507 | struct cmsghdr *cmsg; | 594 | struct cmsghdr *cmsg; |
@@ -741,6 +828,25 @@ int datagram_send_ctl(struct net *net, | |||
741 | 828 | ||
742 | break; | 829 | break; |
743 | } | 830 | } |
831 | |||
832 | case IPV6_DONTFRAG: | ||
833 | { | ||
834 | int df; | ||
835 | |||
836 | err = -EINVAL; | ||
837 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { | ||
838 | goto exit_f; | ||
839 | } | ||
840 | |||
841 | df = *(int *)CMSG_DATA(cmsg); | ||
842 | if (df < 0 || df > 1) | ||
843 | goto exit_f; | ||
844 | |||
845 | err = 0; | ||
846 | *dontfrag = df; | ||
847 | |||
848 | break; | ||
849 | } | ||
744 | default: | 850 | default: |
745 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", | 851 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", |
746 | cmsg->cmsg_type); | 852 | cmsg->cmsg_type); |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 5e463c43fcc2..8e44f8f9c188 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -208,7 +208,6 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | |||
208 | { | 208 | { |
209 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; | 209 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; |
210 | 210 | ||
211 | frh->family = AF_INET6; | ||
212 | frh->dst_len = rule6->dst.plen; | 211 | frh->dst_len = rule6->dst.plen; |
213 | frh->src_len = rule6->src.plen; | 212 | frh->src_len = rule6->src.plen; |
214 | frh->tos = rule6->tclass; | 213 | frh->tos = rule6->tclass; |
@@ -238,7 +237,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) | |||
238 | + nla_total_size(16); /* src */ | 237 | + nla_total_size(16); /* src */ |
239 | } | 238 | } |
240 | 239 | ||
241 | static struct fib_rules_ops fib6_rules_ops_template = { | 240 | static const struct fib_rules_ops __net_initdata fib6_rules_ops_template = { |
242 | .family = AF_INET6, | 241 | .family = AF_INET6, |
243 | .rule_size = sizeof(struct fib6_rule), | 242 | .rule_size = sizeof(struct fib6_rule), |
244 | .addr_size = sizeof(struct in6_addr), | 243 | .addr_size = sizeof(struct in6_addr), |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 3330a4bd6157..ce7992982557 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -481,8 +481,9 @@ route_done: | |||
481 | len + sizeof(struct icmp6hdr), | 481 | len + sizeof(struct icmp6hdr), |
482 | sizeof(struct icmp6hdr), hlimit, | 482 | sizeof(struct icmp6hdr), hlimit, |
483 | np->tclass, NULL, &fl, (struct rt6_info*)dst, | 483 | np->tclass, NULL, &fl, (struct rt6_info*)dst, |
484 | MSG_DONTWAIT); | 484 | MSG_DONTWAIT, np->dontfrag); |
485 | if (err) { | 485 | if (err) { |
486 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | ||
486 | ip6_flush_pending_frames(sk); | 487 | ip6_flush_pending_frames(sk); |
487 | goto out_put; | 488 | goto out_put; |
488 | } | 489 | } |
@@ -560,9 +561,11 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
560 | 561 | ||
561 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), | 562 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), |
562 | sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, | 563 | sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, |
563 | (struct rt6_info*)dst, MSG_DONTWAIT); | 564 | (struct rt6_info*)dst, MSG_DONTWAIT, |
565 | np->dontfrag); | ||
564 | 566 | ||
565 | if (err) { | 567 | if (err) { |
568 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | ||
566 | ip6_flush_pending_frames(sk); | 569 | ip6_flush_pending_frames(sk); |
567 | goto out_put; | 570 | goto out_put; |
568 | } | 571 | } |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 628db24bcf22..0c5e3c3b7fd5 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -178,7 +178,7 @@ struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) | |||
178 | return dst; | 178 | return dst; |
179 | } | 179 | } |
180 | 180 | ||
181 | int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | 181 | int inet6_csk_xmit(struct sk_buff *skb) |
182 | { | 182 | { |
183 | struct sock *sk = skb->sk; | 183 | struct sock *sk = skb->sk; |
184 | struct inet_sock *inet = inet_sk(sk); | 184 | struct inet_sock *inet = inet_sk(sk); |
@@ -234,7 +234,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | |||
234 | /* Restore final destination back after routing done */ | 234 | /* Restore final destination back after routing done */ |
235 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 235 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); |
236 | 236 | ||
237 | return ip6_xmit(sk, skb, &fl, np->opt, 0); | 237 | return ip6_xmit(sk, skb, &fl, np->opt); |
238 | } | 238 | } |
239 | 239 | ||
240 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); | 240 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 6b82e02158c6..92a122b7795d 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -128,12 +128,24 @@ static __inline__ u32 fib6_new_sernum(void) | |||
128 | /* | 128 | /* |
129 | * test bit | 129 | * test bit |
130 | */ | 130 | */ |
131 | #if defined(__LITTLE_ENDIAN) | ||
132 | # define BITOP_BE32_SWIZZLE (0x1F & ~7) | ||
133 | #else | ||
134 | # define BITOP_BE32_SWIZZLE 0 | ||
135 | #endif | ||
131 | 136 | ||
132 | static __inline__ __be32 addr_bit_set(void *token, int fn_bit) | 137 | static __inline__ __be32 addr_bit_set(void *token, int fn_bit) |
133 | { | 138 | { |
134 | __be32 *addr = token; | 139 | __be32 *addr = token; |
135 | 140 | /* | |
136 | return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; | 141 | * Here, |
142 | * 1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f) | ||
143 | * is optimized version of | ||
144 | * htonl(1 << ((~fn_bit)&0x1F)) | ||
145 | * See include/asm-generic/bitops/le.h. | ||
146 | */ | ||
147 | return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) & | ||
148 | addr[fn_bit >> 5]; | ||
137 | } | 149 | } |
138 | 150 | ||
139 | static __inline__ struct fib6_node * node_alloc(void) | 151 | static __inline__ struct fib6_node * node_alloc(void) |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 14e23216eb28..13654686aeab 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -360,7 +360,8 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | |||
360 | msg.msg_control = (void*)(fl->opt+1); | 360 | msg.msg_control = (void*)(fl->opt+1); |
361 | flowi.oif = 0; | 361 | flowi.oif = 0; |
362 | 362 | ||
363 | err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, &junk); | 363 | err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, |
364 | &junk, &junk); | ||
364 | if (err) | 365 | if (err) |
365 | goto done; | 366 | goto done; |
366 | err = -EINVAL; | 367 | err = -EINVAL; |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 6aa7ee1295c2..a83e9209cecc 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -143,7 +143,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
143 | /* Must drop socket now because of tproxy. */ | 143 | /* Must drop socket now because of tproxy. */ |
144 | skb_orphan(skb); | 144 | skb_orphan(skb); |
145 | 145 | ||
146 | return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL, | 146 | return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, dev, NULL, |
147 | ip6_rcv_finish); | 147 | ip6_rcv_finish); |
148 | err: | 148 | err: |
149 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); | 149 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); |
@@ -236,7 +236,7 @@ discard: | |||
236 | 236 | ||
237 | int ip6_input(struct sk_buff *skb) | 237 | int ip6_input(struct sk_buff *skb) |
238 | { | 238 | { |
239 | return NF_HOOK(PF_INET6, NF_INET_LOCAL_IN, skb, skb->dev, NULL, | 239 | return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, skb, skb->dev, NULL, |
240 | ip6_input_finish); | 240 | ip6_input_finish); |
241 | } | 241 | } |
242 | 242 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 75d5ef830097..cd963f64e27c 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -67,8 +67,8 @@ int __ip6_local_out(struct sk_buff *skb) | |||
67 | len = 0; | 67 | len = 0; |
68 | ipv6_hdr(skb)->payload_len = htons(len); | 68 | ipv6_hdr(skb)->payload_len = htons(len); |
69 | 69 | ||
70 | return nf_hook(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb_dst(skb)->dev, | 70 | return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
71 | dst_output); | 71 | skb_dst(skb)->dev, dst_output); |
72 | } | 72 | } |
73 | 73 | ||
74 | int ip6_local_out(struct sk_buff *skb) | 74 | int ip6_local_out(struct sk_buff *skb) |
@@ -83,22 +83,6 @@ int ip6_local_out(struct sk_buff *skb) | |||
83 | } | 83 | } |
84 | EXPORT_SYMBOL_GPL(ip6_local_out); | 84 | EXPORT_SYMBOL_GPL(ip6_local_out); |
85 | 85 | ||
86 | static int ip6_output_finish(struct sk_buff *skb) | ||
87 | { | ||
88 | struct dst_entry *dst = skb_dst(skb); | ||
89 | |||
90 | if (dst->hh) | ||
91 | return neigh_hh_output(dst->hh, skb); | ||
92 | else if (dst->neighbour) | ||
93 | return dst->neighbour->output(skb); | ||
94 | |||
95 | IP6_INC_STATS_BH(dev_net(dst->dev), | ||
96 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | ||
97 | kfree_skb(skb); | ||
98 | return -EINVAL; | ||
99 | |||
100 | } | ||
101 | |||
102 | /* dev_loopback_xmit for use with netfilter. */ | 86 | /* dev_loopback_xmit for use with netfilter. */ |
103 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | 87 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) |
104 | { | 88 | { |
@@ -112,8 +96,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | |||
112 | return 0; | 96 | return 0; |
113 | } | 97 | } |
114 | 98 | ||
115 | 99 | static int ip6_finish_output2(struct sk_buff *skb) | |
116 | static int ip6_output2(struct sk_buff *skb) | ||
117 | { | 100 | { |
118 | struct dst_entry *dst = skb_dst(skb); | 101 | struct dst_entry *dst = skb_dst(skb); |
119 | struct net_device *dev = dst->dev; | 102 | struct net_device *dev = dst->dev; |
@@ -125,7 +108,7 @@ static int ip6_output2(struct sk_buff *skb) | |||
125 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 108 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
126 | 109 | ||
127 | if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) && | 110 | if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) && |
128 | ((mroute6_socket(dev_net(dev)) && | 111 | ((mroute6_socket(dev_net(dev), skb) && |
129 | !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || | 112 | !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || |
130 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, | 113 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, |
131 | &ipv6_hdr(skb)->saddr))) { | 114 | &ipv6_hdr(skb)->saddr))) { |
@@ -135,8 +118,8 @@ static int ip6_output2(struct sk_buff *skb) | |||
135 | is not supported in any case. | 118 | is not supported in any case. |
136 | */ | 119 | */ |
137 | if (newskb) | 120 | if (newskb) |
138 | NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, newskb, | 121 | NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, |
139 | NULL, newskb->dev, | 122 | newskb, NULL, newskb->dev, |
140 | ip6_dev_loopback_xmit); | 123 | ip6_dev_loopback_xmit); |
141 | 124 | ||
142 | if (ipv6_hdr(skb)->hop_limit == 0) { | 125 | if (ipv6_hdr(skb)->hop_limit == 0) { |
@@ -151,8 +134,15 @@ static int ip6_output2(struct sk_buff *skb) | |||
151 | skb->len); | 134 | skb->len); |
152 | } | 135 | } |
153 | 136 | ||
154 | return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, | 137 | if (dst->hh) |
155 | ip6_output_finish); | 138 | return neigh_hh_output(dst->hh, skb); |
139 | else if (dst->neighbour) | ||
140 | return dst->neighbour->output(skb); | ||
141 | |||
142 | IP6_INC_STATS_BH(dev_net(dst->dev), | ||
143 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | ||
144 | kfree_skb(skb); | ||
145 | return -EINVAL; | ||
156 | } | 146 | } |
157 | 147 | ||
158 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | 148 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) |
@@ -163,29 +153,37 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | |||
163 | skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); | 153 | skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); |
164 | } | 154 | } |
165 | 155 | ||
156 | static int ip6_finish_output(struct sk_buff *skb) | ||
157 | { | ||
158 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | ||
159 | dst_allfrag(skb_dst(skb))) | ||
160 | return ip6_fragment(skb, ip6_finish_output2); | ||
161 | else | ||
162 | return ip6_finish_output2(skb); | ||
163 | } | ||
164 | |||
166 | int ip6_output(struct sk_buff *skb) | 165 | int ip6_output(struct sk_buff *skb) |
167 | { | 166 | { |
167 | struct net_device *dev = skb_dst(skb)->dev; | ||
168 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 168 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
169 | if (unlikely(idev->cnf.disable_ipv6)) { | 169 | if (unlikely(idev->cnf.disable_ipv6)) { |
170 | IP6_INC_STATS(dev_net(skb_dst(skb)->dev), idev, | 170 | IP6_INC_STATS(dev_net(dev), idev, |
171 | IPSTATS_MIB_OUTDISCARDS); | 171 | IPSTATS_MIB_OUTDISCARDS); |
172 | kfree_skb(skb); | 172 | kfree_skb(skb); |
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | 176 | return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, dev, |
177 | dst_allfrag(skb_dst(skb))) | 177 | ip6_finish_output, |
178 | return ip6_fragment(skb, ip6_output2); | 178 | !(IP6CB(skb)->flags & IP6SKB_REROUTED)); |
179 | else | ||
180 | return ip6_output2(skb); | ||
181 | } | 179 | } |
182 | 180 | ||
183 | /* | 181 | /* |
184 | * xmit an sk_buff (used by TCP) | 182 | * xmit an sk_buff (used by TCP, SCTP and DCCP) |
185 | */ | 183 | */ |
186 | 184 | ||
187 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | 185 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, |
188 | struct ipv6_txoptions *opt, int ipfragok) | 186 | struct ipv6_txoptions *opt) |
189 | { | 187 | { |
190 | struct net *net = sock_net(sk); | 188 | struct net *net = sock_net(sk); |
191 | struct ipv6_pinfo *np = inet6_sk(sk); | 189 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -218,8 +216,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
218 | } | 216 | } |
219 | kfree_skb(skb); | 217 | kfree_skb(skb); |
220 | skb = skb2; | 218 | skb = skb2; |
221 | if (sk) | 219 | skb_set_owner_w(skb, sk); |
222 | skb_set_owner_w(skb, sk); | ||
223 | } | 220 | } |
224 | if (opt->opt_flen) | 221 | if (opt->opt_flen) |
225 | ipv6_push_frag_opts(skb, opt, &proto); | 222 | ipv6_push_frag_opts(skb, opt, &proto); |
@@ -231,10 +228,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
231 | skb_reset_network_header(skb); | 228 | skb_reset_network_header(skb); |
232 | hdr = ipv6_hdr(skb); | 229 | hdr = ipv6_hdr(skb); |
233 | 230 | ||
234 | /* Allow local fragmentation. */ | ||
235 | if (ipfragok) | ||
236 | skb->local_df = 1; | ||
237 | |||
238 | /* | 231 | /* |
239 | * Fill in the IPv6 header | 232 | * Fill in the IPv6 header |
240 | */ | 233 | */ |
@@ -261,8 +254,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
261 | if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { | 254 | if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { |
262 | IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), | 255 | IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), |
263 | IPSTATS_MIB_OUT, skb->len); | 256 | IPSTATS_MIB_OUT, skb->len); |
264 | return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, | 257 | return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
265 | dst_output); | 258 | dst->dev, dst_output); |
266 | } | 259 | } |
267 | 260 | ||
268 | if (net_ratelimit()) | 261 | if (net_ratelimit()) |
@@ -538,7 +531,7 @@ int ip6_forward(struct sk_buff *skb) | |||
538 | hdr->hop_limit--; | 531 | hdr->hop_limit--; |
539 | 532 | ||
540 | IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); | 533 | IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); |
541 | return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dst->dev, | 534 | return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dst->dev, |
542 | ip6_forward_finish); | 535 | ip6_forward_finish); |
543 | 536 | ||
544 | error: | 537 | error: |
@@ -1109,7 +1102,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1109 | int offset, int len, int odd, struct sk_buff *skb), | 1102 | int offset, int len, int odd, struct sk_buff *skb), |
1110 | void *from, int length, int transhdrlen, | 1103 | void *from, int length, int transhdrlen, |
1111 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, | 1104 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, |
1112 | struct rt6_info *rt, unsigned int flags) | 1105 | struct rt6_info *rt, unsigned int flags, int dontfrag) |
1113 | { | 1106 | { |
1114 | struct inet_sock *inet = inet_sk(sk); | 1107 | struct inet_sock *inet = inet_sk(sk); |
1115 | struct ipv6_pinfo *np = inet6_sk(sk); | 1108 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -1223,15 +1216,23 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1223 | */ | 1216 | */ |
1224 | 1217 | ||
1225 | inet->cork.length += length; | 1218 | inet->cork.length += length; |
1226 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && | 1219 | if (length > mtu) { |
1227 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | 1220 | int proto = sk->sk_protocol; |
1221 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ | ||
1222 | ipv6_local_rxpmtu(sk, fl, mtu-exthdrlen); | ||
1223 | return -EMSGSIZE; | ||
1224 | } | ||
1228 | 1225 | ||
1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len, | 1226 | if (proto == IPPROTO_UDP && |
1230 | fragheaderlen, transhdrlen, mtu, | 1227 | (rt->u.dst.dev->features & NETIF_F_UFO)) { |
1231 | flags); | 1228 | |
1232 | if (err) | 1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, |
1233 | goto error; | 1230 | hh_len, fragheaderlen, |
1234 | return 0; | 1231 | transhdrlen, mtu, flags); |
1232 | if (err) | ||
1233 | goto error; | ||
1234 | return 0; | ||
1235 | } | ||
1235 | } | 1236 | } |
1236 | 1237 | ||
1237 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 1238 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 2599870747ec..8f39893d8081 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -723,14 +723,10 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
723 | skb->protocol = htons(protocol); | 723 | skb->protocol = htons(protocol); |
724 | skb->pkt_type = PACKET_HOST; | 724 | skb->pkt_type = PACKET_HOST; |
725 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); | 725 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); |
726 | skb->dev = t->dev; | ||
727 | skb_dst_drop(skb); | ||
728 | nf_reset(skb); | ||
729 | 726 | ||
730 | dscp_ecn_decapsulate(t, ipv6h, skb); | 727 | skb_tunnel_rx(skb, t->dev); |
731 | 728 | ||
732 | t->dev->stats.rx_packets++; | 729 | dscp_ecn_decapsulate(t, ipv6h, skb); |
733 | t->dev->stats.rx_bytes += skb->len; | ||
734 | netif_rx(skb); | 730 | netif_rx(skb); |
735 | rcu_read_unlock(); | 731 | rcu_read_unlock(); |
736 | return 0; | 732 | return 0; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 3e333268db89..bd9e7d3e9c8e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/if_arp.h> | 42 | #include <linux/if_arp.h> |
43 | #include <net/checksum.h> | 43 | #include <net/checksum.h> |
44 | #include <net/netlink.h> | 44 | #include <net/netlink.h> |
45 | #include <net/fib_rules.h> | ||
45 | 46 | ||
46 | #include <net/ipv6.h> | 47 | #include <net/ipv6.h> |
47 | #include <net/ip6_route.h> | 48 | #include <net/ip6_route.h> |
@@ -51,6 +52,34 @@ | |||
51 | #include <linux/netfilter_ipv6.h> | 52 | #include <linux/netfilter_ipv6.h> |
52 | #include <net/ip6_checksum.h> | 53 | #include <net/ip6_checksum.h> |
53 | 54 | ||
55 | struct mr6_table { | ||
56 | struct list_head list; | ||
57 | #ifdef CONFIG_NET_NS | ||
58 | struct net *net; | ||
59 | #endif | ||
60 | u32 id; | ||
61 | struct sock *mroute6_sk; | ||
62 | struct timer_list ipmr_expire_timer; | ||
63 | struct list_head mfc6_unres_queue; | ||
64 | struct list_head mfc6_cache_array[MFC6_LINES]; | ||
65 | struct mif_device vif6_table[MAXMIFS]; | ||
66 | int maxvif; | ||
67 | atomic_t cache_resolve_queue_len; | ||
68 | int mroute_do_assert; | ||
69 | int mroute_do_pim; | ||
70 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
71 | int mroute_reg_vif_num; | ||
72 | #endif | ||
73 | }; | ||
74 | |||
75 | struct ip6mr_rule { | ||
76 | struct fib_rule common; | ||
77 | }; | ||
78 | |||
79 | struct ip6mr_result { | ||
80 | struct mr6_table *mrt; | ||
81 | }; | ||
82 | |||
54 | /* Big lock, protecting vif table, mrt cache and mroute socket state. | 83 | /* Big lock, protecting vif table, mrt cache and mroute socket state. |
55 | Note that the changes are semaphored via rtnl_lock. | 84 | Note that the changes are semaphored via rtnl_lock. |
56 | */ | 85 | */ |
@@ -61,9 +90,7 @@ static DEFINE_RWLOCK(mrt_lock); | |||
61 | * Multicast router control variables | 90 | * Multicast router control variables |
62 | */ | 91 | */ |
63 | 92 | ||
64 | #define MIF_EXISTS(_net, _idx) ((_net)->ipv6.vif6_table[_idx].dev != NULL) | 93 | #define MIF_EXISTS(_mrt, _idx) ((_mrt)->vif6_table[_idx].dev != NULL) |
65 | |||
66 | static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */ | ||
67 | 94 | ||
68 | /* Special spinlock for queue of unresolved entries */ | 95 | /* Special spinlock for queue of unresolved entries */ |
69 | static DEFINE_SPINLOCK(mfc_unres_lock); | 96 | static DEFINE_SPINLOCK(mfc_unres_lock); |
@@ -78,20 +105,233 @@ static DEFINE_SPINLOCK(mfc_unres_lock); | |||
78 | 105 | ||
79 | static struct kmem_cache *mrt_cachep __read_mostly; | 106 | static struct kmem_cache *mrt_cachep __read_mostly; |
80 | 107 | ||
81 | static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache); | 108 | static struct mr6_table *ip6mr_new_table(struct net *net, u32 id); |
82 | static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, | 109 | static void ip6mr_free_table(struct mr6_table *mrt); |
110 | |||
111 | static int ip6_mr_forward(struct net *net, struct mr6_table *mrt, | ||
112 | struct sk_buff *skb, struct mfc6_cache *cache); | ||
113 | static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt, | ||
83 | mifi_t mifi, int assert); | 114 | mifi_t mifi, int assert); |
84 | static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm); | 115 | static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, |
85 | static void mroute_clean_tables(struct net *net); | 116 | struct mfc6_cache *c, struct rtmsg *rtm); |
117 | static int ip6mr_rtm_dumproute(struct sk_buff *skb, | ||
118 | struct netlink_callback *cb); | ||
119 | static void mroute_clean_tables(struct mr6_table *mrt); | ||
120 | static void ipmr_expire_process(unsigned long arg); | ||
121 | |||
122 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES | ||
123 | #define ip6mr_for_each_table(mrt, met) \ | ||
124 | list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list) | ||
125 | |||
126 | static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | ||
127 | { | ||
128 | struct mr6_table *mrt; | ||
129 | |||
130 | ip6mr_for_each_table(mrt, net) { | ||
131 | if (mrt->id == id) | ||
132 | return mrt; | ||
133 | } | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | static int ip6mr_fib_lookup(struct net *net, struct flowi *flp, | ||
138 | struct mr6_table **mrt) | ||
139 | { | ||
140 | struct ip6mr_result res; | ||
141 | struct fib_lookup_arg arg = { .result = &res, }; | ||
142 | int err; | ||
143 | |||
144 | err = fib_rules_lookup(net->ipv6.mr6_rules_ops, flp, 0, &arg); | ||
145 | if (err < 0) | ||
146 | return err; | ||
147 | *mrt = res.mrt; | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp, | ||
152 | int flags, struct fib_lookup_arg *arg) | ||
153 | { | ||
154 | struct ip6mr_result *res = arg->result; | ||
155 | struct mr6_table *mrt; | ||
156 | |||
157 | switch (rule->action) { | ||
158 | case FR_ACT_TO_TBL: | ||
159 | break; | ||
160 | case FR_ACT_UNREACHABLE: | ||
161 | return -ENETUNREACH; | ||
162 | case FR_ACT_PROHIBIT: | ||
163 | return -EACCES; | ||
164 | case FR_ACT_BLACKHOLE: | ||
165 | default: | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | |||
169 | mrt = ip6mr_get_table(rule->fr_net, rule->table); | ||
170 | if (mrt == NULL) | ||
171 | return -EAGAIN; | ||
172 | res->mrt = mrt; | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int ip6mr_rule_match(struct fib_rule *rule, struct flowi *flp, int flags) | ||
177 | { | ||
178 | return 1; | ||
179 | } | ||
180 | |||
181 | static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = { | ||
182 | FRA_GENERIC_POLICY, | ||
183 | }; | ||
184 | |||
185 | static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | ||
186 | struct fib_rule_hdr *frh, struct nlattr **tb) | ||
187 | { | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static int ip6mr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | ||
192 | struct nlattr **tb) | ||
193 | { | ||
194 | return 1; | ||
195 | } | ||
196 | |||
197 | static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | ||
198 | struct fib_rule_hdr *frh) | ||
199 | { | ||
200 | frh->dst_len = 0; | ||
201 | frh->src_len = 0; | ||
202 | frh->tos = 0; | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static const struct fib_rules_ops __net_initdata ip6mr_rules_ops_template = { | ||
207 | .family = RTNL_FAMILY_IP6MR, | ||
208 | .rule_size = sizeof(struct ip6mr_rule), | ||
209 | .addr_size = sizeof(struct in6_addr), | ||
210 | .action = ip6mr_rule_action, | ||
211 | .match = ip6mr_rule_match, | ||
212 | .configure = ip6mr_rule_configure, | ||
213 | .compare = ip6mr_rule_compare, | ||
214 | .default_pref = fib_default_rule_pref, | ||
215 | .fill = ip6mr_rule_fill, | ||
216 | .nlgroup = RTNLGRP_IPV6_RULE, | ||
217 | .policy = ip6mr_rule_policy, | ||
218 | .owner = THIS_MODULE, | ||
219 | }; | ||
220 | |||
221 | static int __net_init ip6mr_rules_init(struct net *net) | ||
222 | { | ||
223 | struct fib_rules_ops *ops; | ||
224 | struct mr6_table *mrt; | ||
225 | int err; | ||
226 | |||
227 | ops = fib_rules_register(&ip6mr_rules_ops_template, net); | ||
228 | if (IS_ERR(ops)) | ||
229 | return PTR_ERR(ops); | ||
230 | |||
231 | INIT_LIST_HEAD(&net->ipv6.mr6_tables); | ||
232 | |||
233 | mrt = ip6mr_new_table(net, RT6_TABLE_DFLT); | ||
234 | if (mrt == NULL) { | ||
235 | err = -ENOMEM; | ||
236 | goto err1; | ||
237 | } | ||
238 | |||
239 | err = fib_default_rule_add(ops, 0x7fff, RT6_TABLE_DFLT, 0); | ||
240 | if (err < 0) | ||
241 | goto err2; | ||
242 | |||
243 | net->ipv6.mr6_rules_ops = ops; | ||
244 | return 0; | ||
245 | |||
246 | err2: | ||
247 | kfree(mrt); | ||
248 | err1: | ||
249 | fib_rules_unregister(ops); | ||
250 | return err; | ||
251 | } | ||
252 | |||
253 | static void __net_exit ip6mr_rules_exit(struct net *net) | ||
254 | { | ||
255 | struct mr6_table *mrt, *next; | ||
256 | |||
257 | list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) | ||
258 | ip6mr_free_table(mrt); | ||
259 | fib_rules_unregister(net->ipv6.mr6_rules_ops); | ||
260 | } | ||
261 | #else | ||
262 | #define ip6mr_for_each_table(mrt, net) \ | ||
263 | for (mrt = net->ipv6.mrt6; mrt; mrt = NULL) | ||
264 | |||
265 | static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | ||
266 | { | ||
267 | return net->ipv6.mrt6; | ||
268 | } | ||
269 | |||
270 | static int ip6mr_fib_lookup(struct net *net, struct flowi *flp, | ||
271 | struct mr6_table **mrt) | ||
272 | { | ||
273 | *mrt = net->ipv6.mrt6; | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int __net_init ip6mr_rules_init(struct net *net) | ||
278 | { | ||
279 | net->ipv6.mrt6 = ip6mr_new_table(net, RT6_TABLE_DFLT); | ||
280 | return net->ipv6.mrt6 ? 0 : -ENOMEM; | ||
281 | } | ||
86 | 282 | ||
87 | static struct timer_list ipmr_expire_timer; | 283 | static void __net_exit ip6mr_rules_exit(struct net *net) |
284 | { | ||
285 | ip6mr_free_table(net->ipv6.mrt6); | ||
286 | } | ||
287 | #endif | ||
288 | |||
289 | static struct mr6_table *ip6mr_new_table(struct net *net, u32 id) | ||
290 | { | ||
291 | struct mr6_table *mrt; | ||
292 | unsigned int i; | ||
293 | |||
294 | mrt = ip6mr_get_table(net, id); | ||
295 | if (mrt != NULL) | ||
296 | return mrt; | ||
297 | |||
298 | mrt = kzalloc(sizeof(*mrt), GFP_KERNEL); | ||
299 | if (mrt == NULL) | ||
300 | return NULL; | ||
301 | mrt->id = id; | ||
302 | write_pnet(&mrt->net, net); | ||
303 | |||
304 | /* Forwarding cache */ | ||
305 | for (i = 0; i < MFC6_LINES; i++) | ||
306 | INIT_LIST_HEAD(&mrt->mfc6_cache_array[i]); | ||
307 | |||
308 | INIT_LIST_HEAD(&mrt->mfc6_unres_queue); | ||
88 | 309 | ||
310 | setup_timer(&mrt->ipmr_expire_timer, ipmr_expire_process, | ||
311 | (unsigned long)mrt); | ||
312 | |||
313 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
314 | mrt->mroute_reg_vif_num = -1; | ||
315 | #endif | ||
316 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES | ||
317 | list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables); | ||
318 | #endif | ||
319 | return mrt; | ||
320 | } | ||
321 | |||
322 | static void ip6mr_free_table(struct mr6_table *mrt) | ||
323 | { | ||
324 | del_timer(&mrt->ipmr_expire_timer); | ||
325 | mroute_clean_tables(mrt); | ||
326 | kfree(mrt); | ||
327 | } | ||
89 | 328 | ||
90 | #ifdef CONFIG_PROC_FS | 329 | #ifdef CONFIG_PROC_FS |
91 | 330 | ||
92 | struct ipmr_mfc_iter { | 331 | struct ipmr_mfc_iter { |
93 | struct seq_net_private p; | 332 | struct seq_net_private p; |
94 | struct mfc6_cache **cache; | 333 | struct mr6_table *mrt; |
334 | struct list_head *cache; | ||
95 | int ct; | 335 | int ct; |
96 | }; | 336 | }; |
97 | 337 | ||
@@ -99,22 +339,22 @@ struct ipmr_mfc_iter { | |||
99 | static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net, | 339 | static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net, |
100 | struct ipmr_mfc_iter *it, loff_t pos) | 340 | struct ipmr_mfc_iter *it, loff_t pos) |
101 | { | 341 | { |
342 | struct mr6_table *mrt = it->mrt; | ||
102 | struct mfc6_cache *mfc; | 343 | struct mfc6_cache *mfc; |
103 | 344 | ||
104 | it->cache = net->ipv6.mfc6_cache_array; | ||
105 | read_lock(&mrt_lock); | 345 | read_lock(&mrt_lock); |
106 | for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) | 346 | for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) { |
107 | for (mfc = net->ipv6.mfc6_cache_array[it->ct]; | 347 | it->cache = &mrt->mfc6_cache_array[it->ct]; |
108 | mfc; mfc = mfc->next) | 348 | list_for_each_entry(mfc, it->cache, list) |
109 | if (pos-- == 0) | 349 | if (pos-- == 0) |
110 | return mfc; | 350 | return mfc; |
351 | } | ||
111 | read_unlock(&mrt_lock); | 352 | read_unlock(&mrt_lock); |
112 | 353 | ||
113 | it->cache = &mfc_unres_queue; | ||
114 | spin_lock_bh(&mfc_unres_lock); | 354 | spin_lock_bh(&mfc_unres_lock); |
115 | for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) | 355 | it->cache = &mrt->mfc6_unres_queue; |
116 | if (net_eq(mfc6_net(mfc), net) && | 356 | list_for_each_entry(mfc, it->cache, list) |
117 | pos-- == 0) | 357 | if (pos-- == 0) |
118 | return mfc; | 358 | return mfc; |
119 | spin_unlock_bh(&mfc_unres_lock); | 359 | spin_unlock_bh(&mfc_unres_lock); |
120 | 360 | ||
@@ -122,15 +362,13 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net, | |||
122 | return NULL; | 362 | return NULL; |
123 | } | 363 | } |
124 | 364 | ||
125 | |||
126 | |||
127 | |||
128 | /* | 365 | /* |
129 | * The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif | 366 | * The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif |
130 | */ | 367 | */ |
131 | 368 | ||
132 | struct ipmr_vif_iter { | 369 | struct ipmr_vif_iter { |
133 | struct seq_net_private p; | 370 | struct seq_net_private p; |
371 | struct mr6_table *mrt; | ||
134 | int ct; | 372 | int ct; |
135 | }; | 373 | }; |
136 | 374 | ||
@@ -138,11 +376,13 @@ static struct mif_device *ip6mr_vif_seq_idx(struct net *net, | |||
138 | struct ipmr_vif_iter *iter, | 376 | struct ipmr_vif_iter *iter, |
139 | loff_t pos) | 377 | loff_t pos) |
140 | { | 378 | { |
141 | for (iter->ct = 0; iter->ct < net->ipv6.maxvif; ++iter->ct) { | 379 | struct mr6_table *mrt = iter->mrt; |
142 | if (!MIF_EXISTS(net, iter->ct)) | 380 | |
381 | for (iter->ct = 0; iter->ct < mrt->maxvif; ++iter->ct) { | ||
382 | if (!MIF_EXISTS(mrt, iter->ct)) | ||
143 | continue; | 383 | continue; |
144 | if (pos-- == 0) | 384 | if (pos-- == 0) |
145 | return &net->ipv6.vif6_table[iter->ct]; | 385 | return &mrt->vif6_table[iter->ct]; |
146 | } | 386 | } |
147 | return NULL; | 387 | return NULL; |
148 | } | 388 | } |
@@ -150,7 +390,15 @@ static struct mif_device *ip6mr_vif_seq_idx(struct net *net, | |||
150 | static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) | 390 | static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) |
151 | __acquires(mrt_lock) | 391 | __acquires(mrt_lock) |
152 | { | 392 | { |
393 | struct ipmr_vif_iter *iter = seq->private; | ||
153 | struct net *net = seq_file_net(seq); | 394 | struct net *net = seq_file_net(seq); |
395 | struct mr6_table *mrt; | ||
396 | |||
397 | mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); | ||
398 | if (mrt == NULL) | ||
399 | return ERR_PTR(-ENOENT); | ||
400 | |||
401 | iter->mrt = mrt; | ||
154 | 402 | ||
155 | read_lock(&mrt_lock); | 403 | read_lock(&mrt_lock); |
156 | return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1) | 404 | return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1) |
@@ -161,15 +409,16 @@ static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
161 | { | 409 | { |
162 | struct ipmr_vif_iter *iter = seq->private; | 410 | struct ipmr_vif_iter *iter = seq->private; |
163 | struct net *net = seq_file_net(seq); | 411 | struct net *net = seq_file_net(seq); |
412 | struct mr6_table *mrt = iter->mrt; | ||
164 | 413 | ||
165 | ++*pos; | 414 | ++*pos; |
166 | if (v == SEQ_START_TOKEN) | 415 | if (v == SEQ_START_TOKEN) |
167 | return ip6mr_vif_seq_idx(net, iter, 0); | 416 | return ip6mr_vif_seq_idx(net, iter, 0); |
168 | 417 | ||
169 | while (++iter->ct < net->ipv6.maxvif) { | 418 | while (++iter->ct < mrt->maxvif) { |
170 | if (!MIF_EXISTS(net, iter->ct)) | 419 | if (!MIF_EXISTS(mrt, iter->ct)) |
171 | continue; | 420 | continue; |
172 | return &net->ipv6.vif6_table[iter->ct]; | 421 | return &mrt->vif6_table[iter->ct]; |
173 | } | 422 | } |
174 | return NULL; | 423 | return NULL; |
175 | } | 424 | } |
@@ -182,7 +431,8 @@ static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v) | |||
182 | 431 | ||
183 | static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) | 432 | static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) |
184 | { | 433 | { |
185 | struct net *net = seq_file_net(seq); | 434 | struct ipmr_vif_iter *iter = seq->private; |
435 | struct mr6_table *mrt = iter->mrt; | ||
186 | 436 | ||
187 | if (v == SEQ_START_TOKEN) { | 437 | if (v == SEQ_START_TOKEN) { |
188 | seq_puts(seq, | 438 | seq_puts(seq, |
@@ -193,7 +443,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) | |||
193 | 443 | ||
194 | seq_printf(seq, | 444 | seq_printf(seq, |
195 | "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", | 445 | "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", |
196 | vif - net->ipv6.vif6_table, | 446 | vif - mrt->vif6_table, |
197 | name, vif->bytes_in, vif->pkt_in, | 447 | name, vif->bytes_in, vif->pkt_in, |
198 | vif->bytes_out, vif->pkt_out, | 448 | vif->bytes_out, vif->pkt_out, |
199 | vif->flags); | 449 | vif->flags); |
@@ -224,8 +474,15 @@ static const struct file_operations ip6mr_vif_fops = { | |||
224 | 474 | ||
225 | static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) | 475 | static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) |
226 | { | 476 | { |
477 | struct ipmr_mfc_iter *it = seq->private; | ||
227 | struct net *net = seq_file_net(seq); | 478 | struct net *net = seq_file_net(seq); |
479 | struct mr6_table *mrt; | ||
228 | 480 | ||
481 | mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); | ||
482 | if (mrt == NULL) | ||
483 | return ERR_PTR(-ENOENT); | ||
484 | |||
485 | it->mrt = mrt; | ||
229 | return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) | 486 | return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) |
230 | : SEQ_START_TOKEN; | 487 | : SEQ_START_TOKEN; |
231 | } | 488 | } |
@@ -235,35 +492,36 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
235 | struct mfc6_cache *mfc = v; | 492 | struct mfc6_cache *mfc = v; |
236 | struct ipmr_mfc_iter *it = seq->private; | 493 | struct ipmr_mfc_iter *it = seq->private; |
237 | struct net *net = seq_file_net(seq); | 494 | struct net *net = seq_file_net(seq); |
495 | struct mr6_table *mrt = it->mrt; | ||
238 | 496 | ||
239 | ++*pos; | 497 | ++*pos; |
240 | 498 | ||
241 | if (v == SEQ_START_TOKEN) | 499 | if (v == SEQ_START_TOKEN) |
242 | return ipmr_mfc_seq_idx(net, seq->private, 0); | 500 | return ipmr_mfc_seq_idx(net, seq->private, 0); |
243 | 501 | ||
244 | if (mfc->next) | 502 | if (mfc->list.next != it->cache) |
245 | return mfc->next; | 503 | return list_entry(mfc->list.next, struct mfc6_cache, list); |
246 | 504 | ||
247 | if (it->cache == &mfc_unres_queue) | 505 | if (it->cache == &mrt->mfc6_unres_queue) |
248 | goto end_of_list; | 506 | goto end_of_list; |
249 | 507 | ||
250 | BUG_ON(it->cache != net->ipv6.mfc6_cache_array); | 508 | BUG_ON(it->cache != &mrt->mfc6_cache_array[it->ct]); |
251 | 509 | ||
252 | while (++it->ct < MFC6_LINES) { | 510 | while (++it->ct < MFC6_LINES) { |
253 | mfc = net->ipv6.mfc6_cache_array[it->ct]; | 511 | it->cache = &mrt->mfc6_cache_array[it->ct]; |
254 | if (mfc) | 512 | if (list_empty(it->cache)) |
255 | return mfc; | 513 | continue; |
514 | return list_first_entry(it->cache, struct mfc6_cache, list); | ||
256 | } | 515 | } |
257 | 516 | ||
258 | /* exhausted cache_array, show unresolved */ | 517 | /* exhausted cache_array, show unresolved */ |
259 | read_unlock(&mrt_lock); | 518 | read_unlock(&mrt_lock); |
260 | it->cache = &mfc_unres_queue; | 519 | it->cache = &mrt->mfc6_unres_queue; |
261 | it->ct = 0; | 520 | it->ct = 0; |
262 | 521 | ||
263 | spin_lock_bh(&mfc_unres_lock); | 522 | spin_lock_bh(&mfc_unres_lock); |
264 | mfc = mfc_unres_queue; | 523 | if (!list_empty(it->cache)) |
265 | if (mfc) | 524 | return list_first_entry(it->cache, struct mfc6_cache, list); |
266 | return mfc; | ||
267 | 525 | ||
268 | end_of_list: | 526 | end_of_list: |
269 | spin_unlock_bh(&mfc_unres_lock); | 527 | spin_unlock_bh(&mfc_unres_lock); |
@@ -275,18 +533,17 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
275 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) | 533 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) |
276 | { | 534 | { |
277 | struct ipmr_mfc_iter *it = seq->private; | 535 | struct ipmr_mfc_iter *it = seq->private; |
278 | struct net *net = seq_file_net(seq); | 536 | struct mr6_table *mrt = it->mrt; |
279 | 537 | ||
280 | if (it->cache == &mfc_unres_queue) | 538 | if (it->cache == &mrt->mfc6_unres_queue) |
281 | spin_unlock_bh(&mfc_unres_lock); | 539 | spin_unlock_bh(&mfc_unres_lock); |
282 | else if (it->cache == net->ipv6.mfc6_cache_array) | 540 | else if (it->cache == mrt->mfc6_cache_array) |
283 | read_unlock(&mrt_lock); | 541 | read_unlock(&mrt_lock); |
284 | } | 542 | } |
285 | 543 | ||
286 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | 544 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) |
287 | { | 545 | { |
288 | int n; | 546 | int n; |
289 | struct net *net = seq_file_net(seq); | ||
290 | 547 | ||
291 | if (v == SEQ_START_TOKEN) { | 548 | if (v == SEQ_START_TOKEN) { |
292 | seq_puts(seq, | 549 | seq_puts(seq, |
@@ -296,19 +553,20 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | |||
296 | } else { | 553 | } else { |
297 | const struct mfc6_cache *mfc = v; | 554 | const struct mfc6_cache *mfc = v; |
298 | const struct ipmr_mfc_iter *it = seq->private; | 555 | const struct ipmr_mfc_iter *it = seq->private; |
556 | struct mr6_table *mrt = it->mrt; | ||
299 | 557 | ||
300 | seq_printf(seq, "%pI6 %pI6 %-3hd", | 558 | seq_printf(seq, "%pI6 %pI6 %-3hd", |
301 | &mfc->mf6c_mcastgrp, &mfc->mf6c_origin, | 559 | &mfc->mf6c_mcastgrp, &mfc->mf6c_origin, |
302 | mfc->mf6c_parent); | 560 | mfc->mf6c_parent); |
303 | 561 | ||
304 | if (it->cache != &mfc_unres_queue) { | 562 | if (it->cache != &mrt->mfc6_unres_queue) { |
305 | seq_printf(seq, " %8lu %8lu %8lu", | 563 | seq_printf(seq, " %8lu %8lu %8lu", |
306 | mfc->mfc_un.res.pkt, | 564 | mfc->mfc_un.res.pkt, |
307 | mfc->mfc_un.res.bytes, | 565 | mfc->mfc_un.res.bytes, |
308 | mfc->mfc_un.res.wrong_if); | 566 | mfc->mfc_un.res.wrong_if); |
309 | for (n = mfc->mfc_un.res.minvif; | 567 | for (n = mfc->mfc_un.res.minvif; |
310 | n < mfc->mfc_un.res.maxvif; n++) { | 568 | n < mfc->mfc_un.res.maxvif; n++) { |
311 | if (MIF_EXISTS(net, n) && | 569 | if (MIF_EXISTS(mrt, n) && |
312 | mfc->mfc_un.res.ttls[n] < 255) | 570 | mfc->mfc_un.res.ttls[n] < 255) |
313 | seq_printf(seq, | 571 | seq_printf(seq, |
314 | " %2d:%-3d", | 572 | " %2d:%-3d", |
@@ -355,7 +613,12 @@ static int pim6_rcv(struct sk_buff *skb) | |||
355 | struct ipv6hdr *encap; | 613 | struct ipv6hdr *encap; |
356 | struct net_device *reg_dev = NULL; | 614 | struct net_device *reg_dev = NULL; |
357 | struct net *net = dev_net(skb->dev); | 615 | struct net *net = dev_net(skb->dev); |
358 | int reg_vif_num = net->ipv6.mroute_reg_vif_num; | 616 | struct mr6_table *mrt; |
617 | struct flowi fl = { | ||
618 | .iif = skb->dev->ifindex, | ||
619 | .mark = skb->mark, | ||
620 | }; | ||
621 | int reg_vif_num; | ||
359 | 622 | ||
360 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) | 623 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) |
361 | goto drop; | 624 | goto drop; |
@@ -378,9 +641,13 @@ static int pim6_rcv(struct sk_buff *skb) | |||
378 | ntohs(encap->payload_len) + sizeof(*pim) > skb->len) | 641 | ntohs(encap->payload_len) + sizeof(*pim) > skb->len) |
379 | goto drop; | 642 | goto drop; |
380 | 643 | ||
644 | if (ip6mr_fib_lookup(net, &fl, &mrt) < 0) | ||
645 | goto drop; | ||
646 | reg_vif_num = mrt->mroute_reg_vif_num; | ||
647 | |||
381 | read_lock(&mrt_lock); | 648 | read_lock(&mrt_lock); |
382 | if (reg_vif_num >= 0) | 649 | if (reg_vif_num >= 0) |
383 | reg_dev = net->ipv6.vif6_table[reg_vif_num].dev; | 650 | reg_dev = mrt->vif6_table[reg_vif_num].dev; |
384 | if (reg_dev) | 651 | if (reg_dev) |
385 | dev_hold(reg_dev); | 652 | dev_hold(reg_dev); |
386 | read_unlock(&mrt_lock); | 653 | read_unlock(&mrt_lock); |
@@ -391,14 +658,12 @@ static int pim6_rcv(struct sk_buff *skb) | |||
391 | skb->mac_header = skb->network_header; | 658 | skb->mac_header = skb->network_header; |
392 | skb_pull(skb, (u8 *)encap - skb->data); | 659 | skb_pull(skb, (u8 *)encap - skb->data); |
393 | skb_reset_network_header(skb); | 660 | skb_reset_network_header(skb); |
394 | skb->dev = reg_dev; | ||
395 | skb->protocol = htons(ETH_P_IPV6); | 661 | skb->protocol = htons(ETH_P_IPV6); |
396 | skb->ip_summed = 0; | 662 | skb->ip_summed = 0; |
397 | skb->pkt_type = PACKET_HOST; | 663 | skb->pkt_type = PACKET_HOST; |
398 | skb_dst_drop(skb); | 664 | |
399 | reg_dev->stats.rx_bytes += skb->len; | 665 | skb_tunnel_rx(skb, reg_dev); |
400 | reg_dev->stats.rx_packets++; | 666 | |
401 | nf_reset(skb); | ||
402 | netif_rx(skb); | 667 | netif_rx(skb); |
403 | dev_put(reg_dev); | 668 | dev_put(reg_dev); |
404 | return 0; | 669 | return 0; |
@@ -417,12 +682,22 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, | |||
417 | struct net_device *dev) | 682 | struct net_device *dev) |
418 | { | 683 | { |
419 | struct net *net = dev_net(dev); | 684 | struct net *net = dev_net(dev); |
685 | struct mr6_table *mrt; | ||
686 | struct flowi fl = { | ||
687 | .oif = dev->ifindex, | ||
688 | .iif = skb->skb_iif, | ||
689 | .mark = skb->mark, | ||
690 | }; | ||
691 | int err; | ||
692 | |||
693 | err = ip6mr_fib_lookup(net, &fl, &mrt); | ||
694 | if (err < 0) | ||
695 | return err; | ||
420 | 696 | ||
421 | read_lock(&mrt_lock); | 697 | read_lock(&mrt_lock); |
422 | dev->stats.tx_bytes += skb->len; | 698 | dev->stats.tx_bytes += skb->len; |
423 | dev->stats.tx_packets++; | 699 | dev->stats.tx_packets++; |
424 | ip6mr_cache_report(net, skb, net->ipv6.mroute_reg_vif_num, | 700 | ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT); |
425 | MRT6MSG_WHOLEPKT); | ||
426 | read_unlock(&mrt_lock); | 701 | read_unlock(&mrt_lock); |
427 | kfree_skb(skb); | 702 | kfree_skb(skb); |
428 | return NETDEV_TX_OK; | 703 | return NETDEV_TX_OK; |
@@ -442,11 +717,17 @@ static void reg_vif_setup(struct net_device *dev) | |||
442 | dev->features |= NETIF_F_NETNS_LOCAL; | 717 | dev->features |= NETIF_F_NETNS_LOCAL; |
443 | } | 718 | } |
444 | 719 | ||
445 | static struct net_device *ip6mr_reg_vif(struct net *net) | 720 | static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt) |
446 | { | 721 | { |
447 | struct net_device *dev; | 722 | struct net_device *dev; |
723 | char name[IFNAMSIZ]; | ||
724 | |||
725 | if (mrt->id == RT6_TABLE_DFLT) | ||
726 | sprintf(name, "pim6reg"); | ||
727 | else | ||
728 | sprintf(name, "pim6reg%u", mrt->id); | ||
448 | 729 | ||
449 | dev = alloc_netdev(0, "pim6reg", reg_vif_setup); | 730 | dev = alloc_netdev(0, name, reg_vif_setup); |
450 | if (dev == NULL) | 731 | if (dev == NULL) |
451 | return NULL; | 732 | return NULL; |
452 | 733 | ||
@@ -478,15 +759,16 @@ failure: | |||
478 | * Delete a VIF entry | 759 | * Delete a VIF entry |
479 | */ | 760 | */ |
480 | 761 | ||
481 | static int mif6_delete(struct net *net, int vifi, struct list_head *head) | 762 | static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head) |
482 | { | 763 | { |
483 | struct mif_device *v; | 764 | struct mif_device *v; |
484 | struct net_device *dev; | 765 | struct net_device *dev; |
485 | struct inet6_dev *in6_dev; | 766 | struct inet6_dev *in6_dev; |
486 | if (vifi < 0 || vifi >= net->ipv6.maxvif) | 767 | |
768 | if (vifi < 0 || vifi >= mrt->maxvif) | ||
487 | return -EADDRNOTAVAIL; | 769 | return -EADDRNOTAVAIL; |
488 | 770 | ||
489 | v = &net->ipv6.vif6_table[vifi]; | 771 | v = &mrt->vif6_table[vifi]; |
490 | 772 | ||
491 | write_lock_bh(&mrt_lock); | 773 | write_lock_bh(&mrt_lock); |
492 | dev = v->dev; | 774 | dev = v->dev; |
@@ -498,17 +780,17 @@ static int mif6_delete(struct net *net, int vifi, struct list_head *head) | |||
498 | } | 780 | } |
499 | 781 | ||
500 | #ifdef CONFIG_IPV6_PIMSM_V2 | 782 | #ifdef CONFIG_IPV6_PIMSM_V2 |
501 | if (vifi == net->ipv6.mroute_reg_vif_num) | 783 | if (vifi == mrt->mroute_reg_vif_num) |
502 | net->ipv6.mroute_reg_vif_num = -1; | 784 | mrt->mroute_reg_vif_num = -1; |
503 | #endif | 785 | #endif |
504 | 786 | ||
505 | if (vifi + 1 == net->ipv6.maxvif) { | 787 | if (vifi + 1 == mrt->maxvif) { |
506 | int tmp; | 788 | int tmp; |
507 | for (tmp = vifi - 1; tmp >= 0; tmp--) { | 789 | for (tmp = vifi - 1; tmp >= 0; tmp--) { |
508 | if (MIF_EXISTS(net, tmp)) | 790 | if (MIF_EXISTS(mrt, tmp)) |
509 | break; | 791 | break; |
510 | } | 792 | } |
511 | net->ipv6.maxvif = tmp + 1; | 793 | mrt->maxvif = tmp + 1; |
512 | } | 794 | } |
513 | 795 | ||
514 | write_unlock_bh(&mrt_lock); | 796 | write_unlock_bh(&mrt_lock); |
@@ -528,7 +810,6 @@ static int mif6_delete(struct net *net, int vifi, struct list_head *head) | |||
528 | 810 | ||
529 | static inline void ip6mr_cache_free(struct mfc6_cache *c) | 811 | static inline void ip6mr_cache_free(struct mfc6_cache *c) |
530 | { | 812 | { |
531 | release_net(mfc6_net(c)); | ||
532 | kmem_cache_free(mrt_cachep, c); | 813 | kmem_cache_free(mrt_cachep, c); |
533 | } | 814 | } |
534 | 815 | ||
@@ -536,12 +817,12 @@ static inline void ip6mr_cache_free(struct mfc6_cache *c) | |||
536 | and reporting error to netlink readers. | 817 | and reporting error to netlink readers. |
537 | */ | 818 | */ |
538 | 819 | ||
539 | static void ip6mr_destroy_unres(struct mfc6_cache *c) | 820 | static void ip6mr_destroy_unres(struct mr6_table *mrt, struct mfc6_cache *c) |
540 | { | 821 | { |
822 | struct net *net = read_pnet(&mrt->net); | ||
541 | struct sk_buff *skb; | 823 | struct sk_buff *skb; |
542 | struct net *net = mfc6_net(c); | ||
543 | 824 | ||
544 | atomic_dec(&net->ipv6.cache_resolve_queue_len); | 825 | atomic_dec(&mrt->cache_resolve_queue_len); |
545 | 826 | ||
546 | while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) { | 827 | while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) { |
547 | if (ipv6_hdr(skb)->version == 0) { | 828 | if (ipv6_hdr(skb)->version == 0) { |
@@ -559,60 +840,59 @@ static void ip6mr_destroy_unres(struct mfc6_cache *c) | |||
559 | } | 840 | } |
560 | 841 | ||
561 | 842 | ||
562 | /* Single timer process for all the unresolved queue. */ | 843 | /* Timer process for all the unresolved queue. */ |
563 | 844 | ||
564 | static void ipmr_do_expire_process(unsigned long dummy) | 845 | static void ipmr_do_expire_process(struct mr6_table *mrt) |
565 | { | 846 | { |
566 | unsigned long now = jiffies; | 847 | unsigned long now = jiffies; |
567 | unsigned long expires = 10 * HZ; | 848 | unsigned long expires = 10 * HZ; |
568 | struct mfc6_cache *c, **cp; | 849 | struct mfc6_cache *c, *next; |
569 | |||
570 | cp = &mfc_unres_queue; | ||
571 | 850 | ||
572 | while ((c = *cp) != NULL) { | 851 | list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) { |
573 | if (time_after(c->mfc_un.unres.expires, now)) { | 852 | if (time_after(c->mfc_un.unres.expires, now)) { |
574 | /* not yet... */ | 853 | /* not yet... */ |
575 | unsigned long interval = c->mfc_un.unres.expires - now; | 854 | unsigned long interval = c->mfc_un.unres.expires - now; |
576 | if (interval < expires) | 855 | if (interval < expires) |
577 | expires = interval; | 856 | expires = interval; |
578 | cp = &c->next; | ||
579 | continue; | 857 | continue; |
580 | } | 858 | } |
581 | 859 | ||
582 | *cp = c->next; | 860 | list_del(&c->list); |
583 | ip6mr_destroy_unres(c); | 861 | ip6mr_destroy_unres(mrt, c); |
584 | } | 862 | } |
585 | 863 | ||
586 | if (mfc_unres_queue != NULL) | 864 | if (!list_empty(&mrt->mfc6_unres_queue)) |
587 | mod_timer(&ipmr_expire_timer, jiffies + expires); | 865 | mod_timer(&mrt->ipmr_expire_timer, jiffies + expires); |
588 | } | 866 | } |
589 | 867 | ||
590 | static void ipmr_expire_process(unsigned long dummy) | 868 | static void ipmr_expire_process(unsigned long arg) |
591 | { | 869 | { |
870 | struct mr6_table *mrt = (struct mr6_table *)arg; | ||
871 | |||
592 | if (!spin_trylock(&mfc_unres_lock)) { | 872 | if (!spin_trylock(&mfc_unres_lock)) { |
593 | mod_timer(&ipmr_expire_timer, jiffies + 1); | 873 | mod_timer(&mrt->ipmr_expire_timer, jiffies + 1); |
594 | return; | 874 | return; |
595 | } | 875 | } |
596 | 876 | ||
597 | if (mfc_unres_queue != NULL) | 877 | if (!list_empty(&mrt->mfc6_unres_queue)) |
598 | ipmr_do_expire_process(dummy); | 878 | ipmr_do_expire_process(mrt); |
599 | 879 | ||
600 | spin_unlock(&mfc_unres_lock); | 880 | spin_unlock(&mfc_unres_lock); |
601 | } | 881 | } |
602 | 882 | ||
603 | /* Fill oifs list. It is called under write locked mrt_lock. */ | 883 | /* Fill oifs list. It is called under write locked mrt_lock. */ |
604 | 884 | ||
605 | static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttls) | 885 | static void ip6mr_update_thresholds(struct mr6_table *mrt, struct mfc6_cache *cache, |
886 | unsigned char *ttls) | ||
606 | { | 887 | { |
607 | int vifi; | 888 | int vifi; |
608 | struct net *net = mfc6_net(cache); | ||
609 | 889 | ||
610 | cache->mfc_un.res.minvif = MAXMIFS; | 890 | cache->mfc_un.res.minvif = MAXMIFS; |
611 | cache->mfc_un.res.maxvif = 0; | 891 | cache->mfc_un.res.maxvif = 0; |
612 | memset(cache->mfc_un.res.ttls, 255, MAXMIFS); | 892 | memset(cache->mfc_un.res.ttls, 255, MAXMIFS); |
613 | 893 | ||
614 | for (vifi = 0; vifi < net->ipv6.maxvif; vifi++) { | 894 | for (vifi = 0; vifi < mrt->maxvif; vifi++) { |
615 | if (MIF_EXISTS(net, vifi) && | 895 | if (MIF_EXISTS(mrt, vifi) && |
616 | ttls[vifi] && ttls[vifi] < 255) { | 896 | ttls[vifi] && ttls[vifi] < 255) { |
617 | cache->mfc_un.res.ttls[vifi] = ttls[vifi]; | 897 | cache->mfc_un.res.ttls[vifi] = ttls[vifi]; |
618 | if (cache->mfc_un.res.minvif > vifi) | 898 | if (cache->mfc_un.res.minvif > vifi) |
@@ -623,16 +903,17 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl | |||
623 | } | 903 | } |
624 | } | 904 | } |
625 | 905 | ||
626 | static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock) | 906 | static int mif6_add(struct net *net, struct mr6_table *mrt, |
907 | struct mif6ctl *vifc, int mrtsock) | ||
627 | { | 908 | { |
628 | int vifi = vifc->mif6c_mifi; | 909 | int vifi = vifc->mif6c_mifi; |
629 | struct mif_device *v = &net->ipv6.vif6_table[vifi]; | 910 | struct mif_device *v = &mrt->vif6_table[vifi]; |
630 | struct net_device *dev; | 911 | struct net_device *dev; |
631 | struct inet6_dev *in6_dev; | 912 | struct inet6_dev *in6_dev; |
632 | int err; | 913 | int err; |
633 | 914 | ||
634 | /* Is vif busy ? */ | 915 | /* Is vif busy ? */ |
635 | if (MIF_EXISTS(net, vifi)) | 916 | if (MIF_EXISTS(mrt, vifi)) |
636 | return -EADDRINUSE; | 917 | return -EADDRINUSE; |
637 | 918 | ||
638 | switch (vifc->mif6c_flags) { | 919 | switch (vifc->mif6c_flags) { |
@@ -642,9 +923,9 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock) | |||
642 | * Special Purpose VIF in PIM | 923 | * Special Purpose VIF in PIM |
643 | * All the packets will be sent to the daemon | 924 | * All the packets will be sent to the daemon |
644 | */ | 925 | */ |
645 | if (net->ipv6.mroute_reg_vif_num >= 0) | 926 | if (mrt->mroute_reg_vif_num >= 0) |
646 | return -EADDRINUSE; | 927 | return -EADDRINUSE; |
647 | dev = ip6mr_reg_vif(net); | 928 | dev = ip6mr_reg_vif(net, mrt); |
648 | if (!dev) | 929 | if (!dev) |
649 | return -ENOBUFS; | 930 | return -ENOBUFS; |
650 | err = dev_set_allmulti(dev, 1); | 931 | err = dev_set_allmulti(dev, 1); |
@@ -694,50 +975,48 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock) | |||
694 | v->dev = dev; | 975 | v->dev = dev; |
695 | #ifdef CONFIG_IPV6_PIMSM_V2 | 976 | #ifdef CONFIG_IPV6_PIMSM_V2 |
696 | if (v->flags & MIFF_REGISTER) | 977 | if (v->flags & MIFF_REGISTER) |
697 | net->ipv6.mroute_reg_vif_num = vifi; | 978 | mrt->mroute_reg_vif_num = vifi; |
698 | #endif | 979 | #endif |
699 | if (vifi + 1 > net->ipv6.maxvif) | 980 | if (vifi + 1 > mrt->maxvif) |
700 | net->ipv6.maxvif = vifi + 1; | 981 | mrt->maxvif = vifi + 1; |
701 | write_unlock_bh(&mrt_lock); | 982 | write_unlock_bh(&mrt_lock); |
702 | return 0; | 983 | return 0; |
703 | } | 984 | } |
704 | 985 | ||
705 | static struct mfc6_cache *ip6mr_cache_find(struct net *net, | 986 | static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt, |
706 | struct in6_addr *origin, | 987 | struct in6_addr *origin, |
707 | struct in6_addr *mcastgrp) | 988 | struct in6_addr *mcastgrp) |
708 | { | 989 | { |
709 | int line = MFC6_HASH(mcastgrp, origin); | 990 | int line = MFC6_HASH(mcastgrp, origin); |
710 | struct mfc6_cache *c; | 991 | struct mfc6_cache *c; |
711 | 992 | ||
712 | for (c = net->ipv6.mfc6_cache_array[line]; c; c = c->next) { | 993 | list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) { |
713 | if (ipv6_addr_equal(&c->mf6c_origin, origin) && | 994 | if (ipv6_addr_equal(&c->mf6c_origin, origin) && |
714 | ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) | 995 | ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) |
715 | break; | 996 | return c; |
716 | } | 997 | } |
717 | return c; | 998 | return NULL; |
718 | } | 999 | } |
719 | 1000 | ||
720 | /* | 1001 | /* |
721 | * Allocate a multicast cache entry | 1002 | * Allocate a multicast cache entry |
722 | */ | 1003 | */ |
723 | static struct mfc6_cache *ip6mr_cache_alloc(struct net *net) | 1004 | static struct mfc6_cache *ip6mr_cache_alloc(void) |
724 | { | 1005 | { |
725 | struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); | 1006 | struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); |
726 | if (c == NULL) | 1007 | if (c == NULL) |
727 | return NULL; | 1008 | return NULL; |
728 | c->mfc_un.res.minvif = MAXMIFS; | 1009 | c->mfc_un.res.minvif = MAXMIFS; |
729 | mfc6_net_set(c, net); | ||
730 | return c; | 1010 | return c; |
731 | } | 1011 | } |
732 | 1012 | ||
733 | static struct mfc6_cache *ip6mr_cache_alloc_unres(struct net *net) | 1013 | static struct mfc6_cache *ip6mr_cache_alloc_unres(void) |
734 | { | 1014 | { |
735 | struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); | 1015 | struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); |
736 | if (c == NULL) | 1016 | if (c == NULL) |
737 | return NULL; | 1017 | return NULL; |
738 | skb_queue_head_init(&c->mfc_un.unres.unresolved); | 1018 | skb_queue_head_init(&c->mfc_un.unres.unresolved); |
739 | c->mfc_un.unres.expires = jiffies + 10 * HZ; | 1019 | c->mfc_un.unres.expires = jiffies + 10 * HZ; |
740 | mfc6_net_set(c, net); | ||
741 | return c; | 1020 | return c; |
742 | } | 1021 | } |
743 | 1022 | ||
@@ -745,7 +1024,8 @@ static struct mfc6_cache *ip6mr_cache_alloc_unres(struct net *net) | |||
745 | * A cache entry has gone into a resolved state from queued | 1024 | * A cache entry has gone into a resolved state from queued |
746 | */ | 1025 | */ |
747 | 1026 | ||
748 | static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | 1027 | static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt, |
1028 | struct mfc6_cache *uc, struct mfc6_cache *c) | ||
749 | { | 1029 | { |
750 | struct sk_buff *skb; | 1030 | struct sk_buff *skb; |
751 | 1031 | ||
@@ -758,7 +1038,7 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | |||
758 | int err; | 1038 | int err; |
759 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); | 1039 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); |
760 | 1040 | ||
761 | if (ip6mr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) { | 1041 | if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { |
762 | nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh; | 1042 | nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh; |
763 | } else { | 1043 | } else { |
764 | nlh->nlmsg_type = NLMSG_ERROR; | 1044 | nlh->nlmsg_type = NLMSG_ERROR; |
@@ -766,9 +1046,9 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | |||
766 | skb_trim(skb, nlh->nlmsg_len); | 1046 | skb_trim(skb, nlh->nlmsg_len); |
767 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; | 1047 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; |
768 | } | 1048 | } |
769 | err = rtnl_unicast(skb, mfc6_net(uc), NETLINK_CB(skb).pid); | 1049 | err = rtnl_unicast(skb, net, NETLINK_CB(skb).pid); |
770 | } else | 1050 | } else |
771 | ip6_mr_forward(skb, c); | 1051 | ip6_mr_forward(net, mrt, skb, c); |
772 | } | 1052 | } |
773 | } | 1053 | } |
774 | 1054 | ||
@@ -779,8 +1059,8 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | |||
779 | * Called under mrt_lock. | 1059 | * Called under mrt_lock. |
780 | */ | 1060 | */ |
781 | 1061 | ||
782 | static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | 1062 | static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt, |
783 | int assert) | 1063 | mifi_t mifi, int assert) |
784 | { | 1064 | { |
785 | struct sk_buff *skb; | 1065 | struct sk_buff *skb; |
786 | struct mrt6msg *msg; | 1066 | struct mrt6msg *msg; |
@@ -816,7 +1096,7 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | |||
816 | msg = (struct mrt6msg *)skb_transport_header(skb); | 1096 | msg = (struct mrt6msg *)skb_transport_header(skb); |
817 | msg->im6_mbz = 0; | 1097 | msg->im6_mbz = 0; |
818 | msg->im6_msgtype = MRT6MSG_WHOLEPKT; | 1098 | msg->im6_msgtype = MRT6MSG_WHOLEPKT; |
819 | msg->im6_mif = net->ipv6.mroute_reg_vif_num; | 1099 | msg->im6_mif = mrt->mroute_reg_vif_num; |
820 | msg->im6_pad = 0; | 1100 | msg->im6_pad = 0; |
821 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); | 1101 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); |
822 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); | 1102 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); |
@@ -851,7 +1131,7 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | |||
851 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1131 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
852 | } | 1132 | } |
853 | 1133 | ||
854 | if (net->ipv6.mroute6_sk == NULL) { | 1134 | if (mrt->mroute6_sk == NULL) { |
855 | kfree_skb(skb); | 1135 | kfree_skb(skb); |
856 | return -EINVAL; | 1136 | return -EINVAL; |
857 | } | 1137 | } |
@@ -859,7 +1139,7 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | |||
859 | /* | 1139 | /* |
860 | * Deliver to user space multicast routing algorithms | 1140 | * Deliver to user space multicast routing algorithms |
861 | */ | 1141 | */ |
862 | ret = sock_queue_rcv_skb(net->ipv6.mroute6_sk, skb); | 1142 | ret = sock_queue_rcv_skb(mrt->mroute6_sk, skb); |
863 | if (ret < 0) { | 1143 | if (ret < 0) { |
864 | if (net_ratelimit()) | 1144 | if (net_ratelimit()) |
865 | printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n"); | 1145 | printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n"); |
@@ -874,26 +1154,28 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | |||
874 | */ | 1154 | */ |
875 | 1155 | ||
876 | static int | 1156 | static int |
877 | ip6mr_cache_unresolved(struct net *net, mifi_t mifi, struct sk_buff *skb) | 1157 | ip6mr_cache_unresolved(struct mr6_table *mrt, mifi_t mifi, struct sk_buff *skb) |
878 | { | 1158 | { |
1159 | bool found = false; | ||
879 | int err; | 1160 | int err; |
880 | struct mfc6_cache *c; | 1161 | struct mfc6_cache *c; |
881 | 1162 | ||
882 | spin_lock_bh(&mfc_unres_lock); | 1163 | spin_lock_bh(&mfc_unres_lock); |
883 | for (c = mfc_unres_queue; c; c = c->next) { | 1164 | list_for_each_entry(c, &mrt->mfc6_unres_queue, list) { |
884 | if (net_eq(mfc6_net(c), net) && | 1165 | if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) && |
885 | ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) && | 1166 | ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) { |
886 | ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) | 1167 | found = true; |
887 | break; | 1168 | break; |
1169 | } | ||
888 | } | 1170 | } |
889 | 1171 | ||
890 | if (c == NULL) { | 1172 | if (!found) { |
891 | /* | 1173 | /* |
892 | * Create a new entry if allowable | 1174 | * Create a new entry if allowable |
893 | */ | 1175 | */ |
894 | 1176 | ||
895 | if (atomic_read(&net->ipv6.cache_resolve_queue_len) >= 10 || | 1177 | if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 || |
896 | (c = ip6mr_cache_alloc_unres(net)) == NULL) { | 1178 | (c = ip6mr_cache_alloc_unres()) == NULL) { |
897 | spin_unlock_bh(&mfc_unres_lock); | 1179 | spin_unlock_bh(&mfc_unres_lock); |
898 | 1180 | ||
899 | kfree_skb(skb); | 1181 | kfree_skb(skb); |
@@ -910,7 +1192,7 @@ ip6mr_cache_unresolved(struct net *net, mifi_t mifi, struct sk_buff *skb) | |||
910 | /* | 1192 | /* |
911 | * Reflect first query at pim6sd | 1193 | * Reflect first query at pim6sd |
912 | */ | 1194 | */ |
913 | err = ip6mr_cache_report(net, skb, mifi, MRT6MSG_NOCACHE); | 1195 | err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE); |
914 | if (err < 0) { | 1196 | if (err < 0) { |
915 | /* If the report failed throw the cache entry | 1197 | /* If the report failed throw the cache entry |
916 | out - Brad Parker | 1198 | out - Brad Parker |
@@ -922,11 +1204,10 @@ ip6mr_cache_unresolved(struct net *net, mifi_t mifi, struct sk_buff *skb) | |||
922 | return err; | 1204 | return err; |
923 | } | 1205 | } |
924 | 1206 | ||
925 | atomic_inc(&net->ipv6.cache_resolve_queue_len); | 1207 | atomic_inc(&mrt->cache_resolve_queue_len); |
926 | c->next = mfc_unres_queue; | 1208 | list_add(&c->list, &mrt->mfc6_unres_queue); |
927 | mfc_unres_queue = c; | ||
928 | 1209 | ||
929 | ipmr_do_expire_process(1); | 1210 | ipmr_do_expire_process(mrt); |
930 | } | 1211 | } |
931 | 1212 | ||
932 | /* | 1213 | /* |
@@ -948,19 +1229,18 @@ ip6mr_cache_unresolved(struct net *net, mifi_t mifi, struct sk_buff *skb) | |||
948 | * MFC6 cache manipulation by user space | 1229 | * MFC6 cache manipulation by user space |
949 | */ | 1230 | */ |
950 | 1231 | ||
951 | static int ip6mr_mfc_delete(struct net *net, struct mf6cctl *mfc) | 1232 | static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc) |
952 | { | 1233 | { |
953 | int line; | 1234 | int line; |
954 | struct mfc6_cache *c, **cp; | 1235 | struct mfc6_cache *c, *next; |
955 | 1236 | ||
956 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); | 1237 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); |
957 | 1238 | ||
958 | for (cp = &net->ipv6.mfc6_cache_array[line]; | 1239 | list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) { |
959 | (c = *cp) != NULL; cp = &c->next) { | ||
960 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && | 1240 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && |
961 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { | 1241 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { |
962 | write_lock_bh(&mrt_lock); | 1242 | write_lock_bh(&mrt_lock); |
963 | *cp = c->next; | 1243 | list_del(&c->list); |
964 | write_unlock_bh(&mrt_lock); | 1244 | write_unlock_bh(&mrt_lock); |
965 | 1245 | ||
966 | ip6mr_cache_free(c); | 1246 | ip6mr_cache_free(c); |
@@ -975,6 +1255,7 @@ static int ip6mr_device_event(struct notifier_block *this, | |||
975 | { | 1255 | { |
976 | struct net_device *dev = ptr; | 1256 | struct net_device *dev = ptr; |
977 | struct net *net = dev_net(dev); | 1257 | struct net *net = dev_net(dev); |
1258 | struct mr6_table *mrt; | ||
978 | struct mif_device *v; | 1259 | struct mif_device *v; |
979 | int ct; | 1260 | int ct; |
980 | LIST_HEAD(list); | 1261 | LIST_HEAD(list); |
@@ -982,10 +1263,12 @@ static int ip6mr_device_event(struct notifier_block *this, | |||
982 | if (event != NETDEV_UNREGISTER) | 1263 | if (event != NETDEV_UNREGISTER) |
983 | return NOTIFY_DONE; | 1264 | return NOTIFY_DONE; |
984 | 1265 | ||
985 | v = &net->ipv6.vif6_table[0]; | 1266 | ip6mr_for_each_table(mrt, net) { |
986 | for (ct = 0; ct < net->ipv6.maxvif; ct++, v++) { | 1267 | v = &mrt->vif6_table[0]; |
987 | if (v->dev == dev) | 1268 | for (ct = 0; ct < mrt->maxvif; ct++, v++) { |
988 | mif6_delete(net, ct, &list); | 1269 | if (v->dev == dev) |
1270 | mif6_delete(mrt, ct, &list); | ||
1271 | } | ||
989 | } | 1272 | } |
990 | unregister_netdevice_many(&list); | 1273 | unregister_netdevice_many(&list); |
991 | 1274 | ||
@@ -1002,26 +1285,11 @@ static struct notifier_block ip6_mr_notifier = { | |||
1002 | 1285 | ||
1003 | static int __net_init ip6mr_net_init(struct net *net) | 1286 | static int __net_init ip6mr_net_init(struct net *net) |
1004 | { | 1287 | { |
1005 | int err = 0; | 1288 | int err; |
1006 | net->ipv6.vif6_table = kcalloc(MAXMIFS, sizeof(struct mif_device), | ||
1007 | GFP_KERNEL); | ||
1008 | if (!net->ipv6.vif6_table) { | ||
1009 | err = -ENOMEM; | ||
1010 | goto fail; | ||
1011 | } | ||
1012 | |||
1013 | /* Forwarding cache */ | ||
1014 | net->ipv6.mfc6_cache_array = kcalloc(MFC6_LINES, | ||
1015 | sizeof(struct mfc6_cache *), | ||
1016 | GFP_KERNEL); | ||
1017 | if (!net->ipv6.mfc6_cache_array) { | ||
1018 | err = -ENOMEM; | ||
1019 | goto fail_mfc6_cache; | ||
1020 | } | ||
1021 | 1289 | ||
1022 | #ifdef CONFIG_IPV6_PIMSM_V2 | 1290 | err = ip6mr_rules_init(net); |
1023 | net->ipv6.mroute_reg_vif_num = -1; | 1291 | if (err < 0) |
1024 | #endif | 1292 | goto fail; |
1025 | 1293 | ||
1026 | #ifdef CONFIG_PROC_FS | 1294 | #ifdef CONFIG_PROC_FS |
1027 | err = -ENOMEM; | 1295 | err = -ENOMEM; |
@@ -1030,16 +1298,15 @@ static int __net_init ip6mr_net_init(struct net *net) | |||
1030 | if (!proc_net_fops_create(net, "ip6_mr_cache", 0, &ip6mr_mfc_fops)) | 1298 | if (!proc_net_fops_create(net, "ip6_mr_cache", 0, &ip6mr_mfc_fops)) |
1031 | goto proc_cache_fail; | 1299 | goto proc_cache_fail; |
1032 | #endif | 1300 | #endif |
1301 | |||
1033 | return 0; | 1302 | return 0; |
1034 | 1303 | ||
1035 | #ifdef CONFIG_PROC_FS | 1304 | #ifdef CONFIG_PROC_FS |
1036 | proc_cache_fail: | 1305 | proc_cache_fail: |
1037 | proc_net_remove(net, "ip6_mr_vif"); | 1306 | proc_net_remove(net, "ip6_mr_vif"); |
1038 | proc_vif_fail: | 1307 | proc_vif_fail: |
1039 | kfree(net->ipv6.mfc6_cache_array); | 1308 | ip6mr_rules_exit(net); |
1040 | #endif | 1309 | #endif |
1041 | fail_mfc6_cache: | ||
1042 | kfree(net->ipv6.vif6_table); | ||
1043 | fail: | 1310 | fail: |
1044 | return err; | 1311 | return err; |
1045 | } | 1312 | } |
@@ -1050,9 +1317,7 @@ static void __net_exit ip6mr_net_exit(struct net *net) | |||
1050 | proc_net_remove(net, "ip6_mr_cache"); | 1317 | proc_net_remove(net, "ip6_mr_cache"); |
1051 | proc_net_remove(net, "ip6_mr_vif"); | 1318 | proc_net_remove(net, "ip6_mr_vif"); |
1052 | #endif | 1319 | #endif |
1053 | mroute_clean_tables(net); | 1320 | ip6mr_rules_exit(net); |
1054 | kfree(net->ipv6.mfc6_cache_array); | ||
1055 | kfree(net->ipv6.vif6_table); | ||
1056 | } | 1321 | } |
1057 | 1322 | ||
1058 | static struct pernet_operations ip6mr_net_ops = { | 1323 | static struct pernet_operations ip6mr_net_ops = { |
@@ -1075,7 +1340,6 @@ int __init ip6_mr_init(void) | |||
1075 | if (err) | 1340 | if (err) |
1076 | goto reg_pernet_fail; | 1341 | goto reg_pernet_fail; |
1077 | 1342 | ||
1078 | setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); | ||
1079 | err = register_netdevice_notifier(&ip6_mr_notifier); | 1343 | err = register_netdevice_notifier(&ip6_mr_notifier); |
1080 | if (err) | 1344 | if (err) |
1081 | goto reg_notif_fail; | 1345 | goto reg_notif_fail; |
@@ -1086,13 +1350,13 @@ int __init ip6_mr_init(void) | |||
1086 | goto add_proto_fail; | 1350 | goto add_proto_fail; |
1087 | } | 1351 | } |
1088 | #endif | 1352 | #endif |
1353 | rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL, ip6mr_rtm_dumproute); | ||
1089 | return 0; | 1354 | return 0; |
1090 | #ifdef CONFIG_IPV6_PIMSM_V2 | 1355 | #ifdef CONFIG_IPV6_PIMSM_V2 |
1091 | add_proto_fail: | 1356 | add_proto_fail: |
1092 | unregister_netdevice_notifier(&ip6_mr_notifier); | 1357 | unregister_netdevice_notifier(&ip6_mr_notifier); |
1093 | #endif | 1358 | #endif |
1094 | reg_notif_fail: | 1359 | reg_notif_fail: |
1095 | del_timer(&ipmr_expire_timer); | ||
1096 | unregister_pernet_subsys(&ip6mr_net_ops); | 1360 | unregister_pernet_subsys(&ip6mr_net_ops); |
1097 | reg_pernet_fail: | 1361 | reg_pernet_fail: |
1098 | kmem_cache_destroy(mrt_cachep); | 1362 | kmem_cache_destroy(mrt_cachep); |
@@ -1102,15 +1366,16 @@ reg_pernet_fail: | |||
1102 | void ip6_mr_cleanup(void) | 1366 | void ip6_mr_cleanup(void) |
1103 | { | 1367 | { |
1104 | unregister_netdevice_notifier(&ip6_mr_notifier); | 1368 | unregister_netdevice_notifier(&ip6_mr_notifier); |
1105 | del_timer(&ipmr_expire_timer); | ||
1106 | unregister_pernet_subsys(&ip6mr_net_ops); | 1369 | unregister_pernet_subsys(&ip6mr_net_ops); |
1107 | kmem_cache_destroy(mrt_cachep); | 1370 | kmem_cache_destroy(mrt_cachep); |
1108 | } | 1371 | } |
1109 | 1372 | ||
1110 | static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock) | 1373 | static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt, |
1374 | struct mf6cctl *mfc, int mrtsock) | ||
1111 | { | 1375 | { |
1376 | bool found = false; | ||
1112 | int line; | 1377 | int line; |
1113 | struct mfc6_cache *uc, *c, **cp; | 1378 | struct mfc6_cache *uc, *c; |
1114 | unsigned char ttls[MAXMIFS]; | 1379 | unsigned char ttls[MAXMIFS]; |
1115 | int i; | 1380 | int i; |
1116 | 1381 | ||
@@ -1126,17 +1391,18 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock) | |||
1126 | 1391 | ||
1127 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); | 1392 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); |
1128 | 1393 | ||
1129 | for (cp = &net->ipv6.mfc6_cache_array[line]; | 1394 | list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) { |
1130 | (c = *cp) != NULL; cp = &c->next) { | ||
1131 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && | 1395 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && |
1132 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) | 1396 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { |
1397 | found = true; | ||
1133 | break; | 1398 | break; |
1399 | } | ||
1134 | } | 1400 | } |
1135 | 1401 | ||
1136 | if (c != NULL) { | 1402 | if (found) { |
1137 | write_lock_bh(&mrt_lock); | 1403 | write_lock_bh(&mrt_lock); |
1138 | c->mf6c_parent = mfc->mf6cc_parent; | 1404 | c->mf6c_parent = mfc->mf6cc_parent; |
1139 | ip6mr_update_thresholds(c, ttls); | 1405 | ip6mr_update_thresholds(mrt, c, ttls); |
1140 | if (!mrtsock) | 1406 | if (!mrtsock) |
1141 | c->mfc_flags |= MFC_STATIC; | 1407 | c->mfc_flags |= MFC_STATIC; |
1142 | write_unlock_bh(&mrt_lock); | 1408 | write_unlock_bh(&mrt_lock); |
@@ -1146,43 +1412,42 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock) | |||
1146 | if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr)) | 1412 | if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr)) |
1147 | return -EINVAL; | 1413 | return -EINVAL; |
1148 | 1414 | ||
1149 | c = ip6mr_cache_alloc(net); | 1415 | c = ip6mr_cache_alloc(); |
1150 | if (c == NULL) | 1416 | if (c == NULL) |
1151 | return -ENOMEM; | 1417 | return -ENOMEM; |
1152 | 1418 | ||
1153 | c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; | 1419 | c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; |
1154 | c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr; | 1420 | c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr; |
1155 | c->mf6c_parent = mfc->mf6cc_parent; | 1421 | c->mf6c_parent = mfc->mf6cc_parent; |
1156 | ip6mr_update_thresholds(c, ttls); | 1422 | ip6mr_update_thresholds(mrt, c, ttls); |
1157 | if (!mrtsock) | 1423 | if (!mrtsock) |
1158 | c->mfc_flags |= MFC_STATIC; | 1424 | c->mfc_flags |= MFC_STATIC; |
1159 | 1425 | ||
1160 | write_lock_bh(&mrt_lock); | 1426 | write_lock_bh(&mrt_lock); |
1161 | c->next = net->ipv6.mfc6_cache_array[line]; | 1427 | list_add(&c->list, &mrt->mfc6_cache_array[line]); |
1162 | net->ipv6.mfc6_cache_array[line] = c; | ||
1163 | write_unlock_bh(&mrt_lock); | 1428 | write_unlock_bh(&mrt_lock); |
1164 | 1429 | ||
1165 | /* | 1430 | /* |
1166 | * Check to see if we resolved a queued list. If so we | 1431 | * Check to see if we resolved a queued list. If so we |
1167 | * need to send on the frames and tidy up. | 1432 | * need to send on the frames and tidy up. |
1168 | */ | 1433 | */ |
1434 | found = false; | ||
1169 | spin_lock_bh(&mfc_unres_lock); | 1435 | spin_lock_bh(&mfc_unres_lock); |
1170 | for (cp = &mfc_unres_queue; (uc = *cp) != NULL; | 1436 | list_for_each_entry(uc, &mrt->mfc6_unres_queue, list) { |
1171 | cp = &uc->next) { | 1437 | if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) && |
1172 | if (net_eq(mfc6_net(uc), net) && | ||
1173 | ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) && | ||
1174 | ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) { | 1438 | ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) { |
1175 | *cp = uc->next; | 1439 | list_del(&uc->list); |
1176 | atomic_dec(&net->ipv6.cache_resolve_queue_len); | 1440 | atomic_dec(&mrt->cache_resolve_queue_len); |
1441 | found = true; | ||
1177 | break; | 1442 | break; |
1178 | } | 1443 | } |
1179 | } | 1444 | } |
1180 | if (mfc_unres_queue == NULL) | 1445 | if (list_empty(&mrt->mfc6_unres_queue)) |
1181 | del_timer(&ipmr_expire_timer); | 1446 | del_timer(&mrt->ipmr_expire_timer); |
1182 | spin_unlock_bh(&mfc_unres_lock); | 1447 | spin_unlock_bh(&mfc_unres_lock); |
1183 | 1448 | ||
1184 | if (uc) { | 1449 | if (found) { |
1185 | ip6mr_cache_resolve(uc, c); | 1450 | ip6mr_cache_resolve(net, mrt, uc, c); |
1186 | ip6mr_cache_free(uc); | 1451 | ip6mr_cache_free(uc); |
1187 | } | 1452 | } |
1188 | return 0; | 1453 | return 0; |
@@ -1192,17 +1457,18 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock) | |||
1192 | * Close the multicast socket, and clear the vif tables etc | 1457 | * Close the multicast socket, and clear the vif tables etc |
1193 | */ | 1458 | */ |
1194 | 1459 | ||
1195 | static void mroute_clean_tables(struct net *net) | 1460 | static void mroute_clean_tables(struct mr6_table *mrt) |
1196 | { | 1461 | { |
1197 | int i; | 1462 | int i; |
1198 | LIST_HEAD(list); | 1463 | LIST_HEAD(list); |
1464 | struct mfc6_cache *c, *next; | ||
1199 | 1465 | ||
1200 | /* | 1466 | /* |
1201 | * Shut down all active vif entries | 1467 | * Shut down all active vif entries |
1202 | */ | 1468 | */ |
1203 | for (i = 0; i < net->ipv6.maxvif; i++) { | 1469 | for (i = 0; i < mrt->maxvif; i++) { |
1204 | if (!(net->ipv6.vif6_table[i].flags & VIFF_STATIC)) | 1470 | if (!(mrt->vif6_table[i].flags & VIFF_STATIC)) |
1205 | mif6_delete(net, i, &list); | 1471 | mif6_delete(mrt, i, &list); |
1206 | } | 1472 | } |
1207 | unregister_netdevice_many(&list); | 1473 | unregister_netdevice_many(&list); |
1208 | 1474 | ||
@@ -1210,48 +1476,36 @@ static void mroute_clean_tables(struct net *net) | |||
1210 | * Wipe the cache | 1476 | * Wipe the cache |
1211 | */ | 1477 | */ |
1212 | for (i = 0; i < MFC6_LINES; i++) { | 1478 | for (i = 0; i < MFC6_LINES; i++) { |
1213 | struct mfc6_cache *c, **cp; | 1479 | list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) { |
1214 | 1480 | if (c->mfc_flags & MFC_STATIC) | |
1215 | cp = &net->ipv6.mfc6_cache_array[i]; | ||
1216 | while ((c = *cp) != NULL) { | ||
1217 | if (c->mfc_flags & MFC_STATIC) { | ||
1218 | cp = &c->next; | ||
1219 | continue; | 1481 | continue; |
1220 | } | ||
1221 | write_lock_bh(&mrt_lock); | 1482 | write_lock_bh(&mrt_lock); |
1222 | *cp = c->next; | 1483 | list_del(&c->list); |
1223 | write_unlock_bh(&mrt_lock); | 1484 | write_unlock_bh(&mrt_lock); |
1224 | 1485 | ||
1225 | ip6mr_cache_free(c); | 1486 | ip6mr_cache_free(c); |
1226 | } | 1487 | } |
1227 | } | 1488 | } |
1228 | 1489 | ||
1229 | if (atomic_read(&net->ipv6.cache_resolve_queue_len) != 0) { | 1490 | if (atomic_read(&mrt->cache_resolve_queue_len) != 0) { |
1230 | struct mfc6_cache *c, **cp; | ||
1231 | |||
1232 | spin_lock_bh(&mfc_unres_lock); | 1491 | spin_lock_bh(&mfc_unres_lock); |
1233 | cp = &mfc_unres_queue; | 1492 | list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) { |
1234 | while ((c = *cp) != NULL) { | 1493 | list_del(&c->list); |
1235 | if (!net_eq(mfc6_net(c), net)) { | 1494 | ip6mr_destroy_unres(mrt, c); |
1236 | cp = &c->next; | ||
1237 | continue; | ||
1238 | } | ||
1239 | *cp = c->next; | ||
1240 | ip6mr_destroy_unres(c); | ||
1241 | } | 1495 | } |
1242 | spin_unlock_bh(&mfc_unres_lock); | 1496 | spin_unlock_bh(&mfc_unres_lock); |
1243 | } | 1497 | } |
1244 | } | 1498 | } |
1245 | 1499 | ||
1246 | static int ip6mr_sk_init(struct sock *sk) | 1500 | static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk) |
1247 | { | 1501 | { |
1248 | int err = 0; | 1502 | int err = 0; |
1249 | struct net *net = sock_net(sk); | 1503 | struct net *net = sock_net(sk); |
1250 | 1504 | ||
1251 | rtnl_lock(); | 1505 | rtnl_lock(); |
1252 | write_lock_bh(&mrt_lock); | 1506 | write_lock_bh(&mrt_lock); |
1253 | if (likely(net->ipv6.mroute6_sk == NULL)) { | 1507 | if (likely(mrt->mroute6_sk == NULL)) { |
1254 | net->ipv6.mroute6_sk = sk; | 1508 | mrt->mroute6_sk = sk; |
1255 | net->ipv6.devconf_all->mc_forwarding++; | 1509 | net->ipv6.devconf_all->mc_forwarding++; |
1256 | } | 1510 | } |
1257 | else | 1511 | else |
@@ -1265,24 +1519,43 @@ static int ip6mr_sk_init(struct sock *sk) | |||
1265 | 1519 | ||
1266 | int ip6mr_sk_done(struct sock *sk) | 1520 | int ip6mr_sk_done(struct sock *sk) |
1267 | { | 1521 | { |
1268 | int err = 0; | 1522 | int err = -EACCES; |
1269 | struct net *net = sock_net(sk); | 1523 | struct net *net = sock_net(sk); |
1524 | struct mr6_table *mrt; | ||
1270 | 1525 | ||
1271 | rtnl_lock(); | 1526 | rtnl_lock(); |
1272 | if (sk == net->ipv6.mroute6_sk) { | 1527 | ip6mr_for_each_table(mrt, net) { |
1273 | write_lock_bh(&mrt_lock); | 1528 | if (sk == mrt->mroute6_sk) { |
1274 | net->ipv6.mroute6_sk = NULL; | 1529 | write_lock_bh(&mrt_lock); |
1275 | net->ipv6.devconf_all->mc_forwarding--; | 1530 | mrt->mroute6_sk = NULL; |
1276 | write_unlock_bh(&mrt_lock); | 1531 | net->ipv6.devconf_all->mc_forwarding--; |
1532 | write_unlock_bh(&mrt_lock); | ||
1277 | 1533 | ||
1278 | mroute_clean_tables(net); | 1534 | mroute_clean_tables(mrt); |
1279 | } else | 1535 | err = 0; |
1280 | err = -EACCES; | 1536 | break; |
1537 | } | ||
1538 | } | ||
1281 | rtnl_unlock(); | 1539 | rtnl_unlock(); |
1282 | 1540 | ||
1283 | return err; | 1541 | return err; |
1284 | } | 1542 | } |
1285 | 1543 | ||
1544 | struct sock *mroute6_socket(struct net *net, struct sk_buff *skb) | ||
1545 | { | ||
1546 | struct mr6_table *mrt; | ||
1547 | struct flowi fl = { | ||
1548 | .iif = skb->skb_iif, | ||
1549 | .oif = skb->dev->ifindex, | ||
1550 | .mark = skb->mark, | ||
1551 | }; | ||
1552 | |||
1553 | if (ip6mr_fib_lookup(net, &fl, &mrt) < 0) | ||
1554 | return NULL; | ||
1555 | |||
1556 | return mrt->mroute6_sk; | ||
1557 | } | ||
1558 | |||
1286 | /* | 1559 | /* |
1287 | * Socket options and virtual interface manipulation. The whole | 1560 | * Socket options and virtual interface manipulation. The whole |
1288 | * virtual interface system is a complete heap, but unfortunately | 1561 | * virtual interface system is a complete heap, but unfortunately |
@@ -1297,9 +1570,14 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1297 | struct mf6cctl mfc; | 1570 | struct mf6cctl mfc; |
1298 | mifi_t mifi; | 1571 | mifi_t mifi; |
1299 | struct net *net = sock_net(sk); | 1572 | struct net *net = sock_net(sk); |
1573 | struct mr6_table *mrt; | ||
1574 | |||
1575 | mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); | ||
1576 | if (mrt == NULL) | ||
1577 | return -ENOENT; | ||
1300 | 1578 | ||
1301 | if (optname != MRT6_INIT) { | 1579 | if (optname != MRT6_INIT) { |
1302 | if (sk != net->ipv6.mroute6_sk && !capable(CAP_NET_ADMIN)) | 1580 | if (sk != mrt->mroute6_sk && !capable(CAP_NET_ADMIN)) |
1303 | return -EACCES; | 1581 | return -EACCES; |
1304 | } | 1582 | } |
1305 | 1583 | ||
@@ -1311,7 +1589,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1311 | if (optlen < sizeof(int)) | 1589 | if (optlen < sizeof(int)) |
1312 | return -EINVAL; | 1590 | return -EINVAL; |
1313 | 1591 | ||
1314 | return ip6mr_sk_init(sk); | 1592 | return ip6mr_sk_init(mrt, sk); |
1315 | 1593 | ||
1316 | case MRT6_DONE: | 1594 | case MRT6_DONE: |
1317 | return ip6mr_sk_done(sk); | 1595 | return ip6mr_sk_done(sk); |
@@ -1324,7 +1602,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1324 | if (vif.mif6c_mifi >= MAXMIFS) | 1602 | if (vif.mif6c_mifi >= MAXMIFS) |
1325 | return -ENFILE; | 1603 | return -ENFILE; |
1326 | rtnl_lock(); | 1604 | rtnl_lock(); |
1327 | ret = mif6_add(net, &vif, sk == net->ipv6.mroute6_sk); | 1605 | ret = mif6_add(net, mrt, &vif, sk == mrt->mroute6_sk); |
1328 | rtnl_unlock(); | 1606 | rtnl_unlock(); |
1329 | return ret; | 1607 | return ret; |
1330 | 1608 | ||
@@ -1334,7 +1612,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1334 | if (copy_from_user(&mifi, optval, sizeof(mifi_t))) | 1612 | if (copy_from_user(&mifi, optval, sizeof(mifi_t))) |
1335 | return -EFAULT; | 1613 | return -EFAULT; |
1336 | rtnl_lock(); | 1614 | rtnl_lock(); |
1337 | ret = mif6_delete(net, mifi, NULL); | 1615 | ret = mif6_delete(mrt, mifi, NULL); |
1338 | rtnl_unlock(); | 1616 | rtnl_unlock(); |
1339 | return ret; | 1617 | return ret; |
1340 | 1618 | ||
@@ -1350,10 +1628,9 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1350 | return -EFAULT; | 1628 | return -EFAULT; |
1351 | rtnl_lock(); | 1629 | rtnl_lock(); |
1352 | if (optname == MRT6_DEL_MFC) | 1630 | if (optname == MRT6_DEL_MFC) |
1353 | ret = ip6mr_mfc_delete(net, &mfc); | 1631 | ret = ip6mr_mfc_delete(mrt, &mfc); |
1354 | else | 1632 | else |
1355 | ret = ip6mr_mfc_add(net, &mfc, | 1633 | ret = ip6mr_mfc_add(net, mrt, &mfc, sk == mrt->mroute6_sk); |
1356 | sk == net->ipv6.mroute6_sk); | ||
1357 | rtnl_unlock(); | 1634 | rtnl_unlock(); |
1358 | return ret; | 1635 | return ret; |
1359 | 1636 | ||
@@ -1365,7 +1642,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1365 | int v; | 1642 | int v; |
1366 | if (get_user(v, (int __user *)optval)) | 1643 | if (get_user(v, (int __user *)optval)) |
1367 | return -EFAULT; | 1644 | return -EFAULT; |
1368 | net->ipv6.mroute_do_assert = !!v; | 1645 | mrt->mroute_do_assert = !!v; |
1369 | return 0; | 1646 | return 0; |
1370 | } | 1647 | } |
1371 | 1648 | ||
@@ -1378,15 +1655,36 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1378 | v = !!v; | 1655 | v = !!v; |
1379 | rtnl_lock(); | 1656 | rtnl_lock(); |
1380 | ret = 0; | 1657 | ret = 0; |
1381 | if (v != net->ipv6.mroute_do_pim) { | 1658 | if (v != mrt->mroute_do_pim) { |
1382 | net->ipv6.mroute_do_pim = v; | 1659 | mrt->mroute_do_pim = v; |
1383 | net->ipv6.mroute_do_assert = v; | 1660 | mrt->mroute_do_assert = v; |
1384 | } | 1661 | } |
1385 | rtnl_unlock(); | 1662 | rtnl_unlock(); |
1386 | return ret; | 1663 | return ret; |
1387 | } | 1664 | } |
1388 | 1665 | ||
1389 | #endif | 1666 | #endif |
1667 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES | ||
1668 | case MRT6_TABLE: | ||
1669 | { | ||
1670 | u32 v; | ||
1671 | |||
1672 | if (optlen != sizeof(u32)) | ||
1673 | return -EINVAL; | ||
1674 | if (get_user(v, (u32 __user *)optval)) | ||
1675 | return -EFAULT; | ||
1676 | if (sk == mrt->mroute6_sk) | ||
1677 | return -EBUSY; | ||
1678 | |||
1679 | rtnl_lock(); | ||
1680 | ret = 0; | ||
1681 | if (!ip6mr_new_table(net, v)) | ||
1682 | ret = -ENOMEM; | ||
1683 | raw6_sk(sk)->ip6mr_table = v; | ||
1684 | rtnl_unlock(); | ||
1685 | return ret; | ||
1686 | } | ||
1687 | #endif | ||
1390 | /* | 1688 | /* |
1391 | * Spurious command, or MRT6_VERSION which you cannot | 1689 | * Spurious command, or MRT6_VERSION which you cannot |
1392 | * set. | 1690 | * set. |
@@ -1406,6 +1704,11 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, | |||
1406 | int olr; | 1704 | int olr; |
1407 | int val; | 1705 | int val; |
1408 | struct net *net = sock_net(sk); | 1706 | struct net *net = sock_net(sk); |
1707 | struct mr6_table *mrt; | ||
1708 | |||
1709 | mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); | ||
1710 | if (mrt == NULL) | ||
1711 | return -ENOENT; | ||
1409 | 1712 | ||
1410 | switch (optname) { | 1713 | switch (optname) { |
1411 | case MRT6_VERSION: | 1714 | case MRT6_VERSION: |
@@ -1413,11 +1716,11 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, | |||
1413 | break; | 1716 | break; |
1414 | #ifdef CONFIG_IPV6_PIMSM_V2 | 1717 | #ifdef CONFIG_IPV6_PIMSM_V2 |
1415 | case MRT6_PIM: | 1718 | case MRT6_PIM: |
1416 | val = net->ipv6.mroute_do_pim; | 1719 | val = mrt->mroute_do_pim; |
1417 | break; | 1720 | break; |
1418 | #endif | 1721 | #endif |
1419 | case MRT6_ASSERT: | 1722 | case MRT6_ASSERT: |
1420 | val = net->ipv6.mroute_do_assert; | 1723 | val = mrt->mroute_do_assert; |
1421 | break; | 1724 | break; |
1422 | default: | 1725 | default: |
1423 | return -ENOPROTOOPT; | 1726 | return -ENOPROTOOPT; |
@@ -1448,16 +1751,21 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1448 | struct mif_device *vif; | 1751 | struct mif_device *vif; |
1449 | struct mfc6_cache *c; | 1752 | struct mfc6_cache *c; |
1450 | struct net *net = sock_net(sk); | 1753 | struct net *net = sock_net(sk); |
1754 | struct mr6_table *mrt; | ||
1755 | |||
1756 | mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); | ||
1757 | if (mrt == NULL) | ||
1758 | return -ENOENT; | ||
1451 | 1759 | ||
1452 | switch (cmd) { | 1760 | switch (cmd) { |
1453 | case SIOCGETMIFCNT_IN6: | 1761 | case SIOCGETMIFCNT_IN6: |
1454 | if (copy_from_user(&vr, arg, sizeof(vr))) | 1762 | if (copy_from_user(&vr, arg, sizeof(vr))) |
1455 | return -EFAULT; | 1763 | return -EFAULT; |
1456 | if (vr.mifi >= net->ipv6.maxvif) | 1764 | if (vr.mifi >= mrt->maxvif) |
1457 | return -EINVAL; | 1765 | return -EINVAL; |
1458 | read_lock(&mrt_lock); | 1766 | read_lock(&mrt_lock); |
1459 | vif = &net->ipv6.vif6_table[vr.mifi]; | 1767 | vif = &mrt->vif6_table[vr.mifi]; |
1460 | if (MIF_EXISTS(net, vr.mifi)) { | 1768 | if (MIF_EXISTS(mrt, vr.mifi)) { |
1461 | vr.icount = vif->pkt_in; | 1769 | vr.icount = vif->pkt_in; |
1462 | vr.ocount = vif->pkt_out; | 1770 | vr.ocount = vif->pkt_out; |
1463 | vr.ibytes = vif->bytes_in; | 1771 | vr.ibytes = vif->bytes_in; |
@@ -1475,7 +1783,7 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1475 | return -EFAULT; | 1783 | return -EFAULT; |
1476 | 1784 | ||
1477 | read_lock(&mrt_lock); | 1785 | read_lock(&mrt_lock); |
1478 | c = ip6mr_cache_find(net, &sr.src.sin6_addr, &sr.grp.sin6_addr); | 1786 | c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr); |
1479 | if (c) { | 1787 | if (c) { |
1480 | sr.pktcnt = c->mfc_un.res.pkt; | 1788 | sr.pktcnt = c->mfc_un.res.pkt; |
1481 | sr.bytecnt = c->mfc_un.res.bytes; | 1789 | sr.bytecnt = c->mfc_un.res.bytes; |
@@ -1505,11 +1813,11 @@ static inline int ip6mr_forward2_finish(struct sk_buff *skb) | |||
1505 | * Processing handlers for ip6mr_forward | 1813 | * Processing handlers for ip6mr_forward |
1506 | */ | 1814 | */ |
1507 | 1815 | ||
1508 | static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | 1816 | static int ip6mr_forward2(struct net *net, struct mr6_table *mrt, |
1817 | struct sk_buff *skb, struct mfc6_cache *c, int vifi) | ||
1509 | { | 1818 | { |
1510 | struct ipv6hdr *ipv6h; | 1819 | struct ipv6hdr *ipv6h; |
1511 | struct net *net = mfc6_net(c); | 1820 | struct mif_device *vif = &mrt->vif6_table[vifi]; |
1512 | struct mif_device *vif = &net->ipv6.vif6_table[vifi]; | ||
1513 | struct net_device *dev; | 1821 | struct net_device *dev; |
1514 | struct dst_entry *dst; | 1822 | struct dst_entry *dst; |
1515 | struct flowi fl; | 1823 | struct flowi fl; |
@@ -1523,7 +1831,7 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | |||
1523 | vif->bytes_out += skb->len; | 1831 | vif->bytes_out += skb->len; |
1524 | vif->dev->stats.tx_bytes += skb->len; | 1832 | vif->dev->stats.tx_bytes += skb->len; |
1525 | vif->dev->stats.tx_packets++; | 1833 | vif->dev->stats.tx_packets++; |
1526 | ip6mr_cache_report(net, skb, vifi, MRT6MSG_WHOLEPKT); | 1834 | ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT); |
1527 | goto out_free; | 1835 | goto out_free; |
1528 | } | 1836 | } |
1529 | #endif | 1837 | #endif |
@@ -1570,7 +1878,7 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | |||
1570 | 1878 | ||
1571 | IP6CB(skb)->flags |= IP6SKB_FORWARDED; | 1879 | IP6CB(skb)->flags |= IP6SKB_FORWARDED; |
1572 | 1880 | ||
1573 | return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dev, | 1881 | return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dev, |
1574 | ip6mr_forward2_finish); | 1882 | ip6mr_forward2_finish); |
1575 | 1883 | ||
1576 | out_free: | 1884 | out_free: |
@@ -1578,22 +1886,22 @@ out_free: | |||
1578 | return 0; | 1886 | return 0; |
1579 | } | 1887 | } |
1580 | 1888 | ||
1581 | static int ip6mr_find_vif(struct net_device *dev) | 1889 | static int ip6mr_find_vif(struct mr6_table *mrt, struct net_device *dev) |
1582 | { | 1890 | { |
1583 | struct net *net = dev_net(dev); | ||
1584 | int ct; | 1891 | int ct; |
1585 | for (ct = net->ipv6.maxvif - 1; ct >= 0; ct--) { | 1892 | |
1586 | if (net->ipv6.vif6_table[ct].dev == dev) | 1893 | for (ct = mrt->maxvif - 1; ct >= 0; ct--) { |
1894 | if (mrt->vif6_table[ct].dev == dev) | ||
1587 | break; | 1895 | break; |
1588 | } | 1896 | } |
1589 | return ct; | 1897 | return ct; |
1590 | } | 1898 | } |
1591 | 1899 | ||
1592 | static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache) | 1900 | static int ip6_mr_forward(struct net *net, struct mr6_table *mrt, |
1901 | struct sk_buff *skb, struct mfc6_cache *cache) | ||
1593 | { | 1902 | { |
1594 | int psend = -1; | 1903 | int psend = -1; |
1595 | int vif, ct; | 1904 | int vif, ct; |
1596 | struct net *net = mfc6_net(cache); | ||
1597 | 1905 | ||
1598 | vif = cache->mf6c_parent; | 1906 | vif = cache->mf6c_parent; |
1599 | cache->mfc_un.res.pkt++; | 1907 | cache->mfc_un.res.pkt++; |
@@ -1602,30 +1910,30 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache) | |||
1602 | /* | 1910 | /* |
1603 | * Wrong interface: drop packet and (maybe) send PIM assert. | 1911 | * Wrong interface: drop packet and (maybe) send PIM assert. |
1604 | */ | 1912 | */ |
1605 | if (net->ipv6.vif6_table[vif].dev != skb->dev) { | 1913 | if (mrt->vif6_table[vif].dev != skb->dev) { |
1606 | int true_vifi; | 1914 | int true_vifi; |
1607 | 1915 | ||
1608 | cache->mfc_un.res.wrong_if++; | 1916 | cache->mfc_un.res.wrong_if++; |
1609 | true_vifi = ip6mr_find_vif(skb->dev); | 1917 | true_vifi = ip6mr_find_vif(mrt, skb->dev); |
1610 | 1918 | ||
1611 | if (true_vifi >= 0 && net->ipv6.mroute_do_assert && | 1919 | if (true_vifi >= 0 && mrt->mroute_do_assert && |
1612 | /* pimsm uses asserts, when switching from RPT to SPT, | 1920 | /* pimsm uses asserts, when switching from RPT to SPT, |
1613 | so that we cannot check that packet arrived on an oif. | 1921 | so that we cannot check that packet arrived on an oif. |
1614 | It is bad, but otherwise we would need to move pretty | 1922 | It is bad, but otherwise we would need to move pretty |
1615 | large chunk of pimd to kernel. Ough... --ANK | 1923 | large chunk of pimd to kernel. Ough... --ANK |
1616 | */ | 1924 | */ |
1617 | (net->ipv6.mroute_do_pim || | 1925 | (mrt->mroute_do_pim || |
1618 | cache->mfc_un.res.ttls[true_vifi] < 255) && | 1926 | cache->mfc_un.res.ttls[true_vifi] < 255) && |
1619 | time_after(jiffies, | 1927 | time_after(jiffies, |
1620 | cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { | 1928 | cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { |
1621 | cache->mfc_un.res.last_assert = jiffies; | 1929 | cache->mfc_un.res.last_assert = jiffies; |
1622 | ip6mr_cache_report(net, skb, true_vifi, MRT6MSG_WRONGMIF); | 1930 | ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF); |
1623 | } | 1931 | } |
1624 | goto dont_forward; | 1932 | goto dont_forward; |
1625 | } | 1933 | } |
1626 | 1934 | ||
1627 | net->ipv6.vif6_table[vif].pkt_in++; | 1935 | mrt->vif6_table[vif].pkt_in++; |
1628 | net->ipv6.vif6_table[vif].bytes_in += skb->len; | 1936 | mrt->vif6_table[vif].bytes_in += skb->len; |
1629 | 1937 | ||
1630 | /* | 1938 | /* |
1631 | * Forward the frame | 1939 | * Forward the frame |
@@ -1635,13 +1943,13 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache) | |||
1635 | if (psend != -1) { | 1943 | if (psend != -1) { |
1636 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 1944 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
1637 | if (skb2) | 1945 | if (skb2) |
1638 | ip6mr_forward2(skb2, cache, psend); | 1946 | ip6mr_forward2(net, mrt, skb2, cache, psend); |
1639 | } | 1947 | } |
1640 | psend = ct; | 1948 | psend = ct; |
1641 | } | 1949 | } |
1642 | } | 1950 | } |
1643 | if (psend != -1) { | 1951 | if (psend != -1) { |
1644 | ip6mr_forward2(skb, cache, psend); | 1952 | ip6mr_forward2(net, mrt, skb, cache, psend); |
1645 | return 0; | 1953 | return 0; |
1646 | } | 1954 | } |
1647 | 1955 | ||
@@ -1659,9 +1967,19 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1659 | { | 1967 | { |
1660 | struct mfc6_cache *cache; | 1968 | struct mfc6_cache *cache; |
1661 | struct net *net = dev_net(skb->dev); | 1969 | struct net *net = dev_net(skb->dev); |
1970 | struct mr6_table *mrt; | ||
1971 | struct flowi fl = { | ||
1972 | .iif = skb->dev->ifindex, | ||
1973 | .mark = skb->mark, | ||
1974 | }; | ||
1975 | int err; | ||
1976 | |||
1977 | err = ip6mr_fib_lookup(net, &fl, &mrt); | ||
1978 | if (err < 0) | ||
1979 | return err; | ||
1662 | 1980 | ||
1663 | read_lock(&mrt_lock); | 1981 | read_lock(&mrt_lock); |
1664 | cache = ip6mr_cache_find(net, | 1982 | cache = ip6mr_cache_find(mrt, |
1665 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); | 1983 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); |
1666 | 1984 | ||
1667 | /* | 1985 | /* |
@@ -1670,9 +1988,9 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1670 | if (cache == NULL) { | 1988 | if (cache == NULL) { |
1671 | int vif; | 1989 | int vif; |
1672 | 1990 | ||
1673 | vif = ip6mr_find_vif(skb->dev); | 1991 | vif = ip6mr_find_vif(mrt, skb->dev); |
1674 | if (vif >= 0) { | 1992 | if (vif >= 0) { |
1675 | int err = ip6mr_cache_unresolved(net, vif, skb); | 1993 | int err = ip6mr_cache_unresolved(mrt, vif, skb); |
1676 | read_unlock(&mrt_lock); | 1994 | read_unlock(&mrt_lock); |
1677 | 1995 | ||
1678 | return err; | 1996 | return err; |
@@ -1682,7 +2000,7 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1682 | return -ENODEV; | 2000 | return -ENODEV; |
1683 | } | 2001 | } |
1684 | 2002 | ||
1685 | ip6_mr_forward(skb, cache); | 2003 | ip6_mr_forward(net, mrt, skb, cache); |
1686 | 2004 | ||
1687 | read_unlock(&mrt_lock); | 2005 | read_unlock(&mrt_lock); |
1688 | 2006 | ||
@@ -1690,12 +2008,11 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1690 | } | 2008 | } |
1691 | 2009 | ||
1692 | 2010 | ||
1693 | static int | 2011 | static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, |
1694 | ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm) | 2012 | struct mfc6_cache *c, struct rtmsg *rtm) |
1695 | { | 2013 | { |
1696 | int ct; | 2014 | int ct; |
1697 | struct rtnexthop *nhp; | 2015 | struct rtnexthop *nhp; |
1698 | struct net *net = mfc6_net(c); | ||
1699 | u8 *b = skb_tail_pointer(skb); | 2016 | u8 *b = skb_tail_pointer(skb); |
1700 | struct rtattr *mp_head; | 2017 | struct rtattr *mp_head; |
1701 | 2018 | ||
@@ -1703,19 +2020,19 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm) | |||
1703 | if (c->mf6c_parent > MAXMIFS) | 2020 | if (c->mf6c_parent > MAXMIFS) |
1704 | return -ENOENT; | 2021 | return -ENOENT; |
1705 | 2022 | ||
1706 | if (MIF_EXISTS(net, c->mf6c_parent)) | 2023 | if (MIF_EXISTS(mrt, c->mf6c_parent)) |
1707 | RTA_PUT(skb, RTA_IIF, 4, &net->ipv6.vif6_table[c->mf6c_parent].dev->ifindex); | 2024 | RTA_PUT(skb, RTA_IIF, 4, &mrt->vif6_table[c->mf6c_parent].dev->ifindex); |
1708 | 2025 | ||
1709 | mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); | 2026 | mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); |
1710 | 2027 | ||
1711 | for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { | 2028 | for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { |
1712 | if (MIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) { | 2029 | if (MIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) { |
1713 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) | 2030 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) |
1714 | goto rtattr_failure; | 2031 | goto rtattr_failure; |
1715 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); | 2032 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); |
1716 | nhp->rtnh_flags = 0; | 2033 | nhp->rtnh_flags = 0; |
1717 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; | 2034 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; |
1718 | nhp->rtnh_ifindex = net->ipv6.vif6_table[ct].dev->ifindex; | 2035 | nhp->rtnh_ifindex = mrt->vif6_table[ct].dev->ifindex; |
1719 | nhp->rtnh_len = sizeof(*nhp); | 2036 | nhp->rtnh_len = sizeof(*nhp); |
1720 | } | 2037 | } |
1721 | } | 2038 | } |
@@ -1733,11 +2050,16 @@ int ip6mr_get_route(struct net *net, | |||
1733 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) | 2050 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) |
1734 | { | 2051 | { |
1735 | int err; | 2052 | int err; |
2053 | struct mr6_table *mrt; | ||
1736 | struct mfc6_cache *cache; | 2054 | struct mfc6_cache *cache; |
1737 | struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); | 2055 | struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); |
1738 | 2056 | ||
2057 | mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); | ||
2058 | if (mrt == NULL) | ||
2059 | return -ENOENT; | ||
2060 | |||
1739 | read_lock(&mrt_lock); | 2061 | read_lock(&mrt_lock); |
1740 | cache = ip6mr_cache_find(net, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); | 2062 | cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); |
1741 | 2063 | ||
1742 | if (!cache) { | 2064 | if (!cache) { |
1743 | struct sk_buff *skb2; | 2065 | struct sk_buff *skb2; |
@@ -1751,7 +2073,7 @@ int ip6mr_get_route(struct net *net, | |||
1751 | } | 2073 | } |
1752 | 2074 | ||
1753 | dev = skb->dev; | 2075 | dev = skb->dev; |
1754 | if (dev == NULL || (vif = ip6mr_find_vif(dev)) < 0) { | 2076 | if (dev == NULL || (vif = ip6mr_find_vif(mrt, dev)) < 0) { |
1755 | read_unlock(&mrt_lock); | 2077 | read_unlock(&mrt_lock); |
1756 | return -ENODEV; | 2078 | return -ENODEV; |
1757 | } | 2079 | } |
@@ -1780,7 +2102,7 @@ int ip6mr_get_route(struct net *net, | |||
1780 | ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr); | 2102 | ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr); |
1781 | ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr); | 2103 | ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr); |
1782 | 2104 | ||
1783 | err = ip6mr_cache_unresolved(net, vif, skb2); | 2105 | err = ip6mr_cache_unresolved(mrt, vif, skb2); |
1784 | read_unlock(&mrt_lock); | 2106 | read_unlock(&mrt_lock); |
1785 | 2107 | ||
1786 | return err; | 2108 | return err; |
@@ -1789,8 +2111,88 @@ int ip6mr_get_route(struct net *net, | |||
1789 | if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) | 2111 | if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) |
1790 | cache->mfc_flags |= MFC_NOTIFY; | 2112 | cache->mfc_flags |= MFC_NOTIFY; |
1791 | 2113 | ||
1792 | err = ip6mr_fill_mroute(skb, cache, rtm); | 2114 | err = __ip6mr_fill_mroute(mrt, skb, cache, rtm); |
1793 | read_unlock(&mrt_lock); | 2115 | read_unlock(&mrt_lock); |
1794 | return err; | 2116 | return err; |
1795 | } | 2117 | } |
1796 | 2118 | ||
2119 | static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, | ||
2120 | u32 pid, u32 seq, struct mfc6_cache *c) | ||
2121 | { | ||
2122 | struct nlmsghdr *nlh; | ||
2123 | struct rtmsg *rtm; | ||
2124 | |||
2125 | nlh = nlmsg_put(skb, pid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI); | ||
2126 | if (nlh == NULL) | ||
2127 | return -EMSGSIZE; | ||
2128 | |||
2129 | rtm = nlmsg_data(nlh); | ||
2130 | rtm->rtm_family = RTNL_FAMILY_IPMR; | ||
2131 | rtm->rtm_dst_len = 128; | ||
2132 | rtm->rtm_src_len = 128; | ||
2133 | rtm->rtm_tos = 0; | ||
2134 | rtm->rtm_table = mrt->id; | ||
2135 | NLA_PUT_U32(skb, RTA_TABLE, mrt->id); | ||
2136 | rtm->rtm_scope = RT_SCOPE_UNIVERSE; | ||
2137 | rtm->rtm_protocol = RTPROT_UNSPEC; | ||
2138 | rtm->rtm_flags = 0; | ||
2139 | |||
2140 | NLA_PUT(skb, RTA_SRC, 16, &c->mf6c_origin); | ||
2141 | NLA_PUT(skb, RTA_DST, 16, &c->mf6c_mcastgrp); | ||
2142 | |||
2143 | if (__ip6mr_fill_mroute(mrt, skb, c, rtm) < 0) | ||
2144 | goto nla_put_failure; | ||
2145 | |||
2146 | return nlmsg_end(skb, nlh); | ||
2147 | |||
2148 | nla_put_failure: | ||
2149 | nlmsg_cancel(skb, nlh); | ||
2150 | return -EMSGSIZE; | ||
2151 | } | ||
2152 | |||
2153 | static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) | ||
2154 | { | ||
2155 | struct net *net = sock_net(skb->sk); | ||
2156 | struct mr6_table *mrt; | ||
2157 | struct mfc6_cache *mfc; | ||
2158 | unsigned int t = 0, s_t; | ||
2159 | unsigned int h = 0, s_h; | ||
2160 | unsigned int e = 0, s_e; | ||
2161 | |||
2162 | s_t = cb->args[0]; | ||
2163 | s_h = cb->args[1]; | ||
2164 | s_e = cb->args[2]; | ||
2165 | |||
2166 | read_lock(&mrt_lock); | ||
2167 | ip6mr_for_each_table(mrt, net) { | ||
2168 | if (t < s_t) | ||
2169 | goto next_table; | ||
2170 | if (t > s_t) | ||
2171 | s_h = 0; | ||
2172 | for (h = s_h; h < MFC6_LINES; h++) { | ||
2173 | list_for_each_entry(mfc, &mrt->mfc6_cache_array[h], list) { | ||
2174 | if (e < s_e) | ||
2175 | goto next_entry; | ||
2176 | if (ip6mr_fill_mroute(mrt, skb, | ||
2177 | NETLINK_CB(cb->skb).pid, | ||
2178 | cb->nlh->nlmsg_seq, | ||
2179 | mfc) < 0) | ||
2180 | goto done; | ||
2181 | next_entry: | ||
2182 | e++; | ||
2183 | } | ||
2184 | e = s_e = 0; | ||
2185 | } | ||
2186 | s_h = 0; | ||
2187 | next_table: | ||
2188 | t++; | ||
2189 | } | ||
2190 | done: | ||
2191 | read_unlock(&mrt_lock); | ||
2192 | |||
2193 | cb->args[2] = e; | ||
2194 | cb->args[1] = h; | ||
2195 | cb->args[0] = t; | ||
2196 | |||
2197 | return skb->len; | ||
2198 | } | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 33f60fca7aa7..bd43f0152c21 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -114,9 +114,9 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk, | |||
114 | } | 114 | } |
115 | opt = xchg(&inet6_sk(sk)->opt, opt); | 115 | opt = xchg(&inet6_sk(sk)->opt, opt); |
116 | } else { | 116 | } else { |
117 | write_lock(&sk->sk_dst_lock); | 117 | spin_lock(&sk->sk_dst_lock); |
118 | opt = xchg(&inet6_sk(sk)->opt, opt); | 118 | opt = xchg(&inet6_sk(sk)->opt, opt); |
119 | write_unlock(&sk->sk_dst_lock); | 119 | spin_unlock(&sk->sk_dst_lock); |
120 | } | 120 | } |
121 | sk_dst_reset(sk); | 121 | sk_dst_reset(sk); |
122 | 122 | ||
@@ -337,6 +337,13 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
337 | retv = 0; | 337 | retv = 0; |
338 | break; | 338 | break; |
339 | 339 | ||
340 | case IPV6_RECVPATHMTU: | ||
341 | if (optlen < sizeof(int)) | ||
342 | goto e_inval; | ||
343 | np->rxopt.bits.rxpmtu = valbool; | ||
344 | retv = 0; | ||
345 | break; | ||
346 | |||
340 | case IPV6_HOPOPTS: | 347 | case IPV6_HOPOPTS: |
341 | case IPV6_RTHDRDSTOPTS: | 348 | case IPV6_RTHDRDSTOPTS: |
342 | case IPV6_RTHDR: | 349 | case IPV6_RTHDR: |
@@ -451,7 +458,8 @@ sticky_done: | |||
451 | msg.msg_controllen = optlen; | 458 | msg.msg_controllen = optlen; |
452 | msg.msg_control = (void*)(opt+1); | 459 | msg.msg_control = (void*)(opt+1); |
453 | 460 | ||
454 | retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk); | 461 | retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk, |
462 | &junk); | ||
455 | if (retv) | 463 | if (retv) |
456 | goto done; | 464 | goto done; |
457 | update: | 465 | update: |
@@ -767,6 +775,17 @@ pref_skip_coa: | |||
767 | 775 | ||
768 | break; | 776 | break; |
769 | } | 777 | } |
778 | case IPV6_MINHOPCOUNT: | ||
779 | if (optlen < sizeof(int)) | ||
780 | goto e_inval; | ||
781 | if (val < 0 || val > 255) | ||
782 | goto e_inval; | ||
783 | np->min_hopcount = val; | ||
784 | break; | ||
785 | case IPV6_DONTFRAG: | ||
786 | np->dontfrag = valbool; | ||
787 | retv = 0; | ||
788 | break; | ||
770 | } | 789 | } |
771 | 790 | ||
772 | release_sock(sk); | 791 | release_sock(sk); |
@@ -971,14 +990,13 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
971 | case IPV6_MTU: | 990 | case IPV6_MTU: |
972 | { | 991 | { |
973 | struct dst_entry *dst; | 992 | struct dst_entry *dst; |
993 | |||
974 | val = 0; | 994 | val = 0; |
975 | lock_sock(sk); | 995 | rcu_read_lock(); |
976 | dst = sk_dst_get(sk); | 996 | dst = __sk_dst_get(sk); |
977 | if (dst) { | 997 | if (dst) |
978 | val = dst_mtu(dst); | 998 | val = dst_mtu(dst); |
979 | dst_release(dst); | 999 | rcu_read_unlock(); |
980 | } | ||
981 | release_sock(sk); | ||
982 | if (!val) | 1000 | if (!val) |
983 | return -ENOTCONN; | 1001 | return -ENOTCONN; |
984 | break; | 1002 | break; |
@@ -1056,6 +1074,38 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1056 | val = np->rxopt.bits.rxflow; | 1074 | val = np->rxopt.bits.rxflow; |
1057 | break; | 1075 | break; |
1058 | 1076 | ||
1077 | case IPV6_RECVPATHMTU: | ||
1078 | val = np->rxopt.bits.rxpmtu; | ||
1079 | break; | ||
1080 | |||
1081 | case IPV6_PATHMTU: | ||
1082 | { | ||
1083 | struct dst_entry *dst; | ||
1084 | struct ip6_mtuinfo mtuinfo; | ||
1085 | |||
1086 | if (len < sizeof(mtuinfo)) | ||
1087 | return -EINVAL; | ||
1088 | |||
1089 | len = sizeof(mtuinfo); | ||
1090 | memset(&mtuinfo, 0, sizeof(mtuinfo)); | ||
1091 | |||
1092 | rcu_read_lock(); | ||
1093 | dst = __sk_dst_get(sk); | ||
1094 | if (dst) | ||
1095 | mtuinfo.ip6m_mtu = dst_mtu(dst); | ||
1096 | rcu_read_unlock(); | ||
1097 | if (!mtuinfo.ip6m_mtu) | ||
1098 | return -ENOTCONN; | ||
1099 | |||
1100 | if (put_user(len, optlen)) | ||
1101 | return -EFAULT; | ||
1102 | if (copy_to_user(optval, &mtuinfo, len)) | ||
1103 | return -EFAULT; | ||
1104 | |||
1105 | return 0; | ||
1106 | break; | ||
1107 | } | ||
1108 | |||
1059 | case IPV6_UNICAST_HOPS: | 1109 | case IPV6_UNICAST_HOPS: |
1060 | case IPV6_MULTICAST_HOPS: | 1110 | case IPV6_MULTICAST_HOPS: |
1061 | { | 1111 | { |
@@ -1066,12 +1116,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1066 | else | 1116 | else |
1067 | val = np->mcast_hops; | 1117 | val = np->mcast_hops; |
1068 | 1118 | ||
1069 | dst = sk_dst_get(sk); | 1119 | if (val < 0) { |
1070 | if (dst) { | 1120 | rcu_read_lock(); |
1071 | if (val < 0) | 1121 | dst = __sk_dst_get(sk); |
1122 | if (dst) | ||
1072 | val = ip6_dst_hoplimit(dst); | 1123 | val = ip6_dst_hoplimit(dst); |
1073 | dst_release(dst); | 1124 | rcu_read_unlock(); |
1074 | } | 1125 | } |
1126 | |||
1075 | if (val < 0) | 1127 | if (val < 0) |
1076 | val = sock_net(sk)->ipv6.devconf_all->hop_limit; | 1128 | val = sock_net(sk)->ipv6.devconf_all->hop_limit; |
1077 | break; | 1129 | break; |
@@ -1115,6 +1167,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1115 | val |= IPV6_PREFER_SRC_HOME; | 1167 | val |= IPV6_PREFER_SRC_HOME; |
1116 | break; | 1168 | break; |
1117 | 1169 | ||
1170 | case IPV6_MINHOPCOUNT: | ||
1171 | val = np->min_hopcount; | ||
1172 | break; | ||
1173 | |||
1174 | case IPV6_DONTFRAG: | ||
1175 | val = np->dontfrag; | ||
1176 | break; | ||
1177 | |||
1118 | default: | 1178 | default: |
1119 | return -ENOPROTOOPT; | 1179 | return -ENOPROTOOPT; |
1120 | } | 1180 | } |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index c483ab9fd67b..59f1881968c7 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/proc_fs.h> | 44 | #include <linux/proc_fs.h> |
45 | #include <linux/seq_file.h> | 45 | #include <linux/seq_file.h> |
46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
47 | #include <net/mld.h> | ||
47 | 48 | ||
48 | #include <linux/netfilter.h> | 49 | #include <linux/netfilter.h> |
49 | #include <linux/netfilter_ipv6.h> | 50 | #include <linux/netfilter_ipv6.h> |
@@ -71,54 +72,11 @@ | |||
71 | #define MDBG(x) | 72 | #define MDBG(x) |
72 | #endif | 73 | #endif |
73 | 74 | ||
74 | /* | 75 | /* Ensure that we have struct in6_addr aligned on 32bit word. */ |
75 | * These header formats should be in a separate include file, but icmpv6.h | 76 | static void *__mld2_query_bugs[] __attribute__((__unused__)) = { |
76 | * doesn't have in6_addr defined in all cases, there is no __u128, and no | 77 | BUILD_BUG_ON_NULL(offsetof(struct mld2_query, mld2q_srcs) % 4), |
77 | * other files reference these. | 78 | BUILD_BUG_ON_NULL(offsetof(struct mld2_report, mld2r_grec) % 4), |
78 | * | 79 | BUILD_BUG_ON_NULL(offsetof(struct mld2_grec, grec_mca) % 4) |
79 | * +-DLS 4/14/03 | ||
80 | */ | ||
81 | |||
82 | /* Multicast Listener Discovery version 2 headers */ | ||
83 | |||
84 | struct mld2_grec { | ||
85 | __u8 grec_type; | ||
86 | __u8 grec_auxwords; | ||
87 | __be16 grec_nsrcs; | ||
88 | struct in6_addr grec_mca; | ||
89 | struct in6_addr grec_src[0]; | ||
90 | }; | ||
91 | |||
92 | struct mld2_report { | ||
93 | __u8 type; | ||
94 | __u8 resv1; | ||
95 | __sum16 csum; | ||
96 | __be16 resv2; | ||
97 | __be16 ngrec; | ||
98 | struct mld2_grec grec[0]; | ||
99 | }; | ||
100 | |||
101 | struct mld2_query { | ||
102 | __u8 type; | ||
103 | __u8 code; | ||
104 | __sum16 csum; | ||
105 | __be16 mrc; | ||
106 | __be16 resv1; | ||
107 | struct in6_addr mca; | ||
108 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
109 | __u8 qrv:3, | ||
110 | suppress:1, | ||
111 | resv2:4; | ||
112 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
113 | __u8 resv2:4, | ||
114 | suppress:1, | ||
115 | qrv:3; | ||
116 | #else | ||
117 | #error "Please fix <asm/byteorder.h>" | ||
118 | #endif | ||
119 | __u8 qqic; | ||
120 | __be16 nsrcs; | ||
121 | struct in6_addr srcs[0]; | ||
122 | }; | 80 | }; |
123 | 81 | ||
124 | static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; | 82 | static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; |
@@ -157,14 +115,6 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | |||
157 | ((idev)->mc_v1_seen && \ | 115 | ((idev)->mc_v1_seen && \ |
158 | time_before(jiffies, (idev)->mc_v1_seen))) | 116 | time_before(jiffies, (idev)->mc_v1_seen))) |
159 | 117 | ||
160 | #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) | ||
161 | #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ | ||
162 | ((value) < (thresh) ? (value) : \ | ||
163 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ | ||
164 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) | ||
165 | |||
166 | #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) | ||
167 | |||
168 | #define IPV6_MLD_MAX_MSF 64 | 118 | #define IPV6_MLD_MAX_MSF 64 |
169 | 119 | ||
170 | int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; | 120 | int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; |
@@ -715,7 +665,7 @@ static void igmp6_group_added(struct ifmcaddr6 *mc) | |||
715 | if (!(mc->mca_flags&MAF_LOADED)) { | 665 | if (!(mc->mca_flags&MAF_LOADED)) { |
716 | mc->mca_flags |= MAF_LOADED; | 666 | mc->mca_flags |= MAF_LOADED; |
717 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) | 667 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) |
718 | dev_mc_add(dev, buf, dev->addr_len, 0); | 668 | dev_mc_add(dev, buf); |
719 | } | 669 | } |
720 | spin_unlock_bh(&mc->mca_lock); | 670 | spin_unlock_bh(&mc->mca_lock); |
721 | 671 | ||
@@ -741,7 +691,7 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc) | |||
741 | if (mc->mca_flags&MAF_LOADED) { | 691 | if (mc->mca_flags&MAF_LOADED) { |
742 | mc->mca_flags &= ~MAF_LOADED; | 692 | mc->mca_flags &= ~MAF_LOADED; |
743 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) | 693 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) |
744 | dev_mc_delete(dev, buf, dev->addr_len, 0); | 694 | dev_mc_del(dev, buf); |
745 | } | 695 | } |
746 | 696 | ||
747 | if (mc->mca_flags & MAF_NOREPORT) | 697 | if (mc->mca_flags & MAF_NOREPORT) |
@@ -1161,7 +1111,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1161 | struct in6_addr *group; | 1111 | struct in6_addr *group; |
1162 | unsigned long max_delay; | 1112 | unsigned long max_delay; |
1163 | struct inet6_dev *idev; | 1113 | struct inet6_dev *idev; |
1164 | struct icmp6hdr *hdr; | 1114 | struct mld_msg *mld; |
1165 | int group_type; | 1115 | int group_type; |
1166 | int mark = 0; | 1116 | int mark = 0; |
1167 | int len; | 1117 | int len; |
@@ -1182,8 +1132,8 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1182 | if (idev == NULL) | 1132 | if (idev == NULL) |
1183 | return 0; | 1133 | return 0; |
1184 | 1134 | ||
1185 | hdr = icmp6_hdr(skb); | 1135 | mld = (struct mld_msg *)icmp6_hdr(skb); |
1186 | group = (struct in6_addr *) (hdr + 1); | 1136 | group = &mld->mld_mca; |
1187 | group_type = ipv6_addr_type(group); | 1137 | group_type = ipv6_addr_type(group); |
1188 | 1138 | ||
1189 | if (group_type != IPV6_ADDR_ANY && | 1139 | if (group_type != IPV6_ADDR_ANY && |
@@ -1197,7 +1147,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1197 | /* MLDv1 router present */ | 1147 | /* MLDv1 router present */ |
1198 | 1148 | ||
1199 | /* Translate milliseconds to jiffies */ | 1149 | /* Translate milliseconds to jiffies */ |
1200 | max_delay = (ntohs(hdr->icmp6_maxdelay)*HZ)/1000; | 1150 | max_delay = (ntohs(mld->mld_maxdelay)*HZ)/1000; |
1201 | 1151 | ||
1202 | switchback = (idev->mc_qrv + 1) * max_delay; | 1152 | switchback = (idev->mc_qrv + 1) * max_delay; |
1203 | idev->mc_v1_seen = jiffies + switchback; | 1153 | idev->mc_v1_seen = jiffies + switchback; |
@@ -1216,14 +1166,14 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1216 | return -EINVAL; | 1166 | return -EINVAL; |
1217 | } | 1167 | } |
1218 | mlh2 = (struct mld2_query *)skb_transport_header(skb); | 1168 | mlh2 = (struct mld2_query *)skb_transport_header(skb); |
1219 | max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; | 1169 | max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000; |
1220 | if (!max_delay) | 1170 | if (!max_delay) |
1221 | max_delay = 1; | 1171 | max_delay = 1; |
1222 | idev->mc_maxdelay = max_delay; | 1172 | idev->mc_maxdelay = max_delay; |
1223 | if (mlh2->qrv) | 1173 | if (mlh2->mld2q_qrv) |
1224 | idev->mc_qrv = mlh2->qrv; | 1174 | idev->mc_qrv = mlh2->mld2q_qrv; |
1225 | if (group_type == IPV6_ADDR_ANY) { /* general query */ | 1175 | if (group_type == IPV6_ADDR_ANY) { /* general query */ |
1226 | if (mlh2->nsrcs) { | 1176 | if (mlh2->mld2q_nsrcs) { |
1227 | in6_dev_put(idev); | 1177 | in6_dev_put(idev); |
1228 | return -EINVAL; /* no sources allowed */ | 1178 | return -EINVAL; /* no sources allowed */ |
1229 | } | 1179 | } |
@@ -1232,9 +1182,9 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1232 | return 0; | 1182 | return 0; |
1233 | } | 1183 | } |
1234 | /* mark sources to include, if group & source-specific */ | 1184 | /* mark sources to include, if group & source-specific */ |
1235 | if (mlh2->nsrcs != 0) { | 1185 | if (mlh2->mld2q_nsrcs != 0) { |
1236 | if (!pskb_may_pull(skb, srcs_offset + | 1186 | if (!pskb_may_pull(skb, srcs_offset + |
1237 | ntohs(mlh2->nsrcs) * sizeof(struct in6_addr))) { | 1187 | ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) { |
1238 | in6_dev_put(idev); | 1188 | in6_dev_put(idev); |
1239 | return -EINVAL; | 1189 | return -EINVAL; |
1240 | } | 1190 | } |
@@ -1270,7 +1220,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1270 | ma->mca_flags &= ~MAF_GSQUERY; | 1220 | ma->mca_flags &= ~MAF_GSQUERY; |
1271 | } | 1221 | } |
1272 | if (!(ma->mca_flags & MAF_GSQUERY) || | 1222 | if (!(ma->mca_flags & MAF_GSQUERY) || |
1273 | mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) | 1223 | mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), mlh2->mld2q_srcs)) |
1274 | igmp6_group_queried(ma, max_delay); | 1224 | igmp6_group_queried(ma, max_delay); |
1275 | spin_unlock_bh(&ma->mca_lock); | 1225 | spin_unlock_bh(&ma->mca_lock); |
1276 | break; | 1226 | break; |
@@ -1286,9 +1236,8 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1286 | int igmp6_event_report(struct sk_buff *skb) | 1236 | int igmp6_event_report(struct sk_buff *skb) |
1287 | { | 1237 | { |
1288 | struct ifmcaddr6 *ma; | 1238 | struct ifmcaddr6 *ma; |
1289 | struct in6_addr *addrp; | ||
1290 | struct inet6_dev *idev; | 1239 | struct inet6_dev *idev; |
1291 | struct icmp6hdr *hdr; | 1240 | struct mld_msg *mld; |
1292 | int addr_type; | 1241 | int addr_type; |
1293 | 1242 | ||
1294 | /* Our own report looped back. Ignore it. */ | 1243 | /* Our own report looped back. Ignore it. */ |
@@ -1300,10 +1249,10 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1300 | skb->pkt_type != PACKET_BROADCAST) | 1249 | skb->pkt_type != PACKET_BROADCAST) |
1301 | return 0; | 1250 | return 0; |
1302 | 1251 | ||
1303 | if (!pskb_may_pull(skb, sizeof(struct in6_addr))) | 1252 | if (!pskb_may_pull(skb, sizeof(*mld) - sizeof(struct icmp6hdr))) |
1304 | return -EINVAL; | 1253 | return -EINVAL; |
1305 | 1254 | ||
1306 | hdr = icmp6_hdr(skb); | 1255 | mld = (struct mld_msg *)icmp6_hdr(skb); |
1307 | 1256 | ||
1308 | /* Drop reports with not link local source */ | 1257 | /* Drop reports with not link local source */ |
1309 | addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); | 1258 | addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); |
@@ -1311,8 +1260,6 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1311 | !(addr_type&IPV6_ADDR_LINKLOCAL)) | 1260 | !(addr_type&IPV6_ADDR_LINKLOCAL)) |
1312 | return -EINVAL; | 1261 | return -EINVAL; |
1313 | 1262 | ||
1314 | addrp = (struct in6_addr *) (hdr + 1); | ||
1315 | |||
1316 | idev = in6_dev_get(skb->dev); | 1263 | idev = in6_dev_get(skb->dev); |
1317 | if (idev == NULL) | 1264 | if (idev == NULL) |
1318 | return -ENODEV; | 1265 | return -ENODEV; |
@@ -1323,7 +1270,7 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1323 | 1270 | ||
1324 | read_lock_bh(&idev->lock); | 1271 | read_lock_bh(&idev->lock); |
1325 | for (ma = idev->mc_list; ma; ma=ma->next) { | 1272 | for (ma = idev->mc_list; ma; ma=ma->next) { |
1326 | if (ipv6_addr_equal(&ma->mca_addr, addrp)) { | 1273 | if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) { |
1327 | spin_lock(&ma->mca_lock); | 1274 | spin_lock(&ma->mca_lock); |
1328 | if (del_timer(&ma->mca_timer)) | 1275 | if (del_timer(&ma->mca_timer)) |
1329 | atomic_dec(&ma->mca_refcnt); | 1276 | atomic_dec(&ma->mca_refcnt); |
@@ -1432,11 +1379,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1432 | skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); | 1379 | skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); |
1433 | skb_put(skb, sizeof(*pmr)); | 1380 | skb_put(skb, sizeof(*pmr)); |
1434 | pmr = (struct mld2_report *)skb_transport_header(skb); | 1381 | pmr = (struct mld2_report *)skb_transport_header(skb); |
1435 | pmr->type = ICMPV6_MLD2_REPORT; | 1382 | pmr->mld2r_type = ICMPV6_MLD2_REPORT; |
1436 | pmr->resv1 = 0; | 1383 | pmr->mld2r_resv1 = 0; |
1437 | pmr->csum = 0; | 1384 | pmr->mld2r_cksum = 0; |
1438 | pmr->resv2 = 0; | 1385 | pmr->mld2r_resv2 = 0; |
1439 | pmr->ngrec = 0; | 1386 | pmr->mld2r_ngrec = 0; |
1440 | return skb; | 1387 | return skb; |
1441 | } | 1388 | } |
1442 | 1389 | ||
@@ -1458,9 +1405,10 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1458 | mldlen = skb->tail - skb->transport_header; | 1405 | mldlen = skb->tail - skb->transport_header; |
1459 | pip6->payload_len = htons(payload_len); | 1406 | pip6->payload_len = htons(payload_len); |
1460 | 1407 | ||
1461 | pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, | 1408 | pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, |
1462 | IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), | 1409 | IPPROTO_ICMPV6, |
1463 | mldlen, 0)); | 1410 | csum_partial(skb_transport_header(skb), |
1411 | mldlen, 0)); | ||
1464 | 1412 | ||
1465 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | 1413 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); |
1466 | 1414 | ||
@@ -1480,7 +1428,7 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1480 | 1428 | ||
1481 | payload_len = skb->len; | 1429 | payload_len = skb->len; |
1482 | 1430 | ||
1483 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, | 1431 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, |
1484 | dst_output); | 1432 | dst_output); |
1485 | out: | 1433 | out: |
1486 | if (!err) { | 1434 | if (!err) { |
@@ -1521,7 +1469,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1521 | pgr->grec_nsrcs = 0; | 1469 | pgr->grec_nsrcs = 0; |
1522 | pgr->grec_mca = pmc->mca_addr; /* structure copy */ | 1470 | pgr->grec_mca = pmc->mca_addr; /* structure copy */ |
1523 | pmr = (struct mld2_report *)skb_transport_header(skb); | 1471 | pmr = (struct mld2_report *)skb_transport_header(skb); |
1524 | pmr->ngrec = htons(ntohs(pmr->ngrec)+1); | 1472 | pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1); |
1525 | *ppgr = pgr; | 1473 | *ppgr = pgr; |
1526 | return skb; | 1474 | return skb; |
1527 | } | 1475 | } |
@@ -1557,7 +1505,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1557 | 1505 | ||
1558 | /* EX and TO_EX get a fresh packet, if needed */ | 1506 | /* EX and TO_EX get a fresh packet, if needed */ |
1559 | if (truncate) { | 1507 | if (truncate) { |
1560 | if (pmr && pmr->ngrec && | 1508 | if (pmr && pmr->mld2r_ngrec && |
1561 | AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { | 1509 | AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { |
1562 | if (skb) | 1510 | if (skb) |
1563 | mld_sendpack(skb); | 1511 | mld_sendpack(skb); |
@@ -1770,9 +1718,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1770 | struct sock *sk = net->ipv6.igmp_sk; | 1718 | struct sock *sk = net->ipv6.igmp_sk; |
1771 | struct inet6_dev *idev; | 1719 | struct inet6_dev *idev; |
1772 | struct sk_buff *skb; | 1720 | struct sk_buff *skb; |
1773 | struct icmp6hdr *hdr; | 1721 | struct mld_msg *hdr; |
1774 | const struct in6_addr *snd_addr, *saddr; | 1722 | const struct in6_addr *snd_addr, *saddr; |
1775 | struct in6_addr *addrp; | ||
1776 | struct in6_addr addr_buf; | 1723 | struct in6_addr addr_buf; |
1777 | int err, len, payload_len, full_len; | 1724 | int err, len, payload_len, full_len; |
1778 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1725 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
@@ -1820,16 +1767,14 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1820 | 1767 | ||
1821 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); | 1768 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); |
1822 | 1769 | ||
1823 | hdr = (struct icmp6hdr *) skb_put(skb, sizeof(struct icmp6hdr)); | 1770 | hdr = (struct mld_msg *) skb_put(skb, sizeof(struct mld_msg)); |
1824 | memset(hdr, 0, sizeof(struct icmp6hdr)); | 1771 | memset(hdr, 0, sizeof(struct mld_msg)); |
1825 | hdr->icmp6_type = type; | 1772 | hdr->mld_type = type; |
1773 | ipv6_addr_copy(&hdr->mld_mca, addr); | ||
1826 | 1774 | ||
1827 | addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); | 1775 | hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len, |
1828 | ipv6_addr_copy(addrp, addr); | 1776 | IPPROTO_ICMPV6, |
1829 | 1777 | csum_partial(hdr, len, 0)); | |
1830 | hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len, | ||
1831 | IPPROTO_ICMPV6, | ||
1832 | csum_partial(hdr, len, 0)); | ||
1833 | 1778 | ||
1834 | idev = in6_dev_get(skb->dev); | 1779 | idev = in6_dev_get(skb->dev); |
1835 | 1780 | ||
@@ -1848,7 +1793,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1848 | goto err_out; | 1793 | goto err_out; |
1849 | 1794 | ||
1850 | skb_dst_set(skb, dst); | 1795 | skb_dst_set(skb, dst); |
1851 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, | 1796 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, |
1852 | dst_output); | 1797 | dst_output); |
1853 | out: | 1798 | out: |
1854 | if (!err) { | 1799 | if (!err) { |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index da0a4d2adc69..0abdc242ddb7 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -536,7 +536,7 @@ void ndisc_send_skb(struct sk_buff *skb, | |||
536 | idev = in6_dev_get(dst->dev); | 536 | idev = in6_dev_get(dst->dev); |
537 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | 537 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); |
538 | 538 | ||
539 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, | 539 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, |
540 | dst_output); | 540 | dst_output); |
541 | if (!err) { | 541 | if (!err) { |
542 | ICMP6MSGOUT_INC_STATS(net, idev, type); | 542 | ICMP6MSGOUT_INC_STATS(net, idev, type); |
@@ -890,8 +890,6 @@ out: | |||
890 | in6_ifa_put(ifp); | 890 | in6_ifa_put(ifp); |
891 | else | 891 | else |
892 | in6_dev_put(idev); | 892 | in6_dev_put(idev); |
893 | |||
894 | return; | ||
895 | } | 893 | } |
896 | 894 | ||
897 | static void ndisc_recv_na(struct sk_buff *skb) | 895 | static void ndisc_recv_na(struct sk_buff *skb) |
@@ -1618,7 +1616,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1618 | skb_dst_set(buff, dst); | 1616 | skb_dst_set(buff, dst); |
1619 | idev = in6_dev_get(dst->dev); | 1617 | idev = in6_dev_get(dst->dev); |
1620 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | 1618 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); |
1621 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, | 1619 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, |
1622 | dst_output); | 1620 | dst_output); |
1623 | if (!err) { | 1621 | if (!err) { |
1624 | ICMP6MSGOUT_INC_STATS(net, idev, NDISC_REDIRECT); | 1622 | ICMP6MSGOUT_INC_STATS(net, idev, NDISC_REDIRECT); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index d5ed92b14346..a74951c039b6 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -25,20 +25,6 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | dst = ip6_route_output(net, skb->sk, &fl); | 27 | dst = ip6_route_output(net, skb->sk, &fl); |
28 | |||
29 | #ifdef CONFIG_XFRM | ||
30 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | ||
31 | xfrm_decode_session(skb, &fl, AF_INET6) == 0) { | ||
32 | struct dst_entry *dst2 = skb_dst(skb); | ||
33 | |||
34 | if (xfrm_lookup(net, &dst2, &fl, skb->sk, 0)) { | ||
35 | skb_dst_set(skb, NULL); | ||
36 | return -1; | ||
37 | } | ||
38 | skb_dst_set(skb, dst2); | ||
39 | } | ||
40 | #endif | ||
41 | |||
42 | if (dst->error) { | 28 | if (dst->error) { |
43 | IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | 29 | IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
44 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); | 30 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); |
@@ -50,6 +36,17 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
50 | skb_dst_drop(skb); | 36 | skb_dst_drop(skb); |
51 | 37 | ||
52 | skb_dst_set(skb, dst); | 38 | skb_dst_set(skb, dst); |
39 | |||
40 | #ifdef CONFIG_XFRM | ||
41 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | ||
42 | xfrm_decode_session(skb, &fl, AF_INET6) == 0) { | ||
43 | skb_dst_set(skb, NULL); | ||
44 | if (xfrm_lookup(net, &dst, &fl, skb->sk, 0)) | ||
45 | return -1; | ||
46 | skb_dst_set(skb, dst); | ||
47 | } | ||
48 | #endif | ||
49 | |||
53 | return 0; | 50 | return 0; |
54 | } | 51 | } |
55 | EXPORT_SYMBOL(ip6_route_me_harder); | 52 | EXPORT_SYMBOL(ip6_route_me_harder); |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 6a68a74d14a3..8c201743d96d 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -162,8 +162,7 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
162 | break; | 162 | break; |
163 | 163 | ||
164 | case IPQ_COPY_PACKET: | 164 | case IPQ_COPY_PACKET: |
165 | if ((entry->skb->ip_summed == CHECKSUM_PARTIAL || | 165 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && |
166 | entry->skb->ip_summed == CHECKSUM_COMPLETE) && | ||
167 | (*errp = skb_checksum_help(entry->skb))) { | 166 | (*errp = skb_checksum_help(entry->skb))) { |
168 | read_unlock_bh(&queue_lock); | 167 | read_unlock_bh(&queue_lock); |
169 | return NULL; | 168 | return NULL; |
@@ -463,7 +462,6 @@ __ipq_rcv_skb(struct sk_buff *skb) | |||
463 | 462 | ||
464 | if (flags & NLM_F_ACK) | 463 | if (flags & NLM_F_ACK) |
465 | netlink_ack(skb, nlh, 0); | 464 | netlink_ack(skb, nlh, 0); |
466 | return; | ||
467 | } | 465 | } |
468 | 466 | ||
469 | static void | 467 | static void |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 9210e312edf1..6f517bd83692 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -40,24 +40,19 @@ MODULE_DESCRIPTION("IPv6 packet filter"); | |||
40 | /*#define DEBUG_IP_FIREWALL_USER*/ | 40 | /*#define DEBUG_IP_FIREWALL_USER*/ |
41 | 41 | ||
42 | #ifdef DEBUG_IP_FIREWALL | 42 | #ifdef DEBUG_IP_FIREWALL |
43 | #define dprintf(format, args...) printk(format , ## args) | 43 | #define dprintf(format, args...) pr_info(format , ## args) |
44 | #else | 44 | #else |
45 | #define dprintf(format, args...) | 45 | #define dprintf(format, args...) |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #ifdef DEBUG_IP_FIREWALL_USER | 48 | #ifdef DEBUG_IP_FIREWALL_USER |
49 | #define duprintf(format, args...) printk(format , ## args) | 49 | #define duprintf(format, args...) pr_info(format , ## args) |
50 | #else | 50 | #else |
51 | #define duprintf(format, args...) | 51 | #define duprintf(format, args...) |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | #ifdef CONFIG_NETFILTER_DEBUG | 54 | #ifdef CONFIG_NETFILTER_DEBUG |
55 | #define IP_NF_ASSERT(x) \ | 55 | #define IP_NF_ASSERT(x) WARN_ON(!(x)) |
56 | do { \ | ||
57 | if (!(x)) \ | ||
58 | printk("IP_NF_ASSERT: %s:%s:%u\n", \ | ||
59 | __func__, __FILE__, __LINE__); \ | ||
60 | } while(0) | ||
61 | #else | 56 | #else |
62 | #define IP_NF_ASSERT(x) | 57 | #define IP_NF_ASSERT(x) |
63 | #endif | 58 | #endif |
@@ -197,30 +192,14 @@ ip6_checkentry(const struct ip6t_ip6 *ipv6) | |||
197 | } | 192 | } |
198 | 193 | ||
199 | static unsigned int | 194 | static unsigned int |
200 | ip6t_error(struct sk_buff *skb, const struct xt_target_param *par) | 195 | ip6t_error(struct sk_buff *skb, const struct xt_action_param *par) |
201 | { | 196 | { |
202 | if (net_ratelimit()) | 197 | if (net_ratelimit()) |
203 | printk("ip6_tables: error: `%s'\n", | 198 | pr_info("error: `%s'\n", (const char *)par->targinfo); |
204 | (const char *)par->targinfo); | ||
205 | 199 | ||
206 | return NF_DROP; | 200 | return NF_DROP; |
207 | } | 201 | } |
208 | 202 | ||
209 | /* Performance critical - called for every packet */ | ||
210 | static inline bool | ||
211 | do_match(const struct ip6t_entry_match *m, const struct sk_buff *skb, | ||
212 | struct xt_match_param *par) | ||
213 | { | ||
214 | par->match = m->u.kernel.match; | ||
215 | par->matchinfo = m->data; | ||
216 | |||
217 | /* Stop iteration if it doesn't match */ | ||
218 | if (!m->u.kernel.match->match(skb, par)) | ||
219 | return true; | ||
220 | else | ||
221 | return false; | ||
222 | } | ||
223 | |||
224 | static inline struct ip6t_entry * | 203 | static inline struct ip6t_entry * |
225 | get_entry(const void *base, unsigned int offset) | 204 | get_entry(const void *base, unsigned int offset) |
226 | { | 205 | { |
@@ -352,18 +331,15 @@ ip6t_do_table(struct sk_buff *skb, | |||
352 | const struct net_device *out, | 331 | const struct net_device *out, |
353 | struct xt_table *table) | 332 | struct xt_table *table) |
354 | { | 333 | { |
355 | #define tb_comefrom ((struct ip6t_entry *)table_base)->comefrom | ||
356 | |||
357 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 334 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
358 | bool hotdrop = false; | ||
359 | /* Initializing verdict to NF_DROP keeps gcc happy. */ | 335 | /* Initializing verdict to NF_DROP keeps gcc happy. */ |
360 | unsigned int verdict = NF_DROP; | 336 | unsigned int verdict = NF_DROP; |
361 | const char *indev, *outdev; | 337 | const char *indev, *outdev; |
362 | const void *table_base; | 338 | const void *table_base; |
363 | struct ip6t_entry *e, *back; | 339 | struct ip6t_entry *e, **jumpstack; |
340 | unsigned int *stackptr, origptr, cpu; | ||
364 | const struct xt_table_info *private; | 341 | const struct xt_table_info *private; |
365 | struct xt_match_param mtpar; | 342 | struct xt_action_param acpar; |
366 | struct xt_target_param tgpar; | ||
367 | 343 | ||
368 | /* Initialization */ | 344 | /* Initialization */ |
369 | indev = in ? in->name : nulldevname; | 345 | indev = in ? in->name : nulldevname; |
@@ -374,39 +350,42 @@ ip6t_do_table(struct sk_buff *skb, | |||
374 | * things we don't know, ie. tcp syn flag or ports). If the | 350 | * things we don't know, ie. tcp syn flag or ports). If the |
375 | * rule is also a fragment-specific rule, non-fragments won't | 351 | * rule is also a fragment-specific rule, non-fragments won't |
376 | * match it. */ | 352 | * match it. */ |
377 | mtpar.hotdrop = &hotdrop; | 353 | acpar.hotdrop = false; |
378 | mtpar.in = tgpar.in = in; | 354 | acpar.in = in; |
379 | mtpar.out = tgpar.out = out; | 355 | acpar.out = out; |
380 | mtpar.family = tgpar.family = NFPROTO_IPV6; | 356 | acpar.family = NFPROTO_IPV6; |
381 | mtpar.hooknum = tgpar.hooknum = hook; | 357 | acpar.hooknum = hook; |
382 | 358 | ||
383 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 359 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
384 | 360 | ||
385 | xt_info_rdlock_bh(); | 361 | xt_info_rdlock_bh(); |
386 | private = table->private; | 362 | private = table->private; |
387 | table_base = private->entries[smp_processor_id()]; | 363 | cpu = smp_processor_id(); |
364 | table_base = private->entries[cpu]; | ||
365 | jumpstack = (struct ip6t_entry **)private->jumpstack[cpu]; | ||
366 | stackptr = &private->stackptr[cpu]; | ||
367 | origptr = *stackptr; | ||
388 | 368 | ||
389 | e = get_entry(table_base, private->hook_entry[hook]); | 369 | e = get_entry(table_base, private->hook_entry[hook]); |
390 | 370 | ||
391 | /* For return from builtin chain */ | ||
392 | back = get_entry(table_base, private->underflow[hook]); | ||
393 | |||
394 | do { | 371 | do { |
395 | const struct ip6t_entry_target *t; | 372 | const struct ip6t_entry_target *t; |
396 | const struct xt_entry_match *ematch; | 373 | const struct xt_entry_match *ematch; |
397 | 374 | ||
398 | IP_NF_ASSERT(e); | 375 | IP_NF_ASSERT(e); |
399 | IP_NF_ASSERT(back); | ||
400 | if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, | 376 | if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, |
401 | &mtpar.thoff, &mtpar.fragoff, &hotdrop)) { | 377 | &acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) { |
402 | no_match: | 378 | no_match: |
403 | e = ip6t_next_entry(e); | 379 | e = ip6t_next_entry(e); |
404 | continue; | 380 | continue; |
405 | } | 381 | } |
406 | 382 | ||
407 | xt_ematch_foreach(ematch, e) | 383 | xt_ematch_foreach(ematch, e) { |
408 | if (do_match(ematch, skb, &mtpar) != 0) | 384 | acpar.match = ematch->u.kernel.match; |
385 | acpar.matchinfo = ematch->data; | ||
386 | if (!acpar.match->match(skb, &acpar)) | ||
409 | goto no_match; | 387 | goto no_match; |
388 | } | ||
410 | 389 | ||
411 | ADD_COUNTER(e->counters, | 390 | ADD_COUNTER(e->counters, |
412 | ntohs(ipv6_hdr(skb)->payload_len) + | 391 | ntohs(ipv6_hdr(skb)->payload_len) + |
@@ -433,62 +412,47 @@ ip6t_do_table(struct sk_buff *skb, | |||
433 | verdict = (unsigned)(-v) - 1; | 412 | verdict = (unsigned)(-v) - 1; |
434 | break; | 413 | break; |
435 | } | 414 | } |
436 | e = back; | 415 | if (*stackptr == 0) |
437 | back = get_entry(table_base, back->comefrom); | 416 | e = get_entry(table_base, |
417 | private->underflow[hook]); | ||
418 | else | ||
419 | e = ip6t_next_entry(jumpstack[--*stackptr]); | ||
438 | continue; | 420 | continue; |
439 | } | 421 | } |
440 | if (table_base + v != ip6t_next_entry(e) && | 422 | if (table_base + v != ip6t_next_entry(e) && |
441 | !(e->ipv6.flags & IP6T_F_GOTO)) { | 423 | !(e->ipv6.flags & IP6T_F_GOTO)) { |
442 | /* Save old back ptr in next entry */ | 424 | if (*stackptr >= private->stacksize) { |
443 | struct ip6t_entry *next = ip6t_next_entry(e); | 425 | verdict = NF_DROP; |
444 | next->comefrom = (void *)back - table_base; | 426 | break; |
445 | /* set back pointer to next entry */ | 427 | } |
446 | back = next; | 428 | jumpstack[(*stackptr)++] = e; |
447 | } | 429 | } |
448 | 430 | ||
449 | e = get_entry(table_base, v); | 431 | e = get_entry(table_base, v); |
450 | continue; | 432 | continue; |
451 | } | 433 | } |
452 | 434 | ||
453 | /* Targets which reenter must return | 435 | acpar.target = t->u.kernel.target; |
454 | abs. verdicts */ | 436 | acpar.targinfo = t->data; |
455 | tgpar.target = t->u.kernel.target; | ||
456 | tgpar.targinfo = t->data; | ||
457 | |||
458 | #ifdef CONFIG_NETFILTER_DEBUG | ||
459 | tb_comefrom = 0xeeeeeeec; | ||
460 | #endif | ||
461 | verdict = t->u.kernel.target->target(skb, &tgpar); | ||
462 | 437 | ||
463 | #ifdef CONFIG_NETFILTER_DEBUG | 438 | verdict = t->u.kernel.target->target(skb, &acpar); |
464 | if (tb_comefrom != 0xeeeeeeec && verdict == IP6T_CONTINUE) { | ||
465 | printk("Target %s reentered!\n", | ||
466 | t->u.kernel.target->name); | ||
467 | verdict = NF_DROP; | ||
468 | } | ||
469 | tb_comefrom = 0x57acc001; | ||
470 | #endif | ||
471 | if (verdict == IP6T_CONTINUE) | 439 | if (verdict == IP6T_CONTINUE) |
472 | e = ip6t_next_entry(e); | 440 | e = ip6t_next_entry(e); |
473 | else | 441 | else |
474 | /* Verdict */ | 442 | /* Verdict */ |
475 | break; | 443 | break; |
476 | } while (!hotdrop); | 444 | } while (!acpar.hotdrop); |
477 | 445 | ||
478 | #ifdef CONFIG_NETFILTER_DEBUG | ||
479 | tb_comefrom = NETFILTER_LINK_POISON; | ||
480 | #endif | ||
481 | xt_info_rdunlock_bh(); | 446 | xt_info_rdunlock_bh(); |
447 | *stackptr = origptr; | ||
482 | 448 | ||
483 | #ifdef DEBUG_ALLOW_ALL | 449 | #ifdef DEBUG_ALLOW_ALL |
484 | return NF_ACCEPT; | 450 | return NF_ACCEPT; |
485 | #else | 451 | #else |
486 | if (hotdrop) | 452 | if (acpar.hotdrop) |
487 | return NF_DROP; | 453 | return NF_DROP; |
488 | else return verdict; | 454 | else return verdict; |
489 | #endif | 455 | #endif |
490 | |||
491 | #undef tb_comefrom | ||
492 | } | 456 | } |
493 | 457 | ||
494 | /* Figures out from what hook each rule can be called: returns 0 if | 458 | /* Figures out from what hook each rule can be called: returns 0 if |
@@ -517,7 +481,7 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
517 | int visited = e->comefrom & (1 << hook); | 481 | int visited = e->comefrom & (1 << hook); |
518 | 482 | ||
519 | if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { | 483 | if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { |
520 | printk("iptables: loop hook %u pos %u %08X.\n", | 484 | pr_err("iptables: loop hook %u pos %u %08X.\n", |
521 | hook, pos, e->comefrom); | 485 | hook, pos, e->comefrom); |
522 | return 0; | 486 | return 0; |
523 | } | 487 | } |
@@ -661,12 +625,11 @@ find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) | |||
661 | struct xt_match *match; | 625 | struct xt_match *match; |
662 | int ret; | 626 | int ret; |
663 | 627 | ||
664 | match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, | 628 | match = xt_request_find_match(NFPROTO_IPV6, m->u.user.name, |
665 | m->u.user.revision), | 629 | m->u.user.revision); |
666 | "ip6t_%s", m->u.user.name); | 630 | if (IS_ERR(match)) { |
667 | if (IS_ERR(match) || !match) { | ||
668 | duprintf("find_check_match: `%s' not found\n", m->u.user.name); | 631 | duprintf("find_check_match: `%s' not found\n", m->u.user.name); |
669 | return match ? PTR_ERR(match) : -ENOENT; | 632 | return PTR_ERR(match); |
670 | } | 633 | } |
671 | m->u.kernel.match = match; | 634 | m->u.kernel.match = match; |
672 | 635 | ||
@@ -734,13 +697,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | |||
734 | } | 697 | } |
735 | 698 | ||
736 | t = ip6t_get_target(e); | 699 | t = ip6t_get_target(e); |
737 | target = try_then_request_module(xt_find_target(AF_INET6, | 700 | target = xt_request_find_target(NFPROTO_IPV6, t->u.user.name, |
738 | t->u.user.name, | 701 | t->u.user.revision); |
739 | t->u.user.revision), | 702 | if (IS_ERR(target)) { |
740 | "ip6t_%s", t->u.user.name); | ||
741 | if (IS_ERR(target) || !target) { | ||
742 | duprintf("find_check_entry: `%s' not found\n", t->u.user.name); | 703 | duprintf("find_check_entry: `%s' not found\n", t->u.user.name); |
743 | ret = target ? PTR_ERR(target) : -ENOENT; | 704 | ret = PTR_ERR(target); |
744 | goto cleanup_matches; | 705 | goto cleanup_matches; |
745 | } | 706 | } |
746 | t->u.kernel.target = target; | 707 | t->u.kernel.target = target; |
@@ -873,6 +834,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, | |||
873 | if (ret != 0) | 834 | if (ret != 0) |
874 | return ret; | 835 | return ret; |
875 | ++i; | 836 | ++i; |
837 | if (strcmp(ip6t_get_target(iter)->u.user.name, | ||
838 | XT_ERROR_TARGET) == 0) | ||
839 | ++newinfo->stacksize; | ||
876 | } | 840 | } |
877 | 841 | ||
878 | if (i != repl->num_entries) { | 842 | if (i != repl->num_entries) { |
@@ -1509,13 +1473,12 @@ compat_find_calc_match(struct ip6t_entry_match *m, | |||
1509 | { | 1473 | { |
1510 | struct xt_match *match; | 1474 | struct xt_match *match; |
1511 | 1475 | ||
1512 | match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, | 1476 | match = xt_request_find_match(NFPROTO_IPV6, m->u.user.name, |
1513 | m->u.user.revision), | 1477 | m->u.user.revision); |
1514 | "ip6t_%s", m->u.user.name); | 1478 | if (IS_ERR(match)) { |
1515 | if (IS_ERR(match) || !match) { | ||
1516 | duprintf("compat_check_calc_match: `%s' not found\n", | 1479 | duprintf("compat_check_calc_match: `%s' not found\n", |
1517 | m->u.user.name); | 1480 | m->u.user.name); |
1518 | return match ? PTR_ERR(match) : -ENOENT; | 1481 | return PTR_ERR(match); |
1519 | } | 1482 | } |
1520 | m->u.kernel.match = match; | 1483 | m->u.kernel.match = match; |
1521 | *size += xt_compat_match_offset(match); | 1484 | *size += xt_compat_match_offset(match); |
@@ -1582,14 +1545,12 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1582 | } | 1545 | } |
1583 | 1546 | ||
1584 | t = compat_ip6t_get_target(e); | 1547 | t = compat_ip6t_get_target(e); |
1585 | target = try_then_request_module(xt_find_target(AF_INET6, | 1548 | target = xt_request_find_target(NFPROTO_IPV6, t->u.user.name, |
1586 | t->u.user.name, | 1549 | t->u.user.revision); |
1587 | t->u.user.revision), | 1550 | if (IS_ERR(target)) { |
1588 | "ip6t_%s", t->u.user.name); | ||
1589 | if (IS_ERR(target) || !target) { | ||
1590 | duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", | 1551 | duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", |
1591 | t->u.user.name); | 1552 | t->u.user.name); |
1592 | ret = target ? PTR_ERR(target) : -ENOENT; | 1553 | ret = PTR_ERR(target); |
1593 | goto release_matches; | 1554 | goto release_matches; |
1594 | } | 1555 | } |
1595 | t->u.kernel.target = target; | 1556 | t->u.kernel.target = target; |
@@ -2127,8 +2088,7 @@ struct xt_table *ip6t_register_table(struct net *net, | |||
2127 | { | 2088 | { |
2128 | int ret; | 2089 | int ret; |
2129 | struct xt_table_info *newinfo; | 2090 | struct xt_table_info *newinfo; |
2130 | struct xt_table_info bootstrap | 2091 | struct xt_table_info bootstrap = {0}; |
2131 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | ||
2132 | void *loc_cpu_entry; | 2092 | void *loc_cpu_entry; |
2133 | struct xt_table *new_table; | 2093 | struct xt_table *new_table; |
2134 | 2094 | ||
@@ -2188,7 +2148,7 @@ icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, | |||
2188 | } | 2148 | } |
2189 | 2149 | ||
2190 | static bool | 2150 | static bool |
2191 | icmp6_match(const struct sk_buff *skb, const struct xt_match_param *par) | 2151 | icmp6_match(const struct sk_buff *skb, struct xt_action_param *par) |
2192 | { | 2152 | { |
2193 | const struct icmp6hdr *ic; | 2153 | const struct icmp6hdr *ic; |
2194 | struct icmp6hdr _icmph; | 2154 | struct icmp6hdr _icmph; |
@@ -2204,7 +2164,7 @@ icmp6_match(const struct sk_buff *skb, const struct xt_match_param *par) | |||
2204 | * can't. Hence, no choice but to drop. | 2164 | * can't. Hence, no choice but to drop. |
2205 | */ | 2165 | */ |
2206 | duprintf("Dropping evil ICMP tinygram.\n"); | 2166 | duprintf("Dropping evil ICMP tinygram.\n"); |
2207 | *par->hotdrop = true; | 2167 | par->hotdrop = true; |
2208 | return false; | 2168 | return false; |
2209 | } | 2169 | } |
2210 | 2170 | ||
@@ -2216,31 +2176,32 @@ icmp6_match(const struct sk_buff *skb, const struct xt_match_param *par) | |||
2216 | } | 2176 | } |
2217 | 2177 | ||
2218 | /* Called when user tries to insert an entry of this type. */ | 2178 | /* Called when user tries to insert an entry of this type. */ |
2219 | static bool icmp6_checkentry(const struct xt_mtchk_param *par) | 2179 | static int icmp6_checkentry(const struct xt_mtchk_param *par) |
2220 | { | 2180 | { |
2221 | const struct ip6t_icmp *icmpinfo = par->matchinfo; | 2181 | const struct ip6t_icmp *icmpinfo = par->matchinfo; |
2222 | 2182 | ||
2223 | /* Must specify no unknown invflags */ | 2183 | /* Must specify no unknown invflags */ |
2224 | return !(icmpinfo->invflags & ~IP6T_ICMP_INV); | 2184 | return (icmpinfo->invflags & ~IP6T_ICMP_INV) ? -EINVAL : 0; |
2225 | } | 2185 | } |
2226 | 2186 | ||
2227 | /* The built-in targets: standard (NULL) and error. */ | 2187 | /* The built-in targets: standard (NULL) and error. */ |
2228 | static struct xt_target ip6t_standard_target __read_mostly = { | 2188 | static struct xt_target ip6t_builtin_tg[] __read_mostly = { |
2229 | .name = IP6T_STANDARD_TARGET, | 2189 | { |
2230 | .targetsize = sizeof(int), | 2190 | .name = IP6T_STANDARD_TARGET, |
2231 | .family = NFPROTO_IPV6, | 2191 | .targetsize = sizeof(int), |
2192 | .family = NFPROTO_IPV6, | ||
2232 | #ifdef CONFIG_COMPAT | 2193 | #ifdef CONFIG_COMPAT |
2233 | .compatsize = sizeof(compat_int_t), | 2194 | .compatsize = sizeof(compat_int_t), |
2234 | .compat_from_user = compat_standard_from_user, | 2195 | .compat_from_user = compat_standard_from_user, |
2235 | .compat_to_user = compat_standard_to_user, | 2196 | .compat_to_user = compat_standard_to_user, |
2236 | #endif | 2197 | #endif |
2237 | }; | 2198 | }, |
2238 | 2199 | { | |
2239 | static struct xt_target ip6t_error_target __read_mostly = { | 2200 | .name = IP6T_ERROR_TARGET, |
2240 | .name = IP6T_ERROR_TARGET, | 2201 | .target = ip6t_error, |
2241 | .target = ip6t_error, | 2202 | .targetsize = IP6T_FUNCTION_MAXNAMELEN, |
2242 | .targetsize = IP6T_FUNCTION_MAXNAMELEN, | 2203 | .family = NFPROTO_IPV6, |
2243 | .family = NFPROTO_IPV6, | 2204 | }, |
2244 | }; | 2205 | }; |
2245 | 2206 | ||
2246 | static struct nf_sockopt_ops ip6t_sockopts = { | 2207 | static struct nf_sockopt_ops ip6t_sockopts = { |
@@ -2260,13 +2221,15 @@ static struct nf_sockopt_ops ip6t_sockopts = { | |||
2260 | .owner = THIS_MODULE, | 2221 | .owner = THIS_MODULE, |
2261 | }; | 2222 | }; |
2262 | 2223 | ||
2263 | static struct xt_match icmp6_matchstruct __read_mostly = { | 2224 | static struct xt_match ip6t_builtin_mt[] __read_mostly = { |
2264 | .name = "icmp6", | 2225 | { |
2265 | .match = icmp6_match, | 2226 | .name = "icmp6", |
2266 | .matchsize = sizeof(struct ip6t_icmp), | 2227 | .match = icmp6_match, |
2267 | .checkentry = icmp6_checkentry, | 2228 | .matchsize = sizeof(struct ip6t_icmp), |
2268 | .proto = IPPROTO_ICMPV6, | 2229 | .checkentry = icmp6_checkentry, |
2269 | .family = NFPROTO_IPV6, | 2230 | .proto = IPPROTO_ICMPV6, |
2231 | .family = NFPROTO_IPV6, | ||
2232 | }, | ||
2270 | }; | 2233 | }; |
2271 | 2234 | ||
2272 | static int __net_init ip6_tables_net_init(struct net *net) | 2235 | static int __net_init ip6_tables_net_init(struct net *net) |
@@ -2293,13 +2256,10 @@ static int __init ip6_tables_init(void) | |||
2293 | goto err1; | 2256 | goto err1; |
2294 | 2257 | ||
2295 | /* Noone else will be downing sem now, so we won't sleep */ | 2258 | /* Noone else will be downing sem now, so we won't sleep */ |
2296 | ret = xt_register_target(&ip6t_standard_target); | 2259 | ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); |
2297 | if (ret < 0) | 2260 | if (ret < 0) |
2298 | goto err2; | 2261 | goto err2; |
2299 | ret = xt_register_target(&ip6t_error_target); | 2262 | ret = xt_register_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt)); |
2300 | if (ret < 0) | ||
2301 | goto err3; | ||
2302 | ret = xt_register_match(&icmp6_matchstruct); | ||
2303 | if (ret < 0) | 2263 | if (ret < 0) |
2304 | goto err4; | 2264 | goto err4; |
2305 | 2265 | ||
@@ -2308,15 +2268,13 @@ static int __init ip6_tables_init(void) | |||
2308 | if (ret < 0) | 2268 | if (ret < 0) |
2309 | goto err5; | 2269 | goto err5; |
2310 | 2270 | ||
2311 | printk(KERN_INFO "ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); | 2271 | pr_info("(C) 2000-2006 Netfilter Core Team\n"); |
2312 | return 0; | 2272 | return 0; |
2313 | 2273 | ||
2314 | err5: | 2274 | err5: |
2315 | xt_unregister_match(&icmp6_matchstruct); | 2275 | xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt)); |
2316 | err4: | 2276 | err4: |
2317 | xt_unregister_target(&ip6t_error_target); | 2277 | xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); |
2318 | err3: | ||
2319 | xt_unregister_target(&ip6t_standard_target); | ||
2320 | err2: | 2278 | err2: |
2321 | unregister_pernet_subsys(&ip6_tables_net_ops); | 2279 | unregister_pernet_subsys(&ip6_tables_net_ops); |
2322 | err1: | 2280 | err1: |
@@ -2327,10 +2285,8 @@ static void __exit ip6_tables_fini(void) | |||
2327 | { | 2285 | { |
2328 | nf_unregister_sockopt(&ip6t_sockopts); | 2286 | nf_unregister_sockopt(&ip6t_sockopts); |
2329 | 2287 | ||
2330 | xt_unregister_match(&icmp6_matchstruct); | 2288 | xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt)); |
2331 | xt_unregister_target(&ip6t_error_target); | 2289 | xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); |
2332 | xt_unregister_target(&ip6t_standard_target); | ||
2333 | |||
2334 | unregister_pernet_subsys(&ip6_tables_net_ops); | 2290 | unregister_pernet_subsys(&ip6_tables_net_ops); |
2335 | } | 2291 | } |
2336 | 2292 | ||
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index b285fdf19050..af4ee11f2066 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -9,9 +9,8 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
16 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
17 | #include <linux/ip.h> | 16 | #include <linux/ip.h> |
@@ -378,7 +377,7 @@ static struct nf_loginfo default_loginfo = { | |||
378 | .type = NF_LOG_TYPE_LOG, | 377 | .type = NF_LOG_TYPE_LOG, |
379 | .u = { | 378 | .u = { |
380 | .log = { | 379 | .log = { |
381 | .level = 0, | 380 | .level = 5, |
382 | .logflags = NF_LOG_MASK, | 381 | .logflags = NF_LOG_MASK, |
383 | }, | 382 | }, |
384 | }, | 383 | }, |
@@ -437,7 +436,7 @@ ip6t_log_packet(u_int8_t pf, | |||
437 | } | 436 | } |
438 | 437 | ||
439 | static unsigned int | 438 | static unsigned int |
440 | log_tg6(struct sk_buff *skb, const struct xt_target_param *par) | 439 | log_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
441 | { | 440 | { |
442 | const struct ip6t_log_info *loginfo = par->targinfo; | 441 | const struct ip6t_log_info *loginfo = par->targinfo; |
443 | struct nf_loginfo li; | 442 | struct nf_loginfo li; |
@@ -452,20 +451,19 @@ log_tg6(struct sk_buff *skb, const struct xt_target_param *par) | |||
452 | } | 451 | } |
453 | 452 | ||
454 | 453 | ||
455 | static bool log_tg6_check(const struct xt_tgchk_param *par) | 454 | static int log_tg6_check(const struct xt_tgchk_param *par) |
456 | { | 455 | { |
457 | const struct ip6t_log_info *loginfo = par->targinfo; | 456 | const struct ip6t_log_info *loginfo = par->targinfo; |
458 | 457 | ||
459 | if (loginfo->level >= 8) { | 458 | if (loginfo->level >= 8) { |
460 | pr_debug("LOG: level %u >= 8\n", loginfo->level); | 459 | pr_debug("level %u >= 8\n", loginfo->level); |
461 | return false; | 460 | return -EINVAL; |
462 | } | 461 | } |
463 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { | 462 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { |
464 | pr_debug("LOG: prefix term %i\n", | 463 | pr_debug("prefix not null-terminated\n"); |
465 | loginfo->prefix[sizeof(loginfo->prefix)-1]); | 464 | return -EINVAL; |
466 | return false; | ||
467 | } | 465 | } |
468 | return true; | 466 | return 0; |
469 | } | 467 | } |
470 | 468 | ||
471 | static struct xt_target log_tg6_reg __read_mostly = { | 469 | static struct xt_target log_tg6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 39b50c3768e8..47d227713758 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * as published by the Free Software Foundation; either version | 14 | * as published by the Free Software Foundation; either version |
15 | * 2 of the License, or (at your option) any later version. | 15 | * 2 of the License, or (at your option) any later version. |
16 | */ | 16 | */ |
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
17 | 18 | ||
18 | #include <linux/gfp.h> | 19 | #include <linux/gfp.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
@@ -50,7 +51,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
50 | 51 | ||
51 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | 52 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || |
52 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | 53 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { |
53 | pr_debug("ip6t_REJECT: addr is not unicast.\n"); | 54 | pr_debug("addr is not unicast.\n"); |
54 | return; | 55 | return; |
55 | } | 56 | } |
56 | 57 | ||
@@ -58,7 +59,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
58 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); | 59 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); |
59 | 60 | ||
60 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | 61 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { |
61 | pr_debug("ip6t_REJECT: Can't get TCP header.\n"); | 62 | pr_debug("Cannot get TCP header.\n"); |
62 | return; | 63 | return; |
63 | } | 64 | } |
64 | 65 | ||
@@ -66,7 +67,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
66 | 67 | ||
67 | /* IP header checks: fragment, too short. */ | 68 | /* IP header checks: fragment, too short. */ |
68 | if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { | 69 | if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { |
69 | pr_debug("ip6t_REJECT: proto(%d) != IPPROTO_TCP, " | 70 | pr_debug("proto(%d) != IPPROTO_TCP, " |
70 | "or too short. otcplen = %d\n", | 71 | "or too short. otcplen = %d\n", |
71 | proto, otcplen); | 72 | proto, otcplen); |
72 | return; | 73 | return; |
@@ -77,14 +78,14 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
77 | 78 | ||
78 | /* No RST for RST. */ | 79 | /* No RST for RST. */ |
79 | if (otcph.rst) { | 80 | if (otcph.rst) { |
80 | pr_debug("ip6t_REJECT: RST is set\n"); | 81 | pr_debug("RST is set\n"); |
81 | return; | 82 | return; |
82 | } | 83 | } |
83 | 84 | ||
84 | /* Check checksum. */ | 85 | /* Check checksum. */ |
85 | if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP, | 86 | if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP, |
86 | skb_checksum(oldskb, tcphoff, otcplen, 0))) { | 87 | skb_checksum(oldskb, tcphoff, otcplen, 0))) { |
87 | pr_debug("ip6t_REJECT: TCP checksum is invalid\n"); | 88 | pr_debug("TCP checksum is invalid\n"); |
88 | return; | 89 | return; |
89 | } | 90 | } |
90 | 91 | ||
@@ -108,7 +109,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
108 | 109 | ||
109 | if (!nskb) { | 110 | if (!nskb) { |
110 | if (net_ratelimit()) | 111 | if (net_ratelimit()) |
111 | printk("ip6t_REJECT: Can't alloc skb\n"); | 112 | pr_debug("cannot alloc skb\n"); |
112 | dst_release(dst); | 113 | dst_release(dst); |
113 | return; | 114 | return; |
114 | } | 115 | } |
@@ -174,15 +175,12 @@ send_unreach(struct net *net, struct sk_buff *skb_in, unsigned char code, | |||
174 | } | 175 | } |
175 | 176 | ||
176 | static unsigned int | 177 | static unsigned int |
177 | reject_tg6(struct sk_buff *skb, const struct xt_target_param *par) | 178 | reject_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
178 | { | 179 | { |
179 | const struct ip6t_reject_info *reject = par->targinfo; | 180 | const struct ip6t_reject_info *reject = par->targinfo; |
180 | struct net *net = dev_net((par->in != NULL) ? par->in : par->out); | 181 | struct net *net = dev_net((par->in != NULL) ? par->in : par->out); |
181 | 182 | ||
182 | pr_debug("%s: medium point\n", __func__); | 183 | pr_debug("%s: medium point\n", __func__); |
183 | /* WARNING: This code causes reentry within ip6tables. | ||
184 | This means that the ip6tables jump stack is now crap. We | ||
185 | must return an absolute verdict. --RR */ | ||
186 | switch (reject->with) { | 184 | switch (reject->with) { |
187 | case IP6T_ICMP6_NO_ROUTE: | 185 | case IP6T_ICMP6_NO_ROUTE: |
188 | send_unreach(net, skb, ICMPV6_NOROUTE, par->hooknum); | 186 | send_unreach(net, skb, ICMPV6_NOROUTE, par->hooknum); |
@@ -207,30 +205,30 @@ reject_tg6(struct sk_buff *skb, const struct xt_target_param *par) | |||
207 | break; | 205 | break; |
208 | default: | 206 | default: |
209 | if (net_ratelimit()) | 207 | if (net_ratelimit()) |
210 | printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with); | 208 | pr_info("case %u not handled yet\n", reject->with); |
211 | break; | 209 | break; |
212 | } | 210 | } |
213 | 211 | ||
214 | return NF_DROP; | 212 | return NF_DROP; |
215 | } | 213 | } |
216 | 214 | ||
217 | static bool reject_tg6_check(const struct xt_tgchk_param *par) | 215 | static int reject_tg6_check(const struct xt_tgchk_param *par) |
218 | { | 216 | { |
219 | const struct ip6t_reject_info *rejinfo = par->targinfo; | 217 | const struct ip6t_reject_info *rejinfo = par->targinfo; |
220 | const struct ip6t_entry *e = par->entryinfo; | 218 | const struct ip6t_entry *e = par->entryinfo; |
221 | 219 | ||
222 | if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { | 220 | if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { |
223 | printk("ip6t_REJECT: ECHOREPLY is not supported.\n"); | 221 | pr_info("ECHOREPLY is not supported.\n"); |
224 | return false; | 222 | return -EINVAL; |
225 | } else if (rejinfo->with == IP6T_TCP_RESET) { | 223 | } else if (rejinfo->with == IP6T_TCP_RESET) { |
226 | /* Must specify that it's a TCP packet */ | 224 | /* Must specify that it's a TCP packet */ |
227 | if (e->ipv6.proto != IPPROTO_TCP || | 225 | if (e->ipv6.proto != IPPROTO_TCP || |
228 | (e->ipv6.invflags & XT_INV_PROTO)) { | 226 | (e->ipv6.invflags & XT_INV_PROTO)) { |
229 | printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); | 227 | pr_info("TCP_RESET illegal for non-tcp\n"); |
230 | return false; | 228 | return -EINVAL; |
231 | } | 229 | } |
232 | } | 230 | } |
233 | return true; | 231 | return 0; |
234 | } | 232 | } |
235 | 233 | ||
236 | static struct xt_target reject_tg6_reg __read_mostly = { | 234 | static struct xt_target reject_tg6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index ac0b7c629d78..89cccc5a9c92 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/ip.h> | 12 | #include <linux/ip.h> |
@@ -29,14 +29,14 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) | |||
29 | { | 29 | { |
30 | bool r; | 30 | bool r; |
31 | 31 | ||
32 | pr_debug("ah spi_match:%c 0x%x <= 0x%x <= 0x%x", | 32 | pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n", |
33 | invert ? '!' : ' ', min, spi, max); | 33 | invert ? '!' : ' ', min, spi, max); |
34 | r = (spi >= min && spi <= max) ^ invert; | 34 | r = (spi >= min && spi <= max) ^ invert; |
35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); | 35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
36 | return r; | 36 | return r; |
37 | } | 37 | } |
38 | 38 | ||
39 | static bool ah_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 39 | static bool ah_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
40 | { | 40 | { |
41 | struct ip_auth_hdr _ah; | 41 | struct ip_auth_hdr _ah; |
42 | const struct ip_auth_hdr *ah; | 42 | const struct ip_auth_hdr *ah; |
@@ -48,13 +48,13 @@ static bool ah_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
48 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); | 48 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); |
49 | if (err < 0) { | 49 | if (err < 0) { |
50 | if (err != -ENOENT) | 50 | if (err != -ENOENT) |
51 | *par->hotdrop = true; | 51 | par->hotdrop = true; |
52 | return false; | 52 | return false; |
53 | } | 53 | } |
54 | 54 | ||
55 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); | 55 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); |
56 | if (ah == NULL) { | 56 | if (ah == NULL) { |
57 | *par->hotdrop = true; | 57 | par->hotdrop = true; |
58 | return false; | 58 | return false; |
59 | } | 59 | } |
60 | 60 | ||
@@ -87,15 +87,15 @@ static bool ah_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
87 | !(ahinfo->hdrres && ah->reserved); | 87 | !(ahinfo->hdrres && ah->reserved); |
88 | } | 88 | } |
89 | 89 | ||
90 | static bool ah_mt6_check(const struct xt_mtchk_param *par) | 90 | static int ah_mt6_check(const struct xt_mtchk_param *par) |
91 | { | 91 | { |
92 | const struct ip6t_ah *ahinfo = par->matchinfo; | 92 | const struct ip6t_ah *ahinfo = par->matchinfo; |
93 | 93 | ||
94 | if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { | 94 | if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { |
95 | pr_debug("ip6t_ah: unknown flags %X\n", ahinfo->invflags); | 95 | pr_debug("unknown flags %X\n", ahinfo->invflags); |
96 | return false; | 96 | return -EINVAL; |
97 | } | 97 | } |
98 | return true; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | static struct xt_match ah_mt6_reg __read_mostly = { | 101 | static struct xt_match ah_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index ca287f6d2bce..aab0706908c5 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c | |||
@@ -20,14 +20,14 @@ MODULE_LICENSE("GPL"); | |||
20 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 20 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
21 | 21 | ||
22 | static bool | 22 | static bool |
23 | eui64_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 23 | eui64_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
24 | { | 24 | { |
25 | unsigned char eui64[8]; | 25 | unsigned char eui64[8]; |
26 | 26 | ||
27 | if (!(skb_mac_header(skb) >= skb->head && | 27 | if (!(skb_mac_header(skb) >= skb->head && |
28 | skb_mac_header(skb) + ETH_HLEN <= skb->data) && | 28 | skb_mac_header(skb) + ETH_HLEN <= skb->data) && |
29 | par->fragoff != 0) { | 29 | par->fragoff != 0) { |
30 | *par->hotdrop = true; | 30 | par->hotdrop = true; |
31 | return false; | 31 | return false; |
32 | } | 32 | } |
33 | 33 | ||
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 7b91c2598ed5..eda898fda6ca 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/ipv6.h> | 12 | #include <linux/ipv6.h> |
@@ -27,7 +27,7 @@ static inline bool | |||
27 | id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) | 27 | id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) |
28 | { | 28 | { |
29 | bool r; | 29 | bool r; |
30 | pr_debug("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', | 30 | pr_debug("id_match:%c 0x%x <= 0x%x <= 0x%x\n", invert ? '!' : ' ', |
31 | min, id, max); | 31 | min, id, max); |
32 | r = (id >= min && id <= max) ^ invert; | 32 | r = (id >= min && id <= max) ^ invert; |
33 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); | 33 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
@@ -35,7 +35,7 @@ id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) | |||
35 | } | 35 | } |
36 | 36 | ||
37 | static bool | 37 | static bool |
38 | frag_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 38 | frag_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
39 | { | 39 | { |
40 | struct frag_hdr _frag; | 40 | struct frag_hdr _frag; |
41 | const struct frag_hdr *fh; | 41 | const struct frag_hdr *fh; |
@@ -46,13 +46,13 @@ frag_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
46 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); | 46 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); |
47 | if (err < 0) { | 47 | if (err < 0) { |
48 | if (err != -ENOENT) | 48 | if (err != -ENOENT) |
49 | *par->hotdrop = true; | 49 | par->hotdrop = true; |
50 | return false; | 50 | return false; |
51 | } | 51 | } |
52 | 52 | ||
53 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); | 53 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); |
54 | if (fh == NULL) { | 54 | if (fh == NULL) { |
55 | *par->hotdrop = true; | 55 | par->hotdrop = true; |
56 | return false; | 56 | return false; |
57 | } | 57 | } |
58 | 58 | ||
@@ -102,15 +102,15 @@ frag_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
102 | (ntohs(fh->frag_off) & IP6_MF)); | 102 | (ntohs(fh->frag_off) & IP6_MF)); |
103 | } | 103 | } |
104 | 104 | ||
105 | static bool frag_mt6_check(const struct xt_mtchk_param *par) | 105 | static int frag_mt6_check(const struct xt_mtchk_param *par) |
106 | { | 106 | { |
107 | const struct ip6t_frag *fraginfo = par->matchinfo; | 107 | const struct ip6t_frag *fraginfo = par->matchinfo; |
108 | 108 | ||
109 | if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { | 109 | if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { |
110 | pr_debug("ip6t_frag: unknown flags %X\n", fraginfo->invflags); | 110 | pr_debug("unknown flags %X\n", fraginfo->invflags); |
111 | return false; | 111 | return -EINVAL; |
112 | } | 112 | } |
113 | return true; | 113 | return 0; |
114 | } | 114 | } |
115 | 115 | ||
116 | static struct xt_match frag_mt6_reg __read_mostly = { | 116 | static struct xt_match frag_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index cbe8dec9744b..59df051eaef6 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/ipv6.h> | 12 | #include <linux/ipv6.h> |
@@ -41,8 +41,10 @@ MODULE_ALIAS("ip6t_dst"); | |||
41 | * 5 -> RTALERT 2 x x | 41 | * 5 -> RTALERT 2 x x |
42 | */ | 42 | */ |
43 | 43 | ||
44 | static struct xt_match hbh_mt6_reg[] __read_mostly; | ||
45 | |||
44 | static bool | 46 | static bool |
45 | hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 47 | hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
46 | { | 48 | { |
47 | struct ipv6_opt_hdr _optsh; | 49 | struct ipv6_opt_hdr _optsh; |
48 | const struct ipv6_opt_hdr *oh; | 50 | const struct ipv6_opt_hdr *oh; |
@@ -58,16 +60,18 @@ hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
58 | unsigned int optlen; | 60 | unsigned int optlen; |
59 | int err; | 61 | int err; |
60 | 62 | ||
61 | err = ipv6_find_hdr(skb, &ptr, par->match->data, NULL); | 63 | err = ipv6_find_hdr(skb, &ptr, |
64 | (par->match == &hbh_mt6_reg[0]) ? | ||
65 | NEXTHDR_HOP : NEXTHDR_DEST, NULL); | ||
62 | if (err < 0) { | 66 | if (err < 0) { |
63 | if (err != -ENOENT) | 67 | if (err != -ENOENT) |
64 | *par->hotdrop = true; | 68 | par->hotdrop = true; |
65 | return false; | 69 | return false; |
66 | } | 70 | } |
67 | 71 | ||
68 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); | 72 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); |
69 | if (oh == NULL) { | 73 | if (oh == NULL) { |
70 | *par->hotdrop = true; | 74 | par->hotdrop = true; |
71 | return false; | 75 | return false; |
72 | } | 76 | } |
73 | 77 | ||
@@ -141,11 +145,11 @@ hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
141 | } | 145 | } |
142 | 146 | ||
143 | /* Step to the next */ | 147 | /* Step to the next */ |
144 | pr_debug("len%04X \n", optlen); | 148 | pr_debug("len%04X\n", optlen); |
145 | 149 | ||
146 | if ((ptr > skb->len - optlen || hdrlen < optlen) && | 150 | if ((ptr > skb->len - optlen || hdrlen < optlen) && |
147 | temp < optinfo->optsnr - 1) { | 151 | temp < optinfo->optsnr - 1) { |
148 | pr_debug("new pointer is too large! \n"); | 152 | pr_debug("new pointer is too large!\n"); |
149 | break; | 153 | break; |
150 | } | 154 | } |
151 | ptr += optlen; | 155 | ptr += optlen; |
@@ -160,32 +164,32 @@ hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
160 | return false; | 164 | return false; |
161 | } | 165 | } |
162 | 166 | ||
163 | static bool hbh_mt6_check(const struct xt_mtchk_param *par) | 167 | static int hbh_mt6_check(const struct xt_mtchk_param *par) |
164 | { | 168 | { |
165 | const struct ip6t_opts *optsinfo = par->matchinfo; | 169 | const struct ip6t_opts *optsinfo = par->matchinfo; |
166 | 170 | ||
167 | if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { | 171 | if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { |
168 | pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags); | 172 | pr_debug("unknown flags %X\n", optsinfo->invflags); |
169 | return false; | 173 | return -EINVAL; |
170 | } | 174 | } |
171 | 175 | ||
172 | if (optsinfo->flags & IP6T_OPTS_NSTRICT) { | 176 | if (optsinfo->flags & IP6T_OPTS_NSTRICT) { |
173 | pr_debug("ip6t_opts: Not strict - not implemented"); | 177 | pr_debug("Not strict - not implemented"); |
174 | return false; | 178 | return -EINVAL; |
175 | } | 179 | } |
176 | 180 | ||
177 | return true; | 181 | return 0; |
178 | } | 182 | } |
179 | 183 | ||
180 | static struct xt_match hbh_mt6_reg[] __read_mostly = { | 184 | static struct xt_match hbh_mt6_reg[] __read_mostly = { |
181 | { | 185 | { |
186 | /* Note, hbh_mt6 relies on the order of hbh_mt6_reg */ | ||
182 | .name = "hbh", | 187 | .name = "hbh", |
183 | .family = NFPROTO_IPV6, | 188 | .family = NFPROTO_IPV6, |
184 | .match = hbh_mt6, | 189 | .match = hbh_mt6, |
185 | .matchsize = sizeof(struct ip6t_opts), | 190 | .matchsize = sizeof(struct ip6t_opts), |
186 | .checkentry = hbh_mt6_check, | 191 | .checkentry = hbh_mt6_check, |
187 | .me = THIS_MODULE, | 192 | .me = THIS_MODULE, |
188 | .data = NEXTHDR_HOP, | ||
189 | }, | 193 | }, |
190 | { | 194 | { |
191 | .name = "dst", | 195 | .name = "dst", |
@@ -194,7 +198,6 @@ static struct xt_match hbh_mt6_reg[] __read_mostly = { | |||
194 | .matchsize = sizeof(struct ip6t_opts), | 198 | .matchsize = sizeof(struct ip6t_opts), |
195 | .checkentry = hbh_mt6_check, | 199 | .checkentry = hbh_mt6_check, |
196 | .me = THIS_MODULE, | 200 | .me = THIS_MODULE, |
197 | .data = NEXTHDR_DEST, | ||
198 | }, | 201 | }, |
199 | }; | 202 | }; |
200 | 203 | ||
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 91490ad9302c..54bd9790603f 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c | |||
@@ -27,7 +27,7 @@ MODULE_DESCRIPTION("Xtables: IPv6 header types match"); | |||
27 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 27 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
28 | 28 | ||
29 | static bool | 29 | static bool |
30 | ipv6header_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 30 | ipv6header_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
31 | { | 31 | { |
32 | const struct ip6t_ipv6header_info *info = par->matchinfo; | 32 | const struct ip6t_ipv6header_info *info = par->matchinfo; |
33 | unsigned int temp; | 33 | unsigned int temp; |
@@ -118,16 +118,16 @@ ipv6header_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
118 | } | 118 | } |
119 | } | 119 | } |
120 | 120 | ||
121 | static bool ipv6header_mt6_check(const struct xt_mtchk_param *par) | 121 | static int ipv6header_mt6_check(const struct xt_mtchk_param *par) |
122 | { | 122 | { |
123 | const struct ip6t_ipv6header_info *info = par->matchinfo; | 123 | const struct ip6t_ipv6header_info *info = par->matchinfo; |
124 | 124 | ||
125 | /* invflags is 0 or 0xff in hard mode */ | 125 | /* invflags is 0 or 0xff in hard mode */ |
126 | if ((!info->modeflag) && info->invflags != 0x00 && | 126 | if ((!info->modeflag) && info->invflags != 0x00 && |
127 | info->invflags != 0xFF) | 127 | info->invflags != 0xFF) |
128 | return false; | 128 | return -EINVAL; |
129 | 129 | ||
130 | return true; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | static struct xt_match ipv6header_mt6_reg __read_mostly = { | 133 | static struct xt_match ipv6header_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c index aafe4e66577b..0c90c66b1992 100644 --- a/net/ipv6/netfilter/ip6t_mh.c +++ b/net/ipv6/netfilter/ip6t_mh.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * Based on net/netfilter/xt_tcpudp.c | 11 | * Based on net/netfilter/xt_tcpudp.c |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
14 | #include <linux/types.h> | 15 | #include <linux/types.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <net/ip.h> | 17 | #include <net/ip.h> |
@@ -24,12 +25,6 @@ | |||
24 | MODULE_DESCRIPTION("Xtables: IPv6 Mobility Header match"); | 25 | MODULE_DESCRIPTION("Xtables: IPv6 Mobility Header match"); |
25 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
26 | 27 | ||
27 | #ifdef DEBUG_IP_FIREWALL_USER | ||
28 | #define duprintf(format, args...) printk(format , ## args) | ||
29 | #else | ||
30 | #define duprintf(format, args...) | ||
31 | #endif | ||
32 | |||
33 | /* Returns 1 if the type is matched by the range, 0 otherwise */ | 28 | /* Returns 1 if the type is matched by the range, 0 otherwise */ |
34 | static inline bool | 29 | static inline bool |
35 | type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert) | 30 | type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert) |
@@ -37,7 +32,7 @@ type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert) | |||
37 | return (type >= min && type <= max) ^ invert; | 32 | return (type >= min && type <= max) ^ invert; |
38 | } | 33 | } |
39 | 34 | ||
40 | static bool mh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 35 | static bool mh_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
41 | { | 36 | { |
42 | struct ip6_mh _mh; | 37 | struct ip6_mh _mh; |
43 | const struct ip6_mh *mh; | 38 | const struct ip6_mh *mh; |
@@ -51,15 +46,15 @@ static bool mh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
51 | if (mh == NULL) { | 46 | if (mh == NULL) { |
52 | /* We've been asked to examine this packet, and we | 47 | /* We've been asked to examine this packet, and we |
53 | can't. Hence, no choice but to drop. */ | 48 | can't. Hence, no choice but to drop. */ |
54 | duprintf("Dropping evil MH tinygram.\n"); | 49 | pr_debug("Dropping evil MH tinygram.\n"); |
55 | *par->hotdrop = true; | 50 | par->hotdrop = true; |
56 | return false; | 51 | return false; |
57 | } | 52 | } |
58 | 53 | ||
59 | if (mh->ip6mh_proto != IPPROTO_NONE) { | 54 | if (mh->ip6mh_proto != IPPROTO_NONE) { |
60 | duprintf("Dropping invalid MH Payload Proto: %u\n", | 55 | pr_debug("Dropping invalid MH Payload Proto: %u\n", |
61 | mh->ip6mh_proto); | 56 | mh->ip6mh_proto); |
62 | *par->hotdrop = true; | 57 | par->hotdrop = true; |
63 | return false; | 58 | return false; |
64 | } | 59 | } |
65 | 60 | ||
@@ -67,12 +62,12 @@ static bool mh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
67 | !!(mhinfo->invflags & IP6T_MH_INV_TYPE)); | 62 | !!(mhinfo->invflags & IP6T_MH_INV_TYPE)); |
68 | } | 63 | } |
69 | 64 | ||
70 | static bool mh_mt6_check(const struct xt_mtchk_param *par) | 65 | static int mh_mt6_check(const struct xt_mtchk_param *par) |
71 | { | 66 | { |
72 | const struct ip6t_mh *mhinfo = par->matchinfo; | 67 | const struct ip6t_mh *mhinfo = par->matchinfo; |
73 | 68 | ||
74 | /* Must specify no unknown invflags */ | 69 | /* Must specify no unknown invflags */ |
75 | return !(mhinfo->invflags & ~IP6T_MH_INV_MASK); | 70 | return (mhinfo->invflags & ~IP6T_MH_INV_MASK) ? -EINVAL : 0; |
76 | } | 71 | } |
77 | 72 | ||
78 | static struct xt_match mh_mt6_reg __read_mostly = { | 73 | static struct xt_match mh_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index b77307fc8743..d8488c50a8e0 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/ipv6.h> | 12 | #include <linux/ipv6.h> |
@@ -29,14 +29,14 @@ static inline bool | |||
29 | segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) | 29 | segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) |
30 | { | 30 | { |
31 | bool r; | 31 | bool r; |
32 | pr_debug("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x", | 32 | pr_debug("segsleft_match:%c 0x%x <= 0x%x <= 0x%x\n", |
33 | invert ? '!' : ' ', min, id, max); | 33 | invert ? '!' : ' ', min, id, max); |
34 | r = (id >= min && id <= max) ^ invert; | 34 | r = (id >= min && id <= max) ^ invert; |
35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); | 35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
36 | return r; | 36 | return r; |
37 | } | 37 | } |
38 | 38 | ||
39 | static bool rt_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 39 | static bool rt_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
40 | { | 40 | { |
41 | struct ipv6_rt_hdr _route; | 41 | struct ipv6_rt_hdr _route; |
42 | const struct ipv6_rt_hdr *rh; | 42 | const struct ipv6_rt_hdr *rh; |
@@ -52,13 +52,13 @@ static bool rt_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
52 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); | 52 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); |
53 | if (err < 0) { | 53 | if (err < 0) { |
54 | if (err != -ENOENT) | 54 | if (err != -ENOENT) |
55 | *par->hotdrop = true; | 55 | par->hotdrop = true; |
56 | return false; | 56 | return false; |
57 | } | 57 | } |
58 | 58 | ||
59 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); | 59 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); |
60 | if (rh == NULL) { | 60 | if (rh == NULL) { |
61 | *par->hotdrop = true; | 61 | par->hotdrop = true; |
62 | return false; | 62 | return false; |
63 | } | 63 | } |
64 | 64 | ||
@@ -183,23 +183,23 @@ static bool rt_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
183 | return false; | 183 | return false; |
184 | } | 184 | } |
185 | 185 | ||
186 | static bool rt_mt6_check(const struct xt_mtchk_param *par) | 186 | static int rt_mt6_check(const struct xt_mtchk_param *par) |
187 | { | 187 | { |
188 | const struct ip6t_rt *rtinfo = par->matchinfo; | 188 | const struct ip6t_rt *rtinfo = par->matchinfo; |
189 | 189 | ||
190 | if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { | 190 | if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { |
191 | pr_debug("ip6t_rt: unknown flags %X\n", rtinfo->invflags); | 191 | pr_debug("unknown flags %X\n", rtinfo->invflags); |
192 | return false; | 192 | return -EINVAL; |
193 | } | 193 | } |
194 | if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && | 194 | if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && |
195 | (!(rtinfo->flags & IP6T_RT_TYP) || | 195 | (!(rtinfo->flags & IP6T_RT_TYP) || |
196 | (rtinfo->rt_type != 0) || | 196 | (rtinfo->rt_type != 0) || |
197 | (rtinfo->invflags & IP6T_RT_INV_TYP))) { | 197 | (rtinfo->invflags & IP6T_RT_INV_TYP))) { |
198 | pr_debug("`--rt-type 0' required before `--rt-0-*'"); | 198 | pr_debug("`--rt-type 0' required before `--rt-0-*'"); |
199 | return false; | 199 | return -EINVAL; |
200 | } | 200 | } |
201 | 201 | ||
202 | return true; | 202 | return 0; |
203 | } | 203 | } |
204 | 204 | ||
205 | static struct xt_match rt_mt6_reg __read_mostly = { | 205 | static struct xt_match rt_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index d6fc9aff3163..c9e37c8fd62c 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -81,7 +81,7 @@ static int __init ip6table_filter_init(void) | |||
81 | int ret; | 81 | int ret; |
82 | 82 | ||
83 | if (forward < 0 || forward > NF_MAX_VERDICT) { | 83 | if (forward < 0 || forward > NF_MAX_VERDICT) { |
84 | printk("iptables forward must be 0 or 1\n"); | 84 | pr_err("iptables forward must be 0 or 1\n"); |
85 | return -EINVAL; | 85 | return -EINVAL; |
86 | } | 86 | } |
87 | 87 | ||
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 6a102b57f356..679a0a3b7b3c 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -43,7 +43,7 @@ ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out) | |||
43 | if (skb->len < sizeof(struct iphdr) || | 43 | if (skb->len < sizeof(struct iphdr) || |
44 | ip_hdrlen(skb) < sizeof(struct iphdr)) { | 44 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
45 | if (net_ratelimit()) | 45 | if (net_ratelimit()) |
46 | printk("ip6t_hook: happy cracking.\n"); | 46 | pr_warning("ip6t_hook: happy cracking.\n"); |
47 | return NF_ACCEPT; | 47 | return NF_ACCEPT; |
48 | } | 48 | } |
49 | #endif | 49 | #endif |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 996c3f41fecd..ff43461704be 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -280,7 +280,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum, | |||
280 | /* root is playing with raw sockets. */ | 280 | /* root is playing with raw sockets. */ |
281 | if (skb->len < sizeof(struct ipv6hdr)) { | 281 | if (skb->len < sizeof(struct ipv6hdr)) { |
282 | if (net_ratelimit()) | 282 | if (net_ratelimit()) |
283 | printk("ipv6_conntrack_local: packet too short\n"); | 283 | pr_notice("ipv6_conntrack_local: packet too short\n"); |
284 | return NF_ACCEPT; | 284 | return NF_ACCEPT; |
285 | } | 285 | } |
286 | return __ipv6_conntrack_in(dev_net(out), hooknum, skb, okfn); | 286 | return __ipv6_conntrack_in(dev_net(out), hooknum, skb, okfn); |
@@ -406,37 +406,37 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) | |||
406 | 406 | ||
407 | ret = nf_ct_frag6_init(); | 407 | ret = nf_ct_frag6_init(); |
408 | if (ret < 0) { | 408 | if (ret < 0) { |
409 | printk("nf_conntrack_ipv6: can't initialize frag6.\n"); | 409 | pr_err("nf_conntrack_ipv6: can't initialize frag6.\n"); |
410 | return ret; | 410 | return ret; |
411 | } | 411 | } |
412 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); | 412 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); |
413 | if (ret < 0) { | 413 | if (ret < 0) { |
414 | printk("nf_conntrack_ipv6: can't register tcp.\n"); | 414 | pr_err("nf_conntrack_ipv6: can't register tcp.\n"); |
415 | goto cleanup_frag6; | 415 | goto cleanup_frag6; |
416 | } | 416 | } |
417 | 417 | ||
418 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); | 418 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); |
419 | if (ret < 0) { | 419 | if (ret < 0) { |
420 | printk("nf_conntrack_ipv6: can't register udp.\n"); | 420 | pr_err("nf_conntrack_ipv6: can't register udp.\n"); |
421 | goto cleanup_tcp; | 421 | goto cleanup_tcp; |
422 | } | 422 | } |
423 | 423 | ||
424 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6); | 424 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6); |
425 | if (ret < 0) { | 425 | if (ret < 0) { |
426 | printk("nf_conntrack_ipv6: can't register icmpv6.\n"); | 426 | pr_err("nf_conntrack_ipv6: can't register icmpv6.\n"); |
427 | goto cleanup_udp; | 427 | goto cleanup_udp; |
428 | } | 428 | } |
429 | 429 | ||
430 | ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv6); | 430 | ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv6); |
431 | if (ret < 0) { | 431 | if (ret < 0) { |
432 | printk("nf_conntrack_ipv6: can't register ipv6\n"); | 432 | pr_err("nf_conntrack_ipv6: can't register ipv6\n"); |
433 | goto cleanup_icmpv6; | 433 | goto cleanup_icmpv6; |
434 | } | 434 | } |
435 | 435 | ||
436 | ret = nf_register_hooks(ipv6_conntrack_ops, | 436 | ret = nf_register_hooks(ipv6_conntrack_ops, |
437 | ARRAY_SIZE(ipv6_conntrack_ops)); | 437 | ARRAY_SIZE(ipv6_conntrack_ops)); |
438 | if (ret < 0) { | 438 | if (ret < 0) { |
439 | printk("nf_conntrack_ipv6: can't register pre-routing defrag " | 439 | pr_err("nf_conntrack_ipv6: can't register pre-routing defrag " |
440 | "hook.\n"); | 440 | "hook.\n"); |
441 | goto cleanup_ipv6; | 441 | goto cleanup_ipv6; |
442 | } | 442 | } |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index dd5b9bd61c62..6fb890187de0 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -644,7 +644,7 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, | |||
644 | s2 = s->next; | 644 | s2 = s->next; |
645 | s->next = NULL; | 645 | s->next = NULL; |
646 | 646 | ||
647 | NF_HOOK_THRESH(PF_INET6, hooknum, s, in, out, okfn, | 647 | NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, in, out, okfn, |
648 | NF_IP6_PRI_CONNTRACK_DEFRAG + 1); | 648 | NF_IP6_PRI_CONNTRACK_DEFRAG + 1); |
649 | s = s2; | 649 | s = s2; |
650 | } | 650 | } |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 58344c0fbd13..566798d69f37 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -97,6 +97,7 @@ static const struct snmp_mib snmp6_icmp6_list[] = { | |||
97 | SNMP_MIB_ITEM("Icmp6InMsgs", ICMP6_MIB_INMSGS), | 97 | SNMP_MIB_ITEM("Icmp6InMsgs", ICMP6_MIB_INMSGS), |
98 | SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), | 98 | SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), |
99 | SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS), | 99 | SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS), |
100 | SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS), | ||
100 | SNMP_MIB_SENTINEL | 101 | SNMP_MIB_SENTINEL |
101 | }; | 102 | }; |
102 | 103 | ||
@@ -167,7 +168,6 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **mib) | |||
167 | i & 0x100 ? "Out" : "In", i & 0xff); | 168 | i & 0x100 ? "Out" : "In", i & 0xff); |
168 | seq_printf(seq, "%-32s\t%lu\n", name, val); | 169 | seq_printf(seq, "%-32s\t%lu\n", name, val); |
169 | } | 170 | } |
170 | return; | ||
171 | } | 171 | } |
172 | 172 | ||
173 | static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib, | 173 | static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib, |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 8763b1a0814a..4a4dcbe4f8b2 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -381,7 +381,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) | |||
381 | } | 381 | } |
382 | 382 | ||
383 | /* Charge it to the socket. */ | 383 | /* Charge it to the socket. */ |
384 | if (sock_queue_rcv_skb(sk, skb) < 0) { | 384 | if (ip_queue_rcv_skb(sk, skb) < 0) { |
385 | kfree_skb(skb); | 385 | kfree_skb(skb); |
386 | return NET_RX_DROP; | 386 | return NET_RX_DROP; |
387 | } | 387 | } |
@@ -461,6 +461,9 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
461 | if (flags & MSG_ERRQUEUE) | 461 | if (flags & MSG_ERRQUEUE) |
462 | return ipv6_recv_error(sk, msg, len); | 462 | return ipv6_recv_error(sk, msg, len); |
463 | 463 | ||
464 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) | ||
465 | return ipv6_recv_rxpmtu(sk, msg, len); | ||
466 | |||
464 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 467 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
465 | if (!skb) | 468 | if (!skb) |
466 | goto out; | 469 | goto out; |
@@ -637,8 +640,8 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
637 | goto error_fault; | 640 | goto error_fault; |
638 | 641 | ||
639 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); | 642 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); |
640 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, | 643 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
641 | dst_output); | 644 | rt->u.dst.dev, dst_output); |
642 | if (err > 0) | 645 | if (err > 0) |
643 | err = net_xmit_errno(err); | 646 | err = net_xmit_errno(err); |
644 | if (err) | 647 | if (err) |
@@ -733,6 +736,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
733 | int addr_len = msg->msg_namelen; | 736 | int addr_len = msg->msg_namelen; |
734 | int hlimit = -1; | 737 | int hlimit = -1; |
735 | int tclass = -1; | 738 | int tclass = -1; |
739 | int dontfrag = -1; | ||
736 | u16 proto; | 740 | u16 proto; |
737 | int err; | 741 | int err; |
738 | 742 | ||
@@ -811,7 +815,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
811 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 815 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
812 | opt->tot_len = sizeof(struct ipv6_txoptions); | 816 | opt->tot_len = sizeof(struct ipv6_txoptions); |
813 | 817 | ||
814 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); | 818 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, |
819 | &tclass, &dontfrag); | ||
815 | if (err < 0) { | 820 | if (err < 0) { |
816 | fl6_sock_release(flowlabel); | 821 | fl6_sock_release(flowlabel); |
817 | return err; | 822 | return err; |
@@ -880,6 +885,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
880 | if (tclass < 0) | 885 | if (tclass < 0) |
881 | tclass = np->tclass; | 886 | tclass = np->tclass; |
882 | 887 | ||
888 | if (dontfrag < 0) | ||
889 | dontfrag = np->dontfrag; | ||
890 | |||
883 | if (msg->msg_flags&MSG_CONFIRM) | 891 | if (msg->msg_flags&MSG_CONFIRM) |
884 | goto do_confirm; | 892 | goto do_confirm; |
885 | 893 | ||
@@ -890,7 +898,7 @@ back_from_confirm: | |||
890 | lock_sock(sk); | 898 | lock_sock(sk); |
891 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 899 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, |
892 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, | 900 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, |
893 | msg->msg_flags); | 901 | msg->msg_flags, dontfrag); |
894 | 902 | ||
895 | if (err) | 903 | if (err) |
896 | ip6_flush_pending_frames(sk); | 904 | ip6_flush_pending_frames(sk); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 05ebd7833043..294cbe8b0725 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -316,7 +316,6 @@ static void rt6_probe(struct rt6_info *rt) | |||
316 | #else | 316 | #else |
317 | static inline void rt6_probe(struct rt6_info *rt) | 317 | static inline void rt6_probe(struct rt6_info *rt) |
318 | { | 318 | { |
319 | return; | ||
320 | } | 319 | } |
321 | #endif | 320 | #endif |
322 | 321 | ||
@@ -1553,7 +1552,6 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1553 | 1552 | ||
1554 | out: | 1553 | out: |
1555 | dst_release(&rt->u.dst); | 1554 | dst_release(&rt->u.dst); |
1556 | return; | ||
1557 | } | 1555 | } |
1558 | 1556 | ||
1559 | /* | 1557 | /* |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 5abae10cd884..e51e650ea80b 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -566,11 +566,9 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
566 | kfree_skb(skb); | 566 | kfree_skb(skb); |
567 | return 0; | 567 | return 0; |
568 | } | 568 | } |
569 | tunnel->dev->stats.rx_packets++; | 569 | |
570 | tunnel->dev->stats.rx_bytes += skb->len; | 570 | skb_tunnel_rx(skb, tunnel->dev); |
571 | skb->dev = tunnel->dev; | 571 | |
572 | skb_dst_drop(skb); | ||
573 | nf_reset(skb); | ||
574 | ipip6_ecn_decapsulate(iph, skb); | 572 | ipip6_ecn_decapsulate(iph, skb); |
575 | netif_rx(skb); | 573 | netif_rx(skb); |
576 | rcu_read_unlock(); | 574 | rcu_read_unlock(); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 075f540ec197..2b7c3a100e2c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -75,6 +75,9 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
75 | struct request_sock *req); | 75 | struct request_sock *req); |
76 | 76 | ||
77 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); | 77 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); |
78 | static void __tcp_v6_send_check(struct sk_buff *skb, | ||
79 | struct in6_addr *saddr, | ||
80 | struct in6_addr *daddr); | ||
78 | 81 | ||
79 | static const struct inet_connection_sock_af_ops ipv6_mapped; | 82 | static const struct inet_connection_sock_af_ops ipv6_mapped; |
80 | static const struct inet_connection_sock_af_ops ipv6_specific; | 83 | static const struct inet_connection_sock_af_ops ipv6_specific; |
@@ -350,6 +353,11 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
350 | if (sk->sk_state == TCP_CLOSE) | 353 | if (sk->sk_state == TCP_CLOSE) |
351 | goto out; | 354 | goto out; |
352 | 355 | ||
356 | if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) { | ||
357 | NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); | ||
358 | goto out; | ||
359 | } | ||
360 | |||
353 | tp = tcp_sk(sk); | 361 | tp = tcp_sk(sk); |
354 | seq = ntohl(th->seq); | 362 | seq = ntohl(th->seq); |
355 | if (sk->sk_state != TCP_LISTEN && | 363 | if (sk->sk_state != TCP_LISTEN && |
@@ -503,14 +511,10 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
503 | 511 | ||
504 | skb = tcp_make_synack(sk, dst, req, rvp); | 512 | skb = tcp_make_synack(sk, dst, req, rvp); |
505 | if (skb) { | 513 | if (skb) { |
506 | struct tcphdr *th = tcp_hdr(skb); | 514 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
507 | |||
508 | th->check = tcp_v6_check(skb->len, | ||
509 | &treq->loc_addr, &treq->rmt_addr, | ||
510 | csum_partial(th, skb->len, skb->csum)); | ||
511 | 515 | ||
512 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 516 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); |
513 | err = ip6_xmit(sk, skb, &fl, opt, 0); | 517 | err = ip6_xmit(sk, skb, &fl, opt); |
514 | err = net_xmit_eval(err); | 518 | err = net_xmit_eval(err); |
515 | } | 519 | } |
516 | 520 | ||
@@ -600,7 +604,7 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, | |||
600 | kfree(newkey); | 604 | kfree(newkey); |
601 | return -ENOMEM; | 605 | return -ENOMEM; |
602 | } | 606 | } |
603 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 607 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
604 | } | 608 | } |
605 | if (tcp_alloc_md5sig_pool(sk) == NULL) { | 609 | if (tcp_alloc_md5sig_pool(sk) == NULL) { |
606 | kfree(newkey); | 610 | kfree(newkey); |
@@ -737,7 +741,7 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | |||
737 | return -ENOMEM; | 741 | return -ENOMEM; |
738 | 742 | ||
739 | tp->md5sig_info = p; | 743 | tp->md5sig_info = p; |
740 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 744 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
741 | } | 745 | } |
742 | 746 | ||
743 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); | 747 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); |
@@ -918,22 +922,29 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = { | |||
918 | .twsk_destructor= tcp_twsk_destructor, | 922 | .twsk_destructor= tcp_twsk_destructor, |
919 | }; | 923 | }; |
920 | 924 | ||
921 | static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) | 925 | static void __tcp_v6_send_check(struct sk_buff *skb, |
926 | struct in6_addr *saddr, struct in6_addr *daddr) | ||
922 | { | 927 | { |
923 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
924 | struct tcphdr *th = tcp_hdr(skb); | 928 | struct tcphdr *th = tcp_hdr(skb); |
925 | 929 | ||
926 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 930 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
927 | th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); | 931 | th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0); |
928 | skb->csum_start = skb_transport_header(skb) - skb->head; | 932 | skb->csum_start = skb_transport_header(skb) - skb->head; |
929 | skb->csum_offset = offsetof(struct tcphdr, check); | 933 | skb->csum_offset = offsetof(struct tcphdr, check); |
930 | } else { | 934 | } else { |
931 | th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, | 935 | th->check = tcp_v6_check(skb->len, saddr, daddr, |
932 | csum_partial(th, th->doff<<2, | 936 | csum_partial(th, th->doff << 2, |
933 | skb->csum)); | 937 | skb->csum)); |
934 | } | 938 | } |
935 | } | 939 | } |
936 | 940 | ||
941 | static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb) | ||
942 | { | ||
943 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
944 | |||
945 | __tcp_v6_send_check(skb, &np->saddr, &np->daddr); | ||
946 | } | ||
947 | |||
937 | static int tcp_v6_gso_send_check(struct sk_buff *skb) | 948 | static int tcp_v6_gso_send_check(struct sk_buff *skb) |
938 | { | 949 | { |
939 | struct ipv6hdr *ipv6h; | 950 | struct ipv6hdr *ipv6h; |
@@ -946,11 +957,8 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) | |||
946 | th = tcp_hdr(skb); | 957 | th = tcp_hdr(skb); |
947 | 958 | ||
948 | th->check = 0; | 959 | th->check = 0; |
949 | th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, | ||
950 | IPPROTO_TCP, 0); | ||
951 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
952 | skb->csum_offset = offsetof(struct tcphdr, check); | ||
953 | skb->ip_summed = CHECKSUM_PARTIAL; | 960 | skb->ip_summed = CHECKSUM_PARTIAL; |
961 | __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr); | ||
954 | return 0; | 962 | return 0; |
955 | } | 963 | } |
956 | 964 | ||
@@ -1047,15 +1055,14 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1047 | } | 1055 | } |
1048 | #endif | 1056 | #endif |
1049 | 1057 | ||
1050 | buff->csum = csum_partial(t1, tot_len, 0); | ||
1051 | |||
1052 | memset(&fl, 0, sizeof(fl)); | 1058 | memset(&fl, 0, sizeof(fl)); |
1053 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); | 1059 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); |
1054 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); | 1060 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); |
1055 | 1061 | ||
1056 | t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, | 1062 | buff->ip_summed = CHECKSUM_PARTIAL; |
1057 | tot_len, IPPROTO_TCP, | 1063 | buff->csum = 0; |
1058 | buff->csum); | 1064 | |
1065 | __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst); | ||
1059 | 1066 | ||
1060 | fl.proto = IPPROTO_TCP; | 1067 | fl.proto = IPPROTO_TCP; |
1061 | fl.oif = inet6_iif(skb); | 1068 | fl.oif = inet6_iif(skb); |
@@ -1070,7 +1077,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1070 | if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { | 1077 | if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { |
1071 | if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { | 1078 | if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { |
1072 | skb_dst_set(buff, dst); | 1079 | skb_dst_set(buff, dst); |
1073 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); | 1080 | ip6_xmit(ctl_sk, buff, &fl, NULL); |
1074 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 1081 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
1075 | if (rst) | 1082 | if (rst) |
1076 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | 1083 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); |
@@ -1233,12 +1240,12 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1233 | goto drop_and_free; | 1240 | goto drop_and_free; |
1234 | 1241 | ||
1235 | /* Secret recipe starts with IP addresses */ | 1242 | /* Secret recipe starts with IP addresses */ |
1236 | d = &ipv6_hdr(skb)->daddr.s6_addr32[0]; | 1243 | d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0]; |
1237 | *mess++ ^= *d++; | 1244 | *mess++ ^= *d++; |
1238 | *mess++ ^= *d++; | 1245 | *mess++ ^= *d++; |
1239 | *mess++ ^= *d++; | 1246 | *mess++ ^= *d++; |
1240 | *mess++ ^= *d++; | 1247 | *mess++ ^= *d++; |
1241 | d = &ipv6_hdr(skb)->saddr.s6_addr32[0]; | 1248 | d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0]; |
1242 | *mess++ ^= *d++; | 1249 | *mess++ ^= *d++; |
1243 | *mess++ ^= *d++; | 1250 | *mess++ ^= *d++; |
1244 | *mess++ ^= *d++; | 1251 | *mess++ ^= *d++; |
@@ -1676,6 +1683,7 @@ ipv6_pktoptions: | |||
1676 | static int tcp_v6_rcv(struct sk_buff *skb) | 1683 | static int tcp_v6_rcv(struct sk_buff *skb) |
1677 | { | 1684 | { |
1678 | struct tcphdr *th; | 1685 | struct tcphdr *th; |
1686 | struct ipv6hdr *hdr; | ||
1679 | struct sock *sk; | 1687 | struct sock *sk; |
1680 | int ret; | 1688 | int ret; |
1681 | struct net *net = dev_net(skb->dev); | 1689 | struct net *net = dev_net(skb->dev); |
@@ -1702,12 +1710,13 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1702 | goto bad_packet; | 1710 | goto bad_packet; |
1703 | 1711 | ||
1704 | th = tcp_hdr(skb); | 1712 | th = tcp_hdr(skb); |
1713 | hdr = ipv6_hdr(skb); | ||
1705 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | 1714 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); |
1706 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | 1715 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + |
1707 | skb->len - th->doff*4); | 1716 | skb->len - th->doff*4); |
1708 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | 1717 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); |
1709 | TCP_SKB_CB(skb)->when = 0; | 1718 | TCP_SKB_CB(skb)->when = 0; |
1710 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); | 1719 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(hdr); |
1711 | TCP_SKB_CB(skb)->sacked = 0; | 1720 | TCP_SKB_CB(skb)->sacked = 0; |
1712 | 1721 | ||
1713 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); | 1722 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); |
@@ -1718,6 +1727,11 @@ process: | |||
1718 | if (sk->sk_state == TCP_TIME_WAIT) | 1727 | if (sk->sk_state == TCP_TIME_WAIT) |
1719 | goto do_time_wait; | 1728 | goto do_time_wait; |
1720 | 1729 | ||
1730 | if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) { | ||
1731 | NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); | ||
1732 | goto discard_and_relse; | ||
1733 | } | ||
1734 | |||
1721 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 1735 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
1722 | goto discard_and_relse; | 1736 | goto discard_and_relse; |
1723 | 1737 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 90824852f598..3d7a2c0b836a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -91,9 +91,9 @@ static unsigned int udp6_portaddr_hash(struct net *net, | |||
91 | if (ipv6_addr_any(addr6)) | 91 | if (ipv6_addr_any(addr6)) |
92 | hash = jhash_1word(0, mix); | 92 | hash = jhash_1word(0, mix); |
93 | else if (ipv6_addr_v4mapped(addr6)) | 93 | else if (ipv6_addr_v4mapped(addr6)) |
94 | hash = jhash_1word(addr6->s6_addr32[3], mix); | 94 | hash = jhash_1word((__force u32)addr6->s6_addr32[3], mix); |
95 | else | 95 | else |
96 | hash = jhash2(addr6->s6_addr32, 4, mix); | 96 | hash = jhash2((__force u32 *)addr6->s6_addr32, 4, mix); |
97 | 97 | ||
98 | return hash ^ port; | 98 | return hash ^ port; |
99 | } | 99 | } |
@@ -335,6 +335,9 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
335 | if (flags & MSG_ERRQUEUE) | 335 | if (flags & MSG_ERRQUEUE) |
336 | return ipv6_recv_error(sk, msg, len); | 336 | return ipv6_recv_error(sk, msg, len); |
337 | 337 | ||
338 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) | ||
339 | return ipv6_recv_rxpmtu(sk, msg, len); | ||
340 | |||
338 | try_again: | 341 | try_again: |
339 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), | 342 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), |
340 | &peeked, &err); | 343 | &peeked, &err); |
@@ -421,7 +424,7 @@ out: | |||
421 | return err; | 424 | return err; |
422 | 425 | ||
423 | csum_copy_err: | 426 | csum_copy_err: |
424 | lock_sock(sk); | 427 | lock_sock_bh(sk); |
425 | if (!skb_kill_datagram(sk, skb, flags)) { | 428 | if (!skb_kill_datagram(sk, skb, flags)) { |
426 | if (is_udp4) | 429 | if (is_udp4) |
427 | UDP_INC_STATS_USER(sock_net(sk), | 430 | UDP_INC_STATS_USER(sock_net(sk), |
@@ -430,7 +433,7 @@ csum_copy_err: | |||
430 | UDP6_INC_STATS_USER(sock_net(sk), | 433 | UDP6_INC_STATS_USER(sock_net(sk), |
431 | UDP_MIB_INERRORS, is_udplite); | 434 | UDP_MIB_INERRORS, is_udplite); |
432 | } | 435 | } |
433 | release_sock(sk); | 436 | unlock_sock_bh(sk); |
434 | 437 | ||
435 | if (flags & MSG_DONTWAIT) | 438 | if (flags & MSG_DONTWAIT) |
436 | return -EAGAIN; | 439 | return -EAGAIN; |
@@ -511,7 +514,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
511 | goto drop; | 514 | goto drop; |
512 | } | 515 | } |
513 | 516 | ||
514 | if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { | 517 | if ((rc = ip_queue_rcv_skb(sk, skb)) < 0) { |
515 | /* Note that an ENOMEM error is charged twice */ | 518 | /* Note that an ENOMEM error is charged twice */ |
516 | if (rc == -ENOMEM) | 519 | if (rc == -ENOMEM) |
517 | UDP6_INC_STATS_BH(sock_net(sk), | 520 | UDP6_INC_STATS_BH(sock_net(sk), |
@@ -581,6 +584,10 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
581 | 584 | ||
582 | sk = stack[i]; | 585 | sk = stack[i]; |
583 | if (skb1) { | 586 | if (skb1) { |
587 | if (sk_rcvqueues_full(sk, skb)) { | ||
588 | kfree_skb(skb1); | ||
589 | goto drop; | ||
590 | } | ||
584 | bh_lock_sock(sk); | 591 | bh_lock_sock(sk); |
585 | if (!sock_owned_by_user(sk)) | 592 | if (!sock_owned_by_user(sk)) |
586 | udpv6_queue_rcv_skb(sk, skb1); | 593 | udpv6_queue_rcv_skb(sk, skb1); |
@@ -692,7 +699,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
692 | u32 ulen = 0; | 699 | u32 ulen = 0; |
693 | 700 | ||
694 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 701 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
695 | goto short_packet; | 702 | goto discard; |
696 | 703 | ||
697 | saddr = &ipv6_hdr(skb)->saddr; | 704 | saddr = &ipv6_hdr(skb)->saddr; |
698 | daddr = &ipv6_hdr(skb)->daddr; | 705 | daddr = &ipv6_hdr(skb)->daddr; |
@@ -756,6 +763,10 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
756 | 763 | ||
757 | /* deliver */ | 764 | /* deliver */ |
758 | 765 | ||
766 | if (sk_rcvqueues_full(sk, skb)) { | ||
767 | sock_put(sk); | ||
768 | goto discard; | ||
769 | } | ||
759 | bh_lock_sock(sk); | 770 | bh_lock_sock(sk); |
760 | if (!sock_owned_by_user(sk)) | 771 | if (!sock_owned_by_user(sk)) |
761 | udpv6_queue_rcv_skb(sk, skb); | 772 | udpv6_queue_rcv_skb(sk, skb); |
@@ -770,9 +781,14 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
770 | return 0; | 781 | return 0; |
771 | 782 | ||
772 | short_packet: | 783 | short_packet: |
773 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n", | 784 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: From [%pI6c]:%u %d/%d to [%pI6c]:%u\n", |
774 | proto == IPPROTO_UDPLITE ? "-Lite" : "", | 785 | proto == IPPROTO_UDPLITE ? "-Lite" : "", |
775 | ulen, skb->len); | 786 | saddr, |
787 | ntohs(uh->source), | ||
788 | ulen, | ||
789 | skb->len, | ||
790 | daddr, | ||
791 | ntohs(uh->dest)); | ||
776 | 792 | ||
777 | discard: | 793 | discard: |
778 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); | 794 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
@@ -919,6 +935,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
919 | int ulen = len; | 935 | int ulen = len; |
920 | int hlimit = -1; | 936 | int hlimit = -1; |
921 | int tclass = -1; | 937 | int tclass = -1; |
938 | int dontfrag = -1; | ||
922 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 939 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
923 | int err; | 940 | int err; |
924 | int connected = 0; | 941 | int connected = 0; |
@@ -1049,7 +1066,8 @@ do_udp_sendmsg: | |||
1049 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 1066 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
1050 | opt->tot_len = sizeof(*opt); | 1067 | opt->tot_len = sizeof(*opt); |
1051 | 1068 | ||
1052 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); | 1069 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, |
1070 | &tclass, &dontfrag); | ||
1053 | if (err < 0) { | 1071 | if (err < 0) { |
1054 | fl6_sock_release(flowlabel); | 1072 | fl6_sock_release(flowlabel); |
1055 | return err; | 1073 | return err; |
@@ -1120,6 +1138,9 @@ do_udp_sendmsg: | |||
1120 | if (tclass < 0) | 1138 | if (tclass < 0) |
1121 | tclass = np->tclass; | 1139 | tclass = np->tclass; |
1122 | 1140 | ||
1141 | if (dontfrag < 0) | ||
1142 | dontfrag = np->dontfrag; | ||
1143 | |||
1123 | if (msg->msg_flags&MSG_CONFIRM) | 1144 | if (msg->msg_flags&MSG_CONFIRM) |
1124 | goto do_confirm; | 1145 | goto do_confirm; |
1125 | back_from_confirm: | 1146 | back_from_confirm: |
@@ -1143,7 +1164,7 @@ do_append_data: | |||
1143 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, | 1164 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, |
1144 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, | 1165 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, |
1145 | (struct rt6_info*)dst, | 1166 | (struct rt6_info*)dst, |
1146 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 1167 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); |
1147 | if (err) | 1168 | if (err) |
1148 | udp_v6_flush_pending_frames(sk); | 1169 | udp_v6_flush_pending_frames(sk); |
1149 | else if (!corkreq) | 1170 | else if (!corkreq) |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 2bc98ede1235..f8c3cf842f53 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -42,7 +42,7 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async) | |||
42 | ipv6_hdr(skb)->payload_len = htons(skb->len); | 42 | ipv6_hdr(skb)->payload_len = htons(skb->len); |
43 | __skb_push(skb, skb->data - skb_network_header(skb)); | 43 | __skb_push(skb, skb->data - skb_network_header(skb)); |
44 | 44 | ||
45 | NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, | 45 | NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, |
46 | ip6_rcv_finish); | 46 | ip6_rcv_finish); |
47 | return -1; | 47 | return -1; |
48 | } | 48 | } |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 0c92112dcba3..6434bd5ce088 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -90,6 +90,6 @@ static int xfrm6_output_finish(struct sk_buff *skb) | |||
90 | 90 | ||
91 | int xfrm6_output(struct sk_buff *skb) | 91 | int xfrm6_output(struct sk_buff *skb) |
92 | { | 92 | { |
93 | return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb_dst(skb)->dev, | 93 | return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, |
94 | xfrm6_output_finish); | 94 | skb_dst(skb)->dev, xfrm6_output_finish); |
95 | } | 95 | } |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 00bf7c962b7e..4a0e77e14468 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -67,36 +67,6 @@ static int xfrm6_get_saddr(struct net *net, | |||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | static struct dst_entry * | ||
71 | __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | ||
72 | { | ||
73 | struct dst_entry *dst; | ||
74 | |||
75 | /* Still not clear if we should set fl->fl6_{src,dst}... */ | ||
76 | read_lock_bh(&policy->lock); | ||
77 | for (dst = policy->bundles; dst; dst = dst->next) { | ||
78 | struct xfrm_dst *xdst = (struct xfrm_dst*)dst; | ||
79 | struct in6_addr fl_dst_prefix, fl_src_prefix; | ||
80 | |||
81 | ipv6_addr_prefix(&fl_dst_prefix, | ||
82 | &fl->fl6_dst, | ||
83 | xdst->u.rt6.rt6i_dst.plen); | ||
84 | ipv6_addr_prefix(&fl_src_prefix, | ||
85 | &fl->fl6_src, | ||
86 | xdst->u.rt6.rt6i_src.plen); | ||
87 | if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && | ||
88 | ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && | ||
89 | xfrm_bundle_ok(policy, xdst, fl, AF_INET6, | ||
90 | (xdst->u.rt6.rt6i_dst.plen != 128 || | ||
91 | xdst->u.rt6.rt6i_src.plen != 128))) { | ||
92 | dst_clone(dst); | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | read_unlock_bh(&policy->lock); | ||
97 | return dst; | ||
98 | } | ||
99 | |||
100 | static int xfrm6_get_tos(struct flowi *fl) | 70 | static int xfrm6_get_tos(struct flowi *fl) |
101 | { | 71 | { |
102 | return 0; | 72 | return 0; |
@@ -291,7 +261,6 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | |||
291 | .dst_ops = &xfrm6_dst_ops, | 261 | .dst_ops = &xfrm6_dst_ops, |
292 | .dst_lookup = xfrm6_dst_lookup, | 262 | .dst_lookup = xfrm6_dst_lookup, |
293 | .get_saddr = xfrm6_get_saddr, | 263 | .get_saddr = xfrm6_get_saddr, |
294 | .find_bundle = __xfrm6_find_bundle, | ||
295 | .decode_session = _decode_session6, | 264 | .decode_session = _decode_session6, |
296 | .get_tos = xfrm6_get_tos, | 265 | .get_tos = xfrm6_get_tos, |
297 | .init_path = xfrm6_init_path, | 266 | .init_path = xfrm6_init_path, |
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 2a4efcea3423..79986a674f6e 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -347,7 +347,7 @@ static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow) | |||
347 | self->tx_flow = flow; | 347 | self->tx_flow = flow; |
348 | IRDA_DEBUG(1, "%s(), IrTTP wants us to start again\n", | 348 | IRDA_DEBUG(1, "%s(), IrTTP wants us to start again\n", |
349 | __func__); | 349 | __func__); |
350 | wake_up_interruptible(sk->sk_sleep); | 350 | wake_up_interruptible(sk_sleep(sk)); |
351 | break; | 351 | break; |
352 | default: | 352 | default: |
353 | IRDA_DEBUG(0, "%s(), Unknown flow command!\n", __func__); | 353 | IRDA_DEBUG(0, "%s(), Unknown flow command!\n", __func__); |
@@ -900,7 +900,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
900 | if (flags & O_NONBLOCK) | 900 | if (flags & O_NONBLOCK) |
901 | goto out; | 901 | goto out; |
902 | 902 | ||
903 | err = wait_event_interruptible(*(sk->sk_sleep), | 903 | err = wait_event_interruptible(*(sk_sleep(sk)), |
904 | skb_peek(&sk->sk_receive_queue)); | 904 | skb_peek(&sk->sk_receive_queue)); |
905 | if (err) | 905 | if (err) |
906 | goto out; | 906 | goto out; |
@@ -1066,7 +1066,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1066 | goto out; | 1066 | goto out; |
1067 | 1067 | ||
1068 | err = -ERESTARTSYS; | 1068 | err = -ERESTARTSYS; |
1069 | if (wait_event_interruptible(*(sk->sk_sleep), | 1069 | if (wait_event_interruptible(*(sk_sleep(sk)), |
1070 | (sk->sk_state != TCP_SYN_SENT))) | 1070 | (sk->sk_state != TCP_SYN_SENT))) |
1071 | goto out; | 1071 | goto out; |
1072 | 1072 | ||
@@ -1318,7 +1318,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1318 | 1318 | ||
1319 | /* Check if IrTTP is wants us to slow down */ | 1319 | /* Check if IrTTP is wants us to slow down */ |
1320 | 1320 | ||
1321 | if (wait_event_interruptible(*(sk->sk_sleep), | 1321 | if (wait_event_interruptible(*(sk_sleep(sk)), |
1322 | (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) { | 1322 | (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) { |
1323 | err = -ERESTARTSYS; | 1323 | err = -ERESTARTSYS; |
1324 | goto out; | 1324 | goto out; |
@@ -1477,7 +1477,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1477 | if (copied >= target) | 1477 | if (copied >= target) |
1478 | break; | 1478 | break; |
1479 | 1479 | ||
1480 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1480 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1481 | 1481 | ||
1482 | /* | 1482 | /* |
1483 | * POSIX 1003.1g mandates this order. | 1483 | * POSIX 1003.1g mandates this order. |
@@ -1497,7 +1497,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1497 | /* Wait process until data arrives */ | 1497 | /* Wait process until data arrives */ |
1498 | schedule(); | 1498 | schedule(); |
1499 | 1499 | ||
1500 | finish_wait(sk->sk_sleep, &wait); | 1500 | finish_wait(sk_sleep(sk), &wait); |
1501 | 1501 | ||
1502 | if (err) | 1502 | if (err) |
1503 | goto out; | 1503 | goto out; |
@@ -1787,7 +1787,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, | |||
1787 | IRDA_DEBUG(4, "%s()\n", __func__); | 1787 | IRDA_DEBUG(4, "%s()\n", __func__); |
1788 | 1788 | ||
1789 | lock_kernel(); | 1789 | lock_kernel(); |
1790 | poll_wait(file, sk->sk_sleep, wait); | 1790 | poll_wait(file, sk_sleep(sk), wait); |
1791 | mask = 0; | 1791 | mask = 0; |
1792 | 1792 | ||
1793 | /* Exceptional events? */ | 1793 | /* Exceptional events? */ |
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c index e2e893b474e9..8b915f3ac3b9 100644 --- a/net/irda/ircomm/ircomm_param.c +++ b/net/irda/ircomm/ircomm_param.c | |||
@@ -475,7 +475,7 @@ static int ircomm_param_dce(void *instance, irda_param_t *param, int get) | |||
475 | /* Check if any of the settings have changed */ | 475 | /* Check if any of the settings have changed */ |
476 | if (dce & 0x0f) { | 476 | if (dce & 0x0f) { |
477 | if (dce & IRCOMM_DELTA_CTS) { | 477 | if (dce & IRCOMM_DELTA_CTS) { |
478 | IRDA_DEBUG(2, "%s(), CTS \n", __func__ ); | 478 | IRDA_DEBUG(2, "%s(), CTS\n", __func__ ); |
479 | } | 479 | } |
480 | } | 480 | } |
481 | 481 | ||
diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 79a1e5a23e10..fce364c6c71a 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c | |||
@@ -685,8 +685,6 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self, | |||
685 | /* We have a match; send the value. */ | 685 | /* We have a match; send the value. */ |
686 | iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS, | 686 | iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS, |
687 | attrib->value); | 687 | attrib->value); |
688 | |||
689 | return; | ||
690 | } | 688 | } |
691 | 689 | ||
692 | /* | 690 | /* |
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c index df18ab4b6c5e..e98e40d76f4f 100644 --- a/net/irda/irnet/irnet_irda.c +++ b/net/irda/irnet/irnet_irda.c | |||
@@ -678,7 +678,6 @@ irda_irnet_destroy(irnet_socket * self) | |||
678 | self->stsap_sel = 0; | 678 | self->stsap_sel = 0; |
679 | 679 | ||
680 | DEXIT(IRDA_SOCK_TRACE, "\n"); | 680 | DEXIT(IRDA_SOCK_TRACE, "\n"); |
681 | return; | ||
682 | } | 681 | } |
683 | 682 | ||
684 | 683 | ||
@@ -928,7 +927,6 @@ irnet_disconnect_server(irnet_socket * self, | |||
928 | irttp_listen(self->tsap); | 927 | irttp_listen(self->tsap); |
929 | 928 | ||
930 | DEXIT(IRDA_SERV_TRACE, "\n"); | 929 | DEXIT(IRDA_SERV_TRACE, "\n"); |
931 | return; | ||
932 | } | 930 | } |
933 | 931 | ||
934 | /*------------------------------------------------------------------*/ | 932 | /*------------------------------------------------------------------*/ |
@@ -1013,7 +1011,6 @@ irnet_destroy_server(void) | |||
1013 | irda_irnet_destroy(&irnet_server.s); | 1011 | irda_irnet_destroy(&irnet_server.s); |
1014 | 1012 | ||
1015 | DEXIT(IRDA_SERV_TRACE, "\n"); | 1013 | DEXIT(IRDA_SERV_TRACE, "\n"); |
1016 | return; | ||
1017 | } | 1014 | } |
1018 | 1015 | ||
1019 | 1016 | ||
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index c18286a2167b..c8b4599a752e 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -59,7 +59,7 @@ do { \ | |||
59 | DEFINE_WAIT(__wait); \ | 59 | DEFINE_WAIT(__wait); \ |
60 | long __timeo = timeo; \ | 60 | long __timeo = timeo; \ |
61 | ret = 0; \ | 61 | ret = 0; \ |
62 | prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE); \ | 62 | prepare_to_wait(sk_sleep(sk), &__wait, TASK_INTERRUPTIBLE); \ |
63 | while (!(condition)) { \ | 63 | while (!(condition)) { \ |
64 | if (!__timeo) { \ | 64 | if (!__timeo) { \ |
65 | ret = -EAGAIN; \ | 65 | ret = -EAGAIN; \ |
@@ -76,7 +76,7 @@ do { \ | |||
76 | if (ret) \ | 76 | if (ret) \ |
77 | break; \ | 77 | break; \ |
78 | } \ | 78 | } \ |
79 | finish_wait(sk->sk_sleep, &__wait); \ | 79 | finish_wait(sk_sleep(sk), &__wait); \ |
80 | } while (0) | 80 | } while (0) |
81 | 81 | ||
82 | #define iucv_sock_wait(sk, condition, timeo) \ | 82 | #define iucv_sock_wait(sk, condition, timeo) \ |
@@ -136,7 +136,6 @@ static void afiucv_pm_complete(struct device *dev) | |||
136 | #ifdef CONFIG_PM_DEBUG | 136 | #ifdef CONFIG_PM_DEBUG |
137 | printk(KERN_WARNING "afiucv_pm_complete\n"); | 137 | printk(KERN_WARNING "afiucv_pm_complete\n"); |
138 | #endif | 138 | #endif |
139 | return; | ||
140 | } | 139 | } |
141 | 140 | ||
142 | /** | 141 | /** |
@@ -305,11 +304,14 @@ static inline int iucv_below_msglim(struct sock *sk) | |||
305 | */ | 304 | */ |
306 | static void iucv_sock_wake_msglim(struct sock *sk) | 305 | static void iucv_sock_wake_msglim(struct sock *sk) |
307 | { | 306 | { |
308 | read_lock(&sk->sk_callback_lock); | 307 | struct socket_wq *wq; |
309 | if (sk_has_sleeper(sk)) | 308 | |
310 | wake_up_interruptible_all(sk->sk_sleep); | 309 | rcu_read_lock(); |
310 | wq = rcu_dereference(sk->sk_wq); | ||
311 | if (wq_has_sleeper(wq)) | ||
312 | wake_up_interruptible_all(&wq->wait); | ||
311 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 313 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
312 | read_unlock(&sk->sk_callback_lock); | 314 | rcu_read_unlock(); |
313 | } | 315 | } |
314 | 316 | ||
315 | /* Timers */ | 317 | /* Timers */ |
@@ -795,7 +797,7 @@ static int iucv_sock_accept(struct socket *sock, struct socket *newsock, | |||
795 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); | 797 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); |
796 | 798 | ||
797 | /* Wait for an incoming connection */ | 799 | /* Wait for an incoming connection */ |
798 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 800 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
799 | while (!(nsk = iucv_accept_dequeue(sk, newsock))) { | 801 | while (!(nsk = iucv_accept_dequeue(sk, newsock))) { |
800 | set_current_state(TASK_INTERRUPTIBLE); | 802 | set_current_state(TASK_INTERRUPTIBLE); |
801 | if (!timeo) { | 803 | if (!timeo) { |
@@ -819,7 +821,7 @@ static int iucv_sock_accept(struct socket *sock, struct socket *newsock, | |||
819 | } | 821 | } |
820 | 822 | ||
821 | set_current_state(TASK_RUNNING); | 823 | set_current_state(TASK_RUNNING); |
822 | remove_wait_queue(sk->sk_sleep, &wait); | 824 | remove_wait_queue(sk_sleep(sk), &wait); |
823 | 825 | ||
824 | if (err) | 826 | if (err) |
825 | goto done; | 827 | goto done; |
@@ -1269,7 +1271,7 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock, | |||
1269 | struct sock *sk = sock->sk; | 1271 | struct sock *sk = sock->sk; |
1270 | unsigned int mask = 0; | 1272 | unsigned int mask = 0; |
1271 | 1273 | ||
1272 | sock_poll_wait(file, sk->sk_sleep, wait); | 1274 | sock_poll_wait(file, sk_sleep(sk), wait); |
1273 | 1275 | ||
1274 | if (sk->sk_state == IUCV_LISTEN) | 1276 | if (sk->sk_state == IUCV_LISTEN) |
1275 | return iucv_accept_poll(sk); | 1277 | return iucv_accept_poll(sk); |
diff --git a/net/key/af_key.c b/net/key/af_key.c index ba9a3fcc2fed..43040e97c474 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -99,7 +99,7 @@ static void pfkey_sock_destruct(struct sock *sk) | |||
99 | skb_queue_purge(&sk->sk_receive_queue); | 99 | skb_queue_purge(&sk->sk_receive_queue); |
100 | 100 | ||
101 | if (!sock_flag(sk, SOCK_DEAD)) { | 101 | if (!sock_flag(sk, SOCK_DEAD)) { |
102 | printk("Attempt to release alive pfkey socket: %p\n", sk); | 102 | pr_err("Attempt to release alive pfkey socket: %p\n", sk); |
103 | return; | 103 | return; |
104 | } | 104 | } |
105 | 105 | ||
@@ -1402,7 +1402,7 @@ static inline int event2poltype(int event) | |||
1402 | case XFRM_MSG_POLEXPIRE: | 1402 | case XFRM_MSG_POLEXPIRE: |
1403 | // return SADB_X_SPDEXPIRE; | 1403 | // return SADB_X_SPDEXPIRE; |
1404 | default: | 1404 | default: |
1405 | printk("pfkey: Unknown policy event %d\n", event); | 1405 | pr_err("pfkey: Unknown policy event %d\n", event); |
1406 | break; | 1406 | break; |
1407 | } | 1407 | } |
1408 | 1408 | ||
@@ -1421,7 +1421,7 @@ static inline int event2keytype(int event) | |||
1421 | case XFRM_MSG_EXPIRE: | 1421 | case XFRM_MSG_EXPIRE: |
1422 | return SADB_EXPIRE; | 1422 | return SADB_EXPIRE; |
1423 | default: | 1423 | default: |
1424 | printk("pfkey: Unknown SA event %d\n", event); | 1424 | pr_err("pfkey: Unknown SA event %d\n", event); |
1425 | break; | 1425 | break; |
1426 | } | 1426 | } |
1427 | 1427 | ||
@@ -2969,7 +2969,7 @@ static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c) | |||
2969 | case XFRM_MSG_NEWAE: /* not yet supported */ | 2969 | case XFRM_MSG_NEWAE: /* not yet supported */ |
2970 | break; | 2970 | break; |
2971 | default: | 2971 | default: |
2972 | printk("pfkey: Unknown SA event %d\n", c->event); | 2972 | pr_err("pfkey: Unknown SA event %d\n", c->event); |
2973 | break; | 2973 | break; |
2974 | } | 2974 | } |
2975 | 2975 | ||
@@ -2993,7 +2993,7 @@ static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_e | |||
2993 | break; | 2993 | break; |
2994 | return key_notify_policy_flush(c); | 2994 | return key_notify_policy_flush(c); |
2995 | default: | 2995 | default: |
2996 | printk("pfkey: Unknown policy event %d\n", c->event); | 2996 | pr_err("pfkey: Unknown policy event %d\n", c->event); |
2997 | break; | 2997 | break; |
2998 | } | 2998 | } |
2999 | 2999 | ||
diff --git a/net/l2tp/Kconfig b/net/l2tp/Kconfig new file mode 100644 index 000000000000..4b1e71751e10 --- /dev/null +++ b/net/l2tp/Kconfig | |||
@@ -0,0 +1,107 @@ | |||
1 | # | ||
2 | # Layer Two Tunneling Protocol (L2TP) | ||
3 | # | ||
4 | |||
5 | menuconfig L2TP | ||
6 | tristate "Layer Two Tunneling Protocol (L2TP)" | ||
7 | depends on INET | ||
8 | ---help--- | ||
9 | Layer Two Tunneling Protocol | ||
10 | |||
11 | From RFC 2661 <http://www.ietf.org/rfc/rfc2661.txt>. | ||
12 | |||
13 | L2TP facilitates the tunneling of packets across an | ||
14 | intervening network in a way that is as transparent as | ||
15 | possible to both end-users and applications. | ||
16 | |||
17 | L2TP is often used to tunnel PPP traffic over IP | ||
18 | tunnels. One IP tunnel may carry thousands of individual PPP | ||
19 | connections. L2TP is also used as a VPN protocol, popular | ||
20 | with home workers to connect to their offices. | ||
21 | |||
22 | L2TPv3 allows other protocols as well as PPP to be carried | ||
23 | over L2TP tunnels. L2TPv3 is defined in RFC 3931 | ||
24 | <http://www.ietf.org/rfc/rfc3931.txt>. | ||
25 | |||
26 | The kernel component handles only L2TP data packets: a | ||
27 | userland daemon handles L2TP the control protocol (tunnel | ||
28 | and session setup). One such daemon is OpenL2TP | ||
29 | (http://openl2tp.org/). | ||
30 | |||
31 | If you don't need L2TP, say N. To compile all L2TP code as | ||
32 | modules, choose M here. | ||
33 | |||
34 | config L2TP_DEBUGFS | ||
35 | tristate "L2TP debugfs support" | ||
36 | depends on L2TP && DEBUG_FS | ||
37 | help | ||
38 | Support for l2tp directory in debugfs filesystem. This may be | ||
39 | used to dump internal state of the l2tp drivers for problem | ||
40 | analysis. | ||
41 | |||
42 | If unsure, say 'Y'. | ||
43 | |||
44 | To compile this driver as a module, choose M here. The module | ||
45 | will be called l2tp_debugfs. | ||
46 | |||
47 | config L2TP_V3 | ||
48 | bool "L2TPv3 support (EXPERIMENTAL)" | ||
49 | depends on EXPERIMENTAL && L2TP | ||
50 | help | ||
51 | Layer Two Tunneling Protocol Version 3 | ||
52 | |||
53 | From RFC 3931 <http://www.ietf.org/rfc/rfc3931.txt>. | ||
54 | |||
55 | The Layer Two Tunneling Protocol (L2TP) provides a dynamic | ||
56 | mechanism for tunneling Layer 2 (L2) "circuits" across a | ||
57 | packet-oriented data network (e.g., over IP). L2TP, as | ||
58 | originally defined in RFC 2661, is a standard method for | ||
59 | tunneling Point-to-Point Protocol (PPP) [RFC1661] sessions. | ||
60 | L2TP has since been adopted for tunneling a number of other | ||
61 | L2 protocols, including ATM, Frame Relay, HDLC and even raw | ||
62 | ethernet frames. | ||
63 | |||
64 | If you are connecting to L2TPv3 equipment, or you want to | ||
65 | tunnel raw ethernet frames using L2TP, say Y here. If | ||
66 | unsure, say N. | ||
67 | |||
68 | config L2TP_IP | ||
69 | tristate "L2TP IP encapsulation for L2TPv3" | ||
70 | depends on L2TP_V3 | ||
71 | help | ||
72 | Support for L2TP-over-IP socket family. | ||
73 | |||
74 | The L2TPv3 protocol defines two possible encapsulations for | ||
75 | L2TP frames, namely UDP and plain IP (without UDP). This | ||
76 | driver provides a new L2TPIP socket family with which | ||
77 | userspace L2TPv3 daemons may create L2TP/IP tunnel sockets | ||
78 | when UDP encapsulation is not required. When L2TP is carried | ||
79 | in IP packets, it used IP protocol number 115, so this port | ||
80 | must be enabled in firewalls. | ||
81 | |||
82 | To compile this driver as a module, choose M here. The module | ||
83 | will be called l2tp_ip. | ||
84 | |||
85 | config L2TP_ETH | ||
86 | tristate "L2TP ethernet pseudowire support for L2TPv3" | ||
87 | depends on L2TP_V3 | ||
88 | help | ||
89 | Support for carrying raw ethernet frames over L2TPv3. | ||
90 | |||
91 | From RFC 4719 <http://www.ietf.org/rfc/rfc4719.txt>. | ||
92 | |||
93 | The Layer 2 Tunneling Protocol, Version 3 (L2TPv3) can be | ||
94 | used as a control protocol and for data encapsulation to set | ||
95 | up Pseudowires for transporting layer 2 Packet Data Units | ||
96 | across an IP network [RFC3931]. | ||
97 | |||
98 | This driver provides an ethernet virtual interface for each | ||
99 | L2TP ethernet pseudowire instance. Standard Linux tools may | ||
100 | be used to assign an IP address to the local virtual | ||
101 | interface, or add the interface to a bridge. | ||
102 | |||
103 | If you are using L2TPv3, you will almost certainly want to | ||
104 | enable this option. | ||
105 | |||
106 | To compile this driver as a module, choose M here. The module | ||
107 | will be called l2tp_eth. | ||
diff --git a/net/l2tp/Makefile b/net/l2tp/Makefile new file mode 100644 index 000000000000..110e7bc2de5e --- /dev/null +++ b/net/l2tp/Makefile | |||
@@ -0,0 +1,12 @@ | |||
1 | # | ||
2 | # Makefile for the L2TP. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_L2TP) += l2tp_core.o | ||
6 | |||
7 | # Build l2tp as modules if L2TP is M | ||
8 | obj-$(subst y,$(CONFIG_L2TP),$(CONFIG_PPPOL2TP)) += l2tp_ppp.o | ||
9 | obj-$(subst y,$(CONFIG_L2TP),$(CONFIG_L2TP_IP)) += l2tp_ip.o | ||
10 | obj-$(subst y,$(CONFIG_L2TP),$(CONFIG_L2TP_V3)) += l2tp_netlink.o | ||
11 | obj-$(subst y,$(CONFIG_L2TP),$(CONFIG_L2TP_ETH)) += l2tp_eth.o | ||
12 | obj-$(subst y,$(CONFIG_L2TP),$(CONFIG_L2TP_DEBUGFS)) += l2tp_debugfs.o | ||
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c new file mode 100644 index 000000000000..1712af1c7b3f --- /dev/null +++ b/net/l2tp/l2tp_core.c | |||
@@ -0,0 +1,1666 @@ | |||
1 | /* | ||
2 | * L2TP core. | ||
3 | * | ||
4 | * Copyright (c) 2008,2009,2010 Katalix Systems Ltd | ||
5 | * | ||
6 | * This file contains some code of the original L2TPv2 pppol2tp | ||
7 | * driver, which has the following copyright: | ||
8 | * | ||
9 | * Authors: Martijn van Oosterhout <kleptog@svana.org> | ||
10 | * James Chapman (jchapman@katalix.com) | ||
11 | * Contributors: | ||
12 | * Michal Ostrowski <mostrows@speakeasy.net> | ||
13 | * Arnaldo Carvalho de Melo <acme@xconectiva.com.br> | ||
14 | * David S. Miller (davem@redhat.com) | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License version 2 as | ||
18 | * published by the Free Software Foundation. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/rculist.h> | ||
25 | #include <linux/uaccess.h> | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/spinlock.h> | ||
29 | #include <linux/kthread.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/jiffies.h> | ||
34 | |||
35 | #include <linux/netdevice.h> | ||
36 | #include <linux/net.h> | ||
37 | #include <linux/inetdevice.h> | ||
38 | #include <linux/skbuff.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/in.h> | ||
41 | #include <linux/ip.h> | ||
42 | #include <linux/udp.h> | ||
43 | #include <linux/l2tp.h> | ||
44 | #include <linux/hash.h> | ||
45 | #include <linux/sort.h> | ||
46 | #include <linux/file.h> | ||
47 | #include <linux/nsproxy.h> | ||
48 | #include <net/net_namespace.h> | ||
49 | #include <net/netns/generic.h> | ||
50 | #include <net/dst.h> | ||
51 | #include <net/ip.h> | ||
52 | #include <net/udp.h> | ||
53 | #include <net/inet_common.h> | ||
54 | #include <net/xfrm.h> | ||
55 | #include <net/protocol.h> | ||
56 | |||
57 | #include <asm/byteorder.h> | ||
58 | #include <asm/atomic.h> | ||
59 | |||
60 | #include "l2tp_core.h" | ||
61 | |||
62 | #define L2TP_DRV_VERSION "V2.0" | ||
63 | |||
64 | /* L2TP header constants */ | ||
65 | #define L2TP_HDRFLAG_T 0x8000 | ||
66 | #define L2TP_HDRFLAG_L 0x4000 | ||
67 | #define L2TP_HDRFLAG_S 0x0800 | ||
68 | #define L2TP_HDRFLAG_O 0x0200 | ||
69 | #define L2TP_HDRFLAG_P 0x0100 | ||
70 | |||
71 | #define L2TP_HDR_VER_MASK 0x000F | ||
72 | #define L2TP_HDR_VER_2 0x0002 | ||
73 | #define L2TP_HDR_VER_3 0x0003 | ||
74 | |||
75 | /* L2TPv3 default L2-specific sublayer */ | ||
76 | #define L2TP_SLFLAG_S 0x40000000 | ||
77 | #define L2TP_SL_SEQ_MASK 0x00ffffff | ||
78 | |||
79 | #define L2TP_HDR_SIZE_SEQ 10 | ||
80 | #define L2TP_HDR_SIZE_NOSEQ 6 | ||
81 | |||
82 | /* Default trace flags */ | ||
83 | #define L2TP_DEFAULT_DEBUG_FLAGS 0 | ||
84 | |||
85 | #define PRINTK(_mask, _type, _lvl, _fmt, args...) \ | ||
86 | do { \ | ||
87 | if ((_mask) & (_type)) \ | ||
88 | printk(_lvl "L2TP: " _fmt, ##args); \ | ||
89 | } while (0) | ||
90 | |||
91 | /* Private data stored for received packets in the skb. | ||
92 | */ | ||
93 | struct l2tp_skb_cb { | ||
94 | u32 ns; | ||
95 | u16 has_seq; | ||
96 | u16 length; | ||
97 | unsigned long expires; | ||
98 | }; | ||
99 | |||
100 | #define L2TP_SKB_CB(skb) ((struct l2tp_skb_cb *) &skb->cb[sizeof(struct inet_skb_parm)]) | ||
101 | |||
102 | static atomic_t l2tp_tunnel_count; | ||
103 | static atomic_t l2tp_session_count; | ||
104 | |||
105 | /* per-net private data for this module */ | ||
106 | static unsigned int l2tp_net_id; | ||
107 | struct l2tp_net { | ||
108 | struct list_head l2tp_tunnel_list; | ||
109 | spinlock_t l2tp_tunnel_list_lock; | ||
110 | struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2]; | ||
111 | spinlock_t l2tp_session_hlist_lock; | ||
112 | }; | ||
113 | |||
114 | static inline struct l2tp_net *l2tp_pernet(struct net *net) | ||
115 | { | ||
116 | BUG_ON(!net); | ||
117 | |||
118 | return net_generic(net, l2tp_net_id); | ||
119 | } | ||
120 | |||
121 | /* Session hash global list for L2TPv3. | ||
122 | * The session_id SHOULD be random according to RFC3931, but several | ||
123 | * L2TP implementations use incrementing session_ids. So we do a real | ||
124 | * hash on the session_id, rather than a simple bitmask. | ||
125 | */ | ||
126 | static inline struct hlist_head * | ||
127 | l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id) | ||
128 | { | ||
129 | return &pn->l2tp_session_hlist[hash_32(session_id, L2TP_HASH_BITS_2)]; | ||
130 | |||
131 | } | ||
132 | |||
133 | /* Lookup a session by id in the global session list | ||
134 | */ | ||
135 | static struct l2tp_session *l2tp_session_find_2(struct net *net, u32 session_id) | ||
136 | { | ||
137 | struct l2tp_net *pn = l2tp_pernet(net); | ||
138 | struct hlist_head *session_list = | ||
139 | l2tp_session_id_hash_2(pn, session_id); | ||
140 | struct l2tp_session *session; | ||
141 | struct hlist_node *walk; | ||
142 | |||
143 | rcu_read_lock_bh(); | ||
144 | hlist_for_each_entry_rcu(session, walk, session_list, global_hlist) { | ||
145 | if (session->session_id == session_id) { | ||
146 | rcu_read_unlock_bh(); | ||
147 | return session; | ||
148 | } | ||
149 | } | ||
150 | rcu_read_unlock_bh(); | ||
151 | |||
152 | return NULL; | ||
153 | } | ||
154 | |||
155 | /* Session hash list. | ||
156 | * The session_id SHOULD be random according to RFC2661, but several | ||
157 | * L2TP implementations (Cisco and Microsoft) use incrementing | ||
158 | * session_ids. So we do a real hash on the session_id, rather than a | ||
159 | * simple bitmask. | ||
160 | */ | ||
161 | static inline struct hlist_head * | ||
162 | l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id) | ||
163 | { | ||
164 | return &tunnel->session_hlist[hash_32(session_id, L2TP_HASH_BITS)]; | ||
165 | } | ||
166 | |||
167 | /* Lookup a session by id | ||
168 | */ | ||
169 | struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id) | ||
170 | { | ||
171 | struct hlist_head *session_list; | ||
172 | struct l2tp_session *session; | ||
173 | struct hlist_node *walk; | ||
174 | |||
175 | /* In L2TPv3, session_ids are unique over all tunnels and we | ||
176 | * sometimes need to look them up before we know the | ||
177 | * tunnel. | ||
178 | */ | ||
179 | if (tunnel == NULL) | ||
180 | return l2tp_session_find_2(net, session_id); | ||
181 | |||
182 | session_list = l2tp_session_id_hash(tunnel, session_id); | ||
183 | read_lock_bh(&tunnel->hlist_lock); | ||
184 | hlist_for_each_entry(session, walk, session_list, hlist) { | ||
185 | if (session->session_id == session_id) { | ||
186 | read_unlock_bh(&tunnel->hlist_lock); | ||
187 | return session; | ||
188 | } | ||
189 | } | ||
190 | read_unlock_bh(&tunnel->hlist_lock); | ||
191 | |||
192 | return NULL; | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(l2tp_session_find); | ||
195 | |||
196 | struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth) | ||
197 | { | ||
198 | int hash; | ||
199 | struct hlist_node *walk; | ||
200 | struct l2tp_session *session; | ||
201 | int count = 0; | ||
202 | |||
203 | read_lock_bh(&tunnel->hlist_lock); | ||
204 | for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { | ||
205 | hlist_for_each_entry(session, walk, &tunnel->session_hlist[hash], hlist) { | ||
206 | if (++count > nth) { | ||
207 | read_unlock_bh(&tunnel->hlist_lock); | ||
208 | return session; | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | |||
213 | read_unlock_bh(&tunnel->hlist_lock); | ||
214 | |||
215 | return NULL; | ||
216 | } | ||
217 | EXPORT_SYMBOL_GPL(l2tp_session_find_nth); | ||
218 | |||
219 | /* Lookup a session by interface name. | ||
220 | * This is very inefficient but is only used by management interfaces. | ||
221 | */ | ||
222 | struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname) | ||
223 | { | ||
224 | struct l2tp_net *pn = l2tp_pernet(net); | ||
225 | int hash; | ||
226 | struct hlist_node *walk; | ||
227 | struct l2tp_session *session; | ||
228 | |||
229 | rcu_read_lock_bh(); | ||
230 | for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) { | ||
231 | hlist_for_each_entry_rcu(session, walk, &pn->l2tp_session_hlist[hash], global_hlist) { | ||
232 | if (!strcmp(session->ifname, ifname)) { | ||
233 | rcu_read_unlock_bh(); | ||
234 | return session; | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | |||
239 | rcu_read_unlock_bh(); | ||
240 | |||
241 | return NULL; | ||
242 | } | ||
243 | EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname); | ||
244 | |||
245 | /* Lookup a tunnel by id | ||
246 | */ | ||
247 | struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id) | ||
248 | { | ||
249 | struct l2tp_tunnel *tunnel; | ||
250 | struct l2tp_net *pn = l2tp_pernet(net); | ||
251 | |||
252 | rcu_read_lock_bh(); | ||
253 | list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { | ||
254 | if (tunnel->tunnel_id == tunnel_id) { | ||
255 | rcu_read_unlock_bh(); | ||
256 | return tunnel; | ||
257 | } | ||
258 | } | ||
259 | rcu_read_unlock_bh(); | ||
260 | |||
261 | return NULL; | ||
262 | } | ||
263 | EXPORT_SYMBOL_GPL(l2tp_tunnel_find); | ||
264 | |||
265 | struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth) | ||
266 | { | ||
267 | struct l2tp_net *pn = l2tp_pernet(net); | ||
268 | struct l2tp_tunnel *tunnel; | ||
269 | int count = 0; | ||
270 | |||
271 | rcu_read_lock_bh(); | ||
272 | list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { | ||
273 | if (++count > nth) { | ||
274 | rcu_read_unlock_bh(); | ||
275 | return tunnel; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | rcu_read_unlock_bh(); | ||
280 | |||
281 | return NULL; | ||
282 | } | ||
283 | EXPORT_SYMBOL_GPL(l2tp_tunnel_find_nth); | ||
284 | |||
285 | /***************************************************************************** | ||
286 | * Receive data handling | ||
287 | *****************************************************************************/ | ||
288 | |||
289 | /* Queue a skb in order. We come here only if the skb has an L2TP sequence | ||
290 | * number. | ||
291 | */ | ||
292 | static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *skb) | ||
293 | { | ||
294 | struct sk_buff *skbp; | ||
295 | struct sk_buff *tmp; | ||
296 | u32 ns = L2TP_SKB_CB(skb)->ns; | ||
297 | |||
298 | spin_lock_bh(&session->reorder_q.lock); | ||
299 | skb_queue_walk_safe(&session->reorder_q, skbp, tmp) { | ||
300 | if (L2TP_SKB_CB(skbp)->ns > ns) { | ||
301 | __skb_queue_before(&session->reorder_q, skbp, skb); | ||
302 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
303 | "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n", | ||
304 | session->name, ns, L2TP_SKB_CB(skbp)->ns, | ||
305 | skb_queue_len(&session->reorder_q)); | ||
306 | session->stats.rx_oos_packets++; | ||
307 | goto out; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | __skb_queue_tail(&session->reorder_q, skb); | ||
312 | |||
313 | out: | ||
314 | spin_unlock_bh(&session->reorder_q.lock); | ||
315 | } | ||
316 | |||
317 | /* Dequeue a single skb. | ||
318 | */ | ||
319 | static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *skb) | ||
320 | { | ||
321 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
322 | int length = L2TP_SKB_CB(skb)->length; | ||
323 | |||
324 | /* We're about to requeue the skb, so return resources | ||
325 | * to its current owner (a socket receive buffer). | ||
326 | */ | ||
327 | skb_orphan(skb); | ||
328 | |||
329 | tunnel->stats.rx_packets++; | ||
330 | tunnel->stats.rx_bytes += length; | ||
331 | session->stats.rx_packets++; | ||
332 | session->stats.rx_bytes += length; | ||
333 | |||
334 | if (L2TP_SKB_CB(skb)->has_seq) { | ||
335 | /* Bump our Nr */ | ||
336 | session->nr++; | ||
337 | if (tunnel->version == L2TP_HDR_VER_2) | ||
338 | session->nr &= 0xffff; | ||
339 | else | ||
340 | session->nr &= 0xffffff; | ||
341 | |||
342 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
343 | "%s: updated nr to %hu\n", session->name, session->nr); | ||
344 | } | ||
345 | |||
346 | /* call private receive handler */ | ||
347 | if (session->recv_skb != NULL) | ||
348 | (*session->recv_skb)(session, skb, L2TP_SKB_CB(skb)->length); | ||
349 | else | ||
350 | kfree_skb(skb); | ||
351 | |||
352 | if (session->deref) | ||
353 | (*session->deref)(session); | ||
354 | } | ||
355 | |||
356 | /* Dequeue skbs from the session's reorder_q, subject to packet order. | ||
357 | * Skbs that have been in the queue for too long are simply discarded. | ||
358 | */ | ||
359 | static void l2tp_recv_dequeue(struct l2tp_session *session) | ||
360 | { | ||
361 | struct sk_buff *skb; | ||
362 | struct sk_buff *tmp; | ||
363 | |||
364 | /* If the pkt at the head of the queue has the nr that we | ||
365 | * expect to send up next, dequeue it and any other | ||
366 | * in-sequence packets behind it. | ||
367 | */ | ||
368 | spin_lock_bh(&session->reorder_q.lock); | ||
369 | skb_queue_walk_safe(&session->reorder_q, skb, tmp) { | ||
370 | if (time_after(jiffies, L2TP_SKB_CB(skb)->expires)) { | ||
371 | session->stats.rx_seq_discards++; | ||
372 | session->stats.rx_errors++; | ||
373 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
374 | "%s: oos pkt %u len %d discarded (too old), " | ||
375 | "waiting for %u, reorder_q_len=%d\n", | ||
376 | session->name, L2TP_SKB_CB(skb)->ns, | ||
377 | L2TP_SKB_CB(skb)->length, session->nr, | ||
378 | skb_queue_len(&session->reorder_q)); | ||
379 | __skb_unlink(skb, &session->reorder_q); | ||
380 | kfree_skb(skb); | ||
381 | if (session->deref) | ||
382 | (*session->deref)(session); | ||
383 | continue; | ||
384 | } | ||
385 | |||
386 | if (L2TP_SKB_CB(skb)->has_seq) { | ||
387 | if (L2TP_SKB_CB(skb)->ns != session->nr) { | ||
388 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
389 | "%s: holding oos pkt %u len %d, " | ||
390 | "waiting for %u, reorder_q_len=%d\n", | ||
391 | session->name, L2TP_SKB_CB(skb)->ns, | ||
392 | L2TP_SKB_CB(skb)->length, session->nr, | ||
393 | skb_queue_len(&session->reorder_q)); | ||
394 | goto out; | ||
395 | } | ||
396 | } | ||
397 | __skb_unlink(skb, &session->reorder_q); | ||
398 | |||
399 | /* Process the skb. We release the queue lock while we | ||
400 | * do so to let other contexts process the queue. | ||
401 | */ | ||
402 | spin_unlock_bh(&session->reorder_q.lock); | ||
403 | l2tp_recv_dequeue_skb(session, skb); | ||
404 | spin_lock_bh(&session->reorder_q.lock); | ||
405 | } | ||
406 | |||
407 | out: | ||
408 | spin_unlock_bh(&session->reorder_q.lock); | ||
409 | } | ||
410 | |||
411 | static inline int l2tp_verify_udp_checksum(struct sock *sk, | ||
412 | struct sk_buff *skb) | ||
413 | { | ||
414 | struct udphdr *uh = udp_hdr(skb); | ||
415 | u16 ulen = ntohs(uh->len); | ||
416 | struct inet_sock *inet; | ||
417 | __wsum psum; | ||
418 | |||
419 | if (sk->sk_no_check || skb_csum_unnecessary(skb) || !uh->check) | ||
420 | return 0; | ||
421 | |||
422 | inet = inet_sk(sk); | ||
423 | psum = csum_tcpudp_nofold(inet->inet_saddr, inet->inet_daddr, ulen, | ||
424 | IPPROTO_UDP, 0); | ||
425 | |||
426 | if ((skb->ip_summed == CHECKSUM_COMPLETE) && | ||
427 | !csum_fold(csum_add(psum, skb->csum))) | ||
428 | return 0; | ||
429 | |||
430 | skb->csum = psum; | ||
431 | |||
432 | return __skb_checksum_complete(skb); | ||
433 | } | ||
434 | |||
435 | /* Do receive processing of L2TP data frames. We handle both L2TPv2 | ||
436 | * and L2TPv3 data frames here. | ||
437 | * | ||
438 | * L2TPv2 Data Message Header | ||
439 | * | ||
440 | * 0 1 2 3 | ||
441 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
442 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
443 | * |T|L|x|x|S|x|O|P|x|x|x|x| Ver | Length (opt) | | ||
444 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
445 | * | Tunnel ID | Session ID | | ||
446 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
447 | * | Ns (opt) | Nr (opt) | | ||
448 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
449 | * | Offset Size (opt) | Offset pad... (opt) | ||
450 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
451 | * | ||
452 | * Data frames are marked by T=0. All other fields are the same as | ||
453 | * those in L2TP control frames. | ||
454 | * | ||
455 | * L2TPv3 Data Message Header | ||
456 | * | ||
457 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
458 | * | L2TP Session Header | | ||
459 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
460 | * | L2-Specific Sublayer | | ||
461 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
462 | * | Tunnel Payload ... | ||
463 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
464 | * | ||
465 | * L2TPv3 Session Header Over IP | ||
466 | * | ||
467 | * 0 1 2 3 | ||
468 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
469 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
470 | * | Session ID | | ||
471 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
472 | * | Cookie (optional, maximum 64 bits)... | ||
473 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
474 | * | | ||
475 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
476 | * | ||
477 | * L2TPv3 L2-Specific Sublayer Format | ||
478 | * | ||
479 | * 0 1 2 3 | ||
480 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
481 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
482 | * |x|S|x|x|x|x|x|x| Sequence Number | | ||
483 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
484 | * | ||
485 | * Cookie value, sublayer format and offset (pad) are negotiated with | ||
486 | * the peer when the session is set up. Unlike L2TPv2, we do not need | ||
487 | * to parse the packet header to determine if optional fields are | ||
488 | * present. | ||
489 | * | ||
490 | * Caller must already have parsed the frame and determined that it is | ||
491 | * a data (not control) frame before coming here. Fields up to the | ||
492 | * session-id have already been parsed and ptr points to the data | ||
493 | * after the session-id. | ||
494 | */ | ||
495 | void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, | ||
496 | unsigned char *ptr, unsigned char *optr, u16 hdrflags, | ||
497 | int length, int (*payload_hook)(struct sk_buff *skb)) | ||
498 | { | ||
499 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
500 | int offset; | ||
501 | u32 ns, nr; | ||
502 | |||
503 | /* The ref count is increased since we now hold a pointer to | ||
504 | * the session. Take care to decrement the refcnt when exiting | ||
505 | * this function from now on... | ||
506 | */ | ||
507 | l2tp_session_inc_refcount(session); | ||
508 | if (session->ref) | ||
509 | (*session->ref)(session); | ||
510 | |||
511 | /* Parse and check optional cookie */ | ||
512 | if (session->peer_cookie_len > 0) { | ||
513 | if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) { | ||
514 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
515 | "%s: cookie mismatch (%u/%u). Discarding.\n", | ||
516 | tunnel->name, tunnel->tunnel_id, session->session_id); | ||
517 | session->stats.rx_cookie_discards++; | ||
518 | goto discard; | ||
519 | } | ||
520 | ptr += session->peer_cookie_len; | ||
521 | } | ||
522 | |||
523 | /* Handle the optional sequence numbers. Sequence numbers are | ||
524 | * in different places for L2TPv2 and L2TPv3. | ||
525 | * | ||
526 | * If we are the LAC, enable/disable sequence numbers under | ||
527 | * the control of the LNS. If no sequence numbers present but | ||
528 | * we were expecting them, discard frame. | ||
529 | */ | ||
530 | ns = nr = 0; | ||
531 | L2TP_SKB_CB(skb)->has_seq = 0; | ||
532 | if (tunnel->version == L2TP_HDR_VER_2) { | ||
533 | if (hdrflags & L2TP_HDRFLAG_S) { | ||
534 | ns = ntohs(*(__be16 *) ptr); | ||
535 | ptr += 2; | ||
536 | nr = ntohs(*(__be16 *) ptr); | ||
537 | ptr += 2; | ||
538 | |||
539 | /* Store L2TP info in the skb */ | ||
540 | L2TP_SKB_CB(skb)->ns = ns; | ||
541 | L2TP_SKB_CB(skb)->has_seq = 1; | ||
542 | |||
543 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
544 | "%s: recv data ns=%u, nr=%u, session nr=%u\n", | ||
545 | session->name, ns, nr, session->nr); | ||
546 | } | ||
547 | } else if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) { | ||
548 | u32 l2h = ntohl(*(__be32 *) ptr); | ||
549 | |||
550 | if (l2h & 0x40000000) { | ||
551 | ns = l2h & 0x00ffffff; | ||
552 | |||
553 | /* Store L2TP info in the skb */ | ||
554 | L2TP_SKB_CB(skb)->ns = ns; | ||
555 | L2TP_SKB_CB(skb)->has_seq = 1; | ||
556 | |||
557 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
558 | "%s: recv data ns=%u, session nr=%u\n", | ||
559 | session->name, ns, session->nr); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | /* Advance past L2-specific header, if present */ | ||
564 | ptr += session->l2specific_len; | ||
565 | |||
566 | if (L2TP_SKB_CB(skb)->has_seq) { | ||
567 | /* Received a packet with sequence numbers. If we're the LNS, | ||
568 | * check if we sre sending sequence numbers and if not, | ||
569 | * configure it so. | ||
570 | */ | ||
571 | if ((!session->lns_mode) && (!session->send_seq)) { | ||
572 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_INFO, | ||
573 | "%s: requested to enable seq numbers by LNS\n", | ||
574 | session->name); | ||
575 | session->send_seq = -1; | ||
576 | l2tp_session_set_header_len(session, tunnel->version); | ||
577 | } | ||
578 | } else { | ||
579 | /* No sequence numbers. | ||
580 | * If user has configured mandatory sequence numbers, discard. | ||
581 | */ | ||
582 | if (session->recv_seq) { | ||
583 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_WARNING, | ||
584 | "%s: recv data has no seq numbers when required. " | ||
585 | "Discarding\n", session->name); | ||
586 | session->stats.rx_seq_discards++; | ||
587 | goto discard; | ||
588 | } | ||
589 | |||
590 | /* If we're the LAC and we're sending sequence numbers, the | ||
591 | * LNS has requested that we no longer send sequence numbers. | ||
592 | * If we're the LNS and we're sending sequence numbers, the | ||
593 | * LAC is broken. Discard the frame. | ||
594 | */ | ||
595 | if ((!session->lns_mode) && (session->send_seq)) { | ||
596 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_INFO, | ||
597 | "%s: requested to disable seq numbers by LNS\n", | ||
598 | session->name); | ||
599 | session->send_seq = 0; | ||
600 | l2tp_session_set_header_len(session, tunnel->version); | ||
601 | } else if (session->send_seq) { | ||
602 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_WARNING, | ||
603 | "%s: recv data has no seq numbers when required. " | ||
604 | "Discarding\n", session->name); | ||
605 | session->stats.rx_seq_discards++; | ||
606 | goto discard; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | /* Session data offset is handled differently for L2TPv2 and | ||
611 | * L2TPv3. For L2TPv2, there is an optional 16-bit value in | ||
612 | * the header. For L2TPv3, the offset is negotiated using AVPs | ||
613 | * in the session setup control protocol. | ||
614 | */ | ||
615 | if (tunnel->version == L2TP_HDR_VER_2) { | ||
616 | /* If offset bit set, skip it. */ | ||
617 | if (hdrflags & L2TP_HDRFLAG_O) { | ||
618 | offset = ntohs(*(__be16 *)ptr); | ||
619 | ptr += 2 + offset; | ||
620 | } | ||
621 | } else | ||
622 | ptr += session->offset; | ||
623 | |||
624 | offset = ptr - optr; | ||
625 | if (!pskb_may_pull(skb, offset)) | ||
626 | goto discard; | ||
627 | |||
628 | __skb_pull(skb, offset); | ||
629 | |||
630 | /* If caller wants to process the payload before we queue the | ||
631 | * packet, do so now. | ||
632 | */ | ||
633 | if (payload_hook) | ||
634 | if ((*payload_hook)(skb)) | ||
635 | goto discard; | ||
636 | |||
637 | /* Prepare skb for adding to the session's reorder_q. Hold | ||
638 | * packets for max reorder_timeout or 1 second if not | ||
639 | * reordering. | ||
640 | */ | ||
641 | L2TP_SKB_CB(skb)->length = length; | ||
642 | L2TP_SKB_CB(skb)->expires = jiffies + | ||
643 | (session->reorder_timeout ? session->reorder_timeout : HZ); | ||
644 | |||
645 | /* Add packet to the session's receive queue. Reordering is done here, if | ||
646 | * enabled. Saved L2TP protocol info is stored in skb->sb[]. | ||
647 | */ | ||
648 | if (L2TP_SKB_CB(skb)->has_seq) { | ||
649 | if (session->reorder_timeout != 0) { | ||
650 | /* Packet reordering enabled. Add skb to session's | ||
651 | * reorder queue, in order of ns. | ||
652 | */ | ||
653 | l2tp_recv_queue_skb(session, skb); | ||
654 | } else { | ||
655 | /* Packet reordering disabled. Discard out-of-sequence | ||
656 | * packets | ||
657 | */ | ||
658 | if (L2TP_SKB_CB(skb)->ns != session->nr) { | ||
659 | session->stats.rx_seq_discards++; | ||
660 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
661 | "%s: oos pkt %u len %d discarded, " | ||
662 | "waiting for %u, reorder_q_len=%d\n", | ||
663 | session->name, L2TP_SKB_CB(skb)->ns, | ||
664 | L2TP_SKB_CB(skb)->length, session->nr, | ||
665 | skb_queue_len(&session->reorder_q)); | ||
666 | goto discard; | ||
667 | } | ||
668 | skb_queue_tail(&session->reorder_q, skb); | ||
669 | } | ||
670 | } else { | ||
671 | /* No sequence numbers. Add the skb to the tail of the | ||
672 | * reorder queue. This ensures that it will be | ||
673 | * delivered after all previous sequenced skbs. | ||
674 | */ | ||
675 | skb_queue_tail(&session->reorder_q, skb); | ||
676 | } | ||
677 | |||
678 | /* Try to dequeue as many skbs from reorder_q as we can. */ | ||
679 | l2tp_recv_dequeue(session); | ||
680 | |||
681 | l2tp_session_dec_refcount(session); | ||
682 | |||
683 | return; | ||
684 | |||
685 | discard: | ||
686 | session->stats.rx_errors++; | ||
687 | kfree_skb(skb); | ||
688 | |||
689 | if (session->deref) | ||
690 | (*session->deref)(session); | ||
691 | |||
692 | l2tp_session_dec_refcount(session); | ||
693 | } | ||
694 | EXPORT_SYMBOL(l2tp_recv_common); | ||
695 | |||
696 | /* Internal UDP receive frame. Do the real work of receiving an L2TP data frame | ||
697 | * here. The skb is not on a list when we get here. | ||
698 | * Returns 0 if the packet was a data packet and was successfully passed on. | ||
699 | * Returns 1 if the packet was not a good data packet and could not be | ||
700 | * forwarded. All such packets are passed up to userspace to deal with. | ||
701 | */ | ||
702 | int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, | ||
703 | int (*payload_hook)(struct sk_buff *skb)) | ||
704 | { | ||
705 | struct l2tp_session *session = NULL; | ||
706 | unsigned char *ptr, *optr; | ||
707 | u16 hdrflags; | ||
708 | u32 tunnel_id, session_id; | ||
709 | int offset; | ||
710 | u16 version; | ||
711 | int length; | ||
712 | |||
713 | if (tunnel->sock && l2tp_verify_udp_checksum(tunnel->sock, skb)) | ||
714 | goto discard_bad_csum; | ||
715 | |||
716 | /* UDP always verifies the packet length. */ | ||
717 | __skb_pull(skb, sizeof(struct udphdr)); | ||
718 | |||
719 | /* Short packet? */ | ||
720 | if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) { | ||
721 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
722 | "%s: recv short packet (len=%d)\n", tunnel->name, skb->len); | ||
723 | goto error; | ||
724 | } | ||
725 | |||
726 | /* Point to L2TP header */ | ||
727 | optr = ptr = skb->data; | ||
728 | |||
729 | /* Trace packet contents, if enabled */ | ||
730 | if (tunnel->debug & L2TP_MSG_DATA) { | ||
731 | length = min(32u, skb->len); | ||
732 | if (!pskb_may_pull(skb, length)) | ||
733 | goto error; | ||
734 | |||
735 | printk(KERN_DEBUG "%s: recv: ", tunnel->name); | ||
736 | |||
737 | offset = 0; | ||
738 | do { | ||
739 | printk(" %02X", ptr[offset]); | ||
740 | } while (++offset < length); | ||
741 | |||
742 | printk("\n"); | ||
743 | } | ||
744 | |||
745 | /* Get L2TP header flags */ | ||
746 | hdrflags = ntohs(*(__be16 *) ptr); | ||
747 | |||
748 | /* Check protocol version */ | ||
749 | version = hdrflags & L2TP_HDR_VER_MASK; | ||
750 | if (version != tunnel->version) { | ||
751 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
752 | "%s: recv protocol version mismatch: got %d expected %d\n", | ||
753 | tunnel->name, version, tunnel->version); | ||
754 | goto error; | ||
755 | } | ||
756 | |||
757 | /* Get length of L2TP packet */ | ||
758 | length = skb->len; | ||
759 | |||
760 | /* If type is control packet, it is handled by userspace. */ | ||
761 | if (hdrflags & L2TP_HDRFLAG_T) { | ||
762 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_DEBUG, | ||
763 | "%s: recv control packet, len=%d\n", tunnel->name, length); | ||
764 | goto error; | ||
765 | } | ||
766 | |||
767 | /* Skip flags */ | ||
768 | ptr += 2; | ||
769 | |||
770 | if (tunnel->version == L2TP_HDR_VER_2) { | ||
771 | /* If length is present, skip it */ | ||
772 | if (hdrflags & L2TP_HDRFLAG_L) | ||
773 | ptr += 2; | ||
774 | |||
775 | /* Extract tunnel and session ID */ | ||
776 | tunnel_id = ntohs(*(__be16 *) ptr); | ||
777 | ptr += 2; | ||
778 | session_id = ntohs(*(__be16 *) ptr); | ||
779 | ptr += 2; | ||
780 | } else { | ||
781 | ptr += 2; /* skip reserved bits */ | ||
782 | tunnel_id = tunnel->tunnel_id; | ||
783 | session_id = ntohl(*(__be32 *) ptr); | ||
784 | ptr += 4; | ||
785 | } | ||
786 | |||
787 | /* Find the session context */ | ||
788 | session = l2tp_session_find(tunnel->l2tp_net, tunnel, session_id); | ||
789 | if (!session || !session->recv_skb) { | ||
790 | /* Not found? Pass to userspace to deal with */ | ||
791 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO, | ||
792 | "%s: no session found (%u/%u). Passing up.\n", | ||
793 | tunnel->name, tunnel_id, session_id); | ||
794 | goto error; | ||
795 | } | ||
796 | |||
797 | l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook); | ||
798 | |||
799 | return 0; | ||
800 | |||
801 | discard_bad_csum: | ||
802 | LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name); | ||
803 | UDP_INC_STATS_USER(tunnel->l2tp_net, UDP_MIB_INERRORS, 0); | ||
804 | tunnel->stats.rx_errors++; | ||
805 | kfree_skb(skb); | ||
806 | |||
807 | return 0; | ||
808 | |||
809 | error: | ||
810 | /* Put UDP header back */ | ||
811 | __skb_push(skb, sizeof(struct udphdr)); | ||
812 | |||
813 | return 1; | ||
814 | } | ||
815 | EXPORT_SYMBOL_GPL(l2tp_udp_recv_core); | ||
816 | |||
817 | /* UDP encapsulation receive handler. See net/ipv4/udp.c. | ||
818 | * Return codes: | ||
819 | * 0 : success. | ||
820 | * <0: error | ||
821 | * >0: skb should be passed up to userspace as UDP. | ||
822 | */ | ||
823 | int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) | ||
824 | { | ||
825 | struct l2tp_tunnel *tunnel; | ||
826 | |||
827 | tunnel = l2tp_sock_to_tunnel(sk); | ||
828 | if (tunnel == NULL) | ||
829 | goto pass_up; | ||
830 | |||
831 | PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_DEBUG, | ||
832 | "%s: received %d bytes\n", tunnel->name, skb->len); | ||
833 | |||
834 | if (l2tp_udp_recv_core(tunnel, skb, tunnel->recv_payload_hook)) | ||
835 | goto pass_up_put; | ||
836 | |||
837 | sock_put(sk); | ||
838 | return 0; | ||
839 | |||
840 | pass_up_put: | ||
841 | sock_put(sk); | ||
842 | pass_up: | ||
843 | return 1; | ||
844 | } | ||
845 | EXPORT_SYMBOL_GPL(l2tp_udp_encap_recv); | ||
846 | |||
847 | /************************************************************************ | ||
848 | * Transmit handling | ||
849 | ***********************************************************************/ | ||
850 | |||
851 | /* Build an L2TP header for the session into the buffer provided. | ||
852 | */ | ||
853 | static int l2tp_build_l2tpv2_header(struct l2tp_session *session, void *buf) | ||
854 | { | ||
855 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
856 | __be16 *bufp = buf; | ||
857 | __be16 *optr = buf; | ||
858 | u16 flags = L2TP_HDR_VER_2; | ||
859 | u32 tunnel_id = tunnel->peer_tunnel_id; | ||
860 | u32 session_id = session->peer_session_id; | ||
861 | |||
862 | if (session->send_seq) | ||
863 | flags |= L2TP_HDRFLAG_S; | ||
864 | |||
865 | /* Setup L2TP header. */ | ||
866 | *bufp++ = htons(flags); | ||
867 | *bufp++ = htons(tunnel_id); | ||
868 | *bufp++ = htons(session_id); | ||
869 | if (session->send_seq) { | ||
870 | *bufp++ = htons(session->ns); | ||
871 | *bufp++ = 0; | ||
872 | session->ns++; | ||
873 | session->ns &= 0xffff; | ||
874 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
875 | "%s: updated ns to %u\n", session->name, session->ns); | ||
876 | } | ||
877 | |||
878 | return bufp - optr; | ||
879 | } | ||
880 | |||
881 | static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf) | ||
882 | { | ||
883 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
884 | char *bufp = buf; | ||
885 | char *optr = bufp; | ||
886 | |||
887 | /* Setup L2TP header. The header differs slightly for UDP and | ||
888 | * IP encapsulations. For UDP, there is 4 bytes of flags. | ||
889 | */ | ||
890 | if (tunnel->encap == L2TP_ENCAPTYPE_UDP) { | ||
891 | u16 flags = L2TP_HDR_VER_3; | ||
892 | *((__be16 *) bufp) = htons(flags); | ||
893 | bufp += 2; | ||
894 | *((__be16 *) bufp) = 0; | ||
895 | bufp += 2; | ||
896 | } | ||
897 | |||
898 | *((__be32 *) bufp) = htonl(session->peer_session_id); | ||
899 | bufp += 4; | ||
900 | if (session->cookie_len) { | ||
901 | memcpy(bufp, &session->cookie[0], session->cookie_len); | ||
902 | bufp += session->cookie_len; | ||
903 | } | ||
904 | if (session->l2specific_len) { | ||
905 | if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) { | ||
906 | u32 l2h = 0; | ||
907 | if (session->send_seq) { | ||
908 | l2h = 0x40000000 | session->ns; | ||
909 | session->ns++; | ||
910 | session->ns &= 0xffffff; | ||
911 | PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, | ||
912 | "%s: updated ns to %u\n", session->name, session->ns); | ||
913 | } | ||
914 | |||
915 | *((__be32 *) bufp) = htonl(l2h); | ||
916 | } | ||
917 | bufp += session->l2specific_len; | ||
918 | } | ||
919 | if (session->offset) | ||
920 | bufp += session->offset; | ||
921 | |||
922 | return bufp - optr; | ||
923 | } | ||
924 | |||
925 | int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t data_len) | ||
926 | { | ||
927 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
928 | unsigned int len = skb->len; | ||
929 | int error; | ||
930 | |||
931 | /* Debug */ | ||
932 | if (session->send_seq) | ||
933 | PRINTK(session->debug, L2TP_MSG_DATA, KERN_DEBUG, | ||
934 | "%s: send %Zd bytes, ns=%u\n", session->name, | ||
935 | data_len, session->ns - 1); | ||
936 | else | ||
937 | PRINTK(session->debug, L2TP_MSG_DATA, KERN_DEBUG, | ||
938 | "%s: send %Zd bytes\n", session->name, data_len); | ||
939 | |||
940 | if (session->debug & L2TP_MSG_DATA) { | ||
941 | int i; | ||
942 | int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; | ||
943 | unsigned char *datap = skb->data + uhlen; | ||
944 | |||
945 | printk(KERN_DEBUG "%s: xmit:", session->name); | ||
946 | for (i = 0; i < (len - uhlen); i++) { | ||
947 | printk(" %02X", *datap++); | ||
948 | if (i == 31) { | ||
949 | printk(" ..."); | ||
950 | break; | ||
951 | } | ||
952 | } | ||
953 | printk("\n"); | ||
954 | } | ||
955 | |||
956 | /* Queue the packet to IP for output */ | ||
957 | skb->local_df = 1; | ||
958 | error = ip_queue_xmit(skb); | ||
959 | |||
960 | /* Update stats */ | ||
961 | if (error >= 0) { | ||
962 | tunnel->stats.tx_packets++; | ||
963 | tunnel->stats.tx_bytes += len; | ||
964 | session->stats.tx_packets++; | ||
965 | session->stats.tx_bytes += len; | ||
966 | } else { | ||
967 | tunnel->stats.tx_errors++; | ||
968 | session->stats.tx_errors++; | ||
969 | } | ||
970 | |||
971 | return 0; | ||
972 | } | ||
973 | EXPORT_SYMBOL_GPL(l2tp_xmit_core); | ||
974 | |||
975 | /* Automatically called when the skb is freed. | ||
976 | */ | ||
977 | static void l2tp_sock_wfree(struct sk_buff *skb) | ||
978 | { | ||
979 | sock_put(skb->sk); | ||
980 | } | ||
981 | |||
982 | /* For data skbs that we transmit, we associate with the tunnel socket | ||
983 | * but don't do accounting. | ||
984 | */ | ||
985 | static inline void l2tp_skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | ||
986 | { | ||
987 | sock_hold(sk); | ||
988 | skb->sk = sk; | ||
989 | skb->destructor = l2tp_sock_wfree; | ||
990 | } | ||
991 | |||
992 | /* If caller requires the skb to have a ppp header, the header must be | ||
993 | * inserted in the skb data before calling this function. | ||
994 | */ | ||
995 | int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len) | ||
996 | { | ||
997 | int data_len = skb->len; | ||
998 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
999 | struct sock *sk = tunnel->sock; | ||
1000 | struct udphdr *uh; | ||
1001 | struct inet_sock *inet; | ||
1002 | __wsum csum; | ||
1003 | int old_headroom; | ||
1004 | int new_headroom; | ||
1005 | int headroom; | ||
1006 | int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; | ||
1007 | int udp_len; | ||
1008 | |||
1009 | /* Check that there's enough headroom in the skb to insert IP, | ||
1010 | * UDP and L2TP headers. If not enough, expand it to | ||
1011 | * make room. Adjust truesize. | ||
1012 | */ | ||
1013 | headroom = NET_SKB_PAD + sizeof(struct iphdr) + | ||
1014 | uhlen + hdr_len; | ||
1015 | old_headroom = skb_headroom(skb); | ||
1016 | if (skb_cow_head(skb, headroom)) | ||
1017 | goto abort; | ||
1018 | |||
1019 | new_headroom = skb_headroom(skb); | ||
1020 | skb_orphan(skb); | ||
1021 | skb->truesize += new_headroom - old_headroom; | ||
1022 | |||
1023 | /* Setup L2TP header */ | ||
1024 | session->build_header(session, __skb_push(skb, hdr_len)); | ||
1025 | |||
1026 | /* Reset skb netfilter state */ | ||
1027 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | ||
1028 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | | ||
1029 | IPSKB_REROUTED); | ||
1030 | nf_reset(skb); | ||
1031 | |||
1032 | /* Get routing info from the tunnel socket */ | ||
1033 | skb_dst_drop(skb); | ||
1034 | skb_dst_set(skb, dst_clone(__sk_dst_get(sk))); | ||
1035 | |||
1036 | switch (tunnel->encap) { | ||
1037 | case L2TP_ENCAPTYPE_UDP: | ||
1038 | /* Setup UDP header */ | ||
1039 | inet = inet_sk(sk); | ||
1040 | __skb_push(skb, sizeof(*uh)); | ||
1041 | skb_reset_transport_header(skb); | ||
1042 | uh = udp_hdr(skb); | ||
1043 | uh->source = inet->inet_sport; | ||
1044 | uh->dest = inet->inet_dport; | ||
1045 | udp_len = uhlen + hdr_len + data_len; | ||
1046 | uh->len = htons(udp_len); | ||
1047 | uh->check = 0; | ||
1048 | |||
1049 | /* Calculate UDP checksum if configured to do so */ | ||
1050 | if (sk->sk_no_check == UDP_CSUM_NOXMIT) | ||
1051 | skb->ip_summed = CHECKSUM_NONE; | ||
1052 | else if ((skb_dst(skb) && skb_dst(skb)->dev) && | ||
1053 | (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM))) { | ||
1054 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
1055 | csum = skb_checksum(skb, 0, udp_len, 0); | ||
1056 | uh->check = csum_tcpudp_magic(inet->inet_saddr, | ||
1057 | inet->inet_daddr, | ||
1058 | udp_len, IPPROTO_UDP, csum); | ||
1059 | if (uh->check == 0) | ||
1060 | uh->check = CSUM_MANGLED_0; | ||
1061 | } else { | ||
1062 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
1063 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
1064 | skb->csum_offset = offsetof(struct udphdr, check); | ||
1065 | uh->check = ~csum_tcpudp_magic(inet->inet_saddr, | ||
1066 | inet->inet_daddr, | ||
1067 | udp_len, IPPROTO_UDP, 0); | ||
1068 | } | ||
1069 | break; | ||
1070 | |||
1071 | case L2TP_ENCAPTYPE_IP: | ||
1072 | break; | ||
1073 | } | ||
1074 | |||
1075 | l2tp_skb_set_owner_w(skb, sk); | ||
1076 | |||
1077 | l2tp_xmit_core(session, skb, data_len); | ||
1078 | |||
1079 | abort: | ||
1080 | return 0; | ||
1081 | } | ||
1082 | EXPORT_SYMBOL_GPL(l2tp_xmit_skb); | ||
1083 | |||
1084 | /***************************************************************************** | ||
1085 | * Tinnel and session create/destroy. | ||
1086 | *****************************************************************************/ | ||
1087 | |||
1088 | /* Tunnel socket destruct hook. | ||
1089 | * The tunnel context is deleted only when all session sockets have been | ||
1090 | * closed. | ||
1091 | */ | ||
1092 | void l2tp_tunnel_destruct(struct sock *sk) | ||
1093 | { | ||
1094 | struct l2tp_tunnel *tunnel; | ||
1095 | |||
1096 | tunnel = sk->sk_user_data; | ||
1097 | if (tunnel == NULL) | ||
1098 | goto end; | ||
1099 | |||
1100 | PRINTK(tunnel->debug, L2TP_MSG_CONTROL, KERN_INFO, | ||
1101 | "%s: closing...\n", tunnel->name); | ||
1102 | |||
1103 | /* Close all sessions */ | ||
1104 | l2tp_tunnel_closeall(tunnel); | ||
1105 | |||
1106 | switch (tunnel->encap) { | ||
1107 | case L2TP_ENCAPTYPE_UDP: | ||
1108 | /* No longer an encapsulation socket. See net/ipv4/udp.c */ | ||
1109 | (udp_sk(sk))->encap_type = 0; | ||
1110 | (udp_sk(sk))->encap_rcv = NULL; | ||
1111 | break; | ||
1112 | case L2TP_ENCAPTYPE_IP: | ||
1113 | break; | ||
1114 | } | ||
1115 | |||
1116 | /* Remove hooks into tunnel socket */ | ||
1117 | tunnel->sock = NULL; | ||
1118 | sk->sk_destruct = tunnel->old_sk_destruct; | ||
1119 | sk->sk_user_data = NULL; | ||
1120 | |||
1121 | /* Call the original destructor */ | ||
1122 | if (sk->sk_destruct) | ||
1123 | (*sk->sk_destruct)(sk); | ||
1124 | |||
1125 | /* We're finished with the socket */ | ||
1126 | l2tp_tunnel_dec_refcount(tunnel); | ||
1127 | |||
1128 | end: | ||
1129 | return; | ||
1130 | } | ||
1131 | EXPORT_SYMBOL(l2tp_tunnel_destruct); | ||
1132 | |||
1133 | /* When the tunnel is closed, all the attached sessions need to go too. | ||
1134 | */ | ||
1135 | void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel) | ||
1136 | { | ||
1137 | int hash; | ||
1138 | struct hlist_node *walk; | ||
1139 | struct hlist_node *tmp; | ||
1140 | struct l2tp_session *session; | ||
1141 | |||
1142 | BUG_ON(tunnel == NULL); | ||
1143 | |||
1144 | PRINTK(tunnel->debug, L2TP_MSG_CONTROL, KERN_INFO, | ||
1145 | "%s: closing all sessions...\n", tunnel->name); | ||
1146 | |||
1147 | write_lock_bh(&tunnel->hlist_lock); | ||
1148 | for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { | ||
1149 | again: | ||
1150 | hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) { | ||
1151 | session = hlist_entry(walk, struct l2tp_session, hlist); | ||
1152 | |||
1153 | PRINTK(session->debug, L2TP_MSG_CONTROL, KERN_INFO, | ||
1154 | "%s: closing session\n", session->name); | ||
1155 | |||
1156 | hlist_del_init(&session->hlist); | ||
1157 | |||
1158 | /* Since we should hold the sock lock while | ||
1159 | * doing any unbinding, we need to release the | ||
1160 | * lock we're holding before taking that lock. | ||
1161 | * Hold a reference to the sock so it doesn't | ||
1162 | * disappear as we're jumping between locks. | ||
1163 | */ | ||
1164 | if (session->ref != NULL) | ||
1165 | (*session->ref)(session); | ||
1166 | |||
1167 | write_unlock_bh(&tunnel->hlist_lock); | ||
1168 | |||
1169 | if (tunnel->version != L2TP_HDR_VER_2) { | ||
1170 | struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); | ||
1171 | |||
1172 | spin_lock_bh(&pn->l2tp_session_hlist_lock); | ||
1173 | hlist_del_init_rcu(&session->global_hlist); | ||
1174 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); | ||
1175 | synchronize_rcu(); | ||
1176 | } | ||
1177 | |||
1178 | if (session->session_close != NULL) | ||
1179 | (*session->session_close)(session); | ||
1180 | |||
1181 | if (session->deref != NULL) | ||
1182 | (*session->deref)(session); | ||
1183 | |||
1184 | write_lock_bh(&tunnel->hlist_lock); | ||
1185 | |||
1186 | /* Now restart from the beginning of this hash | ||
1187 | * chain. We always remove a session from the | ||
1188 | * list so we are guaranteed to make forward | ||
1189 | * progress. | ||
1190 | */ | ||
1191 | goto again; | ||
1192 | } | ||
1193 | } | ||
1194 | write_unlock_bh(&tunnel->hlist_lock); | ||
1195 | } | ||
1196 | EXPORT_SYMBOL_GPL(l2tp_tunnel_closeall); | ||
1197 | |||
1198 | /* Really kill the tunnel. | ||
1199 | * Come here only when all sessions have been cleared from the tunnel. | ||
1200 | */ | ||
1201 | void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) | ||
1202 | { | ||
1203 | struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); | ||
1204 | |||
1205 | BUG_ON(atomic_read(&tunnel->ref_count) != 0); | ||
1206 | BUG_ON(tunnel->sock != NULL); | ||
1207 | |||
1208 | PRINTK(tunnel->debug, L2TP_MSG_CONTROL, KERN_INFO, | ||
1209 | "%s: free...\n", tunnel->name); | ||
1210 | |||
1211 | /* Remove from tunnel list */ | ||
1212 | spin_lock_bh(&pn->l2tp_tunnel_list_lock); | ||
1213 | list_del_rcu(&tunnel->list); | ||
1214 | spin_unlock_bh(&pn->l2tp_tunnel_list_lock); | ||
1215 | synchronize_rcu(); | ||
1216 | |||
1217 | atomic_dec(&l2tp_tunnel_count); | ||
1218 | kfree(tunnel); | ||
1219 | } | ||
1220 | EXPORT_SYMBOL_GPL(l2tp_tunnel_free); | ||
1221 | |||
1222 | /* Create a socket for the tunnel, if one isn't set up by | ||
1223 | * userspace. This is used for static tunnels where there is no | ||
1224 | * managing L2TP daemon. | ||
1225 | */ | ||
1226 | static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct socket **sockp) | ||
1227 | { | ||
1228 | int err = -EINVAL; | ||
1229 | struct sockaddr_in udp_addr; | ||
1230 | struct sockaddr_l2tpip ip_addr; | ||
1231 | struct socket *sock = NULL; | ||
1232 | |||
1233 | switch (cfg->encap) { | ||
1234 | case L2TP_ENCAPTYPE_UDP: | ||
1235 | err = sock_create(AF_INET, SOCK_DGRAM, 0, sockp); | ||
1236 | if (err < 0) | ||
1237 | goto out; | ||
1238 | |||
1239 | sock = *sockp; | ||
1240 | |||
1241 | memset(&udp_addr, 0, sizeof(udp_addr)); | ||
1242 | udp_addr.sin_family = AF_INET; | ||
1243 | udp_addr.sin_addr = cfg->local_ip; | ||
1244 | udp_addr.sin_port = htons(cfg->local_udp_port); | ||
1245 | err = kernel_bind(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr)); | ||
1246 | if (err < 0) | ||
1247 | goto out; | ||
1248 | |||
1249 | udp_addr.sin_family = AF_INET; | ||
1250 | udp_addr.sin_addr = cfg->peer_ip; | ||
1251 | udp_addr.sin_port = htons(cfg->peer_udp_port); | ||
1252 | err = kernel_connect(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr), 0); | ||
1253 | if (err < 0) | ||
1254 | goto out; | ||
1255 | |||
1256 | if (!cfg->use_udp_checksums) | ||
1257 | sock->sk->sk_no_check = UDP_CSUM_NOXMIT; | ||
1258 | |||
1259 | break; | ||
1260 | |||
1261 | case L2TP_ENCAPTYPE_IP: | ||
1262 | err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp); | ||
1263 | if (err < 0) | ||
1264 | goto out; | ||
1265 | |||
1266 | sock = *sockp; | ||
1267 | |||
1268 | memset(&ip_addr, 0, sizeof(ip_addr)); | ||
1269 | ip_addr.l2tp_family = AF_INET; | ||
1270 | ip_addr.l2tp_addr = cfg->local_ip; | ||
1271 | ip_addr.l2tp_conn_id = tunnel_id; | ||
1272 | err = kernel_bind(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr)); | ||
1273 | if (err < 0) | ||
1274 | goto out; | ||
1275 | |||
1276 | ip_addr.l2tp_family = AF_INET; | ||
1277 | ip_addr.l2tp_addr = cfg->peer_ip; | ||
1278 | ip_addr.l2tp_conn_id = peer_tunnel_id; | ||
1279 | err = kernel_connect(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr), 0); | ||
1280 | if (err < 0) | ||
1281 | goto out; | ||
1282 | |||
1283 | break; | ||
1284 | |||
1285 | default: | ||
1286 | goto out; | ||
1287 | } | ||
1288 | |||
1289 | out: | ||
1290 | if ((err < 0) && sock) { | ||
1291 | sock_release(sock); | ||
1292 | *sockp = NULL; | ||
1293 | } | ||
1294 | |||
1295 | return err; | ||
1296 | } | ||
1297 | |||
1298 | int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp) | ||
1299 | { | ||
1300 | struct l2tp_tunnel *tunnel = NULL; | ||
1301 | int err; | ||
1302 | struct socket *sock = NULL; | ||
1303 | struct sock *sk = NULL; | ||
1304 | struct l2tp_net *pn; | ||
1305 | enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP; | ||
1306 | |||
1307 | /* Get the tunnel socket from the fd, which was opened by | ||
1308 | * the userspace L2TP daemon. If not specified, create a | ||
1309 | * kernel socket. | ||
1310 | */ | ||
1311 | if (fd < 0) { | ||
1312 | err = l2tp_tunnel_sock_create(tunnel_id, peer_tunnel_id, cfg, &sock); | ||
1313 | if (err < 0) | ||
1314 | goto err; | ||
1315 | } else { | ||
1316 | err = -EBADF; | ||
1317 | sock = sockfd_lookup(fd, &err); | ||
1318 | if (!sock) { | ||
1319 | printk(KERN_ERR "tunl %hu: sockfd_lookup(fd=%d) returned %d\n", | ||
1320 | tunnel_id, fd, err); | ||
1321 | goto err; | ||
1322 | } | ||
1323 | } | ||
1324 | |||
1325 | sk = sock->sk; | ||
1326 | |||
1327 | if (cfg != NULL) | ||
1328 | encap = cfg->encap; | ||
1329 | |||
1330 | /* Quick sanity checks */ | ||
1331 | switch (encap) { | ||
1332 | case L2TP_ENCAPTYPE_UDP: | ||
1333 | err = -EPROTONOSUPPORT; | ||
1334 | if (sk->sk_protocol != IPPROTO_UDP) { | ||
1335 | printk(KERN_ERR "tunl %hu: fd %d wrong protocol, got %d, expected %d\n", | ||
1336 | tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP); | ||
1337 | goto err; | ||
1338 | } | ||
1339 | break; | ||
1340 | case L2TP_ENCAPTYPE_IP: | ||
1341 | err = -EPROTONOSUPPORT; | ||
1342 | if (sk->sk_protocol != IPPROTO_L2TP) { | ||
1343 | printk(KERN_ERR "tunl %hu: fd %d wrong protocol, got %d, expected %d\n", | ||
1344 | tunnel_id, fd, sk->sk_protocol, IPPROTO_L2TP); | ||
1345 | goto err; | ||
1346 | } | ||
1347 | break; | ||
1348 | } | ||
1349 | |||
1350 | /* Check if this socket has already been prepped */ | ||
1351 | tunnel = (struct l2tp_tunnel *)sk->sk_user_data; | ||
1352 | if (tunnel != NULL) { | ||
1353 | /* This socket has already been prepped */ | ||
1354 | err = -EBUSY; | ||
1355 | goto err; | ||
1356 | } | ||
1357 | |||
1358 | tunnel = kzalloc(sizeof(struct l2tp_tunnel), GFP_KERNEL); | ||
1359 | if (tunnel == NULL) { | ||
1360 | err = -ENOMEM; | ||
1361 | goto err; | ||
1362 | } | ||
1363 | |||
1364 | tunnel->version = version; | ||
1365 | tunnel->tunnel_id = tunnel_id; | ||
1366 | tunnel->peer_tunnel_id = peer_tunnel_id; | ||
1367 | tunnel->debug = L2TP_DEFAULT_DEBUG_FLAGS; | ||
1368 | |||
1369 | tunnel->magic = L2TP_TUNNEL_MAGIC; | ||
1370 | sprintf(&tunnel->name[0], "tunl %u", tunnel_id); | ||
1371 | rwlock_init(&tunnel->hlist_lock); | ||
1372 | |||
1373 | /* The net we belong to */ | ||
1374 | tunnel->l2tp_net = net; | ||
1375 | pn = l2tp_pernet(net); | ||
1376 | |||
1377 | if (cfg != NULL) | ||
1378 | tunnel->debug = cfg->debug; | ||
1379 | |||
1380 | /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ | ||
1381 | tunnel->encap = encap; | ||
1382 | if (encap == L2TP_ENCAPTYPE_UDP) { | ||
1383 | /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ | ||
1384 | udp_sk(sk)->encap_type = UDP_ENCAP_L2TPINUDP; | ||
1385 | udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv; | ||
1386 | } | ||
1387 | |||
1388 | sk->sk_user_data = tunnel; | ||
1389 | |||
1390 | /* Hook on the tunnel socket destructor so that we can cleanup | ||
1391 | * if the tunnel socket goes away. | ||
1392 | */ | ||
1393 | tunnel->old_sk_destruct = sk->sk_destruct; | ||
1394 | sk->sk_destruct = &l2tp_tunnel_destruct; | ||
1395 | tunnel->sock = sk; | ||
1396 | sk->sk_allocation = GFP_ATOMIC; | ||
1397 | |||
1398 | /* Add tunnel to our list */ | ||
1399 | INIT_LIST_HEAD(&tunnel->list); | ||
1400 | spin_lock_bh(&pn->l2tp_tunnel_list_lock); | ||
1401 | list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); | ||
1402 | spin_unlock_bh(&pn->l2tp_tunnel_list_lock); | ||
1403 | synchronize_rcu(); | ||
1404 | atomic_inc(&l2tp_tunnel_count); | ||
1405 | |||
1406 | /* Bump the reference count. The tunnel context is deleted | ||
1407 | * only when this drops to zero. | ||
1408 | */ | ||
1409 | l2tp_tunnel_inc_refcount(tunnel); | ||
1410 | |||
1411 | err = 0; | ||
1412 | err: | ||
1413 | if (tunnelp) | ||
1414 | *tunnelp = tunnel; | ||
1415 | |||
1416 | /* If tunnel's socket was created by the kernel, it doesn't | ||
1417 | * have a file. | ||
1418 | */ | ||
1419 | if (sock && sock->file) | ||
1420 | sockfd_put(sock); | ||
1421 | |||
1422 | return err; | ||
1423 | } | ||
1424 | EXPORT_SYMBOL_GPL(l2tp_tunnel_create); | ||
1425 | |||
1426 | /* This function is used by the netlink TUNNEL_DELETE command. | ||
1427 | */ | ||
1428 | int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) | ||
1429 | { | ||
1430 | int err = 0; | ||
1431 | struct socket *sock = tunnel->sock ? tunnel->sock->sk_socket : NULL; | ||
1432 | |||
1433 | /* Force the tunnel socket to close. This will eventually | ||
1434 | * cause the tunnel to be deleted via the normal socket close | ||
1435 | * mechanisms when userspace closes the tunnel socket. | ||
1436 | */ | ||
1437 | if (sock != NULL) { | ||
1438 | err = inet_shutdown(sock, 2); | ||
1439 | |||
1440 | /* If the tunnel's socket was created by the kernel, | ||
1441 | * close the socket here since the socket was not | ||
1442 | * created by userspace. | ||
1443 | */ | ||
1444 | if (sock->file == NULL) | ||
1445 | err = inet_release(sock); | ||
1446 | } | ||
1447 | |||
1448 | return err; | ||
1449 | } | ||
1450 | EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); | ||
1451 | |||
1452 | /* Really kill the session. | ||
1453 | */ | ||
1454 | void l2tp_session_free(struct l2tp_session *session) | ||
1455 | { | ||
1456 | struct l2tp_tunnel *tunnel; | ||
1457 | |||
1458 | BUG_ON(atomic_read(&session->ref_count) != 0); | ||
1459 | |||
1460 | tunnel = session->tunnel; | ||
1461 | if (tunnel != NULL) { | ||
1462 | BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); | ||
1463 | |||
1464 | /* Delete the session from the hash */ | ||
1465 | write_lock_bh(&tunnel->hlist_lock); | ||
1466 | hlist_del_init(&session->hlist); | ||
1467 | write_unlock_bh(&tunnel->hlist_lock); | ||
1468 | |||
1469 | /* Unlink from the global hash if not L2TPv2 */ | ||
1470 | if (tunnel->version != L2TP_HDR_VER_2) { | ||
1471 | struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); | ||
1472 | |||
1473 | spin_lock_bh(&pn->l2tp_session_hlist_lock); | ||
1474 | hlist_del_init_rcu(&session->global_hlist); | ||
1475 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); | ||
1476 | synchronize_rcu(); | ||
1477 | } | ||
1478 | |||
1479 | if (session->session_id != 0) | ||
1480 | atomic_dec(&l2tp_session_count); | ||
1481 | |||
1482 | sock_put(tunnel->sock); | ||
1483 | |||
1484 | /* This will delete the tunnel context if this | ||
1485 | * is the last session on the tunnel. | ||
1486 | */ | ||
1487 | session->tunnel = NULL; | ||
1488 | l2tp_tunnel_dec_refcount(tunnel); | ||
1489 | } | ||
1490 | |||
1491 | kfree(session); | ||
1492 | |||
1493 | return; | ||
1494 | } | ||
1495 | EXPORT_SYMBOL_GPL(l2tp_session_free); | ||
1496 | |||
1497 | /* This function is used by the netlink SESSION_DELETE command and by | ||
1498 | pseudowire modules. | ||
1499 | */ | ||
1500 | int l2tp_session_delete(struct l2tp_session *session) | ||
1501 | { | ||
1502 | if (session->session_close != NULL) | ||
1503 | (*session->session_close)(session); | ||
1504 | |||
1505 | l2tp_session_dec_refcount(session); | ||
1506 | |||
1507 | return 0; | ||
1508 | } | ||
1509 | EXPORT_SYMBOL_GPL(l2tp_session_delete); | ||
1510 | |||
1511 | |||
1512 | /* We come here whenever a session's send_seq, cookie_len or | ||
1513 | * l2specific_len parameters are set. | ||
1514 | */ | ||
1515 | void l2tp_session_set_header_len(struct l2tp_session *session, int version) | ||
1516 | { | ||
1517 | if (version == L2TP_HDR_VER_2) { | ||
1518 | session->hdr_len = 6; | ||
1519 | if (session->send_seq) | ||
1520 | session->hdr_len += 4; | ||
1521 | } else { | ||
1522 | session->hdr_len = 4 + session->cookie_len + session->l2specific_len + session->offset; | ||
1523 | if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP) | ||
1524 | session->hdr_len += 4; | ||
1525 | } | ||
1526 | |||
1527 | } | ||
1528 | EXPORT_SYMBOL_GPL(l2tp_session_set_header_len); | ||
1529 | |||
1530 | 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) | ||
1531 | { | ||
1532 | struct l2tp_session *session; | ||
1533 | |||
1534 | session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL); | ||
1535 | if (session != NULL) { | ||
1536 | session->magic = L2TP_SESSION_MAGIC; | ||
1537 | session->tunnel = tunnel; | ||
1538 | |||
1539 | session->session_id = session_id; | ||
1540 | session->peer_session_id = peer_session_id; | ||
1541 | session->nr = 1; | ||
1542 | |||
1543 | sprintf(&session->name[0], "sess %u/%u", | ||
1544 | tunnel->tunnel_id, session->session_id); | ||
1545 | |||
1546 | skb_queue_head_init(&session->reorder_q); | ||
1547 | |||
1548 | INIT_HLIST_NODE(&session->hlist); | ||
1549 | INIT_HLIST_NODE(&session->global_hlist); | ||
1550 | |||
1551 | /* Inherit debug options from tunnel */ | ||
1552 | session->debug = tunnel->debug; | ||
1553 | |||
1554 | if (cfg) { | ||
1555 | session->pwtype = cfg->pw_type; | ||
1556 | session->debug = cfg->debug; | ||
1557 | session->mtu = cfg->mtu; | ||
1558 | session->mru = cfg->mru; | ||
1559 | session->send_seq = cfg->send_seq; | ||
1560 | session->recv_seq = cfg->recv_seq; | ||
1561 | session->lns_mode = cfg->lns_mode; | ||
1562 | session->reorder_timeout = cfg->reorder_timeout; | ||
1563 | session->offset = cfg->offset; | ||
1564 | session->l2specific_type = cfg->l2specific_type; | ||
1565 | session->l2specific_len = cfg->l2specific_len; | ||
1566 | session->cookie_len = cfg->cookie_len; | ||
1567 | memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len); | ||
1568 | session->peer_cookie_len = cfg->peer_cookie_len; | ||
1569 | memcpy(&session->peer_cookie[0], &cfg->peer_cookie[0], cfg->peer_cookie_len); | ||
1570 | } | ||
1571 | |||
1572 | if (tunnel->version == L2TP_HDR_VER_2) | ||
1573 | session->build_header = l2tp_build_l2tpv2_header; | ||
1574 | else | ||
1575 | session->build_header = l2tp_build_l2tpv3_header; | ||
1576 | |||
1577 | l2tp_session_set_header_len(session, tunnel->version); | ||
1578 | |||
1579 | /* Bump the reference count. The session context is deleted | ||
1580 | * only when this drops to zero. | ||
1581 | */ | ||
1582 | l2tp_session_inc_refcount(session); | ||
1583 | l2tp_tunnel_inc_refcount(tunnel); | ||
1584 | |||
1585 | /* Ensure tunnel socket isn't deleted */ | ||
1586 | sock_hold(tunnel->sock); | ||
1587 | |||
1588 | /* Add session to the tunnel's hash list */ | ||
1589 | write_lock_bh(&tunnel->hlist_lock); | ||
1590 | hlist_add_head(&session->hlist, | ||
1591 | l2tp_session_id_hash(tunnel, session_id)); | ||
1592 | write_unlock_bh(&tunnel->hlist_lock); | ||
1593 | |||
1594 | /* And to the global session list if L2TPv3 */ | ||
1595 | if (tunnel->version != L2TP_HDR_VER_2) { | ||
1596 | struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); | ||
1597 | |||
1598 | spin_lock_bh(&pn->l2tp_session_hlist_lock); | ||
1599 | hlist_add_head_rcu(&session->global_hlist, | ||
1600 | l2tp_session_id_hash_2(pn, session_id)); | ||
1601 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); | ||
1602 | synchronize_rcu(); | ||
1603 | } | ||
1604 | |||
1605 | /* Ignore management session in session count value */ | ||
1606 | if (session->session_id != 0) | ||
1607 | atomic_inc(&l2tp_session_count); | ||
1608 | } | ||
1609 | |||
1610 | return session; | ||
1611 | } | ||
1612 | EXPORT_SYMBOL_GPL(l2tp_session_create); | ||
1613 | |||
1614 | /***************************************************************************** | ||
1615 | * Init and cleanup | ||
1616 | *****************************************************************************/ | ||
1617 | |||
1618 | static __net_init int l2tp_init_net(struct net *net) | ||
1619 | { | ||
1620 | struct l2tp_net *pn = net_generic(net, l2tp_net_id); | ||
1621 | int hash; | ||
1622 | |||
1623 | INIT_LIST_HEAD(&pn->l2tp_tunnel_list); | ||
1624 | spin_lock_init(&pn->l2tp_tunnel_list_lock); | ||
1625 | |||
1626 | for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) | ||
1627 | INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]); | ||
1628 | |||
1629 | spin_lock_init(&pn->l2tp_session_hlist_lock); | ||
1630 | |||
1631 | return 0; | ||
1632 | } | ||
1633 | |||
1634 | static struct pernet_operations l2tp_net_ops = { | ||
1635 | .init = l2tp_init_net, | ||
1636 | .id = &l2tp_net_id, | ||
1637 | .size = sizeof(struct l2tp_net), | ||
1638 | }; | ||
1639 | |||
1640 | static int __init l2tp_init(void) | ||
1641 | { | ||
1642 | int rc = 0; | ||
1643 | |||
1644 | rc = register_pernet_device(&l2tp_net_ops); | ||
1645 | if (rc) | ||
1646 | goto out; | ||
1647 | |||
1648 | printk(KERN_INFO "L2TP core driver, %s\n", L2TP_DRV_VERSION); | ||
1649 | |||
1650 | out: | ||
1651 | return rc; | ||
1652 | } | ||
1653 | |||
1654 | static void __exit l2tp_exit(void) | ||
1655 | { | ||
1656 | unregister_pernet_device(&l2tp_net_ops); | ||
1657 | } | ||
1658 | |||
1659 | module_init(l2tp_init); | ||
1660 | module_exit(l2tp_exit); | ||
1661 | |||
1662 | MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | ||
1663 | MODULE_DESCRIPTION("L2TP core"); | ||
1664 | MODULE_LICENSE("GPL"); | ||
1665 | MODULE_VERSION(L2TP_DRV_VERSION); | ||
1666 | |||
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h new file mode 100644 index 000000000000..f0f318edd3f1 --- /dev/null +++ b/net/l2tp/l2tp_core.h | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * L2TP internal definitions. | ||
3 | * | ||
4 | * Copyright (c) 2008,2009 Katalix Systems Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _L2TP_CORE_H_ | ||
12 | #define _L2TP_CORE_H_ | ||
13 | |||
14 | /* Just some random numbers */ | ||
15 | #define L2TP_TUNNEL_MAGIC 0x42114DDA | ||
16 | #define L2TP_SESSION_MAGIC 0x0C04EB7D | ||
17 | |||
18 | /* Per tunnel, session hash table size */ | ||
19 | #define L2TP_HASH_BITS 4 | ||
20 | #define L2TP_HASH_SIZE (1 << L2TP_HASH_BITS) | ||
21 | |||
22 | /* System-wide, session hash table size */ | ||
23 | #define L2TP_HASH_BITS_2 8 | ||
24 | #define L2TP_HASH_SIZE_2 (1 << L2TP_HASH_BITS_2) | ||
25 | |||
26 | /* Debug message categories for the DEBUG socket option */ | ||
27 | enum { | ||
28 | L2TP_MSG_DEBUG = (1 << 0), /* verbose debug (if | ||
29 | * compiled in) */ | ||
30 | L2TP_MSG_CONTROL = (1 << 1), /* userspace - kernel | ||
31 | * interface */ | ||
32 | L2TP_MSG_SEQ = (1 << 2), /* sequence numbers */ | ||
33 | L2TP_MSG_DATA = (1 << 3), /* data packets */ | ||
34 | }; | ||
35 | |||
36 | struct sk_buff; | ||
37 | |||
38 | struct l2tp_stats { | ||
39 | u64 tx_packets; | ||
40 | u64 tx_bytes; | ||
41 | u64 tx_errors; | ||
42 | u64 rx_packets; | ||
43 | u64 rx_bytes; | ||
44 | u64 rx_seq_discards; | ||
45 | u64 rx_oos_packets; | ||
46 | u64 rx_errors; | ||
47 | u64 rx_cookie_discards; | ||
48 | }; | ||
49 | |||
50 | struct l2tp_tunnel; | ||
51 | |||
52 | /* Describes a session. Contains information to determine incoming | ||
53 | * packets and transmit outgoing ones. | ||
54 | */ | ||
55 | struct l2tp_session_cfg { | ||
56 | enum l2tp_pwtype pw_type; | ||
57 | unsigned data_seq:2; /* data sequencing level | ||
58 | * 0 => none, 1 => IP only, | ||
59 | * 2 => all | ||
60 | */ | ||
61 | unsigned recv_seq:1; /* expect receive packets with | ||
62 | * sequence numbers? */ | ||
63 | unsigned send_seq:1; /* send packets with sequence | ||
64 | * numbers? */ | ||
65 | unsigned lns_mode:1; /* behave as LNS? LAC enables | ||
66 | * sequence numbers under | ||
67 | * control of LNS. */ | ||
68 | int debug; /* bitmask of debug message | ||
69 | * categories */ | ||
70 | u16 vlan_id; /* VLAN pseudowire only */ | ||
71 | u16 offset; /* offset to payload */ | ||
72 | u16 l2specific_len; /* Layer 2 specific length */ | ||
73 | u16 l2specific_type; /* Layer 2 specific type */ | ||
74 | u8 cookie[8]; /* optional cookie */ | ||
75 | int cookie_len; /* 0, 4 or 8 bytes */ | ||
76 | u8 peer_cookie[8]; /* peer's cookie */ | ||
77 | int peer_cookie_len; /* 0, 4 or 8 bytes */ | ||
78 | int reorder_timeout; /* configured reorder timeout | ||
79 | * (in jiffies) */ | ||
80 | int mtu; | ||
81 | int mru; | ||
82 | char *ifname; | ||
83 | }; | ||
84 | |||
85 | struct l2tp_session { | ||
86 | int magic; /* should be | ||
87 | * L2TP_SESSION_MAGIC */ | ||
88 | |||
89 | struct l2tp_tunnel *tunnel; /* back pointer to tunnel | ||
90 | * context */ | ||
91 | u32 session_id; | ||
92 | u32 peer_session_id; | ||
93 | u8 cookie[8]; | ||
94 | int cookie_len; | ||
95 | u8 peer_cookie[8]; | ||
96 | int peer_cookie_len; | ||
97 | u16 offset; /* offset from end of L2TP header | ||
98 | to beginning of data */ | ||
99 | u16 l2specific_len; | ||
100 | u16 l2specific_type; | ||
101 | u16 hdr_len; | ||
102 | u32 nr; /* session NR state (receive) */ | ||
103 | u32 ns; /* session NR state (send) */ | ||
104 | struct sk_buff_head reorder_q; /* receive reorder queue */ | ||
105 | struct hlist_node hlist; /* Hash list node */ | ||
106 | atomic_t ref_count; | ||
107 | |||
108 | char name[32]; /* for logging */ | ||
109 | char ifname[IFNAMSIZ]; | ||
110 | unsigned data_seq:2; /* data sequencing level | ||
111 | * 0 => none, 1 => IP only, | ||
112 | * 2 => all | ||
113 | */ | ||
114 | unsigned recv_seq:1; /* expect receive packets with | ||
115 | * sequence numbers? */ | ||
116 | unsigned send_seq:1; /* send packets with sequence | ||
117 | * numbers? */ | ||
118 | unsigned lns_mode:1; /* behave as LNS? LAC enables | ||
119 | * sequence numbers under | ||
120 | * control of LNS. */ | ||
121 | int debug; /* bitmask of debug message | ||
122 | * categories */ | ||
123 | int reorder_timeout; /* configured reorder timeout | ||
124 | * (in jiffies) */ | ||
125 | int mtu; | ||
126 | int mru; | ||
127 | enum l2tp_pwtype pwtype; | ||
128 | struct l2tp_stats stats; | ||
129 | struct hlist_node global_hlist; /* Global hash list node */ | ||
130 | |||
131 | int (*build_header)(struct l2tp_session *session, void *buf); | ||
132 | void (*recv_skb)(struct l2tp_session *session, struct sk_buff *skb, int data_len); | ||
133 | void (*session_close)(struct l2tp_session *session); | ||
134 | void (*ref)(struct l2tp_session *session); | ||
135 | void (*deref)(struct l2tp_session *session); | ||
136 | #if defined(CONFIG_L2TP_DEBUGFS) || defined(CONFIG_L2TP_DEBUGFS_MODULE) | ||
137 | void (*show)(struct seq_file *m, void *priv); | ||
138 | #endif | ||
139 | uint8_t priv[0]; /* private data */ | ||
140 | }; | ||
141 | |||
142 | /* Describes the tunnel. It contains info to track all the associated | ||
143 | * sessions so incoming packets can be sorted out | ||
144 | */ | ||
145 | struct l2tp_tunnel_cfg { | ||
146 | int debug; /* bitmask of debug message | ||
147 | * categories */ | ||
148 | enum l2tp_encap_type encap; | ||
149 | |||
150 | /* Used only for kernel-created sockets */ | ||
151 | struct in_addr local_ip; | ||
152 | struct in_addr peer_ip; | ||
153 | u16 local_udp_port; | ||
154 | u16 peer_udp_port; | ||
155 | unsigned int use_udp_checksums:1; | ||
156 | }; | ||
157 | |||
158 | struct l2tp_tunnel { | ||
159 | int magic; /* Should be L2TP_TUNNEL_MAGIC */ | ||
160 | rwlock_t hlist_lock; /* protect session_hlist */ | ||
161 | struct hlist_head session_hlist[L2TP_HASH_SIZE]; | ||
162 | /* hashed list of sessions, | ||
163 | * hashed by id */ | ||
164 | u32 tunnel_id; | ||
165 | u32 peer_tunnel_id; | ||
166 | int version; /* 2=>L2TPv2, 3=>L2TPv3 */ | ||
167 | |||
168 | char name[20]; /* for logging */ | ||
169 | int debug; /* bitmask of debug message | ||
170 | * categories */ | ||
171 | enum l2tp_encap_type encap; | ||
172 | struct l2tp_stats stats; | ||
173 | |||
174 | struct list_head list; /* Keep a list of all tunnels */ | ||
175 | struct net *l2tp_net; /* the net we belong to */ | ||
176 | |||
177 | atomic_t ref_count; | ||
178 | #ifdef CONFIG_DEBUG_FS | ||
179 | void (*show)(struct seq_file *m, void *arg); | ||
180 | #endif | ||
181 | int (*recv_payload_hook)(struct sk_buff *skb); | ||
182 | void (*old_sk_destruct)(struct sock *); | ||
183 | struct sock *sock; /* Parent socket */ | ||
184 | int fd; | ||
185 | |||
186 | uint8_t priv[0]; /* private data */ | ||
187 | }; | ||
188 | |||
189 | struct l2tp_nl_cmd_ops { | ||
190 | int (*session_create)(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg); | ||
191 | int (*session_delete)(struct l2tp_session *session); | ||
192 | }; | ||
193 | |||
194 | static inline void *l2tp_tunnel_priv(struct l2tp_tunnel *tunnel) | ||
195 | { | ||
196 | return &tunnel->priv[0]; | ||
197 | } | ||
198 | |||
199 | static inline void *l2tp_session_priv(struct l2tp_session *session) | ||
200 | { | ||
201 | return &session->priv[0]; | ||
202 | } | ||
203 | |||
204 | static inline struct l2tp_tunnel *l2tp_sock_to_tunnel(struct sock *sk) | ||
205 | { | ||
206 | struct l2tp_tunnel *tunnel; | ||
207 | |||
208 | if (sk == NULL) | ||
209 | return NULL; | ||
210 | |||
211 | sock_hold(sk); | ||
212 | tunnel = (struct l2tp_tunnel *)(sk->sk_user_data); | ||
213 | if (tunnel == NULL) { | ||
214 | sock_put(sk); | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); | ||
219 | |||
220 | out: | ||
221 | return tunnel; | ||
222 | } | ||
223 | |||
224 | extern struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id); | ||
225 | extern struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth); | ||
226 | extern struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname); | ||
227 | extern struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id); | ||
228 | extern struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth); | ||
229 | |||
230 | extern int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp); | ||
231 | extern int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); | ||
232 | extern 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); | ||
233 | extern int l2tp_session_delete(struct l2tp_session *session); | ||
234 | extern void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); | ||
235 | extern void l2tp_session_free(struct l2tp_session *session); | ||
236 | extern void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, int length, int (*payload_hook)(struct sk_buff *skb)); | ||
237 | extern int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, int (*payload_hook)(struct sk_buff *skb)); | ||
238 | extern int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb); | ||
239 | |||
240 | extern int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, size_t data_len); | ||
241 | extern int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len); | ||
242 | extern void l2tp_tunnel_destruct(struct sock *sk); | ||
243 | extern void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); | ||
244 | extern void l2tp_session_set_header_len(struct l2tp_session *session, int version); | ||
245 | |||
246 | extern int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops); | ||
247 | extern void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type); | ||
248 | |||
249 | /* Tunnel reference counts. Incremented per session that is added to | ||
250 | * the tunnel. | ||
251 | */ | ||
252 | static inline void l2tp_tunnel_inc_refcount_1(struct l2tp_tunnel *tunnel) | ||
253 | { | ||
254 | atomic_inc(&tunnel->ref_count); | ||
255 | } | ||
256 | |||
257 | static inline void l2tp_tunnel_dec_refcount_1(struct l2tp_tunnel *tunnel) | ||
258 | { | ||
259 | if (atomic_dec_and_test(&tunnel->ref_count)) | ||
260 | l2tp_tunnel_free(tunnel); | ||
261 | } | ||
262 | #ifdef L2TP_REFCNT_DEBUG | ||
263 | #define l2tp_tunnel_inc_refcount(_t) do { \ | ||
264 | printk(KERN_DEBUG "l2tp_tunnel_inc_refcount: %s:%d %s: cnt=%d\n", __func__, __LINE__, (_t)->name, atomic_read(&_t->ref_count)); \ | ||
265 | l2tp_tunnel_inc_refcount_1(_t); \ | ||
266 | } while (0) | ||
267 | #define l2tp_tunnel_dec_refcount(_t) do { \ | ||
268 | printk(KERN_DEBUG "l2tp_tunnel_dec_refcount: %s:%d %s: cnt=%d\n", __func__, __LINE__, (_t)->name, atomic_read(&_t->ref_count)); \ | ||
269 | l2tp_tunnel_dec_refcount_1(_t); \ | ||
270 | } while (0) | ||
271 | #else | ||
272 | #define l2tp_tunnel_inc_refcount(t) l2tp_tunnel_inc_refcount_1(t) | ||
273 | #define l2tp_tunnel_dec_refcount(t) l2tp_tunnel_dec_refcount_1(t) | ||
274 | #endif | ||
275 | |||
276 | /* Session reference counts. Incremented when code obtains a reference | ||
277 | * to a session. | ||
278 | */ | ||
279 | static inline void l2tp_session_inc_refcount_1(struct l2tp_session *session) | ||
280 | { | ||
281 | atomic_inc(&session->ref_count); | ||
282 | } | ||
283 | |||
284 | static inline void l2tp_session_dec_refcount_1(struct l2tp_session *session) | ||
285 | { | ||
286 | if (atomic_dec_and_test(&session->ref_count)) | ||
287 | l2tp_session_free(session); | ||
288 | } | ||
289 | |||
290 | #ifdef L2TP_REFCNT_DEBUG | ||
291 | #define l2tp_session_inc_refcount(_s) do { \ | ||
292 | printk(KERN_DEBUG "l2tp_session_inc_refcount: %s:%d %s: cnt=%d\n", __func__, __LINE__, (_s)->name, atomic_read(&_s->ref_count)); \ | ||
293 | l2tp_session_inc_refcount_1(_s); \ | ||
294 | } while (0) | ||
295 | #define l2tp_session_dec_refcount(_s) do { \ | ||
296 | printk(KERN_DEBUG "l2tp_session_dec_refcount: %s:%d %s: cnt=%d\n", __func__, __LINE__, (_s)->name, atomic_read(&_s->ref_count)); \ | ||
297 | l2tp_session_dec_refcount_1(_s); \ | ||
298 | } while (0) | ||
299 | #else | ||
300 | #define l2tp_session_inc_refcount(s) l2tp_session_inc_refcount_1(s) | ||
301 | #define l2tp_session_dec_refcount(s) l2tp_session_dec_refcount_1(s) | ||
302 | #endif | ||
303 | |||
304 | #endif /* _L2TP_CORE_H_ */ | ||
diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c new file mode 100644 index 000000000000..104ec3b283d4 --- /dev/null +++ b/net/l2tp/l2tp_debugfs.c | |||
@@ -0,0 +1,341 @@ | |||
1 | /* | ||
2 | * L2TP subsystem debugfs | ||
3 | * | ||
4 | * Copyright (c) 2010 Katalix Systems Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | #include <linux/socket.h> | ||
15 | #include <linux/hash.h> | ||
16 | #include <linux/l2tp.h> | ||
17 | #include <linux/in.h> | ||
18 | #include <linux/etherdevice.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/debugfs.h> | ||
21 | #include <net/sock.h> | ||
22 | #include <net/ip.h> | ||
23 | #include <net/icmp.h> | ||
24 | #include <net/udp.h> | ||
25 | #include <net/inet_common.h> | ||
26 | #include <net/inet_hashtables.h> | ||
27 | #include <net/tcp_states.h> | ||
28 | #include <net/protocol.h> | ||
29 | #include <net/xfrm.h> | ||
30 | #include <net/net_namespace.h> | ||
31 | #include <net/netns/generic.h> | ||
32 | |||
33 | #include "l2tp_core.h" | ||
34 | |||
35 | static struct dentry *rootdir; | ||
36 | static struct dentry *tunnels; | ||
37 | |||
38 | struct l2tp_dfs_seq_data { | ||
39 | struct net *net; | ||
40 | int tunnel_idx; /* current tunnel */ | ||
41 | int session_idx; /* index of session within current tunnel */ | ||
42 | struct l2tp_tunnel *tunnel; | ||
43 | struct l2tp_session *session; /* NULL means get next tunnel */ | ||
44 | }; | ||
45 | |||
46 | static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd) | ||
47 | { | ||
48 | pd->tunnel = l2tp_tunnel_find_nth(pd->net, pd->tunnel_idx); | ||
49 | pd->tunnel_idx++; | ||
50 | } | ||
51 | |||
52 | static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd) | ||
53 | { | ||
54 | pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx); | ||
55 | pd->session_idx++; | ||
56 | |||
57 | if (pd->session == NULL) { | ||
58 | pd->session_idx = 0; | ||
59 | l2tp_dfs_next_tunnel(pd); | ||
60 | } | ||
61 | |||
62 | } | ||
63 | |||
64 | static void *l2tp_dfs_seq_start(struct seq_file *m, loff_t *offs) | ||
65 | { | ||
66 | struct l2tp_dfs_seq_data *pd = SEQ_START_TOKEN; | ||
67 | loff_t pos = *offs; | ||
68 | |||
69 | if (!pos) | ||
70 | goto out; | ||
71 | |||
72 | BUG_ON(m->private == NULL); | ||
73 | pd = m->private; | ||
74 | |||
75 | if (pd->tunnel == NULL) | ||
76 | l2tp_dfs_next_tunnel(pd); | ||
77 | else | ||
78 | l2tp_dfs_next_session(pd); | ||
79 | |||
80 | /* NULL tunnel and session indicates end of list */ | ||
81 | if ((pd->tunnel == NULL) && (pd->session == NULL)) | ||
82 | pd = NULL; | ||
83 | |||
84 | out: | ||
85 | return pd; | ||
86 | } | ||
87 | |||
88 | |||
89 | static void *l2tp_dfs_seq_next(struct seq_file *m, void *v, loff_t *pos) | ||
90 | { | ||
91 | (*pos)++; | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | static void l2tp_dfs_seq_stop(struct seq_file *p, void *v) | ||
96 | { | ||
97 | /* nothing to do */ | ||
98 | } | ||
99 | |||
100 | static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v) | ||
101 | { | ||
102 | struct l2tp_tunnel *tunnel = v; | ||
103 | int session_count = 0; | ||
104 | int hash; | ||
105 | struct hlist_node *walk; | ||
106 | struct hlist_node *tmp; | ||
107 | |||
108 | read_lock_bh(&tunnel->hlist_lock); | ||
109 | for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { | ||
110 | hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) { | ||
111 | struct l2tp_session *session; | ||
112 | |||
113 | session = hlist_entry(walk, struct l2tp_session, hlist); | ||
114 | if (session->session_id == 0) | ||
115 | continue; | ||
116 | |||
117 | session_count++; | ||
118 | } | ||
119 | } | ||
120 | read_unlock_bh(&tunnel->hlist_lock); | ||
121 | |||
122 | seq_printf(m, "\nTUNNEL %u peer %u", tunnel->tunnel_id, tunnel->peer_tunnel_id); | ||
123 | if (tunnel->sock) { | ||
124 | struct inet_sock *inet = inet_sk(tunnel->sock); | ||
125 | seq_printf(m, " from %pI4 to %pI4\n", | ||
126 | &inet->inet_saddr, &inet->inet_daddr); | ||
127 | if (tunnel->encap == L2TP_ENCAPTYPE_UDP) | ||
128 | seq_printf(m, " source port %hu, dest port %hu\n", | ||
129 | ntohs(inet->inet_sport), ntohs(inet->inet_dport)); | ||
130 | } | ||
131 | seq_printf(m, " L2TPv%d, %s\n", tunnel->version, | ||
132 | tunnel->encap == L2TP_ENCAPTYPE_UDP ? "UDP" : | ||
133 | tunnel->encap == L2TP_ENCAPTYPE_IP ? "IP" : | ||
134 | ""); | ||
135 | seq_printf(m, " %d sessions, refcnt %d/%d\n", session_count, | ||
136 | tunnel->sock ? atomic_read(&tunnel->sock->sk_refcnt) : 0, | ||
137 | atomic_read(&tunnel->ref_count)); | ||
138 | |||
139 | seq_printf(m, " %08x rx %llu/%llu/%llu rx %llu/%llu/%llu\n", | ||
140 | tunnel->debug, | ||
141 | (unsigned long long)tunnel->stats.tx_packets, | ||
142 | (unsigned long long)tunnel->stats.tx_bytes, | ||
143 | (unsigned long long)tunnel->stats.tx_errors, | ||
144 | (unsigned long long)tunnel->stats.rx_packets, | ||
145 | (unsigned long long)tunnel->stats.rx_bytes, | ||
146 | (unsigned long long)tunnel->stats.rx_errors); | ||
147 | |||
148 | if (tunnel->show != NULL) | ||
149 | tunnel->show(m, tunnel); | ||
150 | } | ||
151 | |||
152 | static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v) | ||
153 | { | ||
154 | struct l2tp_session *session = v; | ||
155 | |||
156 | seq_printf(m, " SESSION %u, peer %u, %s\n", session->session_id, | ||
157 | session->peer_session_id, | ||
158 | session->pwtype == L2TP_PWTYPE_ETH ? "ETH" : | ||
159 | session->pwtype == L2TP_PWTYPE_PPP ? "PPP" : | ||
160 | ""); | ||
161 | if (session->send_seq || session->recv_seq) | ||
162 | seq_printf(m, " nr %hu, ns %hu\n", session->nr, session->ns); | ||
163 | seq_printf(m, " refcnt %d\n", atomic_read(&session->ref_count)); | ||
164 | seq_printf(m, " config %d/%d/%c/%c/%s/%s %08x %u\n", | ||
165 | session->mtu, session->mru, | ||
166 | session->recv_seq ? 'R' : '-', | ||
167 | session->send_seq ? 'S' : '-', | ||
168 | session->data_seq == 1 ? "IPSEQ" : | ||
169 | session->data_seq == 2 ? "DATASEQ" : "-", | ||
170 | session->lns_mode ? "LNS" : "LAC", | ||
171 | session->debug, | ||
172 | jiffies_to_msecs(session->reorder_timeout)); | ||
173 | seq_printf(m, " offset %hu l2specific %hu/%hu\n", | ||
174 | session->offset, session->l2specific_type, session->l2specific_len); | ||
175 | if (session->cookie_len) { | ||
176 | seq_printf(m, " cookie %02x%02x%02x%02x", | ||
177 | session->cookie[0], session->cookie[1], | ||
178 | session->cookie[2], session->cookie[3]); | ||
179 | if (session->cookie_len == 8) | ||
180 | seq_printf(m, "%02x%02x%02x%02x", | ||
181 | session->cookie[4], session->cookie[5], | ||
182 | session->cookie[6], session->cookie[7]); | ||
183 | seq_printf(m, "\n"); | ||
184 | } | ||
185 | if (session->peer_cookie_len) { | ||
186 | seq_printf(m, " peer cookie %02x%02x%02x%02x", | ||
187 | session->peer_cookie[0], session->peer_cookie[1], | ||
188 | session->peer_cookie[2], session->peer_cookie[3]); | ||
189 | if (session->peer_cookie_len == 8) | ||
190 | seq_printf(m, "%02x%02x%02x%02x", | ||
191 | session->peer_cookie[4], session->peer_cookie[5], | ||
192 | session->peer_cookie[6], session->peer_cookie[7]); | ||
193 | seq_printf(m, "\n"); | ||
194 | } | ||
195 | |||
196 | seq_printf(m, " %hu/%hu tx %llu/%llu/%llu rx %llu/%llu/%llu\n", | ||
197 | session->nr, session->ns, | ||
198 | (unsigned long long)session->stats.tx_packets, | ||
199 | (unsigned long long)session->stats.tx_bytes, | ||
200 | (unsigned long long)session->stats.tx_errors, | ||
201 | (unsigned long long)session->stats.rx_packets, | ||
202 | (unsigned long long)session->stats.rx_bytes, | ||
203 | (unsigned long long)session->stats.rx_errors); | ||
204 | |||
205 | if (session->show != NULL) | ||
206 | session->show(m, session); | ||
207 | } | ||
208 | |||
209 | static int l2tp_dfs_seq_show(struct seq_file *m, void *v) | ||
210 | { | ||
211 | struct l2tp_dfs_seq_data *pd = v; | ||
212 | |||
213 | /* display header on line 1 */ | ||
214 | if (v == SEQ_START_TOKEN) { | ||
215 | seq_puts(m, "TUNNEL ID, peer ID from IP to IP\n"); | ||
216 | seq_puts(m, " L2TPv2/L2TPv3, UDP/IP\n"); | ||
217 | seq_puts(m, " sessions session-count, refcnt refcnt/sk->refcnt\n"); | ||
218 | seq_puts(m, " debug tx-pkts/bytes/errs rx-pkts/bytes/errs\n"); | ||
219 | seq_puts(m, " SESSION ID, peer ID, PWTYPE\n"); | ||
220 | seq_puts(m, " refcnt cnt\n"); | ||
221 | seq_puts(m, " offset OFFSET l2specific TYPE/LEN\n"); | ||
222 | seq_puts(m, " [ cookie ]\n"); | ||
223 | seq_puts(m, " [ peer cookie ]\n"); | ||
224 | seq_puts(m, " config mtu/mru/rcvseq/sendseq/dataseq/lns debug reorderto\n"); | ||
225 | seq_puts(m, " nr/ns tx-pkts/bytes/errs rx-pkts/bytes/errs\n"); | ||
226 | goto out; | ||
227 | } | ||
228 | |||
229 | /* Show the tunnel or session context */ | ||
230 | if (pd->session == NULL) | ||
231 | l2tp_dfs_seq_tunnel_show(m, pd->tunnel); | ||
232 | else | ||
233 | l2tp_dfs_seq_session_show(m, pd->session); | ||
234 | |||
235 | out: | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static const struct seq_operations l2tp_dfs_seq_ops = { | ||
240 | .start = l2tp_dfs_seq_start, | ||
241 | .next = l2tp_dfs_seq_next, | ||
242 | .stop = l2tp_dfs_seq_stop, | ||
243 | .show = l2tp_dfs_seq_show, | ||
244 | }; | ||
245 | |||
246 | static int l2tp_dfs_seq_open(struct inode *inode, struct file *file) | ||
247 | { | ||
248 | struct l2tp_dfs_seq_data *pd; | ||
249 | struct seq_file *seq; | ||
250 | int rc = -ENOMEM; | ||
251 | |||
252 | pd = kzalloc(GFP_KERNEL, sizeof(*pd)); | ||
253 | if (pd == NULL) | ||
254 | goto out; | ||
255 | |||
256 | /* Derive the network namespace from the pid opening the | ||
257 | * file. | ||
258 | */ | ||
259 | pd->net = get_net_ns_by_pid(current->pid); | ||
260 | if (IS_ERR(pd->net)) { | ||
261 | rc = -PTR_ERR(pd->net); | ||
262 | goto err_free_pd; | ||
263 | } | ||
264 | |||
265 | rc = seq_open(file, &l2tp_dfs_seq_ops); | ||
266 | if (rc) | ||
267 | goto err_free_net; | ||
268 | |||
269 | seq = file->private_data; | ||
270 | seq->private = pd; | ||
271 | |||
272 | out: | ||
273 | return rc; | ||
274 | |||
275 | err_free_net: | ||
276 | put_net(pd->net); | ||
277 | err_free_pd: | ||
278 | kfree(pd); | ||
279 | goto out; | ||
280 | } | ||
281 | |||
282 | static int l2tp_dfs_seq_release(struct inode *inode, struct file *file) | ||
283 | { | ||
284 | struct l2tp_dfs_seq_data *pd; | ||
285 | struct seq_file *seq; | ||
286 | |||
287 | seq = file->private_data; | ||
288 | pd = seq->private; | ||
289 | if (pd->net) | ||
290 | put_net(pd->net); | ||
291 | kfree(pd); | ||
292 | seq_release(inode, file); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static const struct file_operations l2tp_dfs_fops = { | ||
298 | .owner = THIS_MODULE, | ||
299 | .open = l2tp_dfs_seq_open, | ||
300 | .read = seq_read, | ||
301 | .llseek = seq_lseek, | ||
302 | .release = l2tp_dfs_seq_release, | ||
303 | }; | ||
304 | |||
305 | static int __init l2tp_debugfs_init(void) | ||
306 | { | ||
307 | int rc = 0; | ||
308 | |||
309 | rootdir = debugfs_create_dir("l2tp", NULL); | ||
310 | if (IS_ERR(rootdir)) { | ||
311 | rc = PTR_ERR(rootdir); | ||
312 | rootdir = NULL; | ||
313 | goto out; | ||
314 | } | ||
315 | |||
316 | tunnels = debugfs_create_file("tunnels", 0600, rootdir, NULL, &l2tp_dfs_fops); | ||
317 | if (tunnels == NULL) | ||
318 | rc = -EIO; | ||
319 | |||
320 | printk(KERN_INFO "L2TP debugfs support\n"); | ||
321 | |||
322 | out: | ||
323 | if (rc) | ||
324 | printk(KERN_WARNING "l2tp debugfs: unable to init\n"); | ||
325 | |||
326 | return rc; | ||
327 | } | ||
328 | |||
329 | static void __exit l2tp_debugfs_exit(void) | ||
330 | { | ||
331 | debugfs_remove(tunnels); | ||
332 | debugfs_remove(rootdir); | ||
333 | } | ||
334 | |||
335 | module_init(l2tp_debugfs_init); | ||
336 | module_exit(l2tp_debugfs_exit); | ||
337 | |||
338 | MODULE_LICENSE("GPL"); | ||
339 | MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | ||
340 | MODULE_DESCRIPTION("L2TP debugfs driver"); | ||
341 | MODULE_VERSION("1.0"); | ||
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c new file mode 100644 index 000000000000..58c6c4cda73b --- /dev/null +++ b/net/l2tp/l2tp_eth.c | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | * L2TPv3 ethernet pseudowire driver | ||
3 | * | ||
4 | * Copyright (c) 2008,2009,2010 Katalix Systems Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | #include <linux/socket.h> | ||
15 | #include <linux/hash.h> | ||
16 | #include <linux/l2tp.h> | ||
17 | #include <linux/in.h> | ||
18 | #include <linux/etherdevice.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <net/sock.h> | ||
21 | #include <net/ip.h> | ||
22 | #include <net/icmp.h> | ||
23 | #include <net/udp.h> | ||
24 | #include <net/inet_common.h> | ||
25 | #include <net/inet_hashtables.h> | ||
26 | #include <net/tcp_states.h> | ||
27 | #include <net/protocol.h> | ||
28 | #include <net/xfrm.h> | ||
29 | #include <net/net_namespace.h> | ||
30 | #include <net/netns/generic.h> | ||
31 | |||
32 | #include "l2tp_core.h" | ||
33 | |||
34 | /* Default device name. May be overridden by name specified by user */ | ||
35 | #define L2TP_ETH_DEV_NAME "l2tpeth%d" | ||
36 | |||
37 | /* via netdev_priv() */ | ||
38 | struct l2tp_eth { | ||
39 | struct net_device *dev; | ||
40 | struct sock *tunnel_sock; | ||
41 | struct l2tp_session *session; | ||
42 | struct list_head list; | ||
43 | }; | ||
44 | |||
45 | /* via l2tp_session_priv() */ | ||
46 | struct l2tp_eth_sess { | ||
47 | struct net_device *dev; | ||
48 | }; | ||
49 | |||
50 | /* per-net private data for this module */ | ||
51 | static unsigned int l2tp_eth_net_id; | ||
52 | struct l2tp_eth_net { | ||
53 | struct list_head l2tp_eth_dev_list; | ||
54 | spinlock_t l2tp_eth_lock; | ||
55 | }; | ||
56 | |||
57 | static inline struct l2tp_eth_net *l2tp_eth_pernet(struct net *net) | ||
58 | { | ||
59 | return net_generic(net, l2tp_eth_net_id); | ||
60 | } | ||
61 | |||
62 | static int l2tp_eth_dev_init(struct net_device *dev) | ||
63 | { | ||
64 | struct l2tp_eth *priv = netdev_priv(dev); | ||
65 | |||
66 | priv->dev = dev; | ||
67 | random_ether_addr(dev->dev_addr); | ||
68 | memset(&dev->broadcast[0], 0xff, 6); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static void l2tp_eth_dev_uninit(struct net_device *dev) | ||
74 | { | ||
75 | struct l2tp_eth *priv = netdev_priv(dev); | ||
76 | struct l2tp_eth_net *pn = l2tp_eth_pernet(dev_net(dev)); | ||
77 | |||
78 | spin_lock(&pn->l2tp_eth_lock); | ||
79 | list_del_init(&priv->list); | ||
80 | spin_unlock(&pn->l2tp_eth_lock); | ||
81 | dev_put(dev); | ||
82 | } | ||
83 | |||
84 | static int l2tp_eth_dev_xmit(struct sk_buff *skb, struct net_device *dev) | ||
85 | { | ||
86 | struct l2tp_eth *priv = netdev_priv(dev); | ||
87 | struct l2tp_session *session = priv->session; | ||
88 | |||
89 | l2tp_xmit_skb(session, skb, session->hdr_len); | ||
90 | |||
91 | dev->stats.tx_bytes += skb->len; | ||
92 | dev->stats.tx_packets++; | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static struct net_device_ops l2tp_eth_netdev_ops = { | ||
98 | .ndo_init = l2tp_eth_dev_init, | ||
99 | .ndo_uninit = l2tp_eth_dev_uninit, | ||
100 | .ndo_start_xmit = l2tp_eth_dev_xmit, | ||
101 | }; | ||
102 | |||
103 | static void l2tp_eth_dev_setup(struct net_device *dev) | ||
104 | { | ||
105 | ether_setup(dev); | ||
106 | |||
107 | dev->netdev_ops = &l2tp_eth_netdev_ops; | ||
108 | dev->destructor = free_netdev; | ||
109 | } | ||
110 | |||
111 | static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len) | ||
112 | { | ||
113 | struct l2tp_eth_sess *spriv = l2tp_session_priv(session); | ||
114 | struct net_device *dev = spriv->dev; | ||
115 | |||
116 | if (session->debug & L2TP_MSG_DATA) { | ||
117 | unsigned int length; | ||
118 | int offset; | ||
119 | u8 *ptr = skb->data; | ||
120 | |||
121 | length = min(32u, skb->len); | ||
122 | if (!pskb_may_pull(skb, length)) | ||
123 | goto error; | ||
124 | |||
125 | printk(KERN_DEBUG "%s: eth recv: ", session->name); | ||
126 | |||
127 | offset = 0; | ||
128 | do { | ||
129 | printk(" %02X", ptr[offset]); | ||
130 | } while (++offset < length); | ||
131 | |||
132 | printk("\n"); | ||
133 | } | ||
134 | |||
135 | if (data_len < ETH_HLEN) | ||
136 | goto error; | ||
137 | |||
138 | secpath_reset(skb); | ||
139 | |||
140 | /* checksums verified by L2TP */ | ||
141 | skb->ip_summed = CHECKSUM_NONE; | ||
142 | |||
143 | skb_dst_drop(skb); | ||
144 | nf_reset(skb); | ||
145 | |||
146 | if (dev_forward_skb(dev, skb) == NET_RX_SUCCESS) { | ||
147 | dev->last_rx = jiffies; | ||
148 | dev->stats.rx_packets++; | ||
149 | dev->stats.rx_bytes += data_len; | ||
150 | } else | ||
151 | dev->stats.rx_errors++; | ||
152 | |||
153 | return; | ||
154 | |||
155 | error: | ||
156 | dev->stats.rx_errors++; | ||
157 | kfree_skb(skb); | ||
158 | } | ||
159 | |||
160 | static void l2tp_eth_delete(struct l2tp_session *session) | ||
161 | { | ||
162 | struct l2tp_eth_sess *spriv; | ||
163 | struct net_device *dev; | ||
164 | |||
165 | if (session) { | ||
166 | spriv = l2tp_session_priv(session); | ||
167 | dev = spriv->dev; | ||
168 | if (dev) { | ||
169 | unregister_netdev(dev); | ||
170 | spriv->dev = NULL; | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | |||
175 | #if defined(CONFIG_L2TP_DEBUGFS) || defined(CONFIG_L2TP_DEBUGFS_MODULE) | ||
176 | static void l2tp_eth_show(struct seq_file *m, void *arg) | ||
177 | { | ||
178 | struct l2tp_session *session = arg; | ||
179 | struct l2tp_eth_sess *spriv = l2tp_session_priv(session); | ||
180 | struct net_device *dev = spriv->dev; | ||
181 | |||
182 | seq_printf(m, " interface %s\n", dev->name); | ||
183 | } | ||
184 | #endif | ||
185 | |||
186 | static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) | ||
187 | { | ||
188 | struct net_device *dev; | ||
189 | char name[IFNAMSIZ]; | ||
190 | struct l2tp_tunnel *tunnel; | ||
191 | struct l2tp_session *session; | ||
192 | struct l2tp_eth *priv; | ||
193 | struct l2tp_eth_sess *spriv; | ||
194 | int rc; | ||
195 | struct l2tp_eth_net *pn; | ||
196 | |||
197 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
198 | if (!tunnel) { | ||
199 | rc = -ENODEV; | ||
200 | goto out; | ||
201 | } | ||
202 | |||
203 | session = l2tp_session_find(net, tunnel, session_id); | ||
204 | if (session) { | ||
205 | rc = -EEXIST; | ||
206 | goto out; | ||
207 | } | ||
208 | |||
209 | if (cfg->ifname) { | ||
210 | dev = dev_get_by_name(net, cfg->ifname); | ||
211 | if (dev) { | ||
212 | dev_put(dev); | ||
213 | rc = -EEXIST; | ||
214 | goto out; | ||
215 | } | ||
216 | strlcpy(name, cfg->ifname, IFNAMSIZ); | ||
217 | } else | ||
218 | strcpy(name, L2TP_ETH_DEV_NAME); | ||
219 | |||
220 | session = l2tp_session_create(sizeof(*spriv), tunnel, session_id, | ||
221 | peer_session_id, cfg); | ||
222 | if (!session) { | ||
223 | rc = -ENOMEM; | ||
224 | goto out; | ||
225 | } | ||
226 | |||
227 | dev = alloc_netdev(sizeof(*priv), name, l2tp_eth_dev_setup); | ||
228 | if (!dev) { | ||
229 | rc = -ENOMEM; | ||
230 | goto out_del_session; | ||
231 | } | ||
232 | |||
233 | dev_net_set(dev, net); | ||
234 | if (session->mtu == 0) | ||
235 | session->mtu = dev->mtu - session->hdr_len; | ||
236 | dev->mtu = session->mtu; | ||
237 | dev->needed_headroom += session->hdr_len; | ||
238 | |||
239 | priv = netdev_priv(dev); | ||
240 | priv->dev = dev; | ||
241 | priv->session = session; | ||
242 | INIT_LIST_HEAD(&priv->list); | ||
243 | |||
244 | priv->tunnel_sock = tunnel->sock; | ||
245 | session->recv_skb = l2tp_eth_dev_recv; | ||
246 | session->session_close = l2tp_eth_delete; | ||
247 | #if defined(CONFIG_L2TP_DEBUGFS) || defined(CONFIG_L2TP_DEBUGFS_MODULE) | ||
248 | session->show = l2tp_eth_show; | ||
249 | #endif | ||
250 | |||
251 | spriv = l2tp_session_priv(session); | ||
252 | spriv->dev = dev; | ||
253 | |||
254 | rc = register_netdev(dev); | ||
255 | if (rc < 0) | ||
256 | goto out_del_dev; | ||
257 | |||
258 | /* Must be done after register_netdev() */ | ||
259 | strlcpy(session->ifname, dev->name, IFNAMSIZ); | ||
260 | |||
261 | dev_hold(dev); | ||
262 | pn = l2tp_eth_pernet(dev_net(dev)); | ||
263 | spin_lock(&pn->l2tp_eth_lock); | ||
264 | list_add(&priv->list, &pn->l2tp_eth_dev_list); | ||
265 | spin_unlock(&pn->l2tp_eth_lock); | ||
266 | |||
267 | return 0; | ||
268 | |||
269 | out_del_dev: | ||
270 | free_netdev(dev); | ||
271 | out_del_session: | ||
272 | l2tp_session_delete(session); | ||
273 | out: | ||
274 | return rc; | ||
275 | } | ||
276 | |||
277 | static __net_init int l2tp_eth_init_net(struct net *net) | ||
278 | { | ||
279 | struct l2tp_eth_net *pn = net_generic(net, l2tp_eth_net_id); | ||
280 | |||
281 | INIT_LIST_HEAD(&pn->l2tp_eth_dev_list); | ||
282 | spin_lock_init(&pn->l2tp_eth_lock); | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static __net_initdata struct pernet_operations l2tp_eth_net_ops = { | ||
288 | .init = l2tp_eth_init_net, | ||
289 | .id = &l2tp_eth_net_id, | ||
290 | .size = sizeof(struct l2tp_eth_net), | ||
291 | }; | ||
292 | |||
293 | |||
294 | static const struct l2tp_nl_cmd_ops l2tp_eth_nl_cmd_ops = { | ||
295 | .session_create = l2tp_eth_create, | ||
296 | .session_delete = l2tp_session_delete, | ||
297 | }; | ||
298 | |||
299 | |||
300 | static int __init l2tp_eth_init(void) | ||
301 | { | ||
302 | int err = 0; | ||
303 | |||
304 | err = l2tp_nl_register_ops(L2TP_PWTYPE_ETH, &l2tp_eth_nl_cmd_ops); | ||
305 | if (err) | ||
306 | goto out; | ||
307 | |||
308 | err = register_pernet_device(&l2tp_eth_net_ops); | ||
309 | if (err) | ||
310 | goto out_unreg; | ||
311 | |||
312 | printk(KERN_INFO "L2TP ethernet pseudowire support (L2TPv3)\n"); | ||
313 | |||
314 | return 0; | ||
315 | |||
316 | out_unreg: | ||
317 | l2tp_nl_unregister_ops(L2TP_PWTYPE_ETH); | ||
318 | out: | ||
319 | return err; | ||
320 | } | ||
321 | |||
322 | static void __exit l2tp_eth_exit(void) | ||
323 | { | ||
324 | unregister_pernet_device(&l2tp_eth_net_ops); | ||
325 | l2tp_nl_unregister_ops(L2TP_PWTYPE_ETH); | ||
326 | } | ||
327 | |||
328 | module_init(l2tp_eth_init); | ||
329 | module_exit(l2tp_eth_exit); | ||
330 | |||
331 | MODULE_LICENSE("GPL"); | ||
332 | MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | ||
333 | MODULE_DESCRIPTION("L2TP ethernet pseudowire driver"); | ||
334 | MODULE_VERSION("1.0"); | ||
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c new file mode 100644 index 000000000000..0852512d392c --- /dev/null +++ b/net/l2tp/l2tp_ip.c | |||
@@ -0,0 +1,679 @@ | |||
1 | /* | ||
2 | * L2TPv3 IP encapsulation support | ||
3 | * | ||
4 | * Copyright (c) 2008,2009,2010 Katalix Systems Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/icmp.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/random.h> | ||
16 | #include <linux/socket.h> | ||
17 | #include <linux/l2tp.h> | ||
18 | #include <linux/in.h> | ||
19 | #include <net/sock.h> | ||
20 | #include <net/ip.h> | ||
21 | #include <net/icmp.h> | ||
22 | #include <net/udp.h> | ||
23 | #include <net/inet_common.h> | ||
24 | #include <net/inet_hashtables.h> | ||
25 | #include <net/tcp_states.h> | ||
26 | #include <net/protocol.h> | ||
27 | #include <net/xfrm.h> | ||
28 | |||
29 | #include "l2tp_core.h" | ||
30 | |||
31 | struct l2tp_ip_sock { | ||
32 | /* inet_sock has to be the first member of l2tp_ip_sock */ | ||
33 | struct inet_sock inet; | ||
34 | |||
35 | __u32 conn_id; | ||
36 | __u32 peer_conn_id; | ||
37 | |||
38 | __u64 tx_packets; | ||
39 | __u64 tx_bytes; | ||
40 | __u64 tx_errors; | ||
41 | __u64 rx_packets; | ||
42 | __u64 rx_bytes; | ||
43 | __u64 rx_errors; | ||
44 | }; | ||
45 | |||
46 | static DEFINE_RWLOCK(l2tp_ip_lock); | ||
47 | static struct hlist_head l2tp_ip_table; | ||
48 | static struct hlist_head l2tp_ip_bind_table; | ||
49 | |||
50 | static inline struct l2tp_ip_sock *l2tp_ip_sk(const struct sock *sk) | ||
51 | { | ||
52 | return (struct l2tp_ip_sock *)sk; | ||
53 | } | ||
54 | |||
55 | static struct sock *__l2tp_ip_bind_lookup(struct net *net, __be32 laddr, int dif, u32 tunnel_id) | ||
56 | { | ||
57 | struct hlist_node *node; | ||
58 | struct sock *sk; | ||
59 | |||
60 | sk_for_each_bound(sk, node, &l2tp_ip_bind_table) { | ||
61 | struct inet_sock *inet = inet_sk(sk); | ||
62 | struct l2tp_ip_sock *l2tp = l2tp_ip_sk(sk); | ||
63 | |||
64 | if (l2tp == NULL) | ||
65 | continue; | ||
66 | |||
67 | if ((l2tp->conn_id == tunnel_id) && | ||
68 | #ifdef CONFIG_NET_NS | ||
69 | (sk->sk_net == net) && | ||
70 | #endif | ||
71 | !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && | ||
72 | !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) | ||
73 | goto found; | ||
74 | } | ||
75 | |||
76 | sk = NULL; | ||
77 | found: | ||
78 | return sk; | ||
79 | } | ||
80 | |||
81 | static inline struct sock *l2tp_ip_bind_lookup(struct net *net, __be32 laddr, int dif, u32 tunnel_id) | ||
82 | { | ||
83 | struct sock *sk = __l2tp_ip_bind_lookup(net, laddr, dif, tunnel_id); | ||
84 | if (sk) | ||
85 | sock_hold(sk); | ||
86 | |||
87 | return sk; | ||
88 | } | ||
89 | |||
90 | /* When processing receive frames, there are two cases to | ||
91 | * consider. Data frames consist of a non-zero session-id and an | ||
92 | * optional cookie. Control frames consist of a regular L2TP header | ||
93 | * preceded by 32-bits of zeros. | ||
94 | * | ||
95 | * L2TPv3 Session Header Over IP | ||
96 | * | ||
97 | * 0 1 2 3 | ||
98 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
99 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
100 | * | Session ID | | ||
101 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
102 | * | Cookie (optional, maximum 64 bits)... | ||
103 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
104 | * | | ||
105 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
106 | * | ||
107 | * L2TPv3 Control Message Header Over IP | ||
108 | * | ||
109 | * 0 1 2 3 | ||
110 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
111 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
112 | * | (32 bits of zeros) | | ||
113 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
114 | * |T|L|x|x|S|x|x|x|x|x|x|x| Ver | Length | | ||
115 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
116 | * | Control Connection ID | | ||
117 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
118 | * | Ns | Nr | | ||
119 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
120 | * | ||
121 | * All control frames are passed to userspace. | ||
122 | */ | ||
123 | static int l2tp_ip_recv(struct sk_buff *skb) | ||
124 | { | ||
125 | struct sock *sk; | ||
126 | u32 session_id; | ||
127 | u32 tunnel_id; | ||
128 | unsigned char *ptr, *optr; | ||
129 | struct l2tp_session *session; | ||
130 | struct l2tp_tunnel *tunnel = NULL; | ||
131 | int length; | ||
132 | int offset; | ||
133 | |||
134 | /* Point to L2TP header */ | ||
135 | optr = ptr = skb->data; | ||
136 | |||
137 | if (!pskb_may_pull(skb, 4)) | ||
138 | goto discard; | ||
139 | |||
140 | session_id = ntohl(*((__be32 *) ptr)); | ||
141 | ptr += 4; | ||
142 | |||
143 | /* RFC3931: L2TP/IP packets have the first 4 bytes containing | ||
144 | * the session_id. If it is 0, the packet is a L2TP control | ||
145 | * frame and the session_id value can be discarded. | ||
146 | */ | ||
147 | if (session_id == 0) { | ||
148 | __skb_pull(skb, 4); | ||
149 | goto pass_up; | ||
150 | } | ||
151 | |||
152 | /* Ok, this is a data packet. Lookup the session. */ | ||
153 | session = l2tp_session_find(&init_net, NULL, session_id); | ||
154 | if (session == NULL) | ||
155 | goto discard; | ||
156 | |||
157 | tunnel = session->tunnel; | ||
158 | if (tunnel == NULL) | ||
159 | goto discard; | ||
160 | |||
161 | /* Trace packet contents, if enabled */ | ||
162 | if (tunnel->debug & L2TP_MSG_DATA) { | ||
163 | length = min(32u, skb->len); | ||
164 | if (!pskb_may_pull(skb, length)) | ||
165 | goto discard; | ||
166 | |||
167 | printk(KERN_DEBUG "%s: ip recv: ", tunnel->name); | ||
168 | |||
169 | offset = 0; | ||
170 | do { | ||
171 | printk(" %02X", ptr[offset]); | ||
172 | } while (++offset < length); | ||
173 | |||
174 | printk("\n"); | ||
175 | } | ||
176 | |||
177 | l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, tunnel->recv_payload_hook); | ||
178 | |||
179 | return 0; | ||
180 | |||
181 | pass_up: | ||
182 | /* Get the tunnel_id from the L2TP header */ | ||
183 | if (!pskb_may_pull(skb, 12)) | ||
184 | goto discard; | ||
185 | |||
186 | if ((skb->data[0] & 0xc0) != 0xc0) | ||
187 | goto discard; | ||
188 | |||
189 | tunnel_id = ntohl(*(__be32 *) &skb->data[4]); | ||
190 | tunnel = l2tp_tunnel_find(&init_net, tunnel_id); | ||
191 | if (tunnel != NULL) | ||
192 | sk = tunnel->sock; | ||
193 | else { | ||
194 | struct iphdr *iph = (struct iphdr *) skb_network_header(skb); | ||
195 | |||
196 | read_lock_bh(&l2tp_ip_lock); | ||
197 | sk = __l2tp_ip_bind_lookup(&init_net, iph->daddr, 0, tunnel_id); | ||
198 | read_unlock_bh(&l2tp_ip_lock); | ||
199 | } | ||
200 | |||
201 | if (sk == NULL) | ||
202 | goto discard; | ||
203 | |||
204 | sock_hold(sk); | ||
205 | |||
206 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) | ||
207 | goto discard_put; | ||
208 | |||
209 | nf_reset(skb); | ||
210 | |||
211 | return sk_receive_skb(sk, skb, 1); | ||
212 | |||
213 | discard_put: | ||
214 | sock_put(sk); | ||
215 | |||
216 | discard: | ||
217 | kfree_skb(skb); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int l2tp_ip_open(struct sock *sk) | ||
222 | { | ||
223 | /* Prevent autobind. We don't have ports. */ | ||
224 | inet_sk(sk)->inet_num = IPPROTO_L2TP; | ||
225 | |||
226 | write_lock_bh(&l2tp_ip_lock); | ||
227 | sk_add_node(sk, &l2tp_ip_table); | ||
228 | write_unlock_bh(&l2tp_ip_lock); | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static void l2tp_ip_close(struct sock *sk, long timeout) | ||
234 | { | ||
235 | write_lock_bh(&l2tp_ip_lock); | ||
236 | hlist_del_init(&sk->sk_bind_node); | ||
237 | hlist_del_init(&sk->sk_node); | ||
238 | write_unlock_bh(&l2tp_ip_lock); | ||
239 | sk_common_release(sk); | ||
240 | } | ||
241 | |||
242 | static void l2tp_ip_destroy_sock(struct sock *sk) | ||
243 | { | ||
244 | struct sk_buff *skb; | ||
245 | |||
246 | while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) | ||
247 | kfree_skb(skb); | ||
248 | |||
249 | sk_refcnt_debug_dec(sk); | ||
250 | } | ||
251 | |||
252 | static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | ||
253 | { | ||
254 | struct inet_sock *inet = inet_sk(sk); | ||
255 | struct sockaddr_l2tpip *addr = (struct sockaddr_l2tpip *) uaddr; | ||
256 | int ret = -EINVAL; | ||
257 | int chk_addr_ret; | ||
258 | |||
259 | ret = -EADDRINUSE; | ||
260 | read_lock_bh(&l2tp_ip_lock); | ||
261 | if (__l2tp_ip_bind_lookup(&init_net, addr->l2tp_addr.s_addr, sk->sk_bound_dev_if, addr->l2tp_conn_id)) | ||
262 | goto out_in_use; | ||
263 | |||
264 | read_unlock_bh(&l2tp_ip_lock); | ||
265 | |||
266 | lock_sock(sk); | ||
267 | if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_l2tpip)) | ||
268 | goto out; | ||
269 | |||
270 | chk_addr_ret = inet_addr_type(&init_net, addr->l2tp_addr.s_addr); | ||
271 | ret = -EADDRNOTAVAIL; | ||
272 | if (addr->l2tp_addr.s_addr && chk_addr_ret != RTN_LOCAL && | ||
273 | chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) | ||
274 | goto out; | ||
275 | |||
276 | inet->inet_rcv_saddr = inet->inet_saddr = addr->l2tp_addr.s_addr; | ||
277 | if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) | ||
278 | inet->inet_saddr = 0; /* Use device */ | ||
279 | sk_dst_reset(sk); | ||
280 | |||
281 | l2tp_ip_sk(sk)->conn_id = addr->l2tp_conn_id; | ||
282 | |||
283 | write_lock_bh(&l2tp_ip_lock); | ||
284 | sk_add_bind_node(sk, &l2tp_ip_bind_table); | ||
285 | sk_del_node_init(sk); | ||
286 | write_unlock_bh(&l2tp_ip_lock); | ||
287 | ret = 0; | ||
288 | out: | ||
289 | release_sock(sk); | ||
290 | |||
291 | return ret; | ||
292 | |||
293 | out_in_use: | ||
294 | read_unlock_bh(&l2tp_ip_lock); | ||
295 | |||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | ||
300 | { | ||
301 | int rc; | ||
302 | struct inet_sock *inet = inet_sk(sk); | ||
303 | struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr; | ||
304 | struct rtable *rt; | ||
305 | __be32 saddr; | ||
306 | int oif; | ||
307 | |||
308 | rc = -EINVAL; | ||
309 | if (addr_len < sizeof(*lsa)) | ||
310 | goto out; | ||
311 | |||
312 | rc = -EAFNOSUPPORT; | ||
313 | if (lsa->l2tp_family != AF_INET) | ||
314 | goto out; | ||
315 | |||
316 | sk_dst_reset(sk); | ||
317 | |||
318 | oif = sk->sk_bound_dev_if; | ||
319 | saddr = inet->inet_saddr; | ||
320 | |||
321 | rc = -EINVAL; | ||
322 | if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) | ||
323 | goto out; | ||
324 | |||
325 | rc = ip_route_connect(&rt, lsa->l2tp_addr.s_addr, saddr, | ||
326 | RT_CONN_FLAGS(sk), oif, | ||
327 | IPPROTO_L2TP, | ||
328 | 0, 0, sk, 1); | ||
329 | if (rc) { | ||
330 | if (rc == -ENETUNREACH) | ||
331 | IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES); | ||
332 | goto out; | ||
333 | } | ||
334 | |||
335 | rc = -ENETUNREACH; | ||
336 | if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) { | ||
337 | ip_rt_put(rt); | ||
338 | goto out; | ||
339 | } | ||
340 | |||
341 | l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id; | ||
342 | |||
343 | if (!inet->inet_saddr) | ||
344 | inet->inet_saddr = rt->rt_src; | ||
345 | if (!inet->inet_rcv_saddr) | ||
346 | inet->inet_rcv_saddr = rt->rt_src; | ||
347 | inet->inet_daddr = rt->rt_dst; | ||
348 | sk->sk_state = TCP_ESTABLISHED; | ||
349 | inet->inet_id = jiffies; | ||
350 | |||
351 | sk_dst_set(sk, &rt->u.dst); | ||
352 | |||
353 | write_lock_bh(&l2tp_ip_lock); | ||
354 | hlist_del_init(&sk->sk_bind_node); | ||
355 | sk_add_bind_node(sk, &l2tp_ip_bind_table); | ||
356 | write_unlock_bh(&l2tp_ip_lock); | ||
357 | |||
358 | rc = 0; | ||
359 | out: | ||
360 | return rc; | ||
361 | } | ||
362 | |||
363 | static int l2tp_ip_getname(struct socket *sock, struct sockaddr *uaddr, | ||
364 | int *uaddr_len, int peer) | ||
365 | { | ||
366 | struct sock *sk = sock->sk; | ||
367 | struct inet_sock *inet = inet_sk(sk); | ||
368 | struct l2tp_ip_sock *lsk = l2tp_ip_sk(sk); | ||
369 | struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *)uaddr; | ||
370 | |||
371 | memset(lsa, 0, sizeof(*lsa)); | ||
372 | lsa->l2tp_family = AF_INET; | ||
373 | if (peer) { | ||
374 | if (!inet->inet_dport) | ||
375 | return -ENOTCONN; | ||
376 | lsa->l2tp_conn_id = lsk->peer_conn_id; | ||
377 | lsa->l2tp_addr.s_addr = inet->inet_daddr; | ||
378 | } else { | ||
379 | __be32 addr = inet->inet_rcv_saddr; | ||
380 | if (!addr) | ||
381 | addr = inet->inet_saddr; | ||
382 | lsa->l2tp_conn_id = lsk->conn_id; | ||
383 | lsa->l2tp_addr.s_addr = addr; | ||
384 | } | ||
385 | *uaddr_len = sizeof(*lsa); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb) | ||
390 | { | ||
391 | int rc; | ||
392 | |||
393 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) | ||
394 | goto drop; | ||
395 | |||
396 | nf_reset(skb); | ||
397 | |||
398 | /* Charge it to the socket, dropping if the queue is full. */ | ||
399 | rc = sock_queue_rcv_skb(sk, skb); | ||
400 | if (rc < 0) | ||
401 | goto drop; | ||
402 | |||
403 | return 0; | ||
404 | |||
405 | drop: | ||
406 | IP_INC_STATS(&init_net, IPSTATS_MIB_INDISCARDS); | ||
407 | kfree_skb(skb); | ||
408 | return -1; | ||
409 | } | ||
410 | |||
411 | /* Userspace will call sendmsg() on the tunnel socket to send L2TP | ||
412 | * control frames. | ||
413 | */ | ||
414 | static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) | ||
415 | { | ||
416 | struct sk_buff *skb; | ||
417 | int rc; | ||
418 | struct l2tp_ip_sock *lsa = l2tp_ip_sk(sk); | ||
419 | struct inet_sock *inet = inet_sk(sk); | ||
420 | struct ip_options *opt = inet->opt; | ||
421 | struct rtable *rt = NULL; | ||
422 | int connected = 0; | ||
423 | __be32 daddr; | ||
424 | |||
425 | if (sock_flag(sk, SOCK_DEAD)) | ||
426 | return -ENOTCONN; | ||
427 | |||
428 | /* Get and verify the address. */ | ||
429 | if (msg->msg_name) { | ||
430 | struct sockaddr_l2tpip *lip = (struct sockaddr_l2tpip *) msg->msg_name; | ||
431 | if (msg->msg_namelen < sizeof(*lip)) | ||
432 | return -EINVAL; | ||
433 | |||
434 | if (lip->l2tp_family != AF_INET) { | ||
435 | if (lip->l2tp_family != AF_UNSPEC) | ||
436 | return -EAFNOSUPPORT; | ||
437 | } | ||
438 | |||
439 | daddr = lip->l2tp_addr.s_addr; | ||
440 | } else { | ||
441 | if (sk->sk_state != TCP_ESTABLISHED) | ||
442 | return -EDESTADDRREQ; | ||
443 | |||
444 | daddr = inet->inet_daddr; | ||
445 | connected = 1; | ||
446 | } | ||
447 | |||
448 | /* Allocate a socket buffer */ | ||
449 | rc = -ENOMEM; | ||
450 | skb = sock_wmalloc(sk, 2 + NET_SKB_PAD + sizeof(struct iphdr) + | ||
451 | 4 + len, 0, GFP_KERNEL); | ||
452 | if (!skb) | ||
453 | goto error; | ||
454 | |||
455 | /* Reserve space for headers, putting IP header on 4-byte boundary. */ | ||
456 | skb_reserve(skb, 2 + NET_SKB_PAD); | ||
457 | skb_reset_network_header(skb); | ||
458 | skb_reserve(skb, sizeof(struct iphdr)); | ||
459 | skb_reset_transport_header(skb); | ||
460 | |||
461 | /* Insert 0 session_id */ | ||
462 | *((__be32 *) skb_put(skb, 4)) = 0; | ||
463 | |||
464 | /* Copy user data into skb */ | ||
465 | rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | ||
466 | if (rc < 0) { | ||
467 | kfree_skb(skb); | ||
468 | goto error; | ||
469 | } | ||
470 | |||
471 | if (connected) | ||
472 | rt = (struct rtable *) __sk_dst_check(sk, 0); | ||
473 | |||
474 | if (rt == NULL) { | ||
475 | /* Use correct destination address if we have options. */ | ||
476 | if (opt && opt->srr) | ||
477 | daddr = opt->faddr; | ||
478 | |||
479 | { | ||
480 | struct flowi fl = { .oif = sk->sk_bound_dev_if, | ||
481 | .nl_u = { .ip4_u = { | ||
482 | .daddr = daddr, | ||
483 | .saddr = inet->inet_saddr, | ||
484 | .tos = RT_CONN_FLAGS(sk) } }, | ||
485 | .proto = sk->sk_protocol, | ||
486 | .flags = inet_sk_flowi_flags(sk), | ||
487 | .uli_u = { .ports = { | ||
488 | .sport = inet->inet_sport, | ||
489 | .dport = inet->inet_dport } } }; | ||
490 | |||
491 | /* If this fails, retransmit mechanism of transport layer will | ||
492 | * keep trying until route appears or the connection times | ||
493 | * itself out. | ||
494 | */ | ||
495 | security_sk_classify_flow(sk, &fl); | ||
496 | if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0)) | ||
497 | goto no_route; | ||
498 | } | ||
499 | sk_setup_caps(sk, &rt->u.dst); | ||
500 | } | ||
501 | skb_dst_set(skb, dst_clone(&rt->u.dst)); | ||
502 | |||
503 | /* Queue the packet to IP for output */ | ||
504 | rc = ip_queue_xmit(skb); | ||
505 | |||
506 | error: | ||
507 | /* Update stats */ | ||
508 | if (rc >= 0) { | ||
509 | lsa->tx_packets++; | ||
510 | lsa->tx_bytes += len; | ||
511 | rc = len; | ||
512 | } else { | ||
513 | lsa->tx_errors++; | ||
514 | } | ||
515 | |||
516 | return rc; | ||
517 | |||
518 | no_route: | ||
519 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); | ||
520 | kfree_skb(skb); | ||
521 | return -EHOSTUNREACH; | ||
522 | } | ||
523 | |||
524 | static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | ||
525 | size_t len, int noblock, int flags, int *addr_len) | ||
526 | { | ||
527 | struct inet_sock *inet = inet_sk(sk); | ||
528 | struct l2tp_ip_sock *lsk = l2tp_ip_sk(sk); | ||
529 | size_t copied = 0; | ||
530 | int err = -EOPNOTSUPP; | ||
531 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; | ||
532 | struct sk_buff *skb; | ||
533 | |||
534 | if (flags & MSG_OOB) | ||
535 | goto out; | ||
536 | |||
537 | if (addr_len) | ||
538 | *addr_len = sizeof(*sin); | ||
539 | |||
540 | skb = skb_recv_datagram(sk, flags, noblock, &err); | ||
541 | if (!skb) | ||
542 | goto out; | ||
543 | |||
544 | copied = skb->len; | ||
545 | if (len < copied) { | ||
546 | msg->msg_flags |= MSG_TRUNC; | ||
547 | copied = len; | ||
548 | } | ||
549 | |||
550 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | ||
551 | if (err) | ||
552 | goto done; | ||
553 | |||
554 | sock_recv_timestamp(msg, sk, skb); | ||
555 | |||
556 | /* Copy the address. */ | ||
557 | if (sin) { | ||
558 | sin->sin_family = AF_INET; | ||
559 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; | ||
560 | sin->sin_port = 0; | ||
561 | memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
562 | } | ||
563 | if (inet->cmsg_flags) | ||
564 | ip_cmsg_recv(msg, skb); | ||
565 | if (flags & MSG_TRUNC) | ||
566 | copied = skb->len; | ||
567 | done: | ||
568 | skb_free_datagram(sk, skb); | ||
569 | out: | ||
570 | if (err) { | ||
571 | lsk->rx_errors++; | ||
572 | return err; | ||
573 | } | ||
574 | |||
575 | lsk->rx_packets++; | ||
576 | lsk->rx_bytes += copied; | ||
577 | |||
578 | return copied; | ||
579 | } | ||
580 | |||
581 | struct proto l2tp_ip_prot = { | ||
582 | .name = "L2TP/IP", | ||
583 | .owner = THIS_MODULE, | ||
584 | .init = l2tp_ip_open, | ||
585 | .close = l2tp_ip_close, | ||
586 | .bind = l2tp_ip_bind, | ||
587 | .connect = l2tp_ip_connect, | ||
588 | .disconnect = udp_disconnect, | ||
589 | .ioctl = udp_ioctl, | ||
590 | .destroy = l2tp_ip_destroy_sock, | ||
591 | .setsockopt = ip_setsockopt, | ||
592 | .getsockopt = ip_getsockopt, | ||
593 | .sendmsg = l2tp_ip_sendmsg, | ||
594 | .recvmsg = l2tp_ip_recvmsg, | ||
595 | .backlog_rcv = l2tp_ip_backlog_recv, | ||
596 | .hash = inet_hash, | ||
597 | .unhash = inet_unhash, | ||
598 | .obj_size = sizeof(struct l2tp_ip_sock), | ||
599 | #ifdef CONFIG_COMPAT | ||
600 | .compat_setsockopt = compat_ip_setsockopt, | ||
601 | .compat_getsockopt = compat_ip_getsockopt, | ||
602 | #endif | ||
603 | }; | ||
604 | |||
605 | static const struct proto_ops l2tp_ip_ops = { | ||
606 | .family = PF_INET, | ||
607 | .owner = THIS_MODULE, | ||
608 | .release = inet_release, | ||
609 | .bind = inet_bind, | ||
610 | .connect = inet_dgram_connect, | ||
611 | .socketpair = sock_no_socketpair, | ||
612 | .accept = sock_no_accept, | ||
613 | .getname = l2tp_ip_getname, | ||
614 | .poll = datagram_poll, | ||
615 | .ioctl = inet_ioctl, | ||
616 | .listen = sock_no_listen, | ||
617 | .shutdown = inet_shutdown, | ||
618 | .setsockopt = sock_common_setsockopt, | ||
619 | .getsockopt = sock_common_getsockopt, | ||
620 | .sendmsg = inet_sendmsg, | ||
621 | .recvmsg = sock_common_recvmsg, | ||
622 | .mmap = sock_no_mmap, | ||
623 | .sendpage = sock_no_sendpage, | ||
624 | #ifdef CONFIG_COMPAT | ||
625 | .compat_setsockopt = compat_sock_common_setsockopt, | ||
626 | .compat_getsockopt = compat_sock_common_getsockopt, | ||
627 | #endif | ||
628 | }; | ||
629 | |||
630 | static struct inet_protosw l2tp_ip_protosw = { | ||
631 | .type = SOCK_DGRAM, | ||
632 | .protocol = IPPROTO_L2TP, | ||
633 | .prot = &l2tp_ip_prot, | ||
634 | .ops = &l2tp_ip_ops, | ||
635 | .no_check = 0, | ||
636 | }; | ||
637 | |||
638 | static struct net_protocol l2tp_ip_protocol __read_mostly = { | ||
639 | .handler = l2tp_ip_recv, | ||
640 | }; | ||
641 | |||
642 | static int __init l2tp_ip_init(void) | ||
643 | { | ||
644 | int err; | ||
645 | |||
646 | printk(KERN_INFO "L2TP IP encapsulation support (L2TPv3)\n"); | ||
647 | |||
648 | err = proto_register(&l2tp_ip_prot, 1); | ||
649 | if (err != 0) | ||
650 | goto out; | ||
651 | |||
652 | err = inet_add_protocol(&l2tp_ip_protocol, IPPROTO_L2TP); | ||
653 | if (err) | ||
654 | goto out1; | ||
655 | |||
656 | inet_register_protosw(&l2tp_ip_protosw); | ||
657 | return 0; | ||
658 | |||
659 | out1: | ||
660 | proto_unregister(&l2tp_ip_prot); | ||
661 | out: | ||
662 | return err; | ||
663 | } | ||
664 | |||
665 | static void __exit l2tp_ip_exit(void) | ||
666 | { | ||
667 | inet_unregister_protosw(&l2tp_ip_protosw); | ||
668 | inet_del_protocol(&l2tp_ip_protocol, IPPROTO_L2TP); | ||
669 | proto_unregister(&l2tp_ip_prot); | ||
670 | } | ||
671 | |||
672 | module_init(l2tp_ip_init); | ||
673 | module_exit(l2tp_ip_exit); | ||
674 | |||
675 | MODULE_LICENSE("GPL"); | ||
676 | MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | ||
677 | MODULE_DESCRIPTION("L2TP over IP"); | ||
678 | MODULE_VERSION("1.0"); | ||
679 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, SOCK_DGRAM, IPPROTO_L2TP); | ||
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c new file mode 100644 index 000000000000..4c1e540732d7 --- /dev/null +++ b/net/l2tp/l2tp_netlink.c | |||
@@ -0,0 +1,840 @@ | |||
1 | /* | ||
2 | * L2TP netlink layer, for management | ||
3 | * | ||
4 | * Copyright (c) 2008,2009,2010 Katalix Systems Ltd | ||
5 | * | ||
6 | * Partly based on the IrDA nelink implementation | ||
7 | * (see net/irda/irnetlink.c) which is: | ||
8 | * Copyright (c) 2007 Samuel Ortiz <samuel@sortiz.org> | ||
9 | * which is in turn partly based on the wireless netlink code: | ||
10 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <net/sock.h> | ||
18 | #include <net/genetlink.h> | ||
19 | #include <net/udp.h> | ||
20 | #include <linux/in.h> | ||
21 | #include <linux/udp.h> | ||
22 | #include <linux/socket.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/list.h> | ||
25 | #include <net/net_namespace.h> | ||
26 | |||
27 | #include <linux/l2tp.h> | ||
28 | |||
29 | #include "l2tp_core.h" | ||
30 | |||
31 | |||
32 | static struct genl_family l2tp_nl_family = { | ||
33 | .id = GENL_ID_GENERATE, | ||
34 | .name = L2TP_GENL_NAME, | ||
35 | .version = L2TP_GENL_VERSION, | ||
36 | .hdrsize = 0, | ||
37 | .maxattr = L2TP_ATTR_MAX, | ||
38 | }; | ||
39 | |||
40 | /* Accessed under genl lock */ | ||
41 | static const struct l2tp_nl_cmd_ops *l2tp_nl_cmd_ops[__L2TP_PWTYPE_MAX]; | ||
42 | |||
43 | static struct l2tp_session *l2tp_nl_session_find(struct genl_info *info) | ||
44 | { | ||
45 | u32 tunnel_id; | ||
46 | u32 session_id; | ||
47 | char *ifname; | ||
48 | struct l2tp_tunnel *tunnel; | ||
49 | struct l2tp_session *session = NULL; | ||
50 | struct net *net = genl_info_net(info); | ||
51 | |||
52 | if (info->attrs[L2TP_ATTR_IFNAME]) { | ||
53 | ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]); | ||
54 | session = l2tp_session_find_by_ifname(net, ifname); | ||
55 | } else if ((info->attrs[L2TP_ATTR_SESSION_ID]) && | ||
56 | (info->attrs[L2TP_ATTR_CONN_ID])) { | ||
57 | tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); | ||
58 | session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]); | ||
59 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
60 | if (tunnel) | ||
61 | session = l2tp_session_find(net, tunnel, session_id); | ||
62 | } | ||
63 | |||
64 | return session; | ||
65 | } | ||
66 | |||
67 | static int l2tp_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) | ||
68 | { | ||
69 | struct sk_buff *msg; | ||
70 | void *hdr; | ||
71 | int ret = -ENOBUFS; | ||
72 | |||
73 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
74 | if (!msg) { | ||
75 | ret = -ENOMEM; | ||
76 | goto out; | ||
77 | } | ||
78 | |||
79 | hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, | ||
80 | &l2tp_nl_family, 0, L2TP_CMD_NOOP); | ||
81 | if (IS_ERR(hdr)) { | ||
82 | ret = PTR_ERR(hdr); | ||
83 | goto err_out; | ||
84 | } | ||
85 | |||
86 | genlmsg_end(msg, hdr); | ||
87 | |||
88 | return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid); | ||
89 | |||
90 | err_out: | ||
91 | nlmsg_free(msg); | ||
92 | |||
93 | out: | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info) | ||
98 | { | ||
99 | u32 tunnel_id; | ||
100 | u32 peer_tunnel_id; | ||
101 | int proto_version; | ||
102 | int fd; | ||
103 | int ret = 0; | ||
104 | struct l2tp_tunnel_cfg cfg = { 0, }; | ||
105 | struct l2tp_tunnel *tunnel; | ||
106 | struct net *net = genl_info_net(info); | ||
107 | |||
108 | if (!info->attrs[L2TP_ATTR_CONN_ID]) { | ||
109 | ret = -EINVAL; | ||
110 | goto out; | ||
111 | } | ||
112 | tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); | ||
113 | |||
114 | if (!info->attrs[L2TP_ATTR_PEER_CONN_ID]) { | ||
115 | ret = -EINVAL; | ||
116 | goto out; | ||
117 | } | ||
118 | peer_tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_PEER_CONN_ID]); | ||
119 | |||
120 | if (!info->attrs[L2TP_ATTR_PROTO_VERSION]) { | ||
121 | ret = -EINVAL; | ||
122 | goto out; | ||
123 | } | ||
124 | proto_version = nla_get_u8(info->attrs[L2TP_ATTR_PROTO_VERSION]); | ||
125 | |||
126 | if (!info->attrs[L2TP_ATTR_ENCAP_TYPE]) { | ||
127 | ret = -EINVAL; | ||
128 | goto out; | ||
129 | } | ||
130 | cfg.encap = nla_get_u16(info->attrs[L2TP_ATTR_ENCAP_TYPE]); | ||
131 | |||
132 | fd = -1; | ||
133 | if (info->attrs[L2TP_ATTR_FD]) { | ||
134 | fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]); | ||
135 | } else { | ||
136 | if (info->attrs[L2TP_ATTR_IP_SADDR]) | ||
137 | cfg.local_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_SADDR]); | ||
138 | if (info->attrs[L2TP_ATTR_IP_DADDR]) | ||
139 | cfg.peer_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_DADDR]); | ||
140 | if (info->attrs[L2TP_ATTR_UDP_SPORT]) | ||
141 | cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]); | ||
142 | if (info->attrs[L2TP_ATTR_UDP_DPORT]) | ||
143 | cfg.peer_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_DPORT]); | ||
144 | if (info->attrs[L2TP_ATTR_UDP_CSUM]) | ||
145 | cfg.use_udp_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_CSUM]); | ||
146 | } | ||
147 | |||
148 | if (info->attrs[L2TP_ATTR_DEBUG]) | ||
149 | cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]); | ||
150 | |||
151 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
152 | if (tunnel != NULL) { | ||
153 | ret = -EEXIST; | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | ret = -EINVAL; | ||
158 | switch (cfg.encap) { | ||
159 | case L2TP_ENCAPTYPE_UDP: | ||
160 | case L2TP_ENCAPTYPE_IP: | ||
161 | ret = l2tp_tunnel_create(net, fd, proto_version, tunnel_id, | ||
162 | peer_tunnel_id, &cfg, &tunnel); | ||
163 | break; | ||
164 | } | ||
165 | |||
166 | out: | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int l2tp_nl_cmd_tunnel_delete(struct sk_buff *skb, struct genl_info *info) | ||
171 | { | ||
172 | struct l2tp_tunnel *tunnel; | ||
173 | u32 tunnel_id; | ||
174 | int ret = 0; | ||
175 | struct net *net = genl_info_net(info); | ||
176 | |||
177 | if (!info->attrs[L2TP_ATTR_CONN_ID]) { | ||
178 | ret = -EINVAL; | ||
179 | goto out; | ||
180 | } | ||
181 | tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); | ||
182 | |||
183 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
184 | if (tunnel == NULL) { | ||
185 | ret = -ENODEV; | ||
186 | goto out; | ||
187 | } | ||
188 | |||
189 | (void) l2tp_tunnel_delete(tunnel); | ||
190 | |||
191 | out: | ||
192 | return ret; | ||
193 | } | ||
194 | |||
195 | static int l2tp_nl_cmd_tunnel_modify(struct sk_buff *skb, struct genl_info *info) | ||
196 | { | ||
197 | struct l2tp_tunnel *tunnel; | ||
198 | u32 tunnel_id; | ||
199 | int ret = 0; | ||
200 | struct net *net = genl_info_net(info); | ||
201 | |||
202 | if (!info->attrs[L2TP_ATTR_CONN_ID]) { | ||
203 | ret = -EINVAL; | ||
204 | goto out; | ||
205 | } | ||
206 | tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); | ||
207 | |||
208 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
209 | if (tunnel == NULL) { | ||
210 | ret = -ENODEV; | ||
211 | goto out; | ||
212 | } | ||
213 | |||
214 | if (info->attrs[L2TP_ATTR_DEBUG]) | ||
215 | tunnel->debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]); | ||
216 | |||
217 | out: | ||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags, | ||
222 | struct l2tp_tunnel *tunnel) | ||
223 | { | ||
224 | void *hdr; | ||
225 | struct nlattr *nest; | ||
226 | struct sock *sk = NULL; | ||
227 | struct inet_sock *inet; | ||
228 | |||
229 | hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags, | ||
230 | L2TP_CMD_TUNNEL_GET); | ||
231 | if (IS_ERR(hdr)) | ||
232 | return PTR_ERR(hdr); | ||
233 | |||
234 | NLA_PUT_U8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version); | ||
235 | NLA_PUT_U32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id); | ||
236 | NLA_PUT_U32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id); | ||
237 | NLA_PUT_U32(skb, L2TP_ATTR_DEBUG, tunnel->debug); | ||
238 | NLA_PUT_U16(skb, L2TP_ATTR_ENCAP_TYPE, tunnel->encap); | ||
239 | |||
240 | nest = nla_nest_start(skb, L2TP_ATTR_STATS); | ||
241 | if (nest == NULL) | ||
242 | goto nla_put_failure; | ||
243 | |||
244 | NLA_PUT_U64(skb, L2TP_ATTR_TX_PACKETS, tunnel->stats.tx_packets); | ||
245 | NLA_PUT_U64(skb, L2TP_ATTR_TX_BYTES, tunnel->stats.tx_bytes); | ||
246 | NLA_PUT_U64(skb, L2TP_ATTR_TX_ERRORS, tunnel->stats.tx_errors); | ||
247 | NLA_PUT_U64(skb, L2TP_ATTR_RX_PACKETS, tunnel->stats.rx_packets); | ||
248 | NLA_PUT_U64(skb, L2TP_ATTR_RX_BYTES, tunnel->stats.rx_bytes); | ||
249 | NLA_PUT_U64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, tunnel->stats.rx_seq_discards); | ||
250 | NLA_PUT_U64(skb, L2TP_ATTR_RX_OOS_PACKETS, tunnel->stats.rx_oos_packets); | ||
251 | NLA_PUT_U64(skb, L2TP_ATTR_RX_ERRORS, tunnel->stats.rx_errors); | ||
252 | nla_nest_end(skb, nest); | ||
253 | |||
254 | sk = tunnel->sock; | ||
255 | if (!sk) | ||
256 | goto out; | ||
257 | |||
258 | inet = inet_sk(sk); | ||
259 | |||
260 | switch (tunnel->encap) { | ||
261 | case L2TP_ENCAPTYPE_UDP: | ||
262 | NLA_PUT_U16(skb, L2TP_ATTR_UDP_SPORT, ntohs(inet->inet_sport)); | ||
263 | NLA_PUT_U16(skb, L2TP_ATTR_UDP_DPORT, ntohs(inet->inet_dport)); | ||
264 | NLA_PUT_U8(skb, L2TP_ATTR_UDP_CSUM, (sk->sk_no_check != UDP_CSUM_NOXMIT)); | ||
265 | /* NOBREAK */ | ||
266 | case L2TP_ENCAPTYPE_IP: | ||
267 | NLA_PUT_BE32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr); | ||
268 | NLA_PUT_BE32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr); | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | out: | ||
273 | return genlmsg_end(skb, hdr); | ||
274 | |||
275 | nla_put_failure: | ||
276 | genlmsg_cancel(skb, hdr); | ||
277 | return -1; | ||
278 | } | ||
279 | |||
280 | static int l2tp_nl_cmd_tunnel_get(struct sk_buff *skb, struct genl_info *info) | ||
281 | { | ||
282 | struct l2tp_tunnel *tunnel; | ||
283 | struct sk_buff *msg; | ||
284 | u32 tunnel_id; | ||
285 | int ret = -ENOBUFS; | ||
286 | struct net *net = genl_info_net(info); | ||
287 | |||
288 | if (!info->attrs[L2TP_ATTR_CONN_ID]) { | ||
289 | ret = -EINVAL; | ||
290 | goto out; | ||
291 | } | ||
292 | |||
293 | tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); | ||
294 | |||
295 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
296 | if (tunnel == NULL) { | ||
297 | ret = -ENODEV; | ||
298 | goto out; | ||
299 | } | ||
300 | |||
301 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
302 | if (!msg) { | ||
303 | ret = -ENOMEM; | ||
304 | goto out; | ||
305 | } | ||
306 | |||
307 | ret = l2tp_nl_tunnel_send(msg, info->snd_pid, info->snd_seq, | ||
308 | NLM_F_ACK, tunnel); | ||
309 | if (ret < 0) | ||
310 | goto err_out; | ||
311 | |||
312 | return genlmsg_unicast(net, msg, info->snd_pid); | ||
313 | |||
314 | err_out: | ||
315 | nlmsg_free(msg); | ||
316 | |||
317 | out: | ||
318 | return ret; | ||
319 | } | ||
320 | |||
321 | static int l2tp_nl_cmd_tunnel_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
322 | { | ||
323 | int ti = cb->args[0]; | ||
324 | struct l2tp_tunnel *tunnel; | ||
325 | struct net *net = sock_net(skb->sk); | ||
326 | |||
327 | for (;;) { | ||
328 | tunnel = l2tp_tunnel_find_nth(net, ti); | ||
329 | if (tunnel == NULL) | ||
330 | goto out; | ||
331 | |||
332 | if (l2tp_nl_tunnel_send(skb, NETLINK_CB(cb->skb).pid, | ||
333 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
334 | tunnel) <= 0) | ||
335 | goto out; | ||
336 | |||
337 | ti++; | ||
338 | } | ||
339 | |||
340 | out: | ||
341 | cb->args[0] = ti; | ||
342 | |||
343 | return skb->len; | ||
344 | } | ||
345 | |||
346 | static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *info) | ||
347 | { | ||
348 | u32 tunnel_id = 0; | ||
349 | u32 session_id; | ||
350 | u32 peer_session_id; | ||
351 | int ret = 0; | ||
352 | struct l2tp_tunnel *tunnel; | ||
353 | struct l2tp_session *session; | ||
354 | struct l2tp_session_cfg cfg = { 0, }; | ||
355 | struct net *net = genl_info_net(info); | ||
356 | |||
357 | if (!info->attrs[L2TP_ATTR_CONN_ID]) { | ||
358 | ret = -EINVAL; | ||
359 | goto out; | ||
360 | } | ||
361 | tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); | ||
362 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
363 | if (!tunnel) { | ||
364 | ret = -ENODEV; | ||
365 | goto out; | ||
366 | } | ||
367 | |||
368 | if (!info->attrs[L2TP_ATTR_SESSION_ID]) { | ||
369 | ret = -EINVAL; | ||
370 | goto out; | ||
371 | } | ||
372 | session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]); | ||
373 | session = l2tp_session_find(net, tunnel, session_id); | ||
374 | if (session) { | ||
375 | ret = -EEXIST; | ||
376 | goto out; | ||
377 | } | ||
378 | |||
379 | if (!info->attrs[L2TP_ATTR_PEER_SESSION_ID]) { | ||
380 | ret = -EINVAL; | ||
381 | goto out; | ||
382 | } | ||
383 | peer_session_id = nla_get_u32(info->attrs[L2TP_ATTR_PEER_SESSION_ID]); | ||
384 | |||
385 | if (!info->attrs[L2TP_ATTR_PW_TYPE]) { | ||
386 | ret = -EINVAL; | ||
387 | goto out; | ||
388 | } | ||
389 | cfg.pw_type = nla_get_u16(info->attrs[L2TP_ATTR_PW_TYPE]); | ||
390 | if (cfg.pw_type >= __L2TP_PWTYPE_MAX) { | ||
391 | ret = -EINVAL; | ||
392 | goto out; | ||
393 | } | ||
394 | |||
395 | if (tunnel->version > 2) { | ||
396 | if (info->attrs[L2TP_ATTR_OFFSET]) | ||
397 | cfg.offset = nla_get_u16(info->attrs[L2TP_ATTR_OFFSET]); | ||
398 | |||
399 | if (info->attrs[L2TP_ATTR_DATA_SEQ]) | ||
400 | cfg.data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]); | ||
401 | |||
402 | cfg.l2specific_type = L2TP_L2SPECTYPE_DEFAULT; | ||
403 | if (info->attrs[L2TP_ATTR_L2SPEC_TYPE]) | ||
404 | cfg.l2specific_type = nla_get_u8(info->attrs[L2TP_ATTR_L2SPEC_TYPE]); | ||
405 | |||
406 | cfg.l2specific_len = 4; | ||
407 | if (info->attrs[L2TP_ATTR_L2SPEC_LEN]) | ||
408 | cfg.l2specific_len = nla_get_u8(info->attrs[L2TP_ATTR_L2SPEC_LEN]); | ||
409 | |||
410 | if (info->attrs[L2TP_ATTR_COOKIE]) { | ||
411 | u16 len = nla_len(info->attrs[L2TP_ATTR_COOKIE]); | ||
412 | if (len > 8) { | ||
413 | ret = -EINVAL; | ||
414 | goto out; | ||
415 | } | ||
416 | cfg.cookie_len = len; | ||
417 | memcpy(&cfg.cookie[0], nla_data(info->attrs[L2TP_ATTR_COOKIE]), len); | ||
418 | } | ||
419 | if (info->attrs[L2TP_ATTR_PEER_COOKIE]) { | ||
420 | u16 len = nla_len(info->attrs[L2TP_ATTR_PEER_COOKIE]); | ||
421 | if (len > 8) { | ||
422 | ret = -EINVAL; | ||
423 | goto out; | ||
424 | } | ||
425 | cfg.peer_cookie_len = len; | ||
426 | memcpy(&cfg.peer_cookie[0], nla_data(info->attrs[L2TP_ATTR_PEER_COOKIE]), len); | ||
427 | } | ||
428 | if (info->attrs[L2TP_ATTR_IFNAME]) | ||
429 | cfg.ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]); | ||
430 | |||
431 | if (info->attrs[L2TP_ATTR_VLAN_ID]) | ||
432 | cfg.vlan_id = nla_get_u16(info->attrs[L2TP_ATTR_VLAN_ID]); | ||
433 | } | ||
434 | |||
435 | if (info->attrs[L2TP_ATTR_DEBUG]) | ||
436 | cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]); | ||
437 | |||
438 | if (info->attrs[L2TP_ATTR_RECV_SEQ]) | ||
439 | cfg.recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]); | ||
440 | |||
441 | if (info->attrs[L2TP_ATTR_SEND_SEQ]) | ||
442 | cfg.send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]); | ||
443 | |||
444 | if (info->attrs[L2TP_ATTR_LNS_MODE]) | ||
445 | cfg.lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]); | ||
446 | |||
447 | if (info->attrs[L2TP_ATTR_RECV_TIMEOUT]) | ||
448 | cfg.reorder_timeout = nla_get_msecs(info->attrs[L2TP_ATTR_RECV_TIMEOUT]); | ||
449 | |||
450 | if (info->attrs[L2TP_ATTR_MTU]) | ||
451 | cfg.mtu = nla_get_u16(info->attrs[L2TP_ATTR_MTU]); | ||
452 | |||
453 | if (info->attrs[L2TP_ATTR_MRU]) | ||
454 | cfg.mru = nla_get_u16(info->attrs[L2TP_ATTR_MRU]); | ||
455 | |||
456 | if ((l2tp_nl_cmd_ops[cfg.pw_type] == NULL) || | ||
457 | (l2tp_nl_cmd_ops[cfg.pw_type]->session_create == NULL)) { | ||
458 | ret = -EPROTONOSUPPORT; | ||
459 | goto out; | ||
460 | } | ||
461 | |||
462 | /* Check that pseudowire-specific params are present */ | ||
463 | switch (cfg.pw_type) { | ||
464 | case L2TP_PWTYPE_NONE: | ||
465 | break; | ||
466 | case L2TP_PWTYPE_ETH_VLAN: | ||
467 | if (!info->attrs[L2TP_ATTR_VLAN_ID]) { | ||
468 | ret = -EINVAL; | ||
469 | goto out; | ||
470 | } | ||
471 | break; | ||
472 | case L2TP_PWTYPE_ETH: | ||
473 | break; | ||
474 | case L2TP_PWTYPE_PPP: | ||
475 | case L2TP_PWTYPE_PPP_AC: | ||
476 | break; | ||
477 | case L2TP_PWTYPE_IP: | ||
478 | default: | ||
479 | ret = -EPROTONOSUPPORT; | ||
480 | break; | ||
481 | } | ||
482 | |||
483 | ret = -EPROTONOSUPPORT; | ||
484 | if (l2tp_nl_cmd_ops[cfg.pw_type]->session_create) | ||
485 | ret = (*l2tp_nl_cmd_ops[cfg.pw_type]->session_create)(net, tunnel_id, | ||
486 | session_id, peer_session_id, &cfg); | ||
487 | |||
488 | out: | ||
489 | return ret; | ||
490 | } | ||
491 | |||
492 | static int l2tp_nl_cmd_session_delete(struct sk_buff *skb, struct genl_info *info) | ||
493 | { | ||
494 | int ret = 0; | ||
495 | struct l2tp_session *session; | ||
496 | u16 pw_type; | ||
497 | |||
498 | session = l2tp_nl_session_find(info); | ||
499 | if (session == NULL) { | ||
500 | ret = -ENODEV; | ||
501 | goto out; | ||
502 | } | ||
503 | |||
504 | pw_type = session->pwtype; | ||
505 | if (pw_type < __L2TP_PWTYPE_MAX) | ||
506 | if (l2tp_nl_cmd_ops[pw_type] && l2tp_nl_cmd_ops[pw_type]->session_delete) | ||
507 | ret = (*l2tp_nl_cmd_ops[pw_type]->session_delete)(session); | ||
508 | |||
509 | out: | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *info) | ||
514 | { | ||
515 | int ret = 0; | ||
516 | struct l2tp_session *session; | ||
517 | |||
518 | session = l2tp_nl_session_find(info); | ||
519 | if (session == NULL) { | ||
520 | ret = -ENODEV; | ||
521 | goto out; | ||
522 | } | ||
523 | |||
524 | if (info->attrs[L2TP_ATTR_DEBUG]) | ||
525 | session->debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]); | ||
526 | |||
527 | if (info->attrs[L2TP_ATTR_DATA_SEQ]) | ||
528 | session->data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]); | ||
529 | |||
530 | if (info->attrs[L2TP_ATTR_RECV_SEQ]) | ||
531 | session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]); | ||
532 | |||
533 | if (info->attrs[L2TP_ATTR_SEND_SEQ]) | ||
534 | session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]); | ||
535 | |||
536 | if (info->attrs[L2TP_ATTR_LNS_MODE]) | ||
537 | session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]); | ||
538 | |||
539 | if (info->attrs[L2TP_ATTR_RECV_TIMEOUT]) | ||
540 | session->reorder_timeout = nla_get_msecs(info->attrs[L2TP_ATTR_RECV_TIMEOUT]); | ||
541 | |||
542 | if (info->attrs[L2TP_ATTR_MTU]) | ||
543 | session->mtu = nla_get_u16(info->attrs[L2TP_ATTR_MTU]); | ||
544 | |||
545 | if (info->attrs[L2TP_ATTR_MRU]) | ||
546 | session->mru = nla_get_u16(info->attrs[L2TP_ATTR_MRU]); | ||
547 | |||
548 | out: | ||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | static int l2tp_nl_session_send(struct sk_buff *skb, u32 pid, u32 seq, int flags, | ||
553 | struct l2tp_session *session) | ||
554 | { | ||
555 | void *hdr; | ||
556 | struct nlattr *nest; | ||
557 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
558 | struct sock *sk = NULL; | ||
559 | |||
560 | sk = tunnel->sock; | ||
561 | |||
562 | hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags, L2TP_CMD_SESSION_GET); | ||
563 | if (IS_ERR(hdr)) | ||
564 | return PTR_ERR(hdr); | ||
565 | |||
566 | NLA_PUT_U32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id); | ||
567 | NLA_PUT_U32(skb, L2TP_ATTR_SESSION_ID, session->session_id); | ||
568 | NLA_PUT_U32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id); | ||
569 | NLA_PUT_U32(skb, L2TP_ATTR_PEER_SESSION_ID, session->peer_session_id); | ||
570 | NLA_PUT_U32(skb, L2TP_ATTR_DEBUG, session->debug); | ||
571 | NLA_PUT_U16(skb, L2TP_ATTR_PW_TYPE, session->pwtype); | ||
572 | NLA_PUT_U16(skb, L2TP_ATTR_MTU, session->mtu); | ||
573 | if (session->mru) | ||
574 | NLA_PUT_U16(skb, L2TP_ATTR_MRU, session->mru); | ||
575 | |||
576 | if (session->ifname && session->ifname[0]) | ||
577 | NLA_PUT_STRING(skb, L2TP_ATTR_IFNAME, session->ifname); | ||
578 | if (session->cookie_len) | ||
579 | NLA_PUT(skb, L2TP_ATTR_COOKIE, session->cookie_len, &session->cookie[0]); | ||
580 | if (session->peer_cookie_len) | ||
581 | NLA_PUT(skb, L2TP_ATTR_PEER_COOKIE, session->peer_cookie_len, &session->peer_cookie[0]); | ||
582 | NLA_PUT_U8(skb, L2TP_ATTR_RECV_SEQ, session->recv_seq); | ||
583 | NLA_PUT_U8(skb, L2TP_ATTR_SEND_SEQ, session->send_seq); | ||
584 | NLA_PUT_U8(skb, L2TP_ATTR_LNS_MODE, session->lns_mode); | ||
585 | #ifdef CONFIG_XFRM | ||
586 | if ((sk) && (sk->sk_policy[0] || sk->sk_policy[1])) | ||
587 | NLA_PUT_U8(skb, L2TP_ATTR_USING_IPSEC, 1); | ||
588 | #endif | ||
589 | if (session->reorder_timeout) | ||
590 | NLA_PUT_MSECS(skb, L2TP_ATTR_RECV_TIMEOUT, session->reorder_timeout); | ||
591 | |||
592 | nest = nla_nest_start(skb, L2TP_ATTR_STATS); | ||
593 | if (nest == NULL) | ||
594 | goto nla_put_failure; | ||
595 | NLA_PUT_U64(skb, L2TP_ATTR_TX_PACKETS, session->stats.tx_packets); | ||
596 | NLA_PUT_U64(skb, L2TP_ATTR_TX_BYTES, session->stats.tx_bytes); | ||
597 | NLA_PUT_U64(skb, L2TP_ATTR_TX_ERRORS, session->stats.tx_errors); | ||
598 | NLA_PUT_U64(skb, L2TP_ATTR_RX_PACKETS, session->stats.rx_packets); | ||
599 | NLA_PUT_U64(skb, L2TP_ATTR_RX_BYTES, session->stats.rx_bytes); | ||
600 | NLA_PUT_U64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, session->stats.rx_seq_discards); | ||
601 | NLA_PUT_U64(skb, L2TP_ATTR_RX_OOS_PACKETS, session->stats.rx_oos_packets); | ||
602 | NLA_PUT_U64(skb, L2TP_ATTR_RX_ERRORS, session->stats.rx_errors); | ||
603 | nla_nest_end(skb, nest); | ||
604 | |||
605 | return genlmsg_end(skb, hdr); | ||
606 | |||
607 | nla_put_failure: | ||
608 | genlmsg_cancel(skb, hdr); | ||
609 | return -1; | ||
610 | } | ||
611 | |||
612 | static int l2tp_nl_cmd_session_get(struct sk_buff *skb, struct genl_info *info) | ||
613 | { | ||
614 | struct l2tp_session *session; | ||
615 | struct sk_buff *msg; | ||
616 | int ret; | ||
617 | |||
618 | session = l2tp_nl_session_find(info); | ||
619 | if (session == NULL) { | ||
620 | ret = -ENODEV; | ||
621 | goto out; | ||
622 | } | ||
623 | |||
624 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
625 | if (!msg) { | ||
626 | ret = -ENOMEM; | ||
627 | goto out; | ||
628 | } | ||
629 | |||
630 | ret = l2tp_nl_session_send(msg, info->snd_pid, info->snd_seq, | ||
631 | 0, session); | ||
632 | if (ret < 0) | ||
633 | goto err_out; | ||
634 | |||
635 | return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid); | ||
636 | |||
637 | err_out: | ||
638 | nlmsg_free(msg); | ||
639 | |||
640 | out: | ||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
645 | { | ||
646 | struct net *net = sock_net(skb->sk); | ||
647 | struct l2tp_session *session; | ||
648 | struct l2tp_tunnel *tunnel = NULL; | ||
649 | int ti = cb->args[0]; | ||
650 | int si = cb->args[1]; | ||
651 | |||
652 | for (;;) { | ||
653 | if (tunnel == NULL) { | ||
654 | tunnel = l2tp_tunnel_find_nth(net, ti); | ||
655 | if (tunnel == NULL) | ||
656 | goto out; | ||
657 | } | ||
658 | |||
659 | session = l2tp_session_find_nth(tunnel, si); | ||
660 | if (session == NULL) { | ||
661 | ti++; | ||
662 | tunnel = NULL; | ||
663 | si = 0; | ||
664 | continue; | ||
665 | } | ||
666 | |||
667 | if (l2tp_nl_session_send(skb, NETLINK_CB(cb->skb).pid, | ||
668 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
669 | session) <= 0) | ||
670 | break; | ||
671 | |||
672 | si++; | ||
673 | } | ||
674 | |||
675 | out: | ||
676 | cb->args[0] = ti; | ||
677 | cb->args[1] = si; | ||
678 | |||
679 | return skb->len; | ||
680 | } | ||
681 | |||
682 | static struct nla_policy l2tp_nl_policy[L2TP_ATTR_MAX + 1] = { | ||
683 | [L2TP_ATTR_NONE] = { .type = NLA_UNSPEC, }, | ||
684 | [L2TP_ATTR_PW_TYPE] = { .type = NLA_U16, }, | ||
685 | [L2TP_ATTR_ENCAP_TYPE] = { .type = NLA_U16, }, | ||
686 | [L2TP_ATTR_OFFSET] = { .type = NLA_U16, }, | ||
687 | [L2TP_ATTR_DATA_SEQ] = { .type = NLA_U8, }, | ||
688 | [L2TP_ATTR_L2SPEC_TYPE] = { .type = NLA_U8, }, | ||
689 | [L2TP_ATTR_L2SPEC_LEN] = { .type = NLA_U8, }, | ||
690 | [L2TP_ATTR_PROTO_VERSION] = { .type = NLA_U8, }, | ||
691 | [L2TP_ATTR_CONN_ID] = { .type = NLA_U32, }, | ||
692 | [L2TP_ATTR_PEER_CONN_ID] = { .type = NLA_U32, }, | ||
693 | [L2TP_ATTR_SESSION_ID] = { .type = NLA_U32, }, | ||
694 | [L2TP_ATTR_PEER_SESSION_ID] = { .type = NLA_U32, }, | ||
695 | [L2TP_ATTR_UDP_CSUM] = { .type = NLA_U8, }, | ||
696 | [L2TP_ATTR_VLAN_ID] = { .type = NLA_U16, }, | ||
697 | [L2TP_ATTR_DEBUG] = { .type = NLA_U32, }, | ||
698 | [L2TP_ATTR_RECV_SEQ] = { .type = NLA_U8, }, | ||
699 | [L2TP_ATTR_SEND_SEQ] = { .type = NLA_U8, }, | ||
700 | [L2TP_ATTR_LNS_MODE] = { .type = NLA_U8, }, | ||
701 | [L2TP_ATTR_USING_IPSEC] = { .type = NLA_U8, }, | ||
702 | [L2TP_ATTR_RECV_TIMEOUT] = { .type = NLA_MSECS, }, | ||
703 | [L2TP_ATTR_FD] = { .type = NLA_U32, }, | ||
704 | [L2TP_ATTR_IP_SADDR] = { .type = NLA_U32, }, | ||
705 | [L2TP_ATTR_IP_DADDR] = { .type = NLA_U32, }, | ||
706 | [L2TP_ATTR_UDP_SPORT] = { .type = NLA_U16, }, | ||
707 | [L2TP_ATTR_UDP_DPORT] = { .type = NLA_U16, }, | ||
708 | [L2TP_ATTR_MTU] = { .type = NLA_U16, }, | ||
709 | [L2TP_ATTR_MRU] = { .type = NLA_U16, }, | ||
710 | [L2TP_ATTR_STATS] = { .type = NLA_NESTED, }, | ||
711 | [L2TP_ATTR_IFNAME] = { | ||
712 | .type = NLA_NUL_STRING, | ||
713 | .len = IFNAMSIZ - 1, | ||
714 | }, | ||
715 | [L2TP_ATTR_COOKIE] = { | ||
716 | .type = NLA_BINARY, | ||
717 | .len = 8, | ||
718 | }, | ||
719 | [L2TP_ATTR_PEER_COOKIE] = { | ||
720 | .type = NLA_BINARY, | ||
721 | .len = 8, | ||
722 | }, | ||
723 | }; | ||
724 | |||
725 | static struct genl_ops l2tp_nl_ops[] = { | ||
726 | { | ||
727 | .cmd = L2TP_CMD_NOOP, | ||
728 | .doit = l2tp_nl_cmd_noop, | ||
729 | .policy = l2tp_nl_policy, | ||
730 | /* can be retrieved by unprivileged users */ | ||
731 | }, | ||
732 | { | ||
733 | .cmd = L2TP_CMD_TUNNEL_CREATE, | ||
734 | .doit = l2tp_nl_cmd_tunnel_create, | ||
735 | .policy = l2tp_nl_policy, | ||
736 | .flags = GENL_ADMIN_PERM, | ||
737 | }, | ||
738 | { | ||
739 | .cmd = L2TP_CMD_TUNNEL_DELETE, | ||
740 | .doit = l2tp_nl_cmd_tunnel_delete, | ||
741 | .policy = l2tp_nl_policy, | ||
742 | .flags = GENL_ADMIN_PERM, | ||
743 | }, | ||
744 | { | ||
745 | .cmd = L2TP_CMD_TUNNEL_MODIFY, | ||
746 | .doit = l2tp_nl_cmd_tunnel_modify, | ||
747 | .policy = l2tp_nl_policy, | ||
748 | .flags = GENL_ADMIN_PERM, | ||
749 | }, | ||
750 | { | ||
751 | .cmd = L2TP_CMD_TUNNEL_GET, | ||
752 | .doit = l2tp_nl_cmd_tunnel_get, | ||
753 | .dumpit = l2tp_nl_cmd_tunnel_dump, | ||
754 | .policy = l2tp_nl_policy, | ||
755 | .flags = GENL_ADMIN_PERM, | ||
756 | }, | ||
757 | { | ||
758 | .cmd = L2TP_CMD_SESSION_CREATE, | ||
759 | .doit = l2tp_nl_cmd_session_create, | ||
760 | .policy = l2tp_nl_policy, | ||
761 | .flags = GENL_ADMIN_PERM, | ||
762 | }, | ||
763 | { | ||
764 | .cmd = L2TP_CMD_SESSION_DELETE, | ||
765 | .doit = l2tp_nl_cmd_session_delete, | ||
766 | .policy = l2tp_nl_policy, | ||
767 | .flags = GENL_ADMIN_PERM, | ||
768 | }, | ||
769 | { | ||
770 | .cmd = L2TP_CMD_SESSION_MODIFY, | ||
771 | .doit = l2tp_nl_cmd_session_modify, | ||
772 | .policy = l2tp_nl_policy, | ||
773 | .flags = GENL_ADMIN_PERM, | ||
774 | }, | ||
775 | { | ||
776 | .cmd = L2TP_CMD_SESSION_GET, | ||
777 | .doit = l2tp_nl_cmd_session_get, | ||
778 | .dumpit = l2tp_nl_cmd_session_dump, | ||
779 | .policy = l2tp_nl_policy, | ||
780 | .flags = GENL_ADMIN_PERM, | ||
781 | }, | ||
782 | }; | ||
783 | |||
784 | int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops) | ||
785 | { | ||
786 | int ret; | ||
787 | |||
788 | ret = -EINVAL; | ||
789 | if (pw_type >= __L2TP_PWTYPE_MAX) | ||
790 | goto err; | ||
791 | |||
792 | genl_lock(); | ||
793 | ret = -EBUSY; | ||
794 | if (l2tp_nl_cmd_ops[pw_type]) | ||
795 | goto out; | ||
796 | |||
797 | l2tp_nl_cmd_ops[pw_type] = ops; | ||
798 | |||
799 | out: | ||
800 | genl_unlock(); | ||
801 | err: | ||
802 | return 0; | ||
803 | } | ||
804 | EXPORT_SYMBOL_GPL(l2tp_nl_register_ops); | ||
805 | |||
806 | void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type) | ||
807 | { | ||
808 | if (pw_type < __L2TP_PWTYPE_MAX) { | ||
809 | genl_lock(); | ||
810 | l2tp_nl_cmd_ops[pw_type] = NULL; | ||
811 | genl_unlock(); | ||
812 | } | ||
813 | } | ||
814 | EXPORT_SYMBOL_GPL(l2tp_nl_unregister_ops); | ||
815 | |||
816 | static int l2tp_nl_init(void) | ||
817 | { | ||
818 | int err; | ||
819 | |||
820 | printk(KERN_INFO "L2TP netlink interface\n"); | ||
821 | err = genl_register_family_with_ops(&l2tp_nl_family, l2tp_nl_ops, | ||
822 | ARRAY_SIZE(l2tp_nl_ops)); | ||
823 | |||
824 | return err; | ||
825 | } | ||
826 | |||
827 | static void l2tp_nl_cleanup(void) | ||
828 | { | ||
829 | genl_unregister_family(&l2tp_nl_family); | ||
830 | } | ||
831 | |||
832 | module_init(l2tp_nl_init); | ||
833 | module_exit(l2tp_nl_cleanup); | ||
834 | |||
835 | MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | ||
836 | MODULE_DESCRIPTION("L2TP netlink"); | ||
837 | MODULE_LICENSE("GPL"); | ||
838 | MODULE_VERSION("1.0"); | ||
839 | MODULE_ALIAS("net-pf-" __stringify(PF_NETLINK) "-proto-" \ | ||
840 | __stringify(NETLINK_GENERIC) "-type-" "l2tp"); | ||
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c new file mode 100644 index 000000000000..90d82b3f2889 --- /dev/null +++ b/net/l2tp/l2tp_ppp.c | |||
@@ -0,0 +1,1837 @@ | |||
1 | /***************************************************************************** | ||
2 | * Linux PPP over L2TP (PPPoX/PPPoL2TP) Sockets | ||
3 | * | ||
4 | * PPPoX --- Generic PPP encapsulation socket family | ||
5 | * PPPoL2TP --- PPP over L2TP (RFC 2661) | ||
6 | * | ||
7 | * Version: 2.0.0 | ||
8 | * | ||
9 | * Authors: James Chapman (jchapman@katalix.com) | ||
10 | * | ||
11 | * Based on original work by Martijn van Oosterhout <kleptog@svana.org> | ||
12 | * | ||
13 | * License: | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version | ||
17 | * 2 of the License, or (at your option) any later version. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | /* This driver handles only L2TP data frames; control frames are handled by a | ||
22 | * userspace application. | ||
23 | * | ||
24 | * To send data in an L2TP session, userspace opens a PPPoL2TP socket and | ||
25 | * attaches it to a bound UDP socket with local tunnel_id / session_id and | ||
26 | * peer tunnel_id / session_id set. Data can then be sent or received using | ||
27 | * regular socket sendmsg() / recvmsg() calls. Kernel parameters of the socket | ||
28 | * can be read or modified using ioctl() or [gs]etsockopt() calls. | ||
29 | * | ||
30 | * When a PPPoL2TP socket is connected with local and peer session_id values | ||
31 | * zero, the socket is treated as a special tunnel management socket. | ||
32 | * | ||
33 | * Here's example userspace code to create a socket for sending/receiving data | ||
34 | * over an L2TP session:- | ||
35 | * | ||
36 | * struct sockaddr_pppol2tp sax; | ||
37 | * int fd; | ||
38 | * int session_fd; | ||
39 | * | ||
40 | * fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); | ||
41 | * | ||
42 | * sax.sa_family = AF_PPPOX; | ||
43 | * sax.sa_protocol = PX_PROTO_OL2TP; | ||
44 | * sax.pppol2tp.fd = tunnel_fd; // bound UDP socket | ||
45 | * sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr; | ||
46 | * sax.pppol2tp.addr.sin_port = addr->sin_port; | ||
47 | * sax.pppol2tp.addr.sin_family = AF_INET; | ||
48 | * sax.pppol2tp.s_tunnel = tunnel_id; | ||
49 | * sax.pppol2tp.s_session = session_id; | ||
50 | * sax.pppol2tp.d_tunnel = peer_tunnel_id; | ||
51 | * sax.pppol2tp.d_session = peer_session_id; | ||
52 | * | ||
53 | * session_fd = connect(fd, (struct sockaddr *)&sax, sizeof(sax)); | ||
54 | * | ||
55 | * A pppd plugin that allows PPP traffic to be carried over L2TP using | ||
56 | * this driver is available from the OpenL2TP project at | ||
57 | * http://openl2tp.sourceforge.net. | ||
58 | */ | ||
59 | |||
60 | #include <linux/module.h> | ||
61 | #include <linux/string.h> | ||
62 | #include <linux/list.h> | ||
63 | #include <linux/uaccess.h> | ||
64 | |||
65 | #include <linux/kernel.h> | ||
66 | #include <linux/spinlock.h> | ||
67 | #include <linux/kthread.h> | ||
68 | #include <linux/sched.h> | ||
69 | #include <linux/slab.h> | ||
70 | #include <linux/errno.h> | ||
71 | #include <linux/jiffies.h> | ||
72 | |||
73 | #include <linux/netdevice.h> | ||
74 | #include <linux/net.h> | ||
75 | #include <linux/inetdevice.h> | ||
76 | #include <linux/skbuff.h> | ||
77 | #include <linux/init.h> | ||
78 | #include <linux/ip.h> | ||
79 | #include <linux/udp.h> | ||
80 | #include <linux/if_pppox.h> | ||
81 | #include <linux/if_pppol2tp.h> | ||
82 | #include <net/sock.h> | ||
83 | #include <linux/ppp_channel.h> | ||
84 | #include <linux/ppp_defs.h> | ||
85 | #include <linux/if_ppp.h> | ||
86 | #include <linux/file.h> | ||
87 | #include <linux/hash.h> | ||
88 | #include <linux/sort.h> | ||
89 | #include <linux/proc_fs.h> | ||
90 | #include <linux/l2tp.h> | ||
91 | #include <linux/nsproxy.h> | ||
92 | #include <net/net_namespace.h> | ||
93 | #include <net/netns/generic.h> | ||
94 | #include <net/dst.h> | ||
95 | #include <net/ip.h> | ||
96 | #include <net/udp.h> | ||
97 | #include <net/xfrm.h> | ||
98 | |||
99 | #include <asm/byteorder.h> | ||
100 | #include <asm/atomic.h> | ||
101 | |||
102 | #include "l2tp_core.h" | ||
103 | |||
104 | #define PPPOL2TP_DRV_VERSION "V2.0" | ||
105 | |||
106 | /* Space for UDP, L2TP and PPP headers */ | ||
107 | #define PPPOL2TP_HEADER_OVERHEAD 40 | ||
108 | |||
109 | #define PRINTK(_mask, _type, _lvl, _fmt, args...) \ | ||
110 | do { \ | ||
111 | if ((_mask) & (_type)) \ | ||
112 | printk(_lvl "PPPOL2TP: " _fmt, ##args); \ | ||
113 | } while (0) | ||
114 | |||
115 | /* Number of bytes to build transmit L2TP headers. | ||
116 | * Unfortunately the size is different depending on whether sequence numbers | ||
117 | * are enabled. | ||
118 | */ | ||
119 | #define PPPOL2TP_L2TP_HDR_SIZE_SEQ 10 | ||
120 | #define PPPOL2TP_L2TP_HDR_SIZE_NOSEQ 6 | ||
121 | |||
122 | /* Private data of each session. This data lives at the end of struct | ||
123 | * l2tp_session, referenced via session->priv[]. | ||
124 | */ | ||
125 | struct pppol2tp_session { | ||
126 | int owner; /* pid that opened the socket */ | ||
127 | |||
128 | struct sock *sock; /* Pointer to the session | ||
129 | * PPPoX socket */ | ||
130 | struct sock *tunnel_sock; /* Pointer to the tunnel UDP | ||
131 | * socket */ | ||
132 | int flags; /* accessed by PPPIOCGFLAGS. | ||
133 | * Unused. */ | ||
134 | }; | ||
135 | |||
136 | static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb); | ||
137 | |||
138 | static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL }; | ||
139 | static const struct proto_ops pppol2tp_ops; | ||
140 | |||
141 | /* Helpers to obtain tunnel/session contexts from sockets. | ||
142 | */ | ||
143 | static inline struct l2tp_session *pppol2tp_sock_to_session(struct sock *sk) | ||
144 | { | ||
145 | struct l2tp_session *session; | ||
146 | |||
147 | if (sk == NULL) | ||
148 | return NULL; | ||
149 | |||
150 | sock_hold(sk); | ||
151 | session = (struct l2tp_session *)(sk->sk_user_data); | ||
152 | if (session == NULL) { | ||
153 | sock_put(sk); | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); | ||
158 | |||
159 | out: | ||
160 | return session; | ||
161 | } | ||
162 | |||
163 | /***************************************************************************** | ||
164 | * Receive data handling | ||
165 | *****************************************************************************/ | ||
166 | |||
167 | static int pppol2tp_recv_payload_hook(struct sk_buff *skb) | ||
168 | { | ||
169 | /* Skip PPP header, if present. In testing, Microsoft L2TP clients | ||
170 | * don't send the PPP header (PPP header compression enabled), but | ||
171 | * other clients can include the header. So we cope with both cases | ||
172 | * here. The PPP header is always FF03 when using L2TP. | ||
173 | * | ||
174 | * Note that skb->data[] isn't dereferenced from a u16 ptr here since | ||
175 | * the field may be unaligned. | ||
176 | */ | ||
177 | if (!pskb_may_pull(skb, 2)) | ||
178 | return 1; | ||
179 | |||
180 | if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03)) | ||
181 | skb_pull(skb, 2); | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | /* Receive message. This is the recvmsg for the PPPoL2TP socket. | ||
187 | */ | ||
188 | static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
189 | struct msghdr *msg, size_t len, | ||
190 | int flags) | ||
191 | { | ||
192 | int err; | ||
193 | struct sk_buff *skb; | ||
194 | struct sock *sk = sock->sk; | ||
195 | |||
196 | err = -EIO; | ||
197 | if (sk->sk_state & PPPOX_BOUND) | ||
198 | goto end; | ||
199 | |||
200 | msg->msg_namelen = 0; | ||
201 | |||
202 | err = 0; | ||
203 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | ||
204 | flags & MSG_DONTWAIT, &err); | ||
205 | if (!skb) | ||
206 | goto end; | ||
207 | |||
208 | if (len > skb->len) | ||
209 | len = skb->len; | ||
210 | else if (len < skb->len) | ||
211 | msg->msg_flags |= MSG_TRUNC; | ||
212 | |||
213 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len); | ||
214 | if (likely(err == 0)) | ||
215 | err = len; | ||
216 | |||
217 | kfree_skb(skb); | ||
218 | end: | ||
219 | return err; | ||
220 | } | ||
221 | |||
222 | static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len) | ||
223 | { | ||
224 | struct pppol2tp_session *ps = l2tp_session_priv(session); | ||
225 | struct sock *sk = NULL; | ||
226 | |||
227 | /* If the socket is bound, send it in to PPP's input queue. Otherwise | ||
228 | * queue it on the session socket. | ||
229 | */ | ||
230 | sk = ps->sock; | ||
231 | if (sk == NULL) | ||
232 | goto no_sock; | ||
233 | |||
234 | if (sk->sk_state & PPPOX_BOUND) { | ||
235 | struct pppox_sock *po; | ||
236 | PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, | ||
237 | "%s: recv %d byte data frame, passing to ppp\n", | ||
238 | session->name, data_len); | ||
239 | |||
240 | /* We need to forget all info related to the L2TP packet | ||
241 | * gathered in the skb as we are going to reuse the same | ||
242 | * skb for the inner packet. | ||
243 | * Namely we need to: | ||
244 | * - reset xfrm (IPSec) information as it applies to | ||
245 | * the outer L2TP packet and not to the inner one | ||
246 | * - release the dst to force a route lookup on the inner | ||
247 | * IP packet since skb->dst currently points to the dst | ||
248 | * of the UDP tunnel | ||
249 | * - reset netfilter information as it doesn't apply | ||
250 | * to the inner packet either | ||
251 | */ | ||
252 | secpath_reset(skb); | ||
253 | skb_dst_drop(skb); | ||
254 | nf_reset(skb); | ||
255 | |||
256 | po = pppox_sk(sk); | ||
257 | ppp_input(&po->chan, skb); | ||
258 | } else { | ||
259 | PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_INFO, | ||
260 | "%s: socket not bound\n", session->name); | ||
261 | |||
262 | /* Not bound. Nothing we can do, so discard. */ | ||
263 | session->stats.rx_errors++; | ||
264 | kfree_skb(skb); | ||
265 | } | ||
266 | |||
267 | return; | ||
268 | |||
269 | no_sock: | ||
270 | PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_INFO, | ||
271 | "%s: no socket\n", session->name); | ||
272 | kfree_skb(skb); | ||
273 | } | ||
274 | |||
275 | static void pppol2tp_session_sock_hold(struct l2tp_session *session) | ||
276 | { | ||
277 | struct pppol2tp_session *ps = l2tp_session_priv(session); | ||
278 | |||
279 | if (ps->sock) | ||
280 | sock_hold(ps->sock); | ||
281 | } | ||
282 | |||
283 | static void pppol2tp_session_sock_put(struct l2tp_session *session) | ||
284 | { | ||
285 | struct pppol2tp_session *ps = l2tp_session_priv(session); | ||
286 | |||
287 | if (ps->sock) | ||
288 | sock_put(ps->sock); | ||
289 | } | ||
290 | |||
291 | /************************************************************************ | ||
292 | * Transmit handling | ||
293 | ***********************************************************************/ | ||
294 | |||
295 | /* This is the sendmsg for the PPPoL2TP pppol2tp_session socket. We come here | ||
296 | * when a user application does a sendmsg() on the session socket. L2TP and | ||
297 | * PPP headers must be inserted into the user's data. | ||
298 | */ | ||
299 | static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, | ||
300 | size_t total_len) | ||
301 | { | ||
302 | static const unsigned char ppph[2] = { 0xff, 0x03 }; | ||
303 | struct sock *sk = sock->sk; | ||
304 | struct sk_buff *skb; | ||
305 | int error; | ||
306 | struct l2tp_session *session; | ||
307 | struct l2tp_tunnel *tunnel; | ||
308 | struct pppol2tp_session *ps; | ||
309 | int uhlen; | ||
310 | |||
311 | error = -ENOTCONN; | ||
312 | if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) | ||
313 | goto error; | ||
314 | |||
315 | /* Get session and tunnel contexts */ | ||
316 | error = -EBADF; | ||
317 | session = pppol2tp_sock_to_session(sk); | ||
318 | if (session == NULL) | ||
319 | goto error; | ||
320 | |||
321 | ps = l2tp_session_priv(session); | ||
322 | tunnel = l2tp_sock_to_tunnel(ps->tunnel_sock); | ||
323 | if (tunnel == NULL) | ||
324 | goto error_put_sess; | ||
325 | |||
326 | uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; | ||
327 | |||
328 | /* Allocate a socket buffer */ | ||
329 | error = -ENOMEM; | ||
330 | skb = sock_wmalloc(sk, NET_SKB_PAD + sizeof(struct iphdr) + | ||
331 | uhlen + session->hdr_len + | ||
332 | sizeof(ppph) + total_len, | ||
333 | 0, GFP_KERNEL); | ||
334 | if (!skb) | ||
335 | goto error_put_sess_tun; | ||
336 | |||
337 | /* Reserve space for headers. */ | ||
338 | skb_reserve(skb, NET_SKB_PAD); | ||
339 | skb_reset_network_header(skb); | ||
340 | skb_reserve(skb, sizeof(struct iphdr)); | ||
341 | skb_reset_transport_header(skb); | ||
342 | skb_reserve(skb, uhlen); | ||
343 | |||
344 | /* Add PPP header */ | ||
345 | skb->data[0] = ppph[0]; | ||
346 | skb->data[1] = ppph[1]; | ||
347 | skb_put(skb, 2); | ||
348 | |||
349 | /* Copy user data into skb */ | ||
350 | error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); | ||
351 | if (error < 0) { | ||
352 | kfree_skb(skb); | ||
353 | goto error_put_sess_tun; | ||
354 | } | ||
355 | skb_put(skb, total_len); | ||
356 | |||
357 | l2tp_xmit_skb(session, skb, session->hdr_len); | ||
358 | |||
359 | sock_put(ps->tunnel_sock); | ||
360 | |||
361 | return error; | ||
362 | |||
363 | error_put_sess_tun: | ||
364 | sock_put(ps->tunnel_sock); | ||
365 | error_put_sess: | ||
366 | sock_put(sk); | ||
367 | error: | ||
368 | return error; | ||
369 | } | ||
370 | |||
371 | /* Transmit function called by generic PPP driver. Sends PPP frame | ||
372 | * over PPPoL2TP socket. | ||
373 | * | ||
374 | * This is almost the same as pppol2tp_sendmsg(), but rather than | ||
375 | * being called with a msghdr from userspace, it is called with a skb | ||
376 | * from the kernel. | ||
377 | * | ||
378 | * The supplied skb from ppp doesn't have enough headroom for the | ||
379 | * insertion of L2TP, UDP and IP headers so we need to allocate more | ||
380 | * headroom in the skb. This will create a cloned skb. But we must be | ||
381 | * careful in the error case because the caller will expect to free | ||
382 | * the skb it supplied, not our cloned skb. So we take care to always | ||
383 | * leave the original skb unfreed if we return an error. | ||
384 | */ | ||
385 | static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | ||
386 | { | ||
387 | static const u8 ppph[2] = { 0xff, 0x03 }; | ||
388 | struct sock *sk = (struct sock *) chan->private; | ||
389 | struct sock *sk_tun; | ||
390 | struct l2tp_session *session; | ||
391 | struct l2tp_tunnel *tunnel; | ||
392 | struct pppol2tp_session *ps; | ||
393 | int old_headroom; | ||
394 | int new_headroom; | ||
395 | |||
396 | if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) | ||
397 | goto abort; | ||
398 | |||
399 | /* Get session and tunnel contexts from the socket */ | ||
400 | session = pppol2tp_sock_to_session(sk); | ||
401 | if (session == NULL) | ||
402 | goto abort; | ||
403 | |||
404 | ps = l2tp_session_priv(session); | ||
405 | sk_tun = ps->tunnel_sock; | ||
406 | if (sk_tun == NULL) | ||
407 | goto abort_put_sess; | ||
408 | tunnel = l2tp_sock_to_tunnel(sk_tun); | ||
409 | if (tunnel == NULL) | ||
410 | goto abort_put_sess; | ||
411 | |||
412 | old_headroom = skb_headroom(skb); | ||
413 | if (skb_cow_head(skb, sizeof(ppph))) | ||
414 | goto abort_put_sess_tun; | ||
415 | |||
416 | new_headroom = skb_headroom(skb); | ||
417 | skb->truesize += new_headroom - old_headroom; | ||
418 | |||
419 | /* Setup PPP header */ | ||
420 | __skb_push(skb, sizeof(ppph)); | ||
421 | skb->data[0] = ppph[0]; | ||
422 | skb->data[1] = ppph[1]; | ||
423 | |||
424 | l2tp_xmit_skb(session, skb, session->hdr_len); | ||
425 | |||
426 | sock_put(sk_tun); | ||
427 | sock_put(sk); | ||
428 | return 1; | ||
429 | |||
430 | abort_put_sess_tun: | ||
431 | sock_put(sk_tun); | ||
432 | abort_put_sess: | ||
433 | sock_put(sk); | ||
434 | abort: | ||
435 | /* Free the original skb */ | ||
436 | kfree_skb(skb); | ||
437 | return 1; | ||
438 | } | ||
439 | |||
440 | /***************************************************************************** | ||
441 | * Session (and tunnel control) socket create/destroy. | ||
442 | *****************************************************************************/ | ||
443 | |||
444 | /* Called by l2tp_core when a session socket is being closed. | ||
445 | */ | ||
446 | static void pppol2tp_session_close(struct l2tp_session *session) | ||
447 | { | ||
448 | struct pppol2tp_session *ps = l2tp_session_priv(session); | ||
449 | struct sock *sk = ps->sock; | ||
450 | struct sk_buff *skb; | ||
451 | |||
452 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); | ||
453 | |||
454 | if (session->session_id == 0) | ||
455 | goto out; | ||
456 | |||
457 | if (sk != NULL) { | ||
458 | lock_sock(sk); | ||
459 | |||
460 | if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { | ||
461 | pppox_unbind_sock(sk); | ||
462 | sk->sk_state = PPPOX_DEAD; | ||
463 | sk->sk_state_change(sk); | ||
464 | } | ||
465 | |||
466 | /* Purge any queued data */ | ||
467 | skb_queue_purge(&sk->sk_receive_queue); | ||
468 | skb_queue_purge(&sk->sk_write_queue); | ||
469 | while ((skb = skb_dequeue(&session->reorder_q))) { | ||
470 | kfree_skb(skb); | ||
471 | sock_put(sk); | ||
472 | } | ||
473 | |||
474 | release_sock(sk); | ||
475 | } | ||
476 | |||
477 | out: | ||
478 | return; | ||
479 | } | ||
480 | |||
481 | /* Really kill the session socket. (Called from sock_put() if | ||
482 | * refcnt == 0.) | ||
483 | */ | ||
484 | static void pppol2tp_session_destruct(struct sock *sk) | ||
485 | { | ||
486 | struct l2tp_session *session; | ||
487 | |||
488 | if (sk->sk_user_data != NULL) { | ||
489 | session = sk->sk_user_data; | ||
490 | if (session == NULL) | ||
491 | goto out; | ||
492 | |||
493 | sk->sk_user_data = NULL; | ||
494 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); | ||
495 | l2tp_session_dec_refcount(session); | ||
496 | } | ||
497 | |||
498 | out: | ||
499 | return; | ||
500 | } | ||
501 | |||
502 | /* Called when the PPPoX socket (session) is closed. | ||
503 | */ | ||
504 | static int pppol2tp_release(struct socket *sock) | ||
505 | { | ||
506 | struct sock *sk = sock->sk; | ||
507 | struct l2tp_session *session; | ||
508 | int error; | ||
509 | |||
510 | if (!sk) | ||
511 | return 0; | ||
512 | |||
513 | error = -EBADF; | ||
514 | lock_sock(sk); | ||
515 | if (sock_flag(sk, SOCK_DEAD) != 0) | ||
516 | goto error; | ||
517 | |||
518 | pppox_unbind_sock(sk); | ||
519 | |||
520 | /* Signal the death of the socket. */ | ||
521 | sk->sk_state = PPPOX_DEAD; | ||
522 | sock_orphan(sk); | ||
523 | sock->sk = NULL; | ||
524 | |||
525 | session = pppol2tp_sock_to_session(sk); | ||
526 | |||
527 | /* Purge any queued data */ | ||
528 | skb_queue_purge(&sk->sk_receive_queue); | ||
529 | skb_queue_purge(&sk->sk_write_queue); | ||
530 | if (session != NULL) { | ||
531 | struct sk_buff *skb; | ||
532 | while ((skb = skb_dequeue(&session->reorder_q))) { | ||
533 | kfree_skb(skb); | ||
534 | sock_put(sk); | ||
535 | } | ||
536 | sock_put(sk); | ||
537 | } | ||
538 | |||
539 | release_sock(sk); | ||
540 | |||
541 | /* This will delete the session context via | ||
542 | * pppol2tp_session_destruct() if the socket's refcnt drops to | ||
543 | * zero. | ||
544 | */ | ||
545 | sock_put(sk); | ||
546 | |||
547 | return 0; | ||
548 | |||
549 | error: | ||
550 | release_sock(sk); | ||
551 | return error; | ||
552 | } | ||
553 | |||
554 | static struct proto pppol2tp_sk_proto = { | ||
555 | .name = "PPPOL2TP", | ||
556 | .owner = THIS_MODULE, | ||
557 | .obj_size = sizeof(struct pppox_sock), | ||
558 | }; | ||
559 | |||
560 | static int pppol2tp_backlog_recv(struct sock *sk, struct sk_buff *skb) | ||
561 | { | ||
562 | int rc; | ||
563 | |||
564 | rc = l2tp_udp_encap_recv(sk, skb); | ||
565 | if (rc) | ||
566 | kfree_skb(skb); | ||
567 | |||
568 | return NET_RX_SUCCESS; | ||
569 | } | ||
570 | |||
571 | /* socket() handler. Initialize a new struct sock. | ||
572 | */ | ||
573 | static int pppol2tp_create(struct net *net, struct socket *sock) | ||
574 | { | ||
575 | int error = -ENOMEM; | ||
576 | struct sock *sk; | ||
577 | |||
578 | sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto); | ||
579 | if (!sk) | ||
580 | goto out; | ||
581 | |||
582 | sock_init_data(sock, sk); | ||
583 | |||
584 | sock->state = SS_UNCONNECTED; | ||
585 | sock->ops = &pppol2tp_ops; | ||
586 | |||
587 | sk->sk_backlog_rcv = pppol2tp_backlog_recv; | ||
588 | sk->sk_protocol = PX_PROTO_OL2TP; | ||
589 | sk->sk_family = PF_PPPOX; | ||
590 | sk->sk_state = PPPOX_NONE; | ||
591 | sk->sk_type = SOCK_STREAM; | ||
592 | sk->sk_destruct = pppol2tp_session_destruct; | ||
593 | |||
594 | error = 0; | ||
595 | |||
596 | out: | ||
597 | return error; | ||
598 | } | ||
599 | |||
600 | #if defined(CONFIG_L2TP_DEBUGFS) || defined(CONFIG_L2TP_DEBUGFS_MODULE) | ||
601 | static void pppol2tp_show(struct seq_file *m, void *arg) | ||
602 | { | ||
603 | struct l2tp_session *session = arg; | ||
604 | struct pppol2tp_session *ps = l2tp_session_priv(session); | ||
605 | |||
606 | if (ps) { | ||
607 | struct pppox_sock *po = pppox_sk(ps->sock); | ||
608 | if (po) | ||
609 | seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); | ||
610 | } | ||
611 | } | ||
612 | #endif | ||
613 | |||
614 | /* connect() handler. Attach a PPPoX socket to a tunnel UDP socket | ||
615 | */ | ||
616 | static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | ||
617 | int sockaddr_len, int flags) | ||
618 | { | ||
619 | struct sock *sk = sock->sk; | ||
620 | struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr; | ||
621 | struct sockaddr_pppol2tpv3 *sp3 = (struct sockaddr_pppol2tpv3 *) uservaddr; | ||
622 | struct pppox_sock *po = pppox_sk(sk); | ||
623 | struct l2tp_session *session = NULL; | ||
624 | struct l2tp_tunnel *tunnel; | ||
625 | struct pppol2tp_session *ps; | ||
626 | struct dst_entry *dst; | ||
627 | struct l2tp_session_cfg cfg = { 0, }; | ||
628 | int error = 0; | ||
629 | u32 tunnel_id, peer_tunnel_id; | ||
630 | u32 session_id, peer_session_id; | ||
631 | int ver = 2; | ||
632 | int fd; | ||
633 | |||
634 | lock_sock(sk); | ||
635 | |||
636 | error = -EINVAL; | ||
637 | if (sp->sa_protocol != PX_PROTO_OL2TP) | ||
638 | goto end; | ||
639 | |||
640 | /* Check for already bound sockets */ | ||
641 | error = -EBUSY; | ||
642 | if (sk->sk_state & PPPOX_CONNECTED) | ||
643 | goto end; | ||
644 | |||
645 | /* We don't supporting rebinding anyway */ | ||
646 | error = -EALREADY; | ||
647 | if (sk->sk_user_data) | ||
648 | goto end; /* socket is already attached */ | ||
649 | |||
650 | /* Get params from socket address. Handle L2TPv2 and L2TPv3 */ | ||
651 | if (sockaddr_len == sizeof(struct sockaddr_pppol2tp)) { | ||
652 | fd = sp->pppol2tp.fd; | ||
653 | tunnel_id = sp->pppol2tp.s_tunnel; | ||
654 | peer_tunnel_id = sp->pppol2tp.d_tunnel; | ||
655 | session_id = sp->pppol2tp.s_session; | ||
656 | peer_session_id = sp->pppol2tp.d_session; | ||
657 | } else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpv3)) { | ||
658 | ver = 3; | ||
659 | fd = sp3->pppol2tp.fd; | ||
660 | tunnel_id = sp3->pppol2tp.s_tunnel; | ||
661 | peer_tunnel_id = sp3->pppol2tp.d_tunnel; | ||
662 | session_id = sp3->pppol2tp.s_session; | ||
663 | peer_session_id = sp3->pppol2tp.d_session; | ||
664 | } else { | ||
665 | error = -EINVAL; | ||
666 | goto end; /* bad socket address */ | ||
667 | } | ||
668 | |||
669 | /* Don't bind if tunnel_id is 0 */ | ||
670 | error = -EINVAL; | ||
671 | if (tunnel_id == 0) | ||
672 | goto end; | ||
673 | |||
674 | tunnel = l2tp_tunnel_find(sock_net(sk), tunnel_id); | ||
675 | |||
676 | /* Special case: create tunnel context if session_id and | ||
677 | * peer_session_id is 0. Otherwise look up tunnel using supplied | ||
678 | * tunnel id. | ||
679 | */ | ||
680 | if ((session_id == 0) && (peer_session_id == 0)) { | ||
681 | if (tunnel == NULL) { | ||
682 | struct l2tp_tunnel_cfg tcfg = { | ||
683 | .encap = L2TP_ENCAPTYPE_UDP, | ||
684 | .debug = 0, | ||
685 | }; | ||
686 | error = l2tp_tunnel_create(sock_net(sk), fd, ver, tunnel_id, peer_tunnel_id, &tcfg, &tunnel); | ||
687 | if (error < 0) | ||
688 | goto end; | ||
689 | } | ||
690 | } else { | ||
691 | /* Error if we can't find the tunnel */ | ||
692 | error = -ENOENT; | ||
693 | if (tunnel == NULL) | ||
694 | goto end; | ||
695 | |||
696 | /* Error if socket is not prepped */ | ||
697 | if (tunnel->sock == NULL) | ||
698 | goto end; | ||
699 | } | ||
700 | |||
701 | if (tunnel->recv_payload_hook == NULL) | ||
702 | tunnel->recv_payload_hook = pppol2tp_recv_payload_hook; | ||
703 | |||
704 | if (tunnel->peer_tunnel_id == 0) { | ||
705 | if (ver == 2) | ||
706 | tunnel->peer_tunnel_id = sp->pppol2tp.d_tunnel; | ||
707 | else | ||
708 | tunnel->peer_tunnel_id = sp3->pppol2tp.d_tunnel; | ||
709 | } | ||
710 | |||
711 | /* Create session if it doesn't already exist. We handle the | ||
712 | * case where a session was previously created by the netlink | ||
713 | * interface by checking that the session doesn't already have | ||
714 | * a socket and its tunnel socket are what we expect. If any | ||
715 | * of those checks fail, return EEXIST to the caller. | ||
716 | */ | ||
717 | session = l2tp_session_find(sock_net(sk), tunnel, session_id); | ||
718 | if (session == NULL) { | ||
719 | /* Default MTU must allow space for UDP/L2TP/PPP | ||
720 | * headers. | ||
721 | */ | ||
722 | cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD; | ||
723 | |||
724 | /* Allocate and initialize a new session context. */ | ||
725 | session = l2tp_session_create(sizeof(struct pppol2tp_session), | ||
726 | tunnel, session_id, | ||
727 | peer_session_id, &cfg); | ||
728 | if (session == NULL) { | ||
729 | error = -ENOMEM; | ||
730 | goto end; | ||
731 | } | ||
732 | } else { | ||
733 | ps = l2tp_session_priv(session); | ||
734 | error = -EEXIST; | ||
735 | if (ps->sock != NULL) | ||
736 | goto end; | ||
737 | |||
738 | /* consistency checks */ | ||
739 | if (ps->tunnel_sock != tunnel->sock) | ||
740 | goto end; | ||
741 | } | ||
742 | |||
743 | /* Associate session with its PPPoL2TP socket */ | ||
744 | ps = l2tp_session_priv(session); | ||
745 | ps->owner = current->pid; | ||
746 | ps->sock = sk; | ||
747 | ps->tunnel_sock = tunnel->sock; | ||
748 | |||
749 | session->recv_skb = pppol2tp_recv; | ||
750 | session->session_close = pppol2tp_session_close; | ||
751 | #if defined(CONFIG_L2TP_DEBUGFS) || defined(CONFIG_L2TP_DEBUGFS_MODULE) | ||
752 | session->show = pppol2tp_show; | ||
753 | #endif | ||
754 | |||
755 | /* We need to know each time a skb is dropped from the reorder | ||
756 | * queue. | ||
757 | */ | ||
758 | session->ref = pppol2tp_session_sock_hold; | ||
759 | session->deref = pppol2tp_session_sock_put; | ||
760 | |||
761 | /* If PMTU discovery was enabled, use the MTU that was discovered */ | ||
762 | dst = sk_dst_get(sk); | ||
763 | if (dst != NULL) { | ||
764 | u32 pmtu = dst_mtu(__sk_dst_get(sk)); | ||
765 | if (pmtu != 0) | ||
766 | session->mtu = session->mru = pmtu - | ||
767 | PPPOL2TP_HEADER_OVERHEAD; | ||
768 | dst_release(dst); | ||
769 | } | ||
770 | |||
771 | /* Special case: if source & dest session_id == 0x0000, this | ||
772 | * socket is being created to manage the tunnel. Just set up | ||
773 | * the internal context for use by ioctl() and sockopt() | ||
774 | * handlers. | ||
775 | */ | ||
776 | if ((session->session_id == 0) && | ||
777 | (session->peer_session_id == 0)) { | ||
778 | error = 0; | ||
779 | goto out_no_ppp; | ||
780 | } | ||
781 | |||
782 | /* The only header we need to worry about is the L2TP | ||
783 | * header. This size is different depending on whether | ||
784 | * sequence numbers are enabled for the data channel. | ||
785 | */ | ||
786 | po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; | ||
787 | |||
788 | po->chan.private = sk; | ||
789 | po->chan.ops = &pppol2tp_chan_ops; | ||
790 | po->chan.mtu = session->mtu; | ||
791 | |||
792 | error = ppp_register_net_channel(sock_net(sk), &po->chan); | ||
793 | if (error) | ||
794 | goto end; | ||
795 | |||
796 | out_no_ppp: | ||
797 | /* This is how we get the session context from the socket. */ | ||
798 | sk->sk_user_data = session; | ||
799 | sk->sk_state = PPPOX_CONNECTED; | ||
800 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
801 | "%s: created\n", session->name); | ||
802 | |||
803 | end: | ||
804 | release_sock(sk); | ||
805 | |||
806 | return error; | ||
807 | } | ||
808 | |||
809 | #ifdef CONFIG_L2TP_V3 | ||
810 | |||
811 | /* Called when creating sessions via the netlink interface. | ||
812 | */ | ||
813 | static int pppol2tp_session_create(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) | ||
814 | { | ||
815 | int error; | ||
816 | struct l2tp_tunnel *tunnel; | ||
817 | struct l2tp_session *session; | ||
818 | struct pppol2tp_session *ps; | ||
819 | |||
820 | tunnel = l2tp_tunnel_find(net, tunnel_id); | ||
821 | |||
822 | /* Error if we can't find the tunnel */ | ||
823 | error = -ENOENT; | ||
824 | if (tunnel == NULL) | ||
825 | goto out; | ||
826 | |||
827 | /* Error if tunnel socket is not prepped */ | ||
828 | if (tunnel->sock == NULL) | ||
829 | goto out; | ||
830 | |||
831 | /* Check that this session doesn't already exist */ | ||
832 | error = -EEXIST; | ||
833 | session = l2tp_session_find(net, tunnel, session_id); | ||
834 | if (session != NULL) | ||
835 | goto out; | ||
836 | |||
837 | /* Default MTU values. */ | ||
838 | if (cfg->mtu == 0) | ||
839 | cfg->mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD; | ||
840 | if (cfg->mru == 0) | ||
841 | cfg->mru = cfg->mtu; | ||
842 | |||
843 | /* Allocate and initialize a new session context. */ | ||
844 | error = -ENOMEM; | ||
845 | session = l2tp_session_create(sizeof(struct pppol2tp_session), | ||
846 | tunnel, session_id, | ||
847 | peer_session_id, cfg); | ||
848 | if (session == NULL) | ||
849 | goto out; | ||
850 | |||
851 | ps = l2tp_session_priv(session); | ||
852 | ps->tunnel_sock = tunnel->sock; | ||
853 | |||
854 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
855 | "%s: created\n", session->name); | ||
856 | |||
857 | error = 0; | ||
858 | |||
859 | out: | ||
860 | return error; | ||
861 | } | ||
862 | |||
863 | /* Called when deleting sessions via the netlink interface. | ||
864 | */ | ||
865 | static int pppol2tp_session_delete(struct l2tp_session *session) | ||
866 | { | ||
867 | struct pppol2tp_session *ps = l2tp_session_priv(session); | ||
868 | |||
869 | if (ps->sock == NULL) | ||
870 | l2tp_session_dec_refcount(session); | ||
871 | |||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | #endif /* CONFIG_L2TP_V3 */ | ||
876 | |||
877 | /* getname() support. | ||
878 | */ | ||
879 | static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr, | ||
880 | int *usockaddr_len, int peer) | ||
881 | { | ||
882 | int len = 0; | ||
883 | int error = 0; | ||
884 | struct l2tp_session *session; | ||
885 | struct l2tp_tunnel *tunnel; | ||
886 | struct sock *sk = sock->sk; | ||
887 | struct inet_sock *inet; | ||
888 | struct pppol2tp_session *pls; | ||
889 | |||
890 | error = -ENOTCONN; | ||
891 | if (sk == NULL) | ||
892 | goto end; | ||
893 | if (sk->sk_state != PPPOX_CONNECTED) | ||
894 | goto end; | ||
895 | |||
896 | error = -EBADF; | ||
897 | session = pppol2tp_sock_to_session(sk); | ||
898 | if (session == NULL) | ||
899 | goto end; | ||
900 | |||
901 | pls = l2tp_session_priv(session); | ||
902 | tunnel = l2tp_sock_to_tunnel(pls->tunnel_sock); | ||
903 | if (tunnel == NULL) { | ||
904 | error = -EBADF; | ||
905 | goto end_put_sess; | ||
906 | } | ||
907 | |||
908 | inet = inet_sk(sk); | ||
909 | if (tunnel->version == 2) { | ||
910 | struct sockaddr_pppol2tp sp; | ||
911 | len = sizeof(sp); | ||
912 | memset(&sp, 0, len); | ||
913 | sp.sa_family = AF_PPPOX; | ||
914 | sp.sa_protocol = PX_PROTO_OL2TP; | ||
915 | sp.pppol2tp.fd = tunnel->fd; | ||
916 | sp.pppol2tp.pid = pls->owner; | ||
917 | sp.pppol2tp.s_tunnel = tunnel->tunnel_id; | ||
918 | sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id; | ||
919 | sp.pppol2tp.s_session = session->session_id; | ||
920 | sp.pppol2tp.d_session = session->peer_session_id; | ||
921 | sp.pppol2tp.addr.sin_family = AF_INET; | ||
922 | sp.pppol2tp.addr.sin_port = inet->inet_dport; | ||
923 | sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr; | ||
924 | memcpy(uaddr, &sp, len); | ||
925 | } else if (tunnel->version == 3) { | ||
926 | struct sockaddr_pppol2tpv3 sp; | ||
927 | len = sizeof(sp); | ||
928 | memset(&sp, 0, len); | ||
929 | sp.sa_family = AF_PPPOX; | ||
930 | sp.sa_protocol = PX_PROTO_OL2TP; | ||
931 | sp.pppol2tp.fd = tunnel->fd; | ||
932 | sp.pppol2tp.pid = pls->owner; | ||
933 | sp.pppol2tp.s_tunnel = tunnel->tunnel_id; | ||
934 | sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id; | ||
935 | sp.pppol2tp.s_session = session->session_id; | ||
936 | sp.pppol2tp.d_session = session->peer_session_id; | ||
937 | sp.pppol2tp.addr.sin_family = AF_INET; | ||
938 | sp.pppol2tp.addr.sin_port = inet->inet_dport; | ||
939 | sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr; | ||
940 | memcpy(uaddr, &sp, len); | ||
941 | } | ||
942 | |||
943 | *usockaddr_len = len; | ||
944 | |||
945 | sock_put(pls->tunnel_sock); | ||
946 | end_put_sess: | ||
947 | sock_put(sk); | ||
948 | error = 0; | ||
949 | |||
950 | end: | ||
951 | return error; | ||
952 | } | ||
953 | |||
954 | /**************************************************************************** | ||
955 | * ioctl() handlers. | ||
956 | * | ||
957 | * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP | ||
958 | * sockets. However, in order to control kernel tunnel features, we allow | ||
959 | * userspace to create a special "tunnel" PPPoX socket which is used for | ||
960 | * control only. Tunnel PPPoX sockets have session_id == 0 and simply allow | ||
961 | * the user application to issue L2TP setsockopt(), getsockopt() and ioctl() | ||
962 | * calls. | ||
963 | ****************************************************************************/ | ||
964 | |||
965 | static void pppol2tp_copy_stats(struct pppol2tp_ioc_stats *dest, | ||
966 | struct l2tp_stats *stats) | ||
967 | { | ||
968 | dest->tx_packets = stats->tx_packets; | ||
969 | dest->tx_bytes = stats->tx_bytes; | ||
970 | dest->tx_errors = stats->tx_errors; | ||
971 | dest->rx_packets = stats->rx_packets; | ||
972 | dest->rx_bytes = stats->rx_bytes; | ||
973 | dest->rx_seq_discards = stats->rx_seq_discards; | ||
974 | dest->rx_oos_packets = stats->rx_oos_packets; | ||
975 | dest->rx_errors = stats->rx_errors; | ||
976 | } | ||
977 | |||
978 | /* Session ioctl helper. | ||
979 | */ | ||
980 | static int pppol2tp_session_ioctl(struct l2tp_session *session, | ||
981 | unsigned int cmd, unsigned long arg) | ||
982 | { | ||
983 | struct ifreq ifr; | ||
984 | int err = 0; | ||
985 | struct sock *sk; | ||
986 | int val = (int) arg; | ||
987 | struct pppol2tp_session *ps = l2tp_session_priv(session); | ||
988 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
989 | struct pppol2tp_ioc_stats stats; | ||
990 | |||
991 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG, | ||
992 | "%s: pppol2tp_session_ioctl(cmd=%#x, arg=%#lx)\n", | ||
993 | session->name, cmd, arg); | ||
994 | |||
995 | sk = ps->sock; | ||
996 | sock_hold(sk); | ||
997 | |||
998 | switch (cmd) { | ||
999 | case SIOCGIFMTU: | ||
1000 | err = -ENXIO; | ||
1001 | if (!(sk->sk_state & PPPOX_CONNECTED)) | ||
1002 | break; | ||
1003 | |||
1004 | err = -EFAULT; | ||
1005 | if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq))) | ||
1006 | break; | ||
1007 | ifr.ifr_mtu = session->mtu; | ||
1008 | if (copy_to_user((void __user *) arg, &ifr, sizeof(struct ifreq))) | ||
1009 | break; | ||
1010 | |||
1011 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1012 | "%s: get mtu=%d\n", session->name, session->mtu); | ||
1013 | err = 0; | ||
1014 | break; | ||
1015 | |||
1016 | case SIOCSIFMTU: | ||
1017 | err = -ENXIO; | ||
1018 | if (!(sk->sk_state & PPPOX_CONNECTED)) | ||
1019 | break; | ||
1020 | |||
1021 | err = -EFAULT; | ||
1022 | if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq))) | ||
1023 | break; | ||
1024 | |||
1025 | session->mtu = ifr.ifr_mtu; | ||
1026 | |||
1027 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1028 | "%s: set mtu=%d\n", session->name, session->mtu); | ||
1029 | err = 0; | ||
1030 | break; | ||
1031 | |||
1032 | case PPPIOCGMRU: | ||
1033 | err = -ENXIO; | ||
1034 | if (!(sk->sk_state & PPPOX_CONNECTED)) | ||
1035 | break; | ||
1036 | |||
1037 | err = -EFAULT; | ||
1038 | if (put_user(session->mru, (int __user *) arg)) | ||
1039 | break; | ||
1040 | |||
1041 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1042 | "%s: get mru=%d\n", session->name, session->mru); | ||
1043 | err = 0; | ||
1044 | break; | ||
1045 | |||
1046 | case PPPIOCSMRU: | ||
1047 | err = -ENXIO; | ||
1048 | if (!(sk->sk_state & PPPOX_CONNECTED)) | ||
1049 | break; | ||
1050 | |||
1051 | err = -EFAULT; | ||
1052 | if (get_user(val, (int __user *) arg)) | ||
1053 | break; | ||
1054 | |||
1055 | session->mru = val; | ||
1056 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1057 | "%s: set mru=%d\n", session->name, session->mru); | ||
1058 | err = 0; | ||
1059 | break; | ||
1060 | |||
1061 | case PPPIOCGFLAGS: | ||
1062 | err = -EFAULT; | ||
1063 | if (put_user(ps->flags, (int __user *) arg)) | ||
1064 | break; | ||
1065 | |||
1066 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1067 | "%s: get flags=%d\n", session->name, ps->flags); | ||
1068 | err = 0; | ||
1069 | break; | ||
1070 | |||
1071 | case PPPIOCSFLAGS: | ||
1072 | err = -EFAULT; | ||
1073 | if (get_user(val, (int __user *) arg)) | ||
1074 | break; | ||
1075 | ps->flags = val; | ||
1076 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1077 | "%s: set flags=%d\n", session->name, ps->flags); | ||
1078 | err = 0; | ||
1079 | break; | ||
1080 | |||
1081 | case PPPIOCGL2TPSTATS: | ||
1082 | err = -ENXIO; | ||
1083 | if (!(sk->sk_state & PPPOX_CONNECTED)) | ||
1084 | break; | ||
1085 | |||
1086 | memset(&stats, 0, sizeof(stats)); | ||
1087 | stats.tunnel_id = tunnel->tunnel_id; | ||
1088 | stats.session_id = session->session_id; | ||
1089 | pppol2tp_copy_stats(&stats, &session->stats); | ||
1090 | if (copy_to_user((void __user *) arg, &stats, | ||
1091 | sizeof(stats))) | ||
1092 | break; | ||
1093 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1094 | "%s: get L2TP stats\n", session->name); | ||
1095 | err = 0; | ||
1096 | break; | ||
1097 | |||
1098 | default: | ||
1099 | err = -ENOSYS; | ||
1100 | break; | ||
1101 | } | ||
1102 | |||
1103 | sock_put(sk); | ||
1104 | |||
1105 | return err; | ||
1106 | } | ||
1107 | |||
1108 | /* Tunnel ioctl helper. | ||
1109 | * | ||
1110 | * Note the special handling for PPPIOCGL2TPSTATS below. If the ioctl data | ||
1111 | * specifies a session_id, the session ioctl handler is called. This allows an | ||
1112 | * application to retrieve session stats via a tunnel socket. | ||
1113 | */ | ||
1114 | static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel *tunnel, | ||
1115 | unsigned int cmd, unsigned long arg) | ||
1116 | { | ||
1117 | int err = 0; | ||
1118 | struct sock *sk; | ||
1119 | struct pppol2tp_ioc_stats stats; | ||
1120 | |||
1121 | PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG, | ||
1122 | "%s: pppol2tp_tunnel_ioctl(cmd=%#x, arg=%#lx)\n", | ||
1123 | tunnel->name, cmd, arg); | ||
1124 | |||
1125 | sk = tunnel->sock; | ||
1126 | sock_hold(sk); | ||
1127 | |||
1128 | switch (cmd) { | ||
1129 | case PPPIOCGL2TPSTATS: | ||
1130 | err = -ENXIO; | ||
1131 | if (!(sk->sk_state & PPPOX_CONNECTED)) | ||
1132 | break; | ||
1133 | |||
1134 | if (copy_from_user(&stats, (void __user *) arg, | ||
1135 | sizeof(stats))) { | ||
1136 | err = -EFAULT; | ||
1137 | break; | ||
1138 | } | ||
1139 | if (stats.session_id != 0) { | ||
1140 | /* resend to session ioctl handler */ | ||
1141 | struct l2tp_session *session = | ||
1142 | l2tp_session_find(sock_net(sk), tunnel, stats.session_id); | ||
1143 | if (session != NULL) | ||
1144 | err = pppol2tp_session_ioctl(session, cmd, arg); | ||
1145 | else | ||
1146 | err = -EBADR; | ||
1147 | break; | ||
1148 | } | ||
1149 | #ifdef CONFIG_XFRM | ||
1150 | stats.using_ipsec = (sk->sk_policy[0] || sk->sk_policy[1]) ? 1 : 0; | ||
1151 | #endif | ||
1152 | pppol2tp_copy_stats(&stats, &tunnel->stats); | ||
1153 | if (copy_to_user((void __user *) arg, &stats, sizeof(stats))) { | ||
1154 | err = -EFAULT; | ||
1155 | break; | ||
1156 | } | ||
1157 | PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1158 | "%s: get L2TP stats\n", tunnel->name); | ||
1159 | err = 0; | ||
1160 | break; | ||
1161 | |||
1162 | default: | ||
1163 | err = -ENOSYS; | ||
1164 | break; | ||
1165 | } | ||
1166 | |||
1167 | sock_put(sk); | ||
1168 | |||
1169 | return err; | ||
1170 | } | ||
1171 | |||
1172 | /* Main ioctl() handler. | ||
1173 | * Dispatch to tunnel or session helpers depending on the socket. | ||
1174 | */ | ||
1175 | static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd, | ||
1176 | unsigned long arg) | ||
1177 | { | ||
1178 | struct sock *sk = sock->sk; | ||
1179 | struct l2tp_session *session; | ||
1180 | struct l2tp_tunnel *tunnel; | ||
1181 | struct pppol2tp_session *ps; | ||
1182 | int err; | ||
1183 | |||
1184 | if (!sk) | ||
1185 | return 0; | ||
1186 | |||
1187 | err = -EBADF; | ||
1188 | if (sock_flag(sk, SOCK_DEAD) != 0) | ||
1189 | goto end; | ||
1190 | |||
1191 | err = -ENOTCONN; | ||
1192 | if ((sk->sk_user_data == NULL) || | ||
1193 | (!(sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)))) | ||
1194 | goto end; | ||
1195 | |||
1196 | /* Get session context from the socket */ | ||
1197 | err = -EBADF; | ||
1198 | session = pppol2tp_sock_to_session(sk); | ||
1199 | if (session == NULL) | ||
1200 | goto end; | ||
1201 | |||
1202 | /* Special case: if session's session_id is zero, treat ioctl as a | ||
1203 | * tunnel ioctl | ||
1204 | */ | ||
1205 | ps = l2tp_session_priv(session); | ||
1206 | if ((session->session_id == 0) && | ||
1207 | (session->peer_session_id == 0)) { | ||
1208 | err = -EBADF; | ||
1209 | tunnel = l2tp_sock_to_tunnel(ps->tunnel_sock); | ||
1210 | if (tunnel == NULL) | ||
1211 | goto end_put_sess; | ||
1212 | |||
1213 | err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg); | ||
1214 | sock_put(ps->tunnel_sock); | ||
1215 | goto end_put_sess; | ||
1216 | } | ||
1217 | |||
1218 | err = pppol2tp_session_ioctl(session, cmd, arg); | ||
1219 | |||
1220 | end_put_sess: | ||
1221 | sock_put(sk); | ||
1222 | end: | ||
1223 | return err; | ||
1224 | } | ||
1225 | |||
1226 | /***************************************************************************** | ||
1227 | * setsockopt() / getsockopt() support. | ||
1228 | * | ||
1229 | * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP | ||
1230 | * sockets. In order to control kernel tunnel features, we allow userspace to | ||
1231 | * create a special "tunnel" PPPoX socket which is used for control only. | ||
1232 | * Tunnel PPPoX sockets have session_id == 0 and simply allow the user | ||
1233 | * application to issue L2TP setsockopt(), getsockopt() and ioctl() calls. | ||
1234 | *****************************************************************************/ | ||
1235 | |||
1236 | /* Tunnel setsockopt() helper. | ||
1237 | */ | ||
1238 | static int pppol2tp_tunnel_setsockopt(struct sock *sk, | ||
1239 | struct l2tp_tunnel *tunnel, | ||
1240 | int optname, int val) | ||
1241 | { | ||
1242 | int err = 0; | ||
1243 | |||
1244 | switch (optname) { | ||
1245 | case PPPOL2TP_SO_DEBUG: | ||
1246 | tunnel->debug = val; | ||
1247 | PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1248 | "%s: set debug=%x\n", tunnel->name, tunnel->debug); | ||
1249 | break; | ||
1250 | |||
1251 | default: | ||
1252 | err = -ENOPROTOOPT; | ||
1253 | break; | ||
1254 | } | ||
1255 | |||
1256 | return err; | ||
1257 | } | ||
1258 | |||
1259 | /* Session setsockopt helper. | ||
1260 | */ | ||
1261 | static int pppol2tp_session_setsockopt(struct sock *sk, | ||
1262 | struct l2tp_session *session, | ||
1263 | int optname, int val) | ||
1264 | { | ||
1265 | int err = 0; | ||
1266 | struct pppol2tp_session *ps = l2tp_session_priv(session); | ||
1267 | |||
1268 | switch (optname) { | ||
1269 | case PPPOL2TP_SO_RECVSEQ: | ||
1270 | if ((val != 0) && (val != 1)) { | ||
1271 | err = -EINVAL; | ||
1272 | break; | ||
1273 | } | ||
1274 | session->recv_seq = val ? -1 : 0; | ||
1275 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1276 | "%s: set recv_seq=%d\n", session->name, session->recv_seq); | ||
1277 | break; | ||
1278 | |||
1279 | case PPPOL2TP_SO_SENDSEQ: | ||
1280 | if ((val != 0) && (val != 1)) { | ||
1281 | err = -EINVAL; | ||
1282 | break; | ||
1283 | } | ||
1284 | session->send_seq = val ? -1 : 0; | ||
1285 | { | ||
1286 | struct sock *ssk = ps->sock; | ||
1287 | struct pppox_sock *po = pppox_sk(ssk); | ||
1288 | po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ : | ||
1289 | PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; | ||
1290 | } | ||
1291 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1292 | "%s: set send_seq=%d\n", session->name, session->send_seq); | ||
1293 | break; | ||
1294 | |||
1295 | case PPPOL2TP_SO_LNSMODE: | ||
1296 | if ((val != 0) && (val != 1)) { | ||
1297 | err = -EINVAL; | ||
1298 | break; | ||
1299 | } | ||
1300 | session->lns_mode = val ? -1 : 0; | ||
1301 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1302 | "%s: set lns_mode=%d\n", session->name, session->lns_mode); | ||
1303 | break; | ||
1304 | |||
1305 | case PPPOL2TP_SO_DEBUG: | ||
1306 | session->debug = val; | ||
1307 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1308 | "%s: set debug=%x\n", session->name, session->debug); | ||
1309 | break; | ||
1310 | |||
1311 | case PPPOL2TP_SO_REORDERTO: | ||
1312 | session->reorder_timeout = msecs_to_jiffies(val); | ||
1313 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1314 | "%s: set reorder_timeout=%d\n", session->name, session->reorder_timeout); | ||
1315 | break; | ||
1316 | |||
1317 | default: | ||
1318 | err = -ENOPROTOOPT; | ||
1319 | break; | ||
1320 | } | ||
1321 | |||
1322 | return err; | ||
1323 | } | ||
1324 | |||
1325 | /* Main setsockopt() entry point. | ||
1326 | * Does API checks, then calls either the tunnel or session setsockopt | ||
1327 | * handler, according to whether the PPPoL2TP socket is a for a regular | ||
1328 | * session or the special tunnel type. | ||
1329 | */ | ||
1330 | static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, | ||
1331 | char __user *optval, unsigned int optlen) | ||
1332 | { | ||
1333 | struct sock *sk = sock->sk; | ||
1334 | struct l2tp_session *session; | ||
1335 | struct l2tp_tunnel *tunnel; | ||
1336 | struct pppol2tp_session *ps; | ||
1337 | int val; | ||
1338 | int err; | ||
1339 | |||
1340 | if (level != SOL_PPPOL2TP) | ||
1341 | return udp_prot.setsockopt(sk, level, optname, optval, optlen); | ||
1342 | |||
1343 | if (optlen < sizeof(int)) | ||
1344 | return -EINVAL; | ||
1345 | |||
1346 | if (get_user(val, (int __user *)optval)) | ||
1347 | return -EFAULT; | ||
1348 | |||
1349 | err = -ENOTCONN; | ||
1350 | if (sk->sk_user_data == NULL) | ||
1351 | goto end; | ||
1352 | |||
1353 | /* Get session context from the socket */ | ||
1354 | err = -EBADF; | ||
1355 | session = pppol2tp_sock_to_session(sk); | ||
1356 | if (session == NULL) | ||
1357 | goto end; | ||
1358 | |||
1359 | /* Special case: if session_id == 0x0000, treat as operation on tunnel | ||
1360 | */ | ||
1361 | ps = l2tp_session_priv(session); | ||
1362 | if ((session->session_id == 0) && | ||
1363 | (session->peer_session_id == 0)) { | ||
1364 | err = -EBADF; | ||
1365 | tunnel = l2tp_sock_to_tunnel(ps->tunnel_sock); | ||
1366 | if (tunnel == NULL) | ||
1367 | goto end_put_sess; | ||
1368 | |||
1369 | err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val); | ||
1370 | sock_put(ps->tunnel_sock); | ||
1371 | } else | ||
1372 | err = pppol2tp_session_setsockopt(sk, session, optname, val); | ||
1373 | |||
1374 | err = 0; | ||
1375 | |||
1376 | end_put_sess: | ||
1377 | sock_put(sk); | ||
1378 | end: | ||
1379 | return err; | ||
1380 | } | ||
1381 | |||
1382 | /* Tunnel getsockopt helper. Called with sock locked. | ||
1383 | */ | ||
1384 | static int pppol2tp_tunnel_getsockopt(struct sock *sk, | ||
1385 | struct l2tp_tunnel *tunnel, | ||
1386 | int optname, int *val) | ||
1387 | { | ||
1388 | int err = 0; | ||
1389 | |||
1390 | switch (optname) { | ||
1391 | case PPPOL2TP_SO_DEBUG: | ||
1392 | *val = tunnel->debug; | ||
1393 | PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1394 | "%s: get debug=%x\n", tunnel->name, tunnel->debug); | ||
1395 | break; | ||
1396 | |||
1397 | default: | ||
1398 | err = -ENOPROTOOPT; | ||
1399 | break; | ||
1400 | } | ||
1401 | |||
1402 | return err; | ||
1403 | } | ||
1404 | |||
1405 | /* Session getsockopt helper. Called with sock locked. | ||
1406 | */ | ||
1407 | static int pppol2tp_session_getsockopt(struct sock *sk, | ||
1408 | struct l2tp_session *session, | ||
1409 | int optname, int *val) | ||
1410 | { | ||
1411 | int err = 0; | ||
1412 | |||
1413 | switch (optname) { | ||
1414 | case PPPOL2TP_SO_RECVSEQ: | ||
1415 | *val = session->recv_seq; | ||
1416 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1417 | "%s: get recv_seq=%d\n", session->name, *val); | ||
1418 | break; | ||
1419 | |||
1420 | case PPPOL2TP_SO_SENDSEQ: | ||
1421 | *val = session->send_seq; | ||
1422 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1423 | "%s: get send_seq=%d\n", session->name, *val); | ||
1424 | break; | ||
1425 | |||
1426 | case PPPOL2TP_SO_LNSMODE: | ||
1427 | *val = session->lns_mode; | ||
1428 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1429 | "%s: get lns_mode=%d\n", session->name, *val); | ||
1430 | break; | ||
1431 | |||
1432 | case PPPOL2TP_SO_DEBUG: | ||
1433 | *val = session->debug; | ||
1434 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1435 | "%s: get debug=%d\n", session->name, *val); | ||
1436 | break; | ||
1437 | |||
1438 | case PPPOL2TP_SO_REORDERTO: | ||
1439 | *val = (int) jiffies_to_msecs(session->reorder_timeout); | ||
1440 | PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, | ||
1441 | "%s: get reorder_timeout=%d\n", session->name, *val); | ||
1442 | break; | ||
1443 | |||
1444 | default: | ||
1445 | err = -ENOPROTOOPT; | ||
1446 | } | ||
1447 | |||
1448 | return err; | ||
1449 | } | ||
1450 | |||
1451 | /* Main getsockopt() entry point. | ||
1452 | * Does API checks, then calls either the tunnel or session getsockopt | ||
1453 | * handler, according to whether the PPPoX socket is a for a regular session | ||
1454 | * or the special tunnel type. | ||
1455 | */ | ||
1456 | static int pppol2tp_getsockopt(struct socket *sock, int level, | ||
1457 | int optname, char __user *optval, int __user *optlen) | ||
1458 | { | ||
1459 | struct sock *sk = sock->sk; | ||
1460 | struct l2tp_session *session; | ||
1461 | struct l2tp_tunnel *tunnel; | ||
1462 | int val, len; | ||
1463 | int err; | ||
1464 | struct pppol2tp_session *ps; | ||
1465 | |||
1466 | if (level != SOL_PPPOL2TP) | ||
1467 | return udp_prot.getsockopt(sk, level, optname, optval, optlen); | ||
1468 | |||
1469 | if (get_user(len, (int __user *) optlen)) | ||
1470 | return -EFAULT; | ||
1471 | |||
1472 | len = min_t(unsigned int, len, sizeof(int)); | ||
1473 | |||
1474 | if (len < 0) | ||
1475 | return -EINVAL; | ||
1476 | |||
1477 | err = -ENOTCONN; | ||
1478 | if (sk->sk_user_data == NULL) | ||
1479 | goto end; | ||
1480 | |||
1481 | /* Get the session context */ | ||
1482 | err = -EBADF; | ||
1483 | session = pppol2tp_sock_to_session(sk); | ||
1484 | if (session == NULL) | ||
1485 | goto end; | ||
1486 | |||
1487 | /* Special case: if session_id == 0x0000, treat as operation on tunnel */ | ||
1488 | ps = l2tp_session_priv(session); | ||
1489 | if ((session->session_id == 0) && | ||
1490 | (session->peer_session_id == 0)) { | ||
1491 | err = -EBADF; | ||
1492 | tunnel = l2tp_sock_to_tunnel(ps->tunnel_sock); | ||
1493 | if (tunnel == NULL) | ||
1494 | goto end_put_sess; | ||
1495 | |||
1496 | err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); | ||
1497 | sock_put(ps->tunnel_sock); | ||
1498 | } else | ||
1499 | err = pppol2tp_session_getsockopt(sk, session, optname, &val); | ||
1500 | |||
1501 | err = -EFAULT; | ||
1502 | if (put_user(len, (int __user *) optlen)) | ||
1503 | goto end_put_sess; | ||
1504 | |||
1505 | if (copy_to_user((void __user *) optval, &val, len)) | ||
1506 | goto end_put_sess; | ||
1507 | |||
1508 | err = 0; | ||
1509 | |||
1510 | end_put_sess: | ||
1511 | sock_put(sk); | ||
1512 | end: | ||
1513 | return err; | ||
1514 | } | ||
1515 | |||
1516 | /***************************************************************************** | ||
1517 | * /proc filesystem for debug | ||
1518 | * Since the original pppol2tp driver provided /proc/net/pppol2tp for | ||
1519 | * L2TPv2, we dump only L2TPv2 tunnels and sessions here. | ||
1520 | *****************************************************************************/ | ||
1521 | |||
1522 | static unsigned int pppol2tp_net_id; | ||
1523 | |||
1524 | #ifdef CONFIG_PROC_FS | ||
1525 | |||
1526 | struct pppol2tp_seq_data { | ||
1527 | struct seq_net_private p; | ||
1528 | int tunnel_idx; /* current tunnel */ | ||
1529 | int session_idx; /* index of session within current tunnel */ | ||
1530 | struct l2tp_tunnel *tunnel; | ||
1531 | struct l2tp_session *session; /* NULL means get next tunnel */ | ||
1532 | }; | ||
1533 | |||
1534 | static void pppol2tp_next_tunnel(struct net *net, struct pppol2tp_seq_data *pd) | ||
1535 | { | ||
1536 | for (;;) { | ||
1537 | pd->tunnel = l2tp_tunnel_find_nth(net, pd->tunnel_idx); | ||
1538 | pd->tunnel_idx++; | ||
1539 | |||
1540 | if (pd->tunnel == NULL) | ||
1541 | break; | ||
1542 | |||
1543 | /* Ignore L2TPv3 tunnels */ | ||
1544 | if (pd->tunnel->version < 3) | ||
1545 | break; | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd) | ||
1550 | { | ||
1551 | pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx); | ||
1552 | pd->session_idx++; | ||
1553 | |||
1554 | if (pd->session == NULL) { | ||
1555 | pd->session_idx = 0; | ||
1556 | pppol2tp_next_tunnel(net, pd); | ||
1557 | } | ||
1558 | } | ||
1559 | |||
1560 | static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs) | ||
1561 | { | ||
1562 | struct pppol2tp_seq_data *pd = SEQ_START_TOKEN; | ||
1563 | loff_t pos = *offs; | ||
1564 | struct net *net; | ||
1565 | |||
1566 | if (!pos) | ||
1567 | goto out; | ||
1568 | |||
1569 | BUG_ON(m->private == NULL); | ||
1570 | pd = m->private; | ||
1571 | net = seq_file_net(m); | ||
1572 | |||
1573 | if (pd->tunnel == NULL) | ||
1574 | pppol2tp_next_tunnel(net, pd); | ||
1575 | else | ||
1576 | pppol2tp_next_session(net, pd); | ||
1577 | |||
1578 | /* NULL tunnel and session indicates end of list */ | ||
1579 | if ((pd->tunnel == NULL) && (pd->session == NULL)) | ||
1580 | pd = NULL; | ||
1581 | |||
1582 | out: | ||
1583 | return pd; | ||
1584 | } | ||
1585 | |||
1586 | static void *pppol2tp_seq_next(struct seq_file *m, void *v, loff_t *pos) | ||
1587 | { | ||
1588 | (*pos)++; | ||
1589 | return NULL; | ||
1590 | } | ||
1591 | |||
1592 | static void pppol2tp_seq_stop(struct seq_file *p, void *v) | ||
1593 | { | ||
1594 | /* nothing to do */ | ||
1595 | } | ||
1596 | |||
1597 | static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v) | ||
1598 | { | ||
1599 | struct l2tp_tunnel *tunnel = v; | ||
1600 | |||
1601 | seq_printf(m, "\nTUNNEL '%s', %c %d\n", | ||
1602 | tunnel->name, | ||
1603 | (tunnel == tunnel->sock->sk_user_data) ? 'Y' : 'N', | ||
1604 | atomic_read(&tunnel->ref_count) - 1); | ||
1605 | seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n", | ||
1606 | tunnel->debug, | ||
1607 | (unsigned long long)tunnel->stats.tx_packets, | ||
1608 | (unsigned long long)tunnel->stats.tx_bytes, | ||
1609 | (unsigned long long)tunnel->stats.tx_errors, | ||
1610 | (unsigned long long)tunnel->stats.rx_packets, | ||
1611 | (unsigned long long)tunnel->stats.rx_bytes, | ||
1612 | (unsigned long long)tunnel->stats.rx_errors); | ||
1613 | } | ||
1614 | |||
1615 | static void pppol2tp_seq_session_show(struct seq_file *m, void *v) | ||
1616 | { | ||
1617 | struct l2tp_session *session = v; | ||
1618 | struct l2tp_tunnel *tunnel = session->tunnel; | ||
1619 | struct pppol2tp_session *ps = l2tp_session_priv(session); | ||
1620 | struct pppox_sock *po = pppox_sk(ps->sock); | ||
1621 | u32 ip = 0; | ||
1622 | u16 port = 0; | ||
1623 | |||
1624 | if (tunnel->sock) { | ||
1625 | struct inet_sock *inet = inet_sk(tunnel->sock); | ||
1626 | ip = ntohl(inet->inet_saddr); | ||
1627 | port = ntohs(inet->inet_sport); | ||
1628 | } | ||
1629 | |||
1630 | seq_printf(m, " SESSION '%s' %08X/%d %04X/%04X -> " | ||
1631 | "%04X/%04X %d %c\n", | ||
1632 | session->name, ip, port, | ||
1633 | tunnel->tunnel_id, | ||
1634 | session->session_id, | ||
1635 | tunnel->peer_tunnel_id, | ||
1636 | session->peer_session_id, | ||
1637 | ps->sock->sk_state, | ||
1638 | (session == ps->sock->sk_user_data) ? | ||
1639 | 'Y' : 'N'); | ||
1640 | seq_printf(m, " %d/%d/%c/%c/%s %08x %u\n", | ||
1641 | session->mtu, session->mru, | ||
1642 | session->recv_seq ? 'R' : '-', | ||
1643 | session->send_seq ? 'S' : '-', | ||
1644 | session->lns_mode ? "LNS" : "LAC", | ||
1645 | session->debug, | ||
1646 | jiffies_to_msecs(session->reorder_timeout)); | ||
1647 | seq_printf(m, " %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n", | ||
1648 | session->nr, session->ns, | ||
1649 | (unsigned long long)session->stats.tx_packets, | ||
1650 | (unsigned long long)session->stats.tx_bytes, | ||
1651 | (unsigned long long)session->stats.tx_errors, | ||
1652 | (unsigned long long)session->stats.rx_packets, | ||
1653 | (unsigned long long)session->stats.rx_bytes, | ||
1654 | (unsigned long long)session->stats.rx_errors); | ||
1655 | |||
1656 | if (po) | ||
1657 | seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); | ||
1658 | } | ||
1659 | |||
1660 | static int pppol2tp_seq_show(struct seq_file *m, void *v) | ||
1661 | { | ||
1662 | struct pppol2tp_seq_data *pd = v; | ||
1663 | |||
1664 | /* display header on line 1 */ | ||
1665 | if (v == SEQ_START_TOKEN) { | ||
1666 | seq_puts(m, "PPPoL2TP driver info, " PPPOL2TP_DRV_VERSION "\n"); | ||
1667 | seq_puts(m, "TUNNEL name, user-data-ok session-count\n"); | ||
1668 | seq_puts(m, " debug tx-pkts/bytes/errs rx-pkts/bytes/errs\n"); | ||
1669 | seq_puts(m, " SESSION name, addr/port src-tid/sid " | ||
1670 | "dest-tid/sid state user-data-ok\n"); | ||
1671 | seq_puts(m, " mtu/mru/rcvseq/sendseq/lns debug reorderto\n"); | ||
1672 | seq_puts(m, " nr/ns tx-pkts/bytes/errs rx-pkts/bytes/errs\n"); | ||
1673 | goto out; | ||
1674 | } | ||
1675 | |||
1676 | /* Show the tunnel or session context. | ||
1677 | */ | ||
1678 | if (pd->session == NULL) | ||
1679 | pppol2tp_seq_tunnel_show(m, pd->tunnel); | ||
1680 | else | ||
1681 | pppol2tp_seq_session_show(m, pd->session); | ||
1682 | |||
1683 | out: | ||
1684 | return 0; | ||
1685 | } | ||
1686 | |||
1687 | static const struct seq_operations pppol2tp_seq_ops = { | ||
1688 | .start = pppol2tp_seq_start, | ||
1689 | .next = pppol2tp_seq_next, | ||
1690 | .stop = pppol2tp_seq_stop, | ||
1691 | .show = pppol2tp_seq_show, | ||
1692 | }; | ||
1693 | |||
1694 | /* Called when our /proc file is opened. We allocate data for use when | ||
1695 | * iterating our tunnel / session contexts and store it in the private | ||
1696 | * data of the seq_file. | ||
1697 | */ | ||
1698 | static int pppol2tp_proc_open(struct inode *inode, struct file *file) | ||
1699 | { | ||
1700 | return seq_open_net(inode, file, &pppol2tp_seq_ops, | ||
1701 | sizeof(struct pppol2tp_seq_data)); | ||
1702 | } | ||
1703 | |||
1704 | static const struct file_operations pppol2tp_proc_fops = { | ||
1705 | .owner = THIS_MODULE, | ||
1706 | .open = pppol2tp_proc_open, | ||
1707 | .read = seq_read, | ||
1708 | .llseek = seq_lseek, | ||
1709 | .release = seq_release_net, | ||
1710 | }; | ||
1711 | |||
1712 | #endif /* CONFIG_PROC_FS */ | ||
1713 | |||
1714 | /***************************************************************************** | ||
1715 | * Network namespace | ||
1716 | *****************************************************************************/ | ||
1717 | |||
1718 | static __net_init int pppol2tp_init_net(struct net *net) | ||
1719 | { | ||
1720 | struct proc_dir_entry *pde; | ||
1721 | int err = 0; | ||
1722 | |||
1723 | pde = proc_net_fops_create(net, "pppol2tp", S_IRUGO, &pppol2tp_proc_fops); | ||
1724 | if (!pde) { | ||
1725 | err = -ENOMEM; | ||
1726 | goto out; | ||
1727 | } | ||
1728 | |||
1729 | out: | ||
1730 | return err; | ||
1731 | } | ||
1732 | |||
1733 | static __net_exit void pppol2tp_exit_net(struct net *net) | ||
1734 | { | ||
1735 | proc_net_remove(net, "pppol2tp"); | ||
1736 | } | ||
1737 | |||
1738 | static struct pernet_operations pppol2tp_net_ops = { | ||
1739 | .init = pppol2tp_init_net, | ||
1740 | .exit = pppol2tp_exit_net, | ||
1741 | .id = &pppol2tp_net_id, | ||
1742 | }; | ||
1743 | |||
1744 | /***************************************************************************** | ||
1745 | * Init and cleanup | ||
1746 | *****************************************************************************/ | ||
1747 | |||
1748 | static const struct proto_ops pppol2tp_ops = { | ||
1749 | .family = AF_PPPOX, | ||
1750 | .owner = THIS_MODULE, | ||
1751 | .release = pppol2tp_release, | ||
1752 | .bind = sock_no_bind, | ||
1753 | .connect = pppol2tp_connect, | ||
1754 | .socketpair = sock_no_socketpair, | ||
1755 | .accept = sock_no_accept, | ||
1756 | .getname = pppol2tp_getname, | ||
1757 | .poll = datagram_poll, | ||
1758 | .listen = sock_no_listen, | ||
1759 | .shutdown = sock_no_shutdown, | ||
1760 | .setsockopt = pppol2tp_setsockopt, | ||
1761 | .getsockopt = pppol2tp_getsockopt, | ||
1762 | .sendmsg = pppol2tp_sendmsg, | ||
1763 | .recvmsg = pppol2tp_recvmsg, | ||
1764 | .mmap = sock_no_mmap, | ||
1765 | .ioctl = pppox_ioctl, | ||
1766 | }; | ||
1767 | |||
1768 | static struct pppox_proto pppol2tp_proto = { | ||
1769 | .create = pppol2tp_create, | ||
1770 | .ioctl = pppol2tp_ioctl | ||
1771 | }; | ||
1772 | |||
1773 | #ifdef CONFIG_L2TP_V3 | ||
1774 | |||
1775 | static const struct l2tp_nl_cmd_ops pppol2tp_nl_cmd_ops = { | ||
1776 | .session_create = pppol2tp_session_create, | ||
1777 | .session_delete = pppol2tp_session_delete, | ||
1778 | }; | ||
1779 | |||
1780 | #endif /* CONFIG_L2TP_V3 */ | ||
1781 | |||
1782 | static int __init pppol2tp_init(void) | ||
1783 | { | ||
1784 | int err; | ||
1785 | |||
1786 | err = register_pernet_device(&pppol2tp_net_ops); | ||
1787 | if (err) | ||
1788 | goto out; | ||
1789 | |||
1790 | err = proto_register(&pppol2tp_sk_proto, 0); | ||
1791 | if (err) | ||
1792 | goto out_unregister_pppol2tp_pernet; | ||
1793 | |||
1794 | err = register_pppox_proto(PX_PROTO_OL2TP, &pppol2tp_proto); | ||
1795 | if (err) | ||
1796 | goto out_unregister_pppol2tp_proto; | ||
1797 | |||
1798 | #ifdef CONFIG_L2TP_V3 | ||
1799 | err = l2tp_nl_register_ops(L2TP_PWTYPE_PPP, &pppol2tp_nl_cmd_ops); | ||
1800 | if (err) | ||
1801 | goto out_unregister_pppox; | ||
1802 | #endif | ||
1803 | |||
1804 | printk(KERN_INFO "PPPoL2TP kernel driver, %s\n", | ||
1805 | PPPOL2TP_DRV_VERSION); | ||
1806 | |||
1807 | out: | ||
1808 | return err; | ||
1809 | |||
1810 | #ifdef CONFIG_L2TP_V3 | ||
1811 | out_unregister_pppox: | ||
1812 | unregister_pppox_proto(PX_PROTO_OL2TP); | ||
1813 | #endif | ||
1814 | out_unregister_pppol2tp_proto: | ||
1815 | proto_unregister(&pppol2tp_sk_proto); | ||
1816 | out_unregister_pppol2tp_pernet: | ||
1817 | unregister_pernet_device(&pppol2tp_net_ops); | ||
1818 | goto out; | ||
1819 | } | ||
1820 | |||
1821 | static void __exit pppol2tp_exit(void) | ||
1822 | { | ||
1823 | #ifdef CONFIG_L2TP_V3 | ||
1824 | l2tp_nl_unregister_ops(L2TP_PWTYPE_PPP); | ||
1825 | #endif | ||
1826 | unregister_pppox_proto(PX_PROTO_OL2TP); | ||
1827 | proto_unregister(&pppol2tp_sk_proto); | ||
1828 | unregister_pernet_device(&pppol2tp_net_ops); | ||
1829 | } | ||
1830 | |||
1831 | module_init(pppol2tp_init); | ||
1832 | module_exit(pppol2tp_exit); | ||
1833 | |||
1834 | MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | ||
1835 | MODULE_DESCRIPTION("PPP over L2TP over UDP"); | ||
1836 | MODULE_LICENSE("GPL"); | ||
1837 | MODULE_VERSION(PPPOL2TP_DRV_VERSION); | ||
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 2db6a9f75913..023ba820236f 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -536,7 +536,7 @@ static int llc_ui_wait_for_disc(struct sock *sk, long timeout) | |||
536 | int rc = 0; | 536 | int rc = 0; |
537 | 537 | ||
538 | while (1) { | 538 | while (1) { |
539 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 539 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
540 | if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE)) | 540 | if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE)) |
541 | break; | 541 | break; |
542 | rc = -ERESTARTSYS; | 542 | rc = -ERESTARTSYS; |
@@ -547,7 +547,7 @@ static int llc_ui_wait_for_disc(struct sock *sk, long timeout) | |||
547 | break; | 547 | break; |
548 | rc = 0; | 548 | rc = 0; |
549 | } | 549 | } |
550 | finish_wait(sk->sk_sleep, &wait); | 550 | finish_wait(sk_sleep(sk), &wait); |
551 | return rc; | 551 | return rc; |
552 | } | 552 | } |
553 | 553 | ||
@@ -556,13 +556,13 @@ static int llc_ui_wait_for_conn(struct sock *sk, long timeout) | |||
556 | DEFINE_WAIT(wait); | 556 | DEFINE_WAIT(wait); |
557 | 557 | ||
558 | while (1) { | 558 | while (1) { |
559 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 559 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
560 | if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT)) | 560 | if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT)) |
561 | break; | 561 | break; |
562 | if (signal_pending(current) || !timeout) | 562 | if (signal_pending(current) || !timeout) |
563 | break; | 563 | break; |
564 | } | 564 | } |
565 | finish_wait(sk->sk_sleep, &wait); | 565 | finish_wait(sk_sleep(sk), &wait); |
566 | return timeout; | 566 | return timeout; |
567 | } | 567 | } |
568 | 568 | ||
@@ -573,7 +573,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout) | |||
573 | int rc; | 573 | int rc; |
574 | 574 | ||
575 | while (1) { | 575 | while (1) { |
576 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 576 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
577 | rc = 0; | 577 | rc = 0; |
578 | if (sk_wait_event(sk, &timeout, | 578 | if (sk_wait_event(sk, &timeout, |
579 | (sk->sk_shutdown & RCV_SHUTDOWN) || | 579 | (sk->sk_shutdown & RCV_SHUTDOWN) || |
@@ -588,7 +588,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout) | |||
588 | if (!timeout) | 588 | if (!timeout) |
589 | break; | 589 | break; |
590 | } | 590 | } |
591 | finish_wait(sk->sk_sleep, &wait); | 591 | finish_wait(sk_sleep(sk), &wait); |
592 | return rc; | 592 | return rc; |
593 | } | 593 | } |
594 | 594 | ||
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 78167e81dfeb..2bb0ddff8c0f 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c | |||
@@ -144,12 +144,6 @@ static struct packet_type llc_tr_packet_type __read_mostly = { | |||
144 | 144 | ||
145 | static int __init llc_init(void) | 145 | static int __init llc_init(void) |
146 | { | 146 | { |
147 | struct net_device *dev; | ||
148 | |||
149 | dev = first_net_device(&init_net); | ||
150 | if (dev != NULL) | ||
151 | dev = next_net_device(dev); | ||
152 | |||
153 | dev_add_pack(&llc_packet_type); | 147 | dev_add_pack(&llc_packet_type); |
154 | dev_add_pack(&llc_tr_packet_type); | 148 | dev_add_pack(&llc_tr_packet_type); |
155 | return 0; | 149 | return 0; |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index a952b7f8c648..8a91f6c0bb18 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -15,8 +15,12 @@ comment "CFG80211 needs to be enabled for MAC80211" | |||
15 | 15 | ||
16 | if MAC80211 != n | 16 | if MAC80211 != n |
17 | 17 | ||
18 | config MAC80211_HAS_RC | ||
19 | def_bool n | ||
20 | |||
18 | config MAC80211_RC_PID | 21 | config MAC80211_RC_PID |
19 | bool "PID controller based rate control algorithm" if EMBEDDED | 22 | bool "PID controller based rate control algorithm" if EMBEDDED |
23 | select MAC80211_HAS_RC | ||
20 | ---help--- | 24 | ---help--- |
21 | This option enables a TX rate control algorithm for | 25 | This option enables a TX rate control algorithm for |
22 | mac80211 that uses a PID controller to select the TX | 26 | mac80211 that uses a PID controller to select the TX |
@@ -24,12 +28,14 @@ config MAC80211_RC_PID | |||
24 | 28 | ||
25 | config MAC80211_RC_MINSTREL | 29 | config MAC80211_RC_MINSTREL |
26 | bool "Minstrel" if EMBEDDED | 30 | bool "Minstrel" if EMBEDDED |
31 | select MAC80211_HAS_RC | ||
27 | default y | 32 | default y |
28 | ---help--- | 33 | ---help--- |
29 | This option enables the 'minstrel' TX rate control algorithm | 34 | This option enables the 'minstrel' TX rate control algorithm |
30 | 35 | ||
31 | choice | 36 | choice |
32 | prompt "Default rate control algorithm" | 37 | prompt "Default rate control algorithm" |
38 | depends on MAC80211_HAS_RC | ||
33 | default MAC80211_RC_DEFAULT_MINSTREL | 39 | default MAC80211_RC_DEFAULT_MINSTREL |
34 | ---help--- | 40 | ---help--- |
35 | This option selects the default rate control algorithm | 41 | This option selects the default rate control algorithm |
@@ -62,6 +68,9 @@ config MAC80211_RC_DEFAULT | |||
62 | 68 | ||
63 | endif | 69 | endif |
64 | 70 | ||
71 | comment "Some wireless drivers require a rate control algorithm" | ||
72 | depends on MAC80211_HAS_RC=n | ||
73 | |||
65 | config MAC80211_MESH | 74 | config MAC80211_MESH |
66 | bool "Enable mac80211 mesh networking (pre-802.11s) support" | 75 | bool "Enable mac80211 mesh networking (pre-802.11s) support" |
67 | depends on MAC80211 && EXPERIMENTAL | 76 | depends on MAC80211 && EXPERIMENTAL |
@@ -212,8 +221,8 @@ config MAC80211_DRIVER_API_TRACER | |||
212 | depends on EVENT_TRACING | 221 | depends on EVENT_TRACING |
213 | help | 222 | help |
214 | Say Y here to make mac80211 register with the ftrace | 223 | Say Y here to make mac80211 register with the ftrace |
215 | framework for the driver API -- you can see which | 224 | framework for the driver API -- you can then see which |
216 | driver methods it is calling then by looking at the | 225 | driver methods it is calling and which API functions |
217 | trace. | 226 | drivers are calling by looking at the trace. |
218 | 227 | ||
219 | If unsure, say N. | 228 | If unsure, say Y. |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 04420291e7ad..84b48ba8a77e 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -23,7 +23,8 @@ mac80211-y := \ | |||
23 | key.o \ | 23 | key.o \ |
24 | util.o \ | 24 | util.o \ |
25 | wme.o \ | 25 | wme.o \ |
26 | event.o | 26 | event.o \ |
27 | chan.o | ||
27 | 28 | ||
28 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o | 29 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o |
29 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ | 30 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index f9516a27e233..6bb9a9a94960 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -19,23 +19,25 @@ | |||
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "driver-ops.h" | 20 | #include "driver-ops.h" |
21 | 21 | ||
22 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 22 | static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
23 | u16 initiator, u16 reason) | 23 | u16 initiator, u16 reason, |
24 | bool from_timer) | ||
24 | { | 25 | { |
25 | struct ieee80211_local *local = sta->local; | 26 | struct ieee80211_local *local = sta->local; |
27 | struct tid_ampdu_rx *tid_rx; | ||
26 | int i; | 28 | int i; |
27 | 29 | ||
28 | /* check if TID is in operational state */ | ||
29 | spin_lock_bh(&sta->lock); | 30 | spin_lock_bh(&sta->lock); |
30 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) { | 31 | |
32 | /* check if TID is in operational state */ | ||
33 | if (!sta->ampdu_mlme.tid_active_rx[tid]) { | ||
31 | spin_unlock_bh(&sta->lock); | 34 | spin_unlock_bh(&sta->lock); |
32 | return; | 35 | return; |
33 | } | 36 | } |
34 | 37 | ||
35 | sta->ampdu_mlme.tid_state_rx[tid] = | 38 | sta->ampdu_mlme.tid_active_rx[tid] = false; |
36 | HT_AGG_STATE_REQ_STOP_BA_MSK | | 39 | |
37 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 40 | tid_rx = sta->ampdu_mlme.tid_rx[tid]; |
38 | spin_unlock_bh(&sta->lock); | ||
39 | 41 | ||
40 | #ifdef CONFIG_MAC80211_HT_DEBUG | 42 | #ifdef CONFIG_MAC80211_HT_DEBUG |
41 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", | 43 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", |
@@ -47,61 +49,42 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
47 | printk(KERN_DEBUG "HW problem - can not stop rx " | 49 | printk(KERN_DEBUG "HW problem - can not stop rx " |
48 | "aggregation for tid %d\n", tid); | 50 | "aggregation for tid %d\n", tid); |
49 | 51 | ||
50 | /* shutdown timer has not expired */ | ||
51 | if (initiator != WLAN_BACK_TIMER) | ||
52 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
53 | |||
54 | /* check if this is a self generated aggregation halt */ | 52 | /* check if this is a self generated aggregation halt */ |
55 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | 53 | if (initiator == WLAN_BACK_RECIPIENT) |
56 | ieee80211_send_delba(sta->sdata, sta->sta.addr, | 54 | ieee80211_send_delba(sta->sdata, sta->sta.addr, |
57 | tid, 0, reason); | 55 | tid, 0, reason); |
58 | 56 | ||
59 | /* free the reordering buffer */ | 57 | /* free the reordering buffer */ |
60 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { | 58 | for (i = 0; i < tid_rx->buf_size; i++) { |
61 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { | 59 | if (tid_rx->reorder_buf[i]) { |
62 | /* release the reordered frames */ | 60 | /* release the reordered frames */ |
63 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); | 61 | dev_kfree_skb(tid_rx->reorder_buf[i]); |
64 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; | 62 | tid_rx->stored_mpdu_num--; |
65 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; | 63 | tid_rx->reorder_buf[i] = NULL; |
66 | } | 64 | } |
67 | } | 65 | } |
68 | 66 | ||
69 | spin_lock_bh(&sta->lock); | ||
70 | /* free resources */ | 67 | /* free resources */ |
71 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | 68 | kfree(tid_rx->reorder_buf); |
72 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time); | 69 | kfree(tid_rx->reorder_time); |
73 | 70 | sta->ampdu_mlme.tid_rx[tid] = NULL; | |
74 | if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { | ||
75 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
76 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
77 | } | ||
78 | 71 | ||
79 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
80 | spin_unlock_bh(&sta->lock); | 72 | spin_unlock_bh(&sta->lock); |
73 | |||
74 | if (!from_timer) | ||
75 | del_timer_sync(&tid_rx->session_timer); | ||
76 | kfree(tid_rx); | ||
81 | } | 77 | } |
82 | 78 | ||
83 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | 79 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
84 | u16 initiator, u16 reason) | 80 | u16 initiator, u16 reason) |
85 | { | 81 | { |
86 | struct sta_info *sta; | 82 | ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, false); |
87 | |||
88 | rcu_read_lock(); | ||
89 | |||
90 | sta = sta_info_get(sdata, ra); | ||
91 | if (!sta) { | ||
92 | rcu_read_unlock(); | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | __ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); | ||
97 | |||
98 | rcu_read_unlock(); | ||
99 | } | 83 | } |
100 | 84 | ||
101 | /* | 85 | /* |
102 | * After accepting the AddBA Request we activated a timer, | 86 | * After accepting the AddBA Request we activated a timer, |
103 | * resetting it after each frame that arrives from the originator. | 87 | * resetting it after each frame that arrives from the originator. |
104 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | ||
105 | */ | 88 | */ |
106 | static void sta_rx_agg_session_timer_expired(unsigned long data) | 89 | static void sta_rx_agg_session_timer_expired(unsigned long data) |
107 | { | 90 | { |
@@ -117,9 +100,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
117 | #ifdef CONFIG_MAC80211_HT_DEBUG | 100 | #ifdef CONFIG_MAC80211_HT_DEBUG |
118 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 101 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
119 | #endif | 102 | #endif |
120 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | 103 | ___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, |
121 | (u16)*ptid, WLAN_BACK_TIMER, | 104 | WLAN_REASON_QSTA_TIMEOUT, true); |
122 | WLAN_REASON_QSTA_TIMEOUT); | ||
123 | } | 105 | } |
124 | 106 | ||
125 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 107 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, |
@@ -194,7 +176,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
194 | 176 | ||
195 | status = WLAN_STATUS_REQUEST_DECLINED; | 177 | status = WLAN_STATUS_REQUEST_DECLINED; |
196 | 178 | ||
197 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { | 179 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { |
198 | #ifdef CONFIG_MAC80211_HT_DEBUG | 180 | #ifdef CONFIG_MAC80211_HT_DEBUG |
199 | printk(KERN_DEBUG "Suspend in progress. " | 181 | printk(KERN_DEBUG "Suspend in progress. " |
200 | "Denying ADDBA request\n"); | 182 | "Denying ADDBA request\n"); |
@@ -232,7 +214,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
232 | /* examine state machine */ | 214 | /* examine state machine */ |
233 | spin_lock_bh(&sta->lock); | 215 | spin_lock_bh(&sta->lock); |
234 | 216 | ||
235 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | 217 | if (sta->ampdu_mlme.tid_active_rx[tid]) { |
236 | #ifdef CONFIG_MAC80211_HT_DEBUG | 218 | #ifdef CONFIG_MAC80211_HT_DEBUG |
237 | if (net_ratelimit()) | 219 | if (net_ratelimit()) |
238 | printk(KERN_DEBUG "unexpected AddBA Req from " | 220 | printk(KERN_DEBUG "unexpected AddBA Req from " |
@@ -294,7 +276,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
294 | } | 276 | } |
295 | 277 | ||
296 | /* change state and send addba resp */ | 278 | /* change state and send addba resp */ |
297 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; | 279 | sta->ampdu_mlme.tid_active_rx[tid] = true; |
298 | tid_agg_rx->dialog_token = dialog_token; | 280 | tid_agg_rx->dialog_token = dialog_token; |
299 | tid_agg_rx->ssn = start_seq_num; | 281 | tid_agg_rx->ssn = start_seq_num; |
300 | tid_agg_rx->head_seq_num = start_seq_num; | 282 | tid_agg_rx->head_seq_num = start_seq_num; |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 87782a4bb541..c163d0a149f4 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -186,7 +186,7 @@ static void sta_addba_resp_timer_expired(unsigned long data) | |||
186 | spin_unlock_bh(&sta->lock); | 186 | spin_unlock_bh(&sta->lock); |
187 | #ifdef CONFIG_MAC80211_HT_DEBUG | 187 | #ifdef CONFIG_MAC80211_HT_DEBUG |
188 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | 188 | printk(KERN_DEBUG "timer expired on tid %d but we are not " |
189 | "(or no longer) expecting addBA response there", | 189 | "(or no longer) expecting addBA response there\n", |
190 | tid); | 190 | tid); |
191 | #endif | 191 | #endif |
192 | return; | 192 | return; |
@@ -214,6 +214,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
214 | int ret = 0; | 214 | int ret = 0; |
215 | u16 start_seq_num; | 215 | u16 start_seq_num; |
216 | 216 | ||
217 | trace_api_start_tx_ba_session(pubsta, tid); | ||
218 | |||
217 | if (WARN_ON(!local->ops->ampdu_action)) | 219 | if (WARN_ON(!local->ops->ampdu_action)) |
218 | return -EINVAL; | 220 | return -EINVAL; |
219 | 221 | ||
@@ -245,7 +247,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
245 | return -EINVAL; | 247 | return -EINVAL; |
246 | } | 248 | } |
247 | 249 | ||
248 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { | 250 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { |
249 | #ifdef CONFIG_MAC80211_HT_DEBUG | 251 | #ifdef CONFIG_MAC80211_HT_DEBUG |
250 | printk(KERN_DEBUG "Suspend in progress. " | 252 | printk(KERN_DEBUG "Suspend in progress. " |
251 | "Denying BA session request\n"); | 253 | "Denying BA session request\n"); |
@@ -414,7 +416,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
414 | struct sta_info *sta, u16 tid) | 416 | struct sta_info *sta, u16 tid) |
415 | { | 417 | { |
416 | #ifdef CONFIG_MAC80211_HT_DEBUG | 418 | #ifdef CONFIG_MAC80211_HT_DEBUG |
417 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | 419 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); |
418 | #endif | 420 | #endif |
419 | 421 | ||
420 | spin_lock(&local->ampdu_lock); | 422 | spin_lock(&local->ampdu_lock); |
@@ -440,6 +442,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
440 | struct sta_info *sta; | 442 | struct sta_info *sta; |
441 | u8 *state; | 443 | u8 *state; |
442 | 444 | ||
445 | trace_api_start_tx_ba_cb(sdata, ra, tid); | ||
446 | |||
443 | if (tid >= STA_TID_NUM) { | 447 | if (tid >= STA_TID_NUM) { |
444 | #ifdef CONFIG_MAC80211_HT_DEBUG | 448 | #ifdef CONFIG_MAC80211_HT_DEBUG |
445 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | 449 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", |
@@ -541,6 +545,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
541 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 545 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
542 | struct ieee80211_local *local = sdata->local; | 546 | struct ieee80211_local *local = sdata->local; |
543 | 547 | ||
548 | trace_api_stop_tx_ba_session(pubsta, tid, initiator); | ||
549 | |||
544 | if (!local->ops->ampdu_action) | 550 | if (!local->ops->ampdu_action) |
545 | return -EINVAL; | 551 | return -EINVAL; |
546 | 552 | ||
@@ -558,6 +564,8 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
558 | struct sta_info *sta; | 564 | struct sta_info *sta; |
559 | u8 *state; | 565 | u8 *state; |
560 | 566 | ||
567 | trace_api_stop_tx_ba_cb(sdata, ra, tid); | ||
568 | |||
561 | if (tid >= STA_TID_NUM) { | 569 | if (tid >= STA_TID_NUM) { |
562 | #ifdef CONFIG_MAC80211_HT_DEBUG | 570 | #ifdef CONFIG_MAC80211_HT_DEBUG |
563 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | 571 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", |
@@ -674,7 +682,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
674 | del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 682 | del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
675 | 683 | ||
676 | #ifdef CONFIG_MAC80211_HT_DEBUG | 684 | #ifdef CONFIG_MAC80211_HT_DEBUG |
677 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | 685 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); |
678 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 686 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
679 | 687 | ||
680 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 688 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index edc872e22c9b..c7000a6ca379 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -97,9 +97,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
97 | params->mesh_id_len, | 97 | params->mesh_id_len, |
98 | params->mesh_id); | 98 | params->mesh_id); |
99 | 99 | ||
100 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) | ||
101 | return 0; | ||
102 | |||
103 | if (type == NL80211_IFTYPE_AP_VLAN && | 100 | if (type == NL80211_IFTYPE_AP_VLAN && |
104 | params && params->use_4addr == 0) | 101 | params && params->use_4addr == 0) |
105 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | 102 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); |
@@ -107,7 +104,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
107 | params && params->use_4addr >= 0) | 104 | params && params->use_4addr >= 0) |
108 | sdata->u.mgd.use_4addr = params->use_4addr; | 105 | sdata->u.mgd.use_4addr = params->use_4addr; |
109 | 106 | ||
110 | sdata->u.mntr_flags = *flags; | 107 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) |
108 | sdata->u.mntr_flags = *flags; | ||
109 | |||
111 | return 0; | 110 | return 0; |
112 | } | 111 | } |
113 | 112 | ||
@@ -411,6 +410,17 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
411 | return ret; | 410 | return ret; |
412 | } | 411 | } |
413 | 412 | ||
413 | static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, | ||
414 | int idx, struct survey_info *survey) | ||
415 | { | ||
416 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
417 | |||
418 | if (!local->ops->get_survey) | ||
419 | return -EOPNOTSUPP; | ||
420 | |||
421 | return drv_get_survey(local, idx, survey); | ||
422 | } | ||
423 | |||
414 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 424 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
415 | u8 *mac, struct station_info *sinfo) | 425 | u8 *mac, struct station_info *sinfo) |
416 | { | 426 | { |
@@ -1104,6 +1114,13 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1104 | changed |= BSS_CHANGED_BASIC_RATES; | 1114 | changed |= BSS_CHANGED_BASIC_RATES; |
1105 | } | 1115 | } |
1106 | 1116 | ||
1117 | if (params->ap_isolate >= 0) { | ||
1118 | if (params->ap_isolate) | ||
1119 | sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS; | ||
1120 | else | ||
1121 | sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; | ||
1122 | } | ||
1123 | |||
1107 | ieee80211_bss_info_change_notify(sdata, changed); | 1124 | ieee80211_bss_info_change_notify(sdata, changed); |
1108 | 1125 | ||
1109 | return 0; | 1126 | return 0; |
@@ -1137,19 +1154,47 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1137 | return -EINVAL; | 1154 | return -EINVAL; |
1138 | } | 1155 | } |
1139 | 1156 | ||
1157 | /* enable WMM or activate new settings */ | ||
1158 | local->hw.conf.flags |= IEEE80211_CONF_QOS; | ||
1159 | drv_config(local, IEEE80211_CONF_CHANGE_QOS); | ||
1160 | |||
1140 | return 0; | 1161 | return 0; |
1141 | } | 1162 | } |
1142 | 1163 | ||
1143 | static int ieee80211_set_channel(struct wiphy *wiphy, | 1164 | static int ieee80211_set_channel(struct wiphy *wiphy, |
1165 | struct net_device *netdev, | ||
1144 | struct ieee80211_channel *chan, | 1166 | struct ieee80211_channel *chan, |
1145 | enum nl80211_channel_type channel_type) | 1167 | enum nl80211_channel_type channel_type) |
1146 | { | 1168 | { |
1147 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1169 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1170 | struct ieee80211_sub_if_data *sdata = NULL; | ||
1171 | |||
1172 | if (netdev) | ||
1173 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | ||
1174 | |||
1175 | switch (ieee80211_get_channel_mode(local, NULL)) { | ||
1176 | case CHAN_MODE_HOPPING: | ||
1177 | return -EBUSY; | ||
1178 | case CHAN_MODE_FIXED: | ||
1179 | if (local->oper_channel != chan) | ||
1180 | return -EBUSY; | ||
1181 | if (!sdata && local->_oper_channel_type == channel_type) | ||
1182 | return 0; | ||
1183 | break; | ||
1184 | case CHAN_MODE_UNDEFINED: | ||
1185 | break; | ||
1186 | } | ||
1148 | 1187 | ||
1149 | local->oper_channel = chan; | 1188 | local->oper_channel = chan; |
1150 | local->oper_channel_type = channel_type; | ||
1151 | 1189 | ||
1152 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1190 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) |
1191 | return -EBUSY; | ||
1192 | |||
1193 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
1194 | if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) | ||
1195 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); | ||
1196 | |||
1197 | return 0; | ||
1153 | } | 1198 | } |
1154 | 1199 | ||
1155 | #ifdef CONFIG_PM | 1200 | #ifdef CONFIG_PM |
@@ -1193,6 +1238,20 @@ static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, | |||
1193 | static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, | 1238 | static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, |
1194 | struct cfg80211_assoc_request *req) | 1239 | struct cfg80211_assoc_request *req) |
1195 | { | 1240 | { |
1241 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1242 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1243 | |||
1244 | switch (ieee80211_get_channel_mode(local, sdata)) { | ||
1245 | case CHAN_MODE_HOPPING: | ||
1246 | return -EBUSY; | ||
1247 | case CHAN_MODE_FIXED: | ||
1248 | if (local->oper_channel == req->bss->channel) | ||
1249 | break; | ||
1250 | return -EBUSY; | ||
1251 | case CHAN_MODE_UNDEFINED: | ||
1252 | break; | ||
1253 | } | ||
1254 | |||
1196 | return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req); | 1255 | return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req); |
1197 | } | 1256 | } |
1198 | 1257 | ||
@@ -1215,8 +1274,22 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, | |||
1215 | static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | 1274 | static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, |
1216 | struct cfg80211_ibss_params *params) | 1275 | struct cfg80211_ibss_params *params) |
1217 | { | 1276 | { |
1277 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1218 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1278 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1219 | 1279 | ||
1280 | switch (ieee80211_get_channel_mode(local, sdata)) { | ||
1281 | case CHAN_MODE_HOPPING: | ||
1282 | return -EBUSY; | ||
1283 | case CHAN_MODE_FIXED: | ||
1284 | if (!params->channel_fixed) | ||
1285 | return -EBUSY; | ||
1286 | if (local->oper_channel == params->channel) | ||
1287 | break; | ||
1288 | return -EBUSY; | ||
1289 | case CHAN_MODE_UNDEFINED: | ||
1290 | break; | ||
1291 | } | ||
1292 | |||
1220 | return ieee80211_ibss_join(sdata, params); | 1293 | return ieee80211_ibss_join(sdata, params); |
1221 | } | 1294 | } |
1222 | 1295 | ||
@@ -1345,7 +1418,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
1345 | * association, there's no need to send an action frame. | 1418 | * association, there's no need to send an action frame. |
1346 | */ | 1419 | */ |
1347 | if (!sdata->u.mgd.associated || | 1420 | if (!sdata->u.mgd.associated || |
1348 | sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) { | 1421 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { |
1349 | mutex_lock(&sdata->local->iflist_mtx); | 1422 | mutex_lock(&sdata->local->iflist_mtx); |
1350 | ieee80211_recalc_smps(sdata->local, sdata); | 1423 | ieee80211_recalc_smps(sdata->local, sdata); |
1351 | mutex_unlock(&sdata->local->iflist_mtx); | 1424 | mutex_unlock(&sdata->local->iflist_mtx); |
@@ -1384,11 +1457,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
1384 | return -EOPNOTSUPP; | 1457 | return -EOPNOTSUPP; |
1385 | 1458 | ||
1386 | if (enabled == sdata->u.mgd.powersave && | 1459 | if (enabled == sdata->u.mgd.powersave && |
1387 | timeout == conf->dynamic_ps_timeout) | 1460 | timeout == conf->dynamic_ps_forced_timeout) |
1388 | return 0; | 1461 | return 0; |
1389 | 1462 | ||
1390 | sdata->u.mgd.powersave = enabled; | 1463 | sdata->u.mgd.powersave = enabled; |
1391 | conf->dynamic_ps_timeout = timeout; | 1464 | conf->dynamic_ps_forced_timeout = timeout; |
1392 | 1465 | ||
1393 | /* no change, but if automatic follow powersave */ | 1466 | /* no change, but if automatic follow powersave */ |
1394 | mutex_lock(&sdata->u.mgd.mtx); | 1467 | mutex_lock(&sdata->u.mgd.mtx); |
@@ -1403,6 +1476,35 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
1403 | return 0; | 1476 | return 0; |
1404 | } | 1477 | } |
1405 | 1478 | ||
1479 | static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy, | ||
1480 | struct net_device *dev, | ||
1481 | s32 rssi_thold, u32 rssi_hyst) | ||
1482 | { | ||
1483 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1484 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1485 | struct ieee80211_vif *vif = &sdata->vif; | ||
1486 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
1487 | |||
1488 | if (rssi_thold == bss_conf->cqm_rssi_thold && | ||
1489 | rssi_hyst == bss_conf->cqm_rssi_hyst) | ||
1490 | return 0; | ||
1491 | |||
1492 | bss_conf->cqm_rssi_thold = rssi_thold; | ||
1493 | bss_conf->cqm_rssi_hyst = rssi_hyst; | ||
1494 | |||
1495 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | ||
1496 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1497 | return -EOPNOTSUPP; | ||
1498 | return 0; | ||
1499 | } | ||
1500 | |||
1501 | /* tell the driver upon association, unless already associated */ | ||
1502 | if (sdata->u.mgd.associated) | ||
1503 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM); | ||
1504 | |||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1406 | static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | 1508 | static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, |
1407 | struct net_device *dev, | 1509 | struct net_device *dev, |
1408 | const u8 *addr, | 1510 | const u8 *addr, |
@@ -1475,6 +1577,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1475 | .change_station = ieee80211_change_station, | 1577 | .change_station = ieee80211_change_station, |
1476 | .get_station = ieee80211_get_station, | 1578 | .get_station = ieee80211_get_station, |
1477 | .dump_station = ieee80211_dump_station, | 1579 | .dump_station = ieee80211_dump_station, |
1580 | .dump_survey = ieee80211_dump_survey, | ||
1478 | #ifdef CONFIG_MAC80211_MESH | 1581 | #ifdef CONFIG_MAC80211_MESH |
1479 | .add_mpath = ieee80211_add_mpath, | 1582 | .add_mpath = ieee80211_add_mpath, |
1480 | .del_mpath = ieee80211_del_mpath, | 1583 | .del_mpath = ieee80211_del_mpath, |
@@ -1507,4 +1610,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1507 | .remain_on_channel = ieee80211_remain_on_channel, | 1610 | .remain_on_channel = ieee80211_remain_on_channel, |
1508 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1611 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1509 | .action = ieee80211_action, | 1612 | .action = ieee80211_action, |
1613 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | ||
1510 | }; | 1614 | }; |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c new file mode 100644 index 000000000000..5d218c530a4e --- /dev/null +++ b/net/mac80211/chan.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * mac80211 - channel management | ||
3 | */ | ||
4 | |||
5 | #include <linux/nl80211.h> | ||
6 | #include "ieee80211_i.h" | ||
7 | |||
8 | enum ieee80211_chan_mode | ||
9 | __ieee80211_get_channel_mode(struct ieee80211_local *local, | ||
10 | struct ieee80211_sub_if_data *ignore) | ||
11 | { | ||
12 | struct ieee80211_sub_if_data *sdata; | ||
13 | |||
14 | WARN_ON(!mutex_is_locked(&local->iflist_mtx)); | ||
15 | |||
16 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
17 | if (sdata == ignore) | ||
18 | continue; | ||
19 | |||
20 | if (!ieee80211_sdata_running(sdata)) | ||
21 | continue; | ||
22 | |||
23 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) | ||
24 | continue; | ||
25 | |||
26 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
27 | !sdata->u.mgd.associated) | ||
28 | continue; | ||
29 | |||
30 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
31 | if (!sdata->u.ibss.ssid_len) | ||
32 | continue; | ||
33 | if (!sdata->u.ibss.fixed_channel) | ||
34 | return CHAN_MODE_HOPPING; | ||
35 | } | ||
36 | |||
37 | if (sdata->vif.type == NL80211_IFTYPE_AP && | ||
38 | !sdata->u.ap.beacon) | ||
39 | continue; | ||
40 | |||
41 | return CHAN_MODE_FIXED; | ||
42 | } | ||
43 | |||
44 | return CHAN_MODE_UNDEFINED; | ||
45 | } | ||
46 | |||
47 | enum ieee80211_chan_mode | ||
48 | ieee80211_get_channel_mode(struct ieee80211_local *local, | ||
49 | struct ieee80211_sub_if_data *ignore) | ||
50 | { | ||
51 | enum ieee80211_chan_mode mode; | ||
52 | |||
53 | mutex_lock(&local->iflist_mtx); | ||
54 | mode = __ieee80211_get_channel_mode(local, ignore); | ||
55 | mutex_unlock(&local->iflist_mtx); | ||
56 | |||
57 | return mode; | ||
58 | } | ||
59 | |||
60 | bool ieee80211_set_channel_type(struct ieee80211_local *local, | ||
61 | struct ieee80211_sub_if_data *sdata, | ||
62 | enum nl80211_channel_type chantype) | ||
63 | { | ||
64 | struct ieee80211_sub_if_data *tmp; | ||
65 | enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT; | ||
66 | bool result; | ||
67 | |||
68 | mutex_lock(&local->iflist_mtx); | ||
69 | |||
70 | list_for_each_entry(tmp, &local->interfaces, list) { | ||
71 | if (tmp == sdata) | ||
72 | continue; | ||
73 | |||
74 | if (!ieee80211_sdata_running(tmp)) | ||
75 | continue; | ||
76 | |||
77 | switch (tmp->vif.bss_conf.channel_type) { | ||
78 | case NL80211_CHAN_NO_HT: | ||
79 | case NL80211_CHAN_HT20: | ||
80 | superchan = tmp->vif.bss_conf.channel_type; | ||
81 | break; | ||
82 | case NL80211_CHAN_HT40PLUS: | ||
83 | WARN_ON(superchan == NL80211_CHAN_HT40MINUS); | ||
84 | superchan = NL80211_CHAN_HT40PLUS; | ||
85 | break; | ||
86 | case NL80211_CHAN_HT40MINUS: | ||
87 | WARN_ON(superchan == NL80211_CHAN_HT40PLUS); | ||
88 | superchan = NL80211_CHAN_HT40MINUS; | ||
89 | break; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | switch (superchan) { | ||
94 | case NL80211_CHAN_NO_HT: | ||
95 | case NL80211_CHAN_HT20: | ||
96 | /* | ||
97 | * allow any change that doesn't go to no-HT | ||
98 | * (if it already is no-HT no change is needed) | ||
99 | */ | ||
100 | if (chantype == NL80211_CHAN_NO_HT) | ||
101 | break; | ||
102 | superchan = chantype; | ||
103 | break; | ||
104 | case NL80211_CHAN_HT40PLUS: | ||
105 | case NL80211_CHAN_HT40MINUS: | ||
106 | /* allow smaller bandwidth and same */ | ||
107 | if (chantype == NL80211_CHAN_NO_HT) | ||
108 | break; | ||
109 | if (chantype == NL80211_CHAN_HT20) | ||
110 | break; | ||
111 | if (superchan == chantype) | ||
112 | break; | ||
113 | result = false; | ||
114 | goto out; | ||
115 | } | ||
116 | |||
117 | local->_oper_channel_type = superchan; | ||
118 | |||
119 | if (sdata) | ||
120 | sdata->vif.bss_conf.channel_type = chantype; | ||
121 | |||
122 | result = true; | ||
123 | out: | ||
124 | mutex_unlock(&local->iflist_mtx); | ||
125 | |||
126 | return result; | ||
127 | } | ||
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h index 68e6a2050f9a..09cc9be34796 100644 --- a/net/mac80211/debugfs.h +++ b/net/mac80211/debugfs.h | |||
@@ -7,7 +7,6 @@ extern int mac80211_open_file_generic(struct inode *inode, struct file *file); | |||
7 | #else | 7 | #else |
8 | static inline void debugfs_hw_add(struct ieee80211_local *local) | 8 | static inline void debugfs_hw_add(struct ieee80211_local *local) |
9 | { | 9 | { |
10 | return; | ||
11 | } | 10 | } |
12 | #endif | 11 | #endif |
13 | 12 | ||
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 83d4289d954b..20b2998fa0ed 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -100,6 +100,14 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
100 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ | 100 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ |
101 | } | 101 | } |
102 | 102 | ||
103 | #define IEEE80211_IF_FMT_DEC_DIV_16(name, field) \ | ||
104 | static ssize_t ieee80211_if_fmt_##name( \ | ||
105 | const struct ieee80211_sub_if_data *sdata, \ | ||
106 | char *buf, int buflen) \ | ||
107 | { \ | ||
108 | return scnprintf(buf, buflen, "%d\n", sdata->field / 16); \ | ||
109 | } | ||
110 | |||
103 | #define __IEEE80211_IF_FILE(name, _write) \ | 111 | #define __IEEE80211_IF_FILE(name, _write) \ |
104 | static ssize_t ieee80211_if_read_##name(struct file *file, \ | 112 | static ssize_t ieee80211_if_read_##name(struct file *file, \ |
105 | char __user *userbuf, \ | 113 | char __user *userbuf, \ |
@@ -140,6 +148,8 @@ IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | |||
140 | /* STA attributes */ | 148 | /* STA attributes */ |
141 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 149 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
142 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 150 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
151 | IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC); | ||
152 | IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16); | ||
143 | 153 | ||
144 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | 154 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, |
145 | enum ieee80211_smps_mode smps_mode) | 155 | enum ieee80211_smps_mode smps_mode) |
@@ -276,6 +286,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
276 | 286 | ||
277 | DEBUGFS_ADD(bssid); | 287 | DEBUGFS_ADD(bssid); |
278 | DEBUGFS_ADD(aid); | 288 | DEBUGFS_ADD(aid); |
289 | DEBUGFS_ADD(last_beacon); | ||
290 | DEBUGFS_ADD(ave_beacon); | ||
279 | DEBUGFS_ADD_MODE(smps, 0600); | 291 | DEBUGFS_ADD_MODE(smps, 0600); |
280 | } | 292 | } |
281 | 293 | ||
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index d92800bb2d2f..e763f1529ddb 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -39,6 +39,13 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
39 | .open = mac80211_open_file_generic, \ | 39 | .open = mac80211_open_file_generic, \ |
40 | } | 40 | } |
41 | 41 | ||
42 | #define STA_OPS_RW(name) \ | ||
43 | static const struct file_operations sta_ ##name## _ops = { \ | ||
44 | .read = sta_##name##_read, \ | ||
45 | .write = sta_##name##_write, \ | ||
46 | .open = mac80211_open_file_generic, \ | ||
47 | } | ||
48 | |||
42 | #define STA_FILE(name, field, format) \ | 49 | #define STA_FILE(name, field, format) \ |
43 | STA_READ_##format(name, field) \ | 50 | STA_READ_##format(name, field) \ |
44 | STA_OPS(name) | 51 | STA_OPS(name) |
@@ -57,7 +64,6 @@ STA_FILE(tx_filtered, tx_filtered_count, LU); | |||
57 | STA_FILE(tx_retry_failed, tx_retry_failed, LU); | 64 | STA_FILE(tx_retry_failed, tx_retry_failed, LU); |
58 | STA_FILE(tx_retry_count, tx_retry_count, LU); | 65 | STA_FILE(tx_retry_count, tx_retry_count, LU); |
59 | STA_FILE(last_signal, last_signal, D); | 66 | STA_FILE(last_signal, last_signal, D); |
60 | STA_FILE(last_noise, last_noise, D); | ||
61 | STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); | 67 | STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); |
62 | 68 | ||
63 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | 69 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, |
@@ -120,7 +126,7 @@ STA_OPS(last_seq_ctrl); | |||
120 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | 126 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, |
121 | size_t count, loff_t *ppos) | 127 | size_t count, loff_t *ppos) |
122 | { | 128 | { |
123 | char buf[64 + STA_TID_NUM * 40], *p = buf; | 129 | char buf[71 + STA_TID_NUM * 40], *p = buf; |
124 | int i; | 130 | int i; |
125 | struct sta_info *sta = file->private_data; | 131 | struct sta_info *sta = file->private_data; |
126 | 132 | ||
@@ -128,16 +134,16 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
128 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", | 134 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", |
129 | sta->ampdu_mlme.dialog_token_allocator + 1); | 135 | sta->ampdu_mlme.dialog_token_allocator + 1); |
130 | p += scnprintf(p, sizeof(buf) + buf - p, | 136 | p += scnprintf(p, sizeof(buf) + buf - p, |
131 | "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n"); | 137 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n"); |
132 | for (i = 0; i < STA_TID_NUM; i++) { | 138 | for (i = 0; i < STA_TID_NUM; i++) { |
133 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); | 139 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); |
134 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 140 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
135 | sta->ampdu_mlme.tid_state_rx[i]); | 141 | sta->ampdu_mlme.tid_active_rx[i]); |
136 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", | 142 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
137 | sta->ampdu_mlme.tid_state_rx[i] ? | 143 | sta->ampdu_mlme.tid_active_rx[i] ? |
138 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); | 144 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); |
139 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", | 145 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", |
140 | sta->ampdu_mlme.tid_state_rx[i] ? | 146 | sta->ampdu_mlme.tid_active_rx[i] ? |
141 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); | 147 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); |
142 | 148 | ||
143 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 149 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
@@ -157,7 +163,63 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
157 | 163 | ||
158 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | 164 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); |
159 | } | 165 | } |
160 | STA_OPS(agg_status); | 166 | |
167 | static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, | ||
168 | size_t count, loff_t *ppos) | ||
169 | { | ||
170 | char _buf[12], *buf = _buf; | ||
171 | struct sta_info *sta = file->private_data; | ||
172 | bool start, tx; | ||
173 | unsigned long tid; | ||
174 | int ret; | ||
175 | |||
176 | if (count > sizeof(_buf)) | ||
177 | return -EINVAL; | ||
178 | |||
179 | if (copy_from_user(buf, userbuf, count)) | ||
180 | return -EFAULT; | ||
181 | |||
182 | buf[sizeof(_buf) - 1] = '\0'; | ||
183 | |||
184 | if (strncmp(buf, "tx ", 3) == 0) { | ||
185 | buf += 3; | ||
186 | tx = true; | ||
187 | } else if (strncmp(buf, "rx ", 3) == 0) { | ||
188 | buf += 3; | ||
189 | tx = false; | ||
190 | } else | ||
191 | return -EINVAL; | ||
192 | |||
193 | if (strncmp(buf, "start ", 6) == 0) { | ||
194 | buf += 6; | ||
195 | start = true; | ||
196 | if (!tx) | ||
197 | return -EINVAL; | ||
198 | } else if (strncmp(buf, "stop ", 5) == 0) { | ||
199 | buf += 5; | ||
200 | start = false; | ||
201 | } else | ||
202 | return -EINVAL; | ||
203 | |||
204 | tid = simple_strtoul(buf, NULL, 0); | ||
205 | |||
206 | if (tid >= STA_TID_NUM) | ||
207 | return -EINVAL; | ||
208 | |||
209 | if (tx) { | ||
210 | if (start) | ||
211 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid); | ||
212 | else | ||
213 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid, | ||
214 | WLAN_BACK_RECIPIENT); | ||
215 | } else { | ||
216 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3); | ||
217 | ret = 0; | ||
218 | } | ||
219 | |||
220 | return ret ?: count; | ||
221 | } | ||
222 | STA_OPS_RW(agg_status); | ||
161 | 223 | ||
162 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | 224 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, |
163 | size_t count, loff_t *ppos) | 225 | size_t count, loff_t *ppos) |
@@ -177,7 +239,7 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | |||
177 | if (htc->ht_supported) { | 239 | if (htc->ht_supported) { |
178 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap); | 240 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap); |
179 | 241 | ||
180 | PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDCP"); | 242 | PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDPC"); |
181 | PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40"); | 243 | PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40"); |
182 | PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20"); | 244 | PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20"); |
183 | 245 | ||
@@ -289,7 +351,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
289 | DEBUGFS_ADD(tx_retry_failed); | 351 | DEBUGFS_ADD(tx_retry_failed); |
290 | DEBUGFS_ADD(tx_retry_count); | 352 | DEBUGFS_ADD(tx_retry_count); |
291 | DEBUGFS_ADD(last_signal); | 353 | DEBUGFS_ADD(last_signal); |
292 | DEBUGFS_ADD(last_noise); | ||
293 | DEBUGFS_ADD(wep_weak_iv_count); | 354 | DEBUGFS_ADD(wep_weak_iv_count); |
294 | DEBUGFS_ADD(ht_capa); | 355 | DEBUGFS_ADD(ht_capa); |
295 | } | 356 | } |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index c3d844093a2f..4f2271316650 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -84,16 +84,14 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
84 | } | 84 | } |
85 | 85 | ||
86 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | 86 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, |
87 | int mc_count, | 87 | struct netdev_hw_addr_list *mc_list) |
88 | struct dev_addr_list *mc_list) | ||
89 | { | 88 | { |
90 | u64 ret = 0; | 89 | u64 ret = 0; |
91 | 90 | ||
92 | if (local->ops->prepare_multicast) | 91 | if (local->ops->prepare_multicast) |
93 | ret = local->ops->prepare_multicast(&local->hw, mc_count, | 92 | ret = local->ops->prepare_multicast(&local->hw, mc_list); |
94 | mc_list); | ||
95 | 93 | ||
96 | trace_drv_prepare_multicast(local, mc_count, ret); | 94 | trace_drv_prepare_multicast(local, mc_list->count, ret); |
97 | 95 | ||
98 | return ret; | 96 | return ret; |
99 | } | 97 | } |
@@ -154,14 +152,15 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
154 | } | 152 | } |
155 | 153 | ||
156 | static inline int drv_hw_scan(struct ieee80211_local *local, | 154 | static inline int drv_hw_scan(struct ieee80211_local *local, |
155 | struct ieee80211_sub_if_data *sdata, | ||
157 | struct cfg80211_scan_request *req) | 156 | struct cfg80211_scan_request *req) |
158 | { | 157 | { |
159 | int ret; | 158 | int ret; |
160 | 159 | ||
161 | might_sleep(); | 160 | might_sleep(); |
162 | 161 | ||
163 | ret = local->ops->hw_scan(&local->hw, req); | 162 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); |
164 | trace_drv_hw_scan(local, req, ret); | 163 | trace_drv_hw_scan(local, sdata, req, ret); |
165 | return ret; | 164 | return ret; |
166 | } | 165 | } |
167 | 166 | ||
@@ -346,6 +345,15 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
346 | return ret; | 345 | return ret; |
347 | } | 346 | } |
348 | 347 | ||
348 | static inline int drv_get_survey(struct ieee80211_local *local, int idx, | ||
349 | struct survey_info *survey) | ||
350 | { | ||
351 | int ret = -EOPNOTSUPP; | ||
352 | if (local->ops->conf_tx) | ||
353 | ret = local->ops->get_survey(&local->hw, idx, survey); | ||
354 | /* trace_drv_get_survey(local, idx, survey, ret); */ | ||
355 | return ret; | ||
356 | } | ||
349 | 357 | ||
350 | static inline void drv_rfkill_poll(struct ieee80211_local *local) | 358 | static inline void drv_rfkill_poll(struct ieee80211_local *local) |
351 | { | 359 | { |
@@ -363,4 +371,15 @@ static inline void drv_flush(struct ieee80211_local *local, bool drop) | |||
363 | if (local->ops->flush) | 371 | if (local->ops->flush) |
364 | local->ops->flush(&local->hw, drop); | 372 | local->ops->flush(&local->hw, drop); |
365 | } | 373 | } |
374 | |||
375 | static inline void drv_channel_switch(struct ieee80211_local *local, | ||
376 | struct ieee80211_channel_switch *ch_switch) | ||
377 | { | ||
378 | might_sleep(); | ||
379 | |||
380 | local->ops->channel_switch(&local->hw, ch_switch); | ||
381 | |||
382 | trace_drv_channel_switch(local, ch_switch); | ||
383 | } | ||
384 | |||
366 | #endif /* __MAC80211_DRIVER_OPS */ | 385 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 41baf730a5c7..6a9b2342a9c2 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -32,6 +32,10 @@ static inline void trace_ ## name(proto) {} | |||
32 | #define VIF_PR_FMT " vif:%s(%d)" | 32 | #define VIF_PR_FMT " vif:%s(%d)" |
33 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type | 33 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type |
34 | 34 | ||
35 | /* | ||
36 | * Tracing for driver callbacks. | ||
37 | */ | ||
38 | |||
35 | TRACE_EVENT(drv_start, | 39 | TRACE_EVENT(drv_start, |
36 | TP_PROTO(struct ieee80211_local *local, int ret), | 40 | TP_PROTO(struct ieee80211_local *local, int ret), |
37 | 41 | ||
@@ -359,23 +363,26 @@ TRACE_EVENT(drv_update_tkip_key, | |||
359 | 363 | ||
360 | TRACE_EVENT(drv_hw_scan, | 364 | TRACE_EVENT(drv_hw_scan, |
361 | TP_PROTO(struct ieee80211_local *local, | 365 | TP_PROTO(struct ieee80211_local *local, |
366 | struct ieee80211_sub_if_data *sdata, | ||
362 | struct cfg80211_scan_request *req, int ret), | 367 | struct cfg80211_scan_request *req, int ret), |
363 | 368 | ||
364 | TP_ARGS(local, req, ret), | 369 | TP_ARGS(local, sdata, req, ret), |
365 | 370 | ||
366 | TP_STRUCT__entry( | 371 | TP_STRUCT__entry( |
367 | LOCAL_ENTRY | 372 | LOCAL_ENTRY |
373 | VIF_ENTRY | ||
368 | __field(int, ret) | 374 | __field(int, ret) |
369 | ), | 375 | ), |
370 | 376 | ||
371 | TP_fast_assign( | 377 | TP_fast_assign( |
372 | LOCAL_ASSIGN; | 378 | LOCAL_ASSIGN; |
379 | VIF_ASSIGN; | ||
373 | __entry->ret = ret; | 380 | __entry->ret = ret; |
374 | ), | 381 | ), |
375 | 382 | ||
376 | TP_printk( | 383 | TP_printk( |
377 | LOCAL_PR_FMT " ret:%d", | 384 | LOCAL_PR_FMT VIF_PR_FMT " ret:%d", |
378 | LOCAL_PR_ARG, __entry->ret | 385 | LOCAL_PR_ARG,VIF_PR_ARG, __entry->ret |
379 | ) | 386 | ) |
380 | ); | 387 | ); |
381 | 388 | ||
@@ -766,6 +773,326 @@ TRACE_EVENT(drv_flush, | |||
766 | LOCAL_PR_ARG, __entry->drop | 773 | LOCAL_PR_ARG, __entry->drop |
767 | ) | 774 | ) |
768 | ); | 775 | ); |
776 | |||
777 | TRACE_EVENT(drv_channel_switch, | ||
778 | TP_PROTO(struct ieee80211_local *local, | ||
779 | struct ieee80211_channel_switch *ch_switch), | ||
780 | |||
781 | TP_ARGS(local, ch_switch), | ||
782 | |||
783 | TP_STRUCT__entry( | ||
784 | LOCAL_ENTRY | ||
785 | __field(u64, timestamp) | ||
786 | __field(bool, block_tx) | ||
787 | __field(u16, freq) | ||
788 | __field(u8, count) | ||
789 | ), | ||
790 | |||
791 | TP_fast_assign( | ||
792 | LOCAL_ASSIGN; | ||
793 | __entry->timestamp = ch_switch->timestamp; | ||
794 | __entry->block_tx = ch_switch->block_tx; | ||
795 | __entry->freq = ch_switch->channel->center_freq; | ||
796 | __entry->count = ch_switch->count; | ||
797 | ), | ||
798 | |||
799 | TP_printk( | ||
800 | LOCAL_PR_FMT " new freq:%u count:%d", | ||
801 | LOCAL_PR_ARG, __entry->freq, __entry->count | ||
802 | ) | ||
803 | ); | ||
804 | |||
805 | /* | ||
806 | * Tracing for API calls that drivers call. | ||
807 | */ | ||
808 | |||
809 | TRACE_EVENT(api_start_tx_ba_session, | ||
810 | TP_PROTO(struct ieee80211_sta *sta, u16 tid), | ||
811 | |||
812 | TP_ARGS(sta, tid), | ||
813 | |||
814 | TP_STRUCT__entry( | ||
815 | STA_ENTRY | ||
816 | __field(u16, tid) | ||
817 | ), | ||
818 | |||
819 | TP_fast_assign( | ||
820 | STA_ASSIGN; | ||
821 | __entry->tid = tid; | ||
822 | ), | ||
823 | |||
824 | TP_printk( | ||
825 | STA_PR_FMT " tid:%d", | ||
826 | STA_PR_ARG, __entry->tid | ||
827 | ) | ||
828 | ); | ||
829 | |||
830 | TRACE_EVENT(api_start_tx_ba_cb, | ||
831 | TP_PROTO(struct ieee80211_sub_if_data *sdata, const u8 *ra, u16 tid), | ||
832 | |||
833 | TP_ARGS(sdata, ra, tid), | ||
834 | |||
835 | TP_STRUCT__entry( | ||
836 | VIF_ENTRY | ||
837 | __array(u8, ra, ETH_ALEN) | ||
838 | __field(u16, tid) | ||
839 | ), | ||
840 | |||
841 | TP_fast_assign( | ||
842 | VIF_ASSIGN; | ||
843 | memcpy(__entry->ra, ra, ETH_ALEN); | ||
844 | __entry->tid = tid; | ||
845 | ), | ||
846 | |||
847 | TP_printk( | ||
848 | VIF_PR_FMT " ra:%pM tid:%d", | ||
849 | VIF_PR_ARG, __entry->ra, __entry->tid | ||
850 | ) | ||
851 | ); | ||
852 | |||
853 | TRACE_EVENT(api_stop_tx_ba_session, | ||
854 | TP_PROTO(struct ieee80211_sta *sta, u16 tid, u16 initiator), | ||
855 | |||
856 | TP_ARGS(sta, tid, initiator), | ||
857 | |||
858 | TP_STRUCT__entry( | ||
859 | STA_ENTRY | ||
860 | __field(u16, tid) | ||
861 | __field(u16, initiator) | ||
862 | ), | ||
863 | |||
864 | TP_fast_assign( | ||
865 | STA_ASSIGN; | ||
866 | __entry->tid = tid; | ||
867 | __entry->initiator = initiator; | ||
868 | ), | ||
869 | |||
870 | TP_printk( | ||
871 | STA_PR_FMT " tid:%d initiator:%d", | ||
872 | STA_PR_ARG, __entry->tid, __entry->initiator | ||
873 | ) | ||
874 | ); | ||
875 | |||
876 | TRACE_EVENT(api_stop_tx_ba_cb, | ||
877 | TP_PROTO(struct ieee80211_sub_if_data *sdata, const u8 *ra, u16 tid), | ||
878 | |||
879 | TP_ARGS(sdata, ra, tid), | ||
880 | |||
881 | TP_STRUCT__entry( | ||
882 | VIF_ENTRY | ||
883 | __array(u8, ra, ETH_ALEN) | ||
884 | __field(u16, tid) | ||
885 | ), | ||
886 | |||
887 | TP_fast_assign( | ||
888 | VIF_ASSIGN; | ||
889 | memcpy(__entry->ra, ra, ETH_ALEN); | ||
890 | __entry->tid = tid; | ||
891 | ), | ||
892 | |||
893 | TP_printk( | ||
894 | VIF_PR_FMT " ra:%pM tid:%d", | ||
895 | VIF_PR_ARG, __entry->ra, __entry->tid | ||
896 | ) | ||
897 | ); | ||
898 | |||
899 | TRACE_EVENT(api_restart_hw, | ||
900 | TP_PROTO(struct ieee80211_local *local), | ||
901 | |||
902 | TP_ARGS(local), | ||
903 | |||
904 | TP_STRUCT__entry( | ||
905 | LOCAL_ENTRY | ||
906 | ), | ||
907 | |||
908 | TP_fast_assign( | ||
909 | LOCAL_ASSIGN; | ||
910 | ), | ||
911 | |||
912 | TP_printk( | ||
913 | LOCAL_PR_FMT, | ||
914 | LOCAL_PR_ARG | ||
915 | ) | ||
916 | ); | ||
917 | |||
918 | TRACE_EVENT(api_beacon_loss, | ||
919 | TP_PROTO(struct ieee80211_sub_if_data *sdata), | ||
920 | |||
921 | TP_ARGS(sdata), | ||
922 | |||
923 | TP_STRUCT__entry( | ||
924 | VIF_ENTRY | ||
925 | ), | ||
926 | |||
927 | TP_fast_assign( | ||
928 | VIF_ASSIGN; | ||
929 | ), | ||
930 | |||
931 | TP_printk( | ||
932 | VIF_PR_FMT, | ||
933 | VIF_PR_ARG | ||
934 | ) | ||
935 | ); | ||
936 | |||
937 | TRACE_EVENT(api_connection_loss, | ||
938 | TP_PROTO(struct ieee80211_sub_if_data *sdata), | ||
939 | |||
940 | TP_ARGS(sdata), | ||
941 | |||
942 | TP_STRUCT__entry( | ||
943 | VIF_ENTRY | ||
944 | ), | ||
945 | |||
946 | TP_fast_assign( | ||
947 | VIF_ASSIGN; | ||
948 | ), | ||
949 | |||
950 | TP_printk( | ||
951 | VIF_PR_FMT, | ||
952 | VIF_PR_ARG | ||
953 | ) | ||
954 | ); | ||
955 | |||
956 | TRACE_EVENT(api_cqm_rssi_notify, | ||
957 | TP_PROTO(struct ieee80211_sub_if_data *sdata, | ||
958 | enum nl80211_cqm_rssi_threshold_event rssi_event), | ||
959 | |||
960 | TP_ARGS(sdata, rssi_event), | ||
961 | |||
962 | TP_STRUCT__entry( | ||
963 | VIF_ENTRY | ||
964 | __field(u32, rssi_event) | ||
965 | ), | ||
966 | |||
967 | TP_fast_assign( | ||
968 | VIF_ASSIGN; | ||
969 | __entry->rssi_event = rssi_event; | ||
970 | ), | ||
971 | |||
972 | TP_printk( | ||
973 | VIF_PR_FMT " event:%d", | ||
974 | VIF_PR_ARG, __entry->rssi_event | ||
975 | ) | ||
976 | ); | ||
977 | |||
978 | TRACE_EVENT(api_scan_completed, | ||
979 | TP_PROTO(struct ieee80211_local *local, bool aborted), | ||
980 | |||
981 | TP_ARGS(local, aborted), | ||
982 | |||
983 | TP_STRUCT__entry( | ||
984 | LOCAL_ENTRY | ||
985 | __field(bool, aborted) | ||
986 | ), | ||
987 | |||
988 | TP_fast_assign( | ||
989 | LOCAL_ASSIGN; | ||
990 | __entry->aborted = aborted; | ||
991 | ), | ||
992 | |||
993 | TP_printk( | ||
994 | LOCAL_PR_FMT " aborted:%d", | ||
995 | LOCAL_PR_ARG, __entry->aborted | ||
996 | ) | ||
997 | ); | ||
998 | |||
999 | TRACE_EVENT(api_sta_block_awake, | ||
1000 | TP_PROTO(struct ieee80211_local *local, | ||
1001 | struct ieee80211_sta *sta, bool block), | ||
1002 | |||
1003 | TP_ARGS(local, sta, block), | ||
1004 | |||
1005 | TP_STRUCT__entry( | ||
1006 | LOCAL_ENTRY | ||
1007 | STA_ENTRY | ||
1008 | __field(bool, block) | ||
1009 | ), | ||
1010 | |||
1011 | TP_fast_assign( | ||
1012 | LOCAL_ASSIGN; | ||
1013 | STA_ASSIGN; | ||
1014 | __entry->block = block; | ||
1015 | ), | ||
1016 | |||
1017 | TP_printk( | ||
1018 | LOCAL_PR_FMT STA_PR_FMT " block:%d", | ||
1019 | LOCAL_PR_ARG, STA_PR_FMT, __entry->block | ||
1020 | ) | ||
1021 | ); | ||
1022 | |||
1023 | TRACE_EVENT(api_chswitch_done, | ||
1024 | TP_PROTO(struct ieee80211_sub_if_data *sdata, bool success), | ||
1025 | |||
1026 | TP_ARGS(sdata, success), | ||
1027 | |||
1028 | TP_STRUCT__entry( | ||
1029 | VIF_ENTRY | ||
1030 | __field(bool, success) | ||
1031 | ), | ||
1032 | |||
1033 | TP_fast_assign( | ||
1034 | VIF_ASSIGN; | ||
1035 | __entry->success = success; | ||
1036 | ), | ||
1037 | |||
1038 | TP_printk( | ||
1039 | VIF_PR_FMT " success=%d", | ||
1040 | VIF_PR_ARG, __entry->success | ||
1041 | ) | ||
1042 | ); | ||
1043 | |||
1044 | /* | ||
1045 | * Tracing for internal functions | ||
1046 | * (which may also be called in response to driver calls) | ||
1047 | */ | ||
1048 | |||
1049 | TRACE_EVENT(wake_queue, | ||
1050 | TP_PROTO(struct ieee80211_local *local, u16 queue, | ||
1051 | enum queue_stop_reason reason), | ||
1052 | |||
1053 | TP_ARGS(local, queue, reason), | ||
1054 | |||
1055 | TP_STRUCT__entry( | ||
1056 | LOCAL_ENTRY | ||
1057 | __field(u16, queue) | ||
1058 | __field(u32, reason) | ||
1059 | ), | ||
1060 | |||
1061 | TP_fast_assign( | ||
1062 | LOCAL_ASSIGN; | ||
1063 | __entry->queue = queue; | ||
1064 | __entry->reason = reason; | ||
1065 | ), | ||
1066 | |||
1067 | TP_printk( | ||
1068 | LOCAL_PR_FMT " queue:%d, reason:%d", | ||
1069 | LOCAL_PR_ARG, __entry->queue, __entry->reason | ||
1070 | ) | ||
1071 | ); | ||
1072 | |||
1073 | TRACE_EVENT(stop_queue, | ||
1074 | TP_PROTO(struct ieee80211_local *local, u16 queue, | ||
1075 | enum queue_stop_reason reason), | ||
1076 | |||
1077 | TP_ARGS(local, queue, reason), | ||
1078 | |||
1079 | TP_STRUCT__entry( | ||
1080 | LOCAL_ENTRY | ||
1081 | __field(u16, queue) | ||
1082 | __field(u32, reason) | ||
1083 | ), | ||
1084 | |||
1085 | TP_fast_assign( | ||
1086 | LOCAL_ASSIGN; | ||
1087 | __entry->queue = queue; | ||
1088 | __entry->reason = reason; | ||
1089 | ), | ||
1090 | |||
1091 | TP_printk( | ||
1092 | LOCAL_PR_FMT " queue:%d, reason:%d", | ||
1093 | LOCAL_PR_ARG, __entry->queue, __entry->reason | ||
1094 | ) | ||
1095 | ); | ||
769 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ | 1096 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ |
770 | 1097 | ||
771 | #undef TRACE_INCLUDE_PATH | 1098 | #undef TRACE_INCLUDE_PATH |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index bb677a73b7c9..2ab106a0a491 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -175,8 +175,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
175 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 175 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
176 | 176 | ||
177 | if (initiator == WLAN_BACK_INITIATOR) | 177 | if (initiator == WLAN_BACK_INITIATOR) |
178 | ieee80211_sta_stop_rx_ba_session(sdata, sta->sta.addr, tid, | 178 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0); |
179 | WLAN_BACK_INITIATOR, 0); | ||
180 | else { /* WLAN_BACK_RECIPIENT */ | 179 | else { /* WLAN_BACK_RECIPIENT */ |
181 | spin_lock_bh(&sta->lock); | 180 | spin_lock_bh(&sta->lock); |
182 | if (sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK) | 181 | if (sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK) |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index e2976da4e0d9..b2cc1fda6cfd 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -92,12 +92,18 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
92 | if (memcmp(ifibss->bssid, bssid, ETH_ALEN)) | 92 | if (memcmp(ifibss->bssid, bssid, ETH_ALEN)) |
93 | sta_info_flush(sdata->local, sdata); | 93 | sta_info_flush(sdata->local, sdata); |
94 | 94 | ||
95 | /* if merging, indicate to driver that we leave the old IBSS */ | ||
96 | if (sdata->vif.bss_conf.ibss_joined) { | ||
97 | sdata->vif.bss_conf.ibss_joined = false; | ||
98 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS); | ||
99 | } | ||
100 | |||
95 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | 101 | memcpy(ifibss->bssid, bssid, ETH_ALEN); |
96 | 102 | ||
97 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 103 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
98 | 104 | ||
99 | local->oper_channel = chan; | 105 | local->oper_channel = chan; |
100 | local->oper_channel_type = NL80211_CHAN_NO_HT; | 106 | WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); |
101 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 107 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
102 | 108 | ||
103 | sband = local->hw.wiphy->bands[chan->band]; | 109 | sband = local->hw.wiphy->bands[chan->band]; |
@@ -171,6 +177,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
171 | bss_change |= BSS_CHANGED_BSSID; | 177 | bss_change |= BSS_CHANGED_BSSID; |
172 | bss_change |= BSS_CHANGED_BEACON; | 178 | bss_change |= BSS_CHANGED_BEACON; |
173 | bss_change |= BSS_CHANGED_BEACON_ENABLED; | 179 | bss_change |= BSS_CHANGED_BEACON_ENABLED; |
180 | bss_change |= BSS_CHANGED_IBSS; | ||
181 | sdata->vif.bss_conf.ibss_joined = true; | ||
174 | ieee80211_bss_info_change_notify(sdata, bss_change); | 182 | ieee80211_bss_info_change_notify(sdata, bss_change); |
175 | 183 | ||
176 | ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); | 184 | ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); |
@@ -265,17 +273,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
265 | sta->sta.supp_rates[band] = supp_rates | | 273 | sta->sta.supp_rates[band] = supp_rates | |
266 | ieee80211_mandatory_rates(local, band); | 274 | ieee80211_mandatory_rates(local, band); |
267 | 275 | ||
276 | if (sta->sta.supp_rates[band] != prev_rates) { | ||
268 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 277 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
269 | if (sta->sta.supp_rates[band] != prev_rates) | ||
270 | printk(KERN_DEBUG "%s: updated supp_rates set " | 278 | printk(KERN_DEBUG "%s: updated supp_rates set " |
271 | "for %pM based on beacon info (0x%llx | " | 279 | "for %pM based on beacon/probe_response " |
272 | "0x%llx -> 0x%llx)\n", | 280 | "(0x%x -> 0x%x)\n", |
273 | sdata->name, | 281 | sdata->name, sta->sta.addr, |
274 | sta->sta.addr, | 282 | prev_rates, sta->sta.supp_rates[band]); |
275 | (unsigned long long) prev_rates, | ||
276 | (unsigned long long) supp_rates, | ||
277 | (unsigned long long) sta->sta.supp_rates[band]); | ||
278 | #endif | 283 | #endif |
284 | rate_control_rate_init(sta); | ||
285 | } | ||
279 | rcu_read_unlock(); | 286 | rcu_read_unlock(); |
280 | } else { | 287 | } else { |
281 | rcu_read_unlock(); | 288 | rcu_read_unlock(); |
@@ -371,6 +378,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
371 | sdata->name, mgmt->bssid); | 378 | sdata->name, mgmt->bssid); |
372 | #endif | 379 | #endif |
373 | ieee80211_sta_join_ibss(sdata, bss); | 380 | ieee80211_sta_join_ibss(sdata, bss); |
381 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | ||
374 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 382 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
375 | supp_rates, GFP_KERNEL); | 383 | supp_rates, GFP_KERNEL); |
376 | } | 384 | } |
@@ -481,7 +489,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
481 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 489 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " |
482 | "IBSS networks with same SSID (merge)\n", sdata->name); | 490 | "IBSS networks with same SSID (merge)\n", sdata->name); |
483 | 491 | ||
484 | ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); | 492 | ieee80211_request_internal_scan(sdata, |
493 | ifibss->ssid, ifibss->ssid_len, | ||
494 | ifibss->fixed_channel ? ifibss->channel : NULL); | ||
485 | } | 495 | } |
486 | 496 | ||
487 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 497 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -588,8 +598,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
588 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 598 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " |
589 | "join\n", sdata->name); | 599 | "join\n", sdata->name); |
590 | 600 | ||
591 | ieee80211_request_internal_scan(sdata, ifibss->ssid, | 601 | ieee80211_request_internal_scan(sdata, |
592 | ifibss->ssid_len); | 602 | ifibss->ssid, ifibss->ssid_len, |
603 | ifibss->fixed_channel ? ifibss->channel : NULL); | ||
593 | } else { | 604 | } else { |
594 | int interval = IEEE80211_SCAN_INTERVAL; | 605 | int interval = IEEE80211_SCAN_INTERVAL; |
595 | 606 | ||
@@ -897,6 +908,13 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
897 | sdata->u.ibss.channel = params->channel; | 908 | sdata->u.ibss.channel = params->channel; |
898 | sdata->u.ibss.fixed_channel = params->channel_fixed; | 909 | sdata->u.ibss.fixed_channel = params->channel_fixed; |
899 | 910 | ||
911 | /* fix ourselves to that channel now already */ | ||
912 | if (params->channel_fixed) { | ||
913 | sdata->local->oper_channel = params->channel; | ||
914 | WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata, | ||
915 | NL80211_CHAN_NO_HT)); | ||
916 | } | ||
917 | |||
900 | if (params->ie) { | 918 | if (params->ie) { |
901 | sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, | 919 | sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, |
902 | GFP_KERNEL); | 920 | GFP_KERNEL); |
@@ -951,7 +969,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
951 | kfree(sdata->u.ibss.ie); | 969 | kfree(sdata->u.ibss.ie); |
952 | skb = sdata->u.ibss.presp; | 970 | skb = sdata->u.ibss.presp; |
953 | rcu_assign_pointer(sdata->u.ibss.presp, NULL); | 971 | rcu_assign_pointer(sdata->u.ibss.presp, NULL); |
954 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 972 | sdata->vif.bss_conf.ibss_joined = false; |
973 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | ||
974 | BSS_CHANGED_IBSS); | ||
955 | synchronize_rcu(); | 975 | synchronize_rcu(); |
956 | kfree_skb(skb); | 976 | kfree_skb(skb); |
957 | 977 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 241533e1bc03..1a9e2da37a93 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -317,6 +317,7 @@ enum ieee80211_sta_flags { | |||
317 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 317 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
318 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), | 318 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
319 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | 319 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), |
320 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), | ||
320 | }; | 321 | }; |
321 | 322 | ||
322 | struct ieee80211_if_managed { | 323 | struct ieee80211_if_managed { |
@@ -327,7 +328,7 @@ struct ieee80211_if_managed { | |||
327 | struct work_struct work; | 328 | struct work_struct work; |
328 | struct work_struct monitor_work; | 329 | struct work_struct monitor_work; |
329 | struct work_struct chswitch_work; | 330 | struct work_struct chswitch_work; |
330 | struct work_struct beacon_loss_work; | 331 | struct work_struct beacon_connection_loss_work; |
331 | 332 | ||
332 | unsigned long probe_timeout; | 333 | unsigned long probe_timeout; |
333 | int probe_send_count; | 334 | int probe_send_count; |
@@ -359,6 +360,24 @@ struct ieee80211_if_managed { | |||
359 | int wmm_last_param_set; | 360 | int wmm_last_param_set; |
360 | 361 | ||
361 | u8 use_4addr; | 362 | u8 use_4addr; |
363 | |||
364 | /* Signal strength from the last Beacon frame in the current BSS. */ | ||
365 | int last_beacon_signal; | ||
366 | |||
367 | /* | ||
368 | * Weighted average of the signal strength from Beacon frames in the | ||
369 | * current BSS. This is in units of 1/16 of the signal unit to maintain | ||
370 | * accuracy and to speed up calculations, i.e., the value need to be | ||
371 | * divided by 16 to get the actual value. | ||
372 | */ | ||
373 | int ave_beacon_signal; | ||
374 | |||
375 | /* | ||
376 | * Last Beacon frame signal strength average (ave_beacon_signal / 16) | ||
377 | * that triggered a cqm event. 0 indicates that no event has been | ||
378 | * generated for the current association. | ||
379 | */ | ||
380 | int last_cqm_event_signal; | ||
362 | }; | 381 | }; |
363 | 382 | ||
364 | enum ieee80211_ibss_request { | 383 | enum ieee80211_ibss_request { |
@@ -646,8 +665,7 @@ struct ieee80211_local { | |||
646 | struct work_struct recalc_smps; | 665 | struct work_struct recalc_smps; |
647 | 666 | ||
648 | /* aggregated multicast list */ | 667 | /* aggregated multicast list */ |
649 | struct dev_addr_list *mc_list; | 668 | struct netdev_hw_addr_list mc_list; |
650 | int mc_count; | ||
651 | 669 | ||
652 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ | 670 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ |
653 | 671 | ||
@@ -745,10 +763,11 @@ struct ieee80211_local { | |||
745 | int scan_channel_idx; | 763 | int scan_channel_idx; |
746 | int scan_ies_len; | 764 | int scan_ies_len; |
747 | 765 | ||
766 | unsigned long leave_oper_channel_time; | ||
748 | enum mac80211_scan_state next_scan_state; | 767 | enum mac80211_scan_state next_scan_state; |
749 | struct delayed_work scan_work; | 768 | struct delayed_work scan_work; |
750 | struct ieee80211_sub_if_data *scan_sdata; | 769 | struct ieee80211_sub_if_data *scan_sdata; |
751 | enum nl80211_channel_type oper_channel_type; | 770 | enum nl80211_channel_type _oper_channel_type; |
752 | struct ieee80211_channel *oper_channel, *csa_channel; | 771 | struct ieee80211_channel *oper_channel, *csa_channel; |
753 | 772 | ||
754 | /* Temporary remain-on-channel for off-channel operations */ | 773 | /* Temporary remain-on-channel for off-channel operations */ |
@@ -979,7 +998,8 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
979 | unsigned long data, void *dummy); | 998 | unsigned long data, void *dummy); |
980 | void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 999 | void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
981 | struct ieee80211_channel_sw_ie *sw_elem, | 1000 | struct ieee80211_channel_sw_ie *sw_elem, |
982 | struct ieee80211_bss *bss); | 1001 | struct ieee80211_bss *bss, |
1002 | u64 timestamp); | ||
983 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); | 1003 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); |
984 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | 1004 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); |
985 | 1005 | ||
@@ -1000,7 +1020,8 @@ void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); | |||
1000 | /* scan/BSS handling */ | 1020 | /* scan/BSS handling */ |
1001 | void ieee80211_scan_work(struct work_struct *work); | 1021 | void ieee80211_scan_work(struct work_struct *work); |
1002 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | 1022 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, |
1003 | const u8 *ssid, u8 ssid_len); | 1023 | const u8 *ssid, u8 ssid_len, |
1024 | struct ieee80211_channel *chan); | ||
1004 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 1025 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
1005 | struct cfg80211_scan_request *req); | 1026 | struct cfg80211_scan_request *req); |
1006 | void ieee80211_scan_cancel(struct ieee80211_local *local); | 1027 | void ieee80211_scan_cancel(struct ieee80211_local *local); |
@@ -1078,8 +1099,6 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
1078 | enum ieee80211_smps_mode smps, const u8 *da, | 1099 | enum ieee80211_smps_mode smps, const u8 *da, |
1079 | const u8 *bssid); | 1100 | const u8 *bssid); |
1080 | 1101 | ||
1081 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | ||
1082 | u16 tid, u16 initiator, u16 reason); | ||
1083 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1102 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1084 | u16 initiator, u16 reason); | 1103 | u16 initiator, u16 reason); |
1085 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); | 1104 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); |
@@ -1155,7 +1174,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
1155 | int powersave); | 1174 | int powersave); |
1156 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1175 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1157 | struct ieee80211_hdr *hdr); | 1176 | struct ieee80211_hdr *hdr); |
1158 | void ieee80211_beacon_loss_work(struct work_struct *work); | 1177 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); |
1159 | 1178 | ||
1160 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1179 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1161 | enum queue_stop_reason reason); | 1180 | enum queue_stop_reason reason); |
@@ -1210,6 +1229,20 @@ int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | |||
1210 | int ieee80211_wk_cancel_remain_on_channel( | 1229 | int ieee80211_wk_cancel_remain_on_channel( |
1211 | struct ieee80211_sub_if_data *sdata, u64 cookie); | 1230 | struct ieee80211_sub_if_data *sdata, u64 cookie); |
1212 | 1231 | ||
1232 | /* channel management */ | ||
1233 | enum ieee80211_chan_mode { | ||
1234 | CHAN_MODE_UNDEFINED, | ||
1235 | CHAN_MODE_HOPPING, | ||
1236 | CHAN_MODE_FIXED, | ||
1237 | }; | ||
1238 | |||
1239 | enum ieee80211_chan_mode | ||
1240 | ieee80211_get_channel_mode(struct ieee80211_local *local, | ||
1241 | struct ieee80211_sub_if_data *ignore); | ||
1242 | bool ieee80211_set_channel_type(struct ieee80211_local *local, | ||
1243 | struct ieee80211_sub_if_data *sdata, | ||
1244 | enum nl80211_channel_type chantype); | ||
1245 | |||
1213 | #ifdef CONFIG_MAC80211_NOINLINE | 1246 | #ifdef CONFIG_MAC80211_NOINLINE |
1214 | #define debug_noinline noinline | 1247 | #define debug_noinline noinline |
1215 | #else | 1248 | #else |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index e08fa8eda1b3..50deb017fd6e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -413,8 +413,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
413 | 413 | ||
414 | netif_addr_lock_bh(dev); | 414 | netif_addr_lock_bh(dev); |
415 | spin_lock_bh(&local->filter_lock); | 415 | spin_lock_bh(&local->filter_lock); |
416 | __dev_addr_unsync(&local->mc_list, &local->mc_count, | 416 | __hw_addr_unsync(&local->mc_list, &dev->mc, dev->addr_len); |
417 | &dev->mc_list, &dev->mc_count); | ||
418 | spin_unlock_bh(&local->filter_lock); | 417 | spin_unlock_bh(&local->filter_lock); |
419 | netif_addr_unlock_bh(dev); | 418 | netif_addr_unlock_bh(dev); |
420 | 419 | ||
@@ -487,7 +486,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
487 | cancel_work_sync(&sdata->u.mgd.work); | 486 | cancel_work_sync(&sdata->u.mgd.work); |
488 | cancel_work_sync(&sdata->u.mgd.chswitch_work); | 487 | cancel_work_sync(&sdata->u.mgd.chswitch_work); |
489 | cancel_work_sync(&sdata->u.mgd.monitor_work); | 488 | cancel_work_sync(&sdata->u.mgd.monitor_work); |
490 | cancel_work_sync(&sdata->u.mgd.beacon_loss_work); | 489 | cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work); |
491 | 490 | ||
492 | /* | 491 | /* |
493 | * When we get here, the interface is marked down. | 492 | * When we get here, the interface is marked down. |
@@ -597,8 +596,7 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
597 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 596 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
598 | } | 597 | } |
599 | spin_lock_bh(&local->filter_lock); | 598 | spin_lock_bh(&local->filter_lock); |
600 | __dev_addr_sync(&local->mc_list, &local->mc_count, | 599 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); |
601 | &dev->mc_list, &dev->mc_count); | ||
602 | spin_unlock_bh(&local->filter_lock); | 600 | spin_unlock_bh(&local->filter_lock); |
603 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); | 601 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); |
604 | } | 602 | } |
@@ -816,6 +814,118 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
816 | return 0; | 814 | return 0; |
817 | } | 815 | } |
818 | 816 | ||
817 | static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | ||
818 | struct net_device *dev, | ||
819 | enum nl80211_iftype type) | ||
820 | { | ||
821 | struct ieee80211_sub_if_data *sdata; | ||
822 | u64 mask, start, addr, val, inc; | ||
823 | u8 *m; | ||
824 | u8 tmp_addr[ETH_ALEN]; | ||
825 | int i; | ||
826 | |||
827 | /* default ... something at least */ | ||
828 | memcpy(dev->perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | ||
829 | |||
830 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && | ||
831 | local->hw.wiphy->n_addresses <= 1) | ||
832 | return; | ||
833 | |||
834 | |||
835 | mutex_lock(&local->iflist_mtx); | ||
836 | |||
837 | switch (type) { | ||
838 | case NL80211_IFTYPE_MONITOR: | ||
839 | /* doesn't matter */ | ||
840 | break; | ||
841 | case NL80211_IFTYPE_WDS: | ||
842 | case NL80211_IFTYPE_AP_VLAN: | ||
843 | /* match up with an AP interface */ | ||
844 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
845 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
846 | continue; | ||
847 | memcpy(dev->perm_addr, sdata->vif.addr, ETH_ALEN); | ||
848 | break; | ||
849 | } | ||
850 | /* keep default if no AP interface present */ | ||
851 | break; | ||
852 | default: | ||
853 | /* assign a new address if possible -- try n_addresses first */ | ||
854 | for (i = 0; i < local->hw.wiphy->n_addresses; i++) { | ||
855 | bool used = false; | ||
856 | |||
857 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
858 | if (memcmp(local->hw.wiphy->addresses[i].addr, | ||
859 | sdata->vif.addr, ETH_ALEN) == 0) { | ||
860 | used = true; | ||
861 | break; | ||
862 | } | ||
863 | } | ||
864 | |||
865 | if (!used) { | ||
866 | memcpy(dev->perm_addr, | ||
867 | local->hw.wiphy->addresses[i].addr, | ||
868 | ETH_ALEN); | ||
869 | break; | ||
870 | } | ||
871 | } | ||
872 | |||
873 | /* try mask if available */ | ||
874 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask)) | ||
875 | break; | ||
876 | |||
877 | m = local->hw.wiphy->addr_mask; | ||
878 | mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | | ||
879 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | ||
880 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | ||
881 | |||
882 | if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { | ||
883 | /* not a contiguous mask ... not handled now! */ | ||
884 | printk(KERN_DEBUG "not contiguous\n"); | ||
885 | break; | ||
886 | } | ||
887 | |||
888 | m = local->hw.wiphy->perm_addr; | ||
889 | start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | | ||
890 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | ||
891 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | ||
892 | |||
893 | inc = 1ULL<<__ffs64(mask); | ||
894 | val = (start & mask); | ||
895 | addr = (start & ~mask) | (val & mask); | ||
896 | do { | ||
897 | bool used = false; | ||
898 | |||
899 | tmp_addr[5] = addr >> 0*8; | ||
900 | tmp_addr[4] = addr >> 1*8; | ||
901 | tmp_addr[3] = addr >> 2*8; | ||
902 | tmp_addr[2] = addr >> 3*8; | ||
903 | tmp_addr[1] = addr >> 4*8; | ||
904 | tmp_addr[0] = addr >> 5*8; | ||
905 | |||
906 | val += inc; | ||
907 | |||
908 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
909 | if (memcmp(tmp_addr, sdata->vif.addr, | ||
910 | ETH_ALEN) == 0) { | ||
911 | used = true; | ||
912 | break; | ||
913 | } | ||
914 | } | ||
915 | |||
916 | if (!used) { | ||
917 | memcpy(dev->perm_addr, tmp_addr, ETH_ALEN); | ||
918 | break; | ||
919 | } | ||
920 | addr = (start & ~mask) | (val & mask); | ||
921 | } while (addr != start); | ||
922 | |||
923 | break; | ||
924 | } | ||
925 | |||
926 | mutex_unlock(&local->iflist_mtx); | ||
927 | } | ||
928 | |||
819 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 929 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
820 | struct net_device **new_dev, enum nl80211_iftype type, | 930 | struct net_device **new_dev, enum nl80211_iftype type, |
821 | struct vif_params *params) | 931 | struct vif_params *params) |
@@ -845,8 +955,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
845 | if (ret < 0) | 955 | if (ret < 0) |
846 | goto fail; | 956 | goto fail; |
847 | 957 | ||
848 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | 958 | ieee80211_assign_perm_addr(local, ndev, type); |
849 | memcpy(ndev->perm_addr, ndev->dev_addr, ETH_ALEN); | 959 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); |
850 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | 960 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); |
851 | 961 | ||
852 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 962 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index e8f6e3b252d8..8d4b41787dcf 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -140,6 +140,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
140 | struct ieee80211_sub_if_data, | 140 | struct ieee80211_sub_if_data, |
141 | u.ap); | 141 | u.ap); |
142 | 142 | ||
143 | key->conf.ap_addr = sdata->dev->dev_addr; | ||
143 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); | 144 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); |
144 | 145 | ||
145 | if (!ret) { | 146 | if (!ret) { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b887e484ae04..22a384dfab65 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -71,7 +71,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
71 | spin_lock_bh(&local->filter_lock); | 71 | spin_lock_bh(&local->filter_lock); |
72 | changed_flags = local->filter_flags ^ new_flags; | 72 | changed_flags = local->filter_flags ^ new_flags; |
73 | 73 | ||
74 | mc = drv_prepare_multicast(local, local->mc_count, local->mc_list); | 74 | mc = drv_prepare_multicast(local, &local->mc_list); |
75 | spin_unlock_bh(&local->filter_lock); | 75 | spin_unlock_bh(&local->filter_lock); |
76 | 76 | ||
77 | /* be a bit nasty */ | 77 | /* be a bit nasty */ |
@@ -111,7 +111,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
111 | channel_type = local->tmp_channel_type; | 111 | channel_type = local->tmp_channel_type; |
112 | } else { | 112 | } else { |
113 | chan = local->oper_channel; | 113 | chan = local->oper_channel; |
114 | channel_type = local->oper_channel_type; | 114 | channel_type = local->_oper_channel_type; |
115 | } | 115 | } |
116 | 116 | ||
117 | if (chan != local->hw.conf.channel || | 117 | if (chan != local->hw.conf.channel || |
@@ -309,6 +309,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
309 | { | 309 | { |
310 | struct ieee80211_local *local = hw_to_local(hw); | 310 | struct ieee80211_local *local = hw_to_local(hw); |
311 | 311 | ||
312 | trace_api_restart_hw(local); | ||
313 | |||
312 | /* use this reason, __ieee80211_resume will unblock it */ | 314 | /* use this reason, __ieee80211_resume will unblock it */ |
313 | ieee80211_stop_queues_by_reason(hw, | 315 | ieee80211_stop_queues_by_reason(hw, |
314 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 316 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
@@ -388,6 +390,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
388 | local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; | 390 | local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; |
389 | 391 | ||
390 | INIT_LIST_HEAD(&local->interfaces); | 392 | INIT_LIST_HEAD(&local->interfaces); |
393 | |||
394 | __hw_addr_init(&local->mc_list); | ||
395 | |||
391 | mutex_init(&local->iflist_mtx); | 396 | mutex_init(&local->iflist_mtx); |
392 | mutex_init(&local->scan_mtx); | 397 | mutex_init(&local->scan_mtx); |
393 | 398 | ||
@@ -437,7 +442,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
437 | struct ieee80211_local *local = hw_to_local(hw); | 442 | struct ieee80211_local *local = hw_to_local(hw); |
438 | int result; | 443 | int result; |
439 | enum ieee80211_band band; | 444 | enum ieee80211_band band; |
440 | int channels, i, j, max_bitrates; | 445 | int channels, max_bitrates; |
441 | bool supp_ht; | 446 | bool supp_ht; |
442 | static const u32 cipher_suites[] = { | 447 | static const u32 cipher_suites[] = { |
443 | WLAN_CIPHER_SUITE_WEP40, | 448 | WLAN_CIPHER_SUITE_WEP40, |
@@ -567,6 +572,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
567 | 572 | ||
568 | local->hw.conf.listen_interval = local->hw.max_listen_interval; | 573 | local->hw.conf.listen_interval = local->hw.max_listen_interval; |
569 | 574 | ||
575 | local->hw.conf.dynamic_ps_forced_timeout = -1; | ||
576 | |||
570 | result = sta_info_start(local); | 577 | result = sta_info_start(local); |
571 | if (result < 0) | 578 | if (result < 0) |
572 | goto fail_sta_info; | 579 | goto fail_sta_info; |
@@ -601,21 +608,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
601 | 608 | ||
602 | ieee80211_led_init(local); | 609 | ieee80211_led_init(local); |
603 | 610 | ||
604 | /* alloc internal scan request */ | ||
605 | i = 0; | ||
606 | local->int_scan_req->ssids = &local->scan_ssid; | ||
607 | local->int_scan_req->n_ssids = 1; | ||
608 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
609 | if (!hw->wiphy->bands[band]) | ||
610 | continue; | ||
611 | for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) { | ||
612 | local->int_scan_req->channels[i] = | ||
613 | &hw->wiphy->bands[band]->channels[j]; | ||
614 | i++; | ||
615 | } | ||
616 | } | ||
617 | local->int_scan_req->n_channels = i; | ||
618 | |||
619 | local->network_latency_notifier.notifier_call = | 611 | local->network_latency_notifier.notifier_call = |
620 | ieee80211_max_network_latency; | 612 | ieee80211_max_network_latency; |
621 | result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, | 613 | result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 859ee5f3d941..bde81031727a 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -287,8 +287,6 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
287 | *pos++ |= sdata->u.mesh.accepting_plinks ? | 287 | *pos++ |= sdata->u.mesh.accepting_plinks ? |
288 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 288 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
289 | *pos++ = 0x00; | 289 | *pos++ = 0x00; |
290 | |||
291 | return; | ||
292 | } | 290 | } |
293 | 291 | ||
294 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) | 292 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) |
@@ -601,10 +599,10 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | |||
601 | struct ieee80211_rx_status *rx_status) | 599 | struct ieee80211_rx_status *rx_status) |
602 | { | 600 | { |
603 | switch (mgmt->u.action.category) { | 601 | switch (mgmt->u.action.category) { |
604 | case MESH_PLINK_CATEGORY: | 602 | case WLAN_CATEGORY_MESH_PLINK: |
605 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | 603 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); |
606 | break; | 604 | break; |
607 | case MESH_PATH_SEL_CATEGORY: | 605 | case WLAN_CATEGORY_MESH_PATH_SEL: |
608 | mesh_rx_path_sel_frame(sdata, mgmt, len); | 606 | mesh_rx_path_sel_frame(sdata, mgmt, len); |
609 | break; | 607 | break; |
610 | } | 608 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 85562c59d7d6..c88087f1cd0f 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -209,8 +209,6 @@ struct mesh_rmc { | |||
209 | #define MESH_MAX_MPATHS 1024 | 209 | #define MESH_MAX_MPATHS 1024 |
210 | 210 | ||
211 | /* Pending ANA approval */ | 211 | /* Pending ANA approval */ |
212 | #define MESH_PLINK_CATEGORY 30 | ||
213 | #define MESH_PATH_SEL_CATEGORY 32 | ||
214 | #define MESH_PATH_SEL_ACTION 0 | 212 | #define MESH_PATH_SEL_ACTION 0 |
215 | 213 | ||
216 | /* PERR reason codes */ | 214 | /* PERR reason codes */ |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index fefc45c4b4e8..0705018d8d1e 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -132,7 +132,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
132 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 132 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
133 | /* BSSID == SA */ | 133 | /* BSSID == SA */ |
134 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 134 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
135 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 135 | mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; |
136 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 136 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; |
137 | 137 | ||
138 | switch (action) { | 138 | switch (action) { |
@@ -225,7 +225,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
225 | memcpy(mgmt->da, ra, ETH_ALEN); | 225 | memcpy(mgmt->da, ra, ETH_ALEN); |
226 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 226 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
227 | /* BSSID is left zeroed, wildcard value */ | 227 | /* BSSID is left zeroed, wildcard value */ |
228 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 228 | mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; |
229 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 229 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; |
230 | ie_len = 15; | 230 | ie_len = 15; |
231 | pos = skb_put(skb, 2 + ie_len); | 231 | pos = skb_put(skb, 2 + ie_len); |
@@ -624,7 +624,6 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
624 | fail: | 624 | fail: |
625 | rcu_read_unlock(); | 625 | rcu_read_unlock(); |
626 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 626 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
627 | return; | ||
628 | } | 627 | } |
629 | 628 | ||
630 | static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | 629 | static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7b7080e2b49f..3cd5f7b5d693 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -172,7 +172,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
172 | memcpy(mgmt->da, da, ETH_ALEN); | 172 | memcpy(mgmt->da, da, ETH_ALEN); |
173 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 173 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
174 | /* BSSID is left zeroed, wildcard value */ | 174 | /* BSSID is left zeroed, wildcard value */ |
175 | mgmt->u.action.category = MESH_PLINK_CATEGORY; | 175 | mgmt->u.action.category = WLAN_CATEGORY_MESH_PLINK; |
176 | mgmt->u.action.u.plink_action.action_code = action; | 176 | mgmt->u.action.u.plink_action.action_code = action; |
177 | 177 | ||
178 | if (action == PLINK_CLOSE) | 178 | if (action == PLINK_CLOSE) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 88f95e7bab49..0839c4e8fd2e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -47,6 +47,13 @@ | |||
47 | */ | 47 | */ |
48 | #define IEEE80211_PROBE_WAIT (HZ / 2) | 48 | #define IEEE80211_PROBE_WAIT (HZ / 2) |
49 | 49 | ||
50 | /* | ||
51 | * Weight given to the latest Beacon frame when calculating average signal | ||
52 | * strength for Beacon frames received in the current BSS. This must be | ||
53 | * between 1 and 15. | ||
54 | */ | ||
55 | #define IEEE80211_SIGNAL_AVE_WEIGHT 3 | ||
56 | |||
50 | #define TMR_RUNNING_TIMER 0 | 57 | #define TMR_RUNNING_TIMER 0 |
51 | #define TMR_RUNNING_CHANSW 1 | 58 | #define TMR_RUNNING_CHANSW 1 |
52 | 59 | ||
@@ -130,11 +137,14 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
130 | struct sta_info *sta; | 137 | struct sta_info *sta; |
131 | u32 changed = 0; | 138 | u32 changed = 0; |
132 | u16 ht_opmode; | 139 | u16 ht_opmode; |
133 | bool enable_ht = true, ht_changed; | 140 | bool enable_ht = true; |
141 | enum nl80211_channel_type prev_chantype; | ||
134 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 142 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
135 | 143 | ||
136 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 144 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
137 | 145 | ||
146 | prev_chantype = sdata->vif.bss_conf.channel_type; | ||
147 | |||
138 | /* HT is not supported */ | 148 | /* HT is not supported */ |
139 | if (!sband->ht_cap.ht_supported) | 149 | if (!sband->ht_cap.ht_supported) |
140 | enable_ht = false; | 150 | enable_ht = false; |
@@ -165,38 +175,37 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
165 | } | 175 | } |
166 | } | 176 | } |
167 | 177 | ||
168 | ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || | ||
169 | channel_type != local->hw.conf.channel_type; | ||
170 | |||
171 | if (local->tmp_channel) | 178 | if (local->tmp_channel) |
172 | local->tmp_channel_type = channel_type; | 179 | local->tmp_channel_type = channel_type; |
173 | local->oper_channel_type = channel_type; | ||
174 | 180 | ||
175 | if (ht_changed) { | 181 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { |
176 | /* channel_type change automatically detected */ | 182 | /* can only fail due to HT40+/- mismatch */ |
177 | ieee80211_hw_config(local, 0); | 183 | channel_type = NL80211_CHAN_HT20; |
184 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); | ||
185 | } | ||
186 | |||
187 | /* channel_type change automatically detected */ | ||
188 | ieee80211_hw_config(local, 0); | ||
178 | 189 | ||
190 | if (prev_chantype != channel_type) { | ||
179 | rcu_read_lock(); | 191 | rcu_read_lock(); |
180 | sta = sta_info_get(sdata, bssid); | 192 | sta = sta_info_get(sdata, bssid); |
181 | if (sta) | 193 | if (sta) |
182 | rate_control_rate_update(local, sband, sta, | 194 | rate_control_rate_update(local, sband, sta, |
183 | IEEE80211_RC_HT_CHANGED, | 195 | IEEE80211_RC_HT_CHANGED, |
184 | local->oper_channel_type); | 196 | channel_type); |
185 | rcu_read_unlock(); | 197 | rcu_read_unlock(); |
186 | } | 198 | } |
187 | |||
188 | /* disable HT */ | ||
189 | if (!enable_ht) | ||
190 | return 0; | ||
191 | 199 | ||
192 | ht_opmode = le16_to_cpu(hti->operation_mode); | 200 | ht_opmode = le16_to_cpu(hti->operation_mode); |
193 | 201 | ||
194 | /* if bss configuration changed store the new one */ | 202 | /* if bss configuration changed store the new one */ |
195 | if (!sdata->ht_opmode_valid || | 203 | if (sdata->ht_opmode_valid != enable_ht || |
196 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { | 204 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode || |
205 | prev_chantype != channel_type) { | ||
197 | changed |= BSS_CHANGED_HT; | 206 | changed |= BSS_CHANGED_HT; |
198 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | 207 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; |
199 | sdata->ht_opmode_valid = true; | 208 | sdata->ht_opmode_valid = enable_ht; |
200 | } | 209 | } |
201 | 210 | ||
202 | return changed; | 211 | return changed; |
@@ -206,7 +215,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
206 | 215 | ||
207 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | 216 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, |
208 | const u8 *bssid, u16 stype, u16 reason, | 217 | const u8 *bssid, u16 stype, u16 reason, |
209 | void *cookie) | 218 | void *cookie, bool send_frame) |
210 | { | 219 | { |
211 | struct ieee80211_local *local = sdata->local; | 220 | struct ieee80211_local *local = sdata->local; |
212 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 221 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -243,7 +252,11 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
243 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); | 252 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); |
244 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) | 253 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) |
245 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 254 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
246 | ieee80211_tx_skb(sdata, skb); | 255 | |
256 | if (send_frame) | ||
257 | ieee80211_tx_skb(sdata, skb); | ||
258 | else | ||
259 | kfree_skb(skb); | ||
247 | } | 260 | } |
248 | 261 | ||
249 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 262 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
@@ -329,7 +342,11 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
329 | goto out; | 342 | goto out; |
330 | 343 | ||
331 | sdata->local->oper_channel = sdata->local->csa_channel; | 344 | sdata->local->oper_channel = sdata->local->csa_channel; |
332 | ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL); | 345 | if (!sdata->local->ops->channel_switch) { |
346 | /* call "hw_config" only if doing sw channel switch */ | ||
347 | ieee80211_hw_config(sdata->local, | ||
348 | IEEE80211_CONF_CHANGE_CHANNEL); | ||
349 | } | ||
333 | 350 | ||
334 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 351 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
335 | ifmgd->associated->channel = sdata->local->oper_channel; | 352 | ifmgd->associated->channel = sdata->local->oper_channel; |
@@ -341,6 +358,29 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
341 | mutex_unlock(&ifmgd->mtx); | 358 | mutex_unlock(&ifmgd->mtx); |
342 | } | 359 | } |
343 | 360 | ||
361 | void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) | ||
362 | { | ||
363 | struct ieee80211_sub_if_data *sdata; | ||
364 | struct ieee80211_if_managed *ifmgd; | ||
365 | |||
366 | sdata = vif_to_sdata(vif); | ||
367 | ifmgd = &sdata->u.mgd; | ||
368 | |||
369 | trace_api_chswitch_done(sdata, success); | ||
370 | if (!success) { | ||
371 | /* | ||
372 | * If the channel switch was not successful, stay | ||
373 | * around on the old channel. We currently lack | ||
374 | * good handling of this situation, possibly we | ||
375 | * should just drop the association. | ||
376 | */ | ||
377 | sdata->local->csa_channel = sdata->local->oper_channel; | ||
378 | } | ||
379 | |||
380 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); | ||
381 | } | ||
382 | EXPORT_SYMBOL(ieee80211_chswitch_done); | ||
383 | |||
344 | static void ieee80211_chswitch_timer(unsigned long data) | 384 | static void ieee80211_chswitch_timer(unsigned long data) |
345 | { | 385 | { |
346 | struct ieee80211_sub_if_data *sdata = | 386 | struct ieee80211_sub_if_data *sdata = |
@@ -357,7 +397,8 @@ static void ieee80211_chswitch_timer(unsigned long data) | |||
357 | 397 | ||
358 | void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 398 | void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
359 | struct ieee80211_channel_sw_ie *sw_elem, | 399 | struct ieee80211_channel_sw_ie *sw_elem, |
360 | struct ieee80211_bss *bss) | 400 | struct ieee80211_bss *bss, |
401 | u64 timestamp) | ||
361 | { | 402 | { |
362 | struct cfg80211_bss *cbss = | 403 | struct cfg80211_bss *cbss = |
363 | container_of((void *)bss, struct cfg80211_bss, priv); | 404 | container_of((void *)bss, struct cfg80211_bss, priv); |
@@ -385,10 +426,29 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
385 | 426 | ||
386 | sdata->local->csa_channel = new_ch; | 427 | sdata->local->csa_channel = new_ch; |
387 | 428 | ||
429 | if (sdata->local->ops->channel_switch) { | ||
430 | /* use driver's channel switch callback */ | ||
431 | struct ieee80211_channel_switch ch_switch; | ||
432 | memset(&ch_switch, 0, sizeof(ch_switch)); | ||
433 | ch_switch.timestamp = timestamp; | ||
434 | if (sw_elem->mode) { | ||
435 | ch_switch.block_tx = true; | ||
436 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
437 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
438 | } | ||
439 | ch_switch.channel = new_ch; | ||
440 | ch_switch.count = sw_elem->count; | ||
441 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
442 | drv_channel_switch(sdata->local, &ch_switch); | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | /* channel switch handled in software */ | ||
388 | if (sw_elem->count <= 1) { | 447 | if (sw_elem->count <= 1) { |
389 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); | 448 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); |
390 | } else { | 449 | } else { |
391 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 450 | if (sw_elem->mode) |
451 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
392 | IEEE80211_QUEUE_STOP_REASON_CSA); | 452 | IEEE80211_QUEUE_STOP_REASON_CSA); |
393 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | 453 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; |
394 | mod_timer(&ifmgd->chswitch_timer, | 454 | mod_timer(&ifmgd->chswitch_timer, |
@@ -467,6 +527,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
467 | { | 527 | { |
468 | struct ieee80211_sub_if_data *sdata, *found = NULL; | 528 | struct ieee80211_sub_if_data *sdata, *found = NULL; |
469 | int count = 0; | 529 | int count = 0; |
530 | int timeout; | ||
470 | 531 | ||
471 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) { | 532 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) { |
472 | local->ps_sdata = NULL; | 533 | local->ps_sdata = NULL; |
@@ -500,6 +561,26 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
500 | beaconint_us = ieee80211_tu_to_usec( | 561 | beaconint_us = ieee80211_tu_to_usec( |
501 | found->vif.bss_conf.beacon_int); | 562 | found->vif.bss_conf.beacon_int); |
502 | 563 | ||
564 | timeout = local->hw.conf.dynamic_ps_forced_timeout; | ||
565 | if (timeout < 0) { | ||
566 | /* | ||
567 | * The 2 second value is there for compatibility until | ||
568 | * the PM_QOS_NETWORK_LATENCY is configured with real | ||
569 | * values. | ||
570 | */ | ||
571 | if (latency == 2000000000) | ||
572 | timeout = 100; | ||
573 | else if (latency <= 50000) | ||
574 | timeout = 300; | ||
575 | else if (latency <= 100000) | ||
576 | timeout = 100; | ||
577 | else if (latency <= 500000) | ||
578 | timeout = 50; | ||
579 | else | ||
580 | timeout = 0; | ||
581 | } | ||
582 | local->hw.conf.dynamic_ps_timeout = timeout; | ||
583 | |||
503 | if (beaconint_us > latency) { | 584 | if (beaconint_us > latency) { |
504 | local->ps_sdata = NULL; | 585 | local->ps_sdata = NULL; |
505 | } else { | 586 | } else { |
@@ -592,6 +673,9 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
592 | int count; | 673 | int count; |
593 | u8 *pos, uapsd_queues = 0; | 674 | u8 *pos, uapsd_queues = 0; |
594 | 675 | ||
676 | if (!local->ops->conf_tx) | ||
677 | return; | ||
678 | |||
595 | if (local->hw.queues < 4) | 679 | if (local->hw.queues < 4) |
596 | return; | 680 | return; |
597 | 681 | ||
@@ -666,11 +750,15 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
666 | params.aifs, params.cw_min, params.cw_max, params.txop, | 750 | params.aifs, params.cw_min, params.cw_max, params.txop, |
667 | params.uapsd); | 751 | params.uapsd); |
668 | #endif | 752 | #endif |
669 | if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx) | 753 | if (drv_conf_tx(local, queue, ¶ms)) |
670 | printk(KERN_DEBUG "%s: failed to set TX queue " | 754 | printk(KERN_DEBUG "%s: failed to set TX queue " |
671 | "parameters for queue %d\n", | 755 | "parameters for queue %d\n", |
672 | wiphy_name(local->hw.wiphy), queue); | 756 | wiphy_name(local->hw.wiphy), queue); |
673 | } | 757 | } |
758 | |||
759 | /* enable WMM or activate new settings */ | ||
760 | local->hw.conf.flags |= IEEE80211_CONF_QOS; | ||
761 | drv_config(local, IEEE80211_CONF_CHANGE_QOS); | ||
674 | } | 762 | } |
675 | 763 | ||
676 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | 764 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, |
@@ -731,6 +819,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
731 | sdata->u.mgd.associated = cbss; | 819 | sdata->u.mgd.associated = cbss; |
732 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); | 820 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
733 | 821 | ||
822 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; | ||
823 | |||
734 | /* just to be sure */ | 824 | /* just to be sure */ |
735 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 825 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
736 | IEEE80211_STA_BEACON_POLL); | 826 | IEEE80211_STA_BEACON_POLL); |
@@ -756,6 +846,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
756 | /* And the BSSID changed - we're associated now */ | 846 | /* And the BSSID changed - we're associated now */ |
757 | bss_info_changed |= BSS_CHANGED_BSSID; | 847 | bss_info_changed |= BSS_CHANGED_BSSID; |
758 | 848 | ||
849 | /* Tell the driver to monitor connection quality (if supported) */ | ||
850 | if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) && | ||
851 | sdata->vif.bss_conf.cqm_rssi_thold) | ||
852 | bss_info_changed |= BSS_CHANGED_CQM; | ||
853 | |||
759 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); | 854 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
760 | 855 | ||
761 | mutex_lock(&local->iflist_mtx); | 856 | mutex_lock(&local->iflist_mtx); |
@@ -767,7 +862,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
767 | netif_carrier_on(sdata->dev); | 862 | netif_carrier_on(sdata->dev); |
768 | } | 863 | } |
769 | 864 | ||
770 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | 865 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
866 | bool remove_sta) | ||
771 | { | 867 | { |
772 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 868 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
773 | struct ieee80211_local *local = sdata->local; | 869 | struct ieee80211_local *local = sdata->local; |
@@ -819,7 +915,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | |||
819 | ieee80211_set_wmm_default(sdata); | 915 | ieee80211_set_wmm_default(sdata); |
820 | 916 | ||
821 | /* channel(_type) changes are handled by ieee80211_hw_config */ | 917 | /* channel(_type) changes are handled by ieee80211_hw_config */ |
822 | local->oper_channel_type = NL80211_CHAN_NO_HT; | 918 | WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); |
823 | 919 | ||
824 | /* on the next assoc, re-program HT parameters */ | 920 | /* on the next assoc, re-program HT parameters */ |
825 | sdata->ht_opmode_valid = false; | 921 | sdata->ht_opmode_valid = false; |
@@ -836,11 +932,12 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | |||
836 | 932 | ||
837 | ieee80211_hw_config(local, config_changed); | 933 | ieee80211_hw_config(local, config_changed); |
838 | 934 | ||
839 | /* And the BSSID changed -- not very interesting here */ | 935 | /* The BSSID (not really interesting) and HT changed */ |
840 | changed |= BSS_CHANGED_BSSID; | 936 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; |
841 | ieee80211_bss_info_change_notify(sdata, changed); | 937 | ieee80211_bss_info_change_notify(sdata, changed); |
842 | 938 | ||
843 | sta_info_destroy_addr(sdata, bssid); | 939 | if (remove_sta) |
940 | sta_info_destroy_addr(sdata, bssid); | ||
844 | } | 941 | } |
845 | 942 | ||
846 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 943 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -857,6 +954,9 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
857 | if (is_multicast_ether_addr(hdr->addr1)) | 954 | if (is_multicast_ether_addr(hdr->addr1)) |
858 | return; | 955 | return; |
859 | 956 | ||
957 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
958 | return; | ||
959 | |||
860 | mod_timer(&sdata->u.mgd.conn_mon_timer, | 960 | mod_timer(&sdata->u.mgd.conn_mon_timer, |
861 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | 961 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); |
862 | } | 962 | } |
@@ -934,23 +1034,72 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
934 | mutex_unlock(&ifmgd->mtx); | 1034 | mutex_unlock(&ifmgd->mtx); |
935 | } | 1035 | } |
936 | 1036 | ||
937 | void ieee80211_beacon_loss_work(struct work_struct *work) | 1037 | static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) |
1038 | { | ||
1039 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1040 | struct ieee80211_local *local = sdata->local; | ||
1041 | u8 bssid[ETH_ALEN]; | ||
1042 | |||
1043 | mutex_lock(&ifmgd->mtx); | ||
1044 | if (!ifmgd->associated) { | ||
1045 | mutex_unlock(&ifmgd->mtx); | ||
1046 | return; | ||
1047 | } | ||
1048 | |||
1049 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | ||
1050 | |||
1051 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | ||
1052 | |||
1053 | ieee80211_set_disassoc(sdata, true); | ||
1054 | ieee80211_recalc_idle(local); | ||
1055 | mutex_unlock(&ifmgd->mtx); | ||
1056 | /* | ||
1057 | * must be outside lock due to cfg80211, | ||
1058 | * but that's not a problem. | ||
1059 | */ | ||
1060 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
1061 | IEEE80211_STYPE_DEAUTH, | ||
1062 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
1063 | NULL, true); | ||
1064 | } | ||
1065 | |||
1066 | void ieee80211_beacon_connection_loss_work(struct work_struct *work) | ||
938 | { | 1067 | { |
939 | struct ieee80211_sub_if_data *sdata = | 1068 | struct ieee80211_sub_if_data *sdata = |
940 | container_of(work, struct ieee80211_sub_if_data, | 1069 | container_of(work, struct ieee80211_sub_if_data, |
941 | u.mgd.beacon_loss_work); | 1070 | u.mgd.beacon_connection_loss_work); |
942 | 1071 | ||
943 | ieee80211_mgd_probe_ap(sdata, true); | 1072 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) |
1073 | __ieee80211_connection_loss(sdata); | ||
1074 | else | ||
1075 | ieee80211_mgd_probe_ap(sdata, true); | ||
944 | } | 1076 | } |
945 | 1077 | ||
946 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) | 1078 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) |
947 | { | 1079 | { |
948 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1080 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
1081 | struct ieee80211_hw *hw = &sdata->local->hw; | ||
949 | 1082 | ||
950 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); | 1083 | trace_api_beacon_loss(sdata); |
1084 | |||
1085 | WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR); | ||
1086 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); | ||
951 | } | 1087 | } |
952 | EXPORT_SYMBOL(ieee80211_beacon_loss); | 1088 | EXPORT_SYMBOL(ieee80211_beacon_loss); |
953 | 1089 | ||
1090 | void ieee80211_connection_loss(struct ieee80211_vif *vif) | ||
1091 | { | ||
1092 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1093 | struct ieee80211_hw *hw = &sdata->local->hw; | ||
1094 | |||
1095 | trace_api_connection_loss(sdata); | ||
1096 | |||
1097 | WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR)); | ||
1098 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); | ||
1099 | } | ||
1100 | EXPORT_SYMBOL(ieee80211_connection_loss); | ||
1101 | |||
1102 | |||
954 | static enum rx_mgmt_action __must_check | 1103 | static enum rx_mgmt_action __must_check |
955 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | 1104 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
956 | struct ieee80211_mgmt *mgmt, size_t len) | 1105 | struct ieee80211_mgmt *mgmt, size_t len) |
@@ -971,7 +1120,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
971 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1120 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
972 | sdata->name, bssid, reason_code); | 1121 | sdata->name, bssid, reason_code); |
973 | 1122 | ||
974 | ieee80211_set_disassoc(sdata); | 1123 | ieee80211_set_disassoc(sdata, true); |
975 | ieee80211_recalc_idle(sdata->local); | 1124 | ieee80211_recalc_idle(sdata->local); |
976 | 1125 | ||
977 | return RX_MGMT_CFG80211_DEAUTH; | 1126 | return RX_MGMT_CFG80211_DEAUTH; |
@@ -1001,7 +1150,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1001 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1150 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
1002 | sdata->name, mgmt->sa, reason_code); | 1151 | sdata->name, mgmt->sa, reason_code); |
1003 | 1152 | ||
1004 | ieee80211_set_disassoc(sdata); | 1153 | ieee80211_set_disassoc(sdata, true); |
1005 | ieee80211_recalc_idle(sdata->local); | 1154 | ieee80211_recalc_idle(sdata->local); |
1006 | return RX_MGMT_CFG80211_DISASSOC; | 1155 | return RX_MGMT_CFG80211_DISASSOC; |
1007 | } | 1156 | } |
@@ -1215,7 +1364,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1215 | ETH_ALEN) == 0)) { | 1364 | ETH_ALEN) == 0)) { |
1216 | struct ieee80211_channel_sw_ie *sw_elem = | 1365 | struct ieee80211_channel_sw_ie *sw_elem = |
1217 | (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; | 1366 | (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; |
1218 | ieee80211_sta_process_chanswitch(sdata, sw_elem, bss); | 1367 | ieee80211_sta_process_chanswitch(sdata, sw_elem, |
1368 | bss, rx_status->mactime); | ||
1219 | } | 1369 | } |
1220 | } | 1370 | } |
1221 | 1371 | ||
@@ -1254,12 +1404,17 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1254 | mutex_lock(&sdata->local->iflist_mtx); | 1404 | mutex_lock(&sdata->local->iflist_mtx); |
1255 | ieee80211_recalc_ps(sdata->local, -1); | 1405 | ieee80211_recalc_ps(sdata->local, -1); |
1256 | mutex_unlock(&sdata->local->iflist_mtx); | 1406 | mutex_unlock(&sdata->local->iflist_mtx); |
1407 | |||
1408 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
1409 | return; | ||
1410 | |||
1257 | /* | 1411 | /* |
1258 | * We've received a probe response, but are not sure whether | 1412 | * We've received a probe response, but are not sure whether |
1259 | * we have or will be receiving any beacons or data, so let's | 1413 | * we have or will be receiving any beacons or data, so let's |
1260 | * schedule the timers again, just in case. | 1414 | * schedule the timers again, just in case. |
1261 | */ | 1415 | */ |
1262 | mod_beacon_timer(sdata); | 1416 | mod_beacon_timer(sdata); |
1417 | |||
1263 | mod_timer(&ifmgd->conn_mon_timer, | 1418 | mod_timer(&ifmgd->conn_mon_timer, |
1264 | round_jiffies_up(jiffies + | 1419 | round_jiffies_up(jiffies + |
1265 | IEEE80211_CONNECTION_IDLE_TIME)); | 1420 | IEEE80211_CONNECTION_IDLE_TIME)); |
@@ -1293,6 +1448,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1293 | struct ieee80211_rx_status *rx_status) | 1448 | struct ieee80211_rx_status *rx_status) |
1294 | { | 1449 | { |
1295 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1450 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1451 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | ||
1296 | size_t baselen; | 1452 | size_t baselen; |
1297 | struct ieee802_11_elems elems; | 1453 | struct ieee802_11_elems elems; |
1298 | struct ieee80211_local *local = sdata->local; | 1454 | struct ieee80211_local *local = sdata->local; |
@@ -1328,6 +1484,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1328 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) | 1484 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) |
1329 | return; | 1485 | return; |
1330 | 1486 | ||
1487 | /* Track average RSSI from the Beacon frames of the current AP */ | ||
1488 | ifmgd->last_beacon_signal = rx_status->signal; | ||
1489 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { | ||
1490 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; | ||
1491 | ifmgd->ave_beacon_signal = rx_status->signal; | ||
1492 | ifmgd->last_cqm_event_signal = 0; | ||
1493 | } else { | ||
1494 | ifmgd->ave_beacon_signal = | ||
1495 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + | ||
1496 | (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * | ||
1497 | ifmgd->ave_beacon_signal) / 16; | ||
1498 | } | ||
1499 | if (bss_conf->cqm_rssi_thold && | ||
1500 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | ||
1501 | int sig = ifmgd->ave_beacon_signal / 16; | ||
1502 | int last_event = ifmgd->last_cqm_event_signal; | ||
1503 | int thold = bss_conf->cqm_rssi_thold; | ||
1504 | int hyst = bss_conf->cqm_rssi_hyst; | ||
1505 | if (sig < thold && | ||
1506 | (last_event == 0 || sig < last_event - hyst)) { | ||
1507 | ifmgd->last_cqm_event_signal = sig; | ||
1508 | ieee80211_cqm_rssi_notify( | ||
1509 | &sdata->vif, | ||
1510 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | ||
1511 | GFP_KERNEL); | ||
1512 | } else if (sig > thold && | ||
1513 | (last_event == 0 || sig > last_event + hyst)) { | ||
1514 | ifmgd->last_cqm_event_signal = sig; | ||
1515 | ieee80211_cqm_rssi_notify( | ||
1516 | &sdata->vif, | ||
1517 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | ||
1518 | GFP_KERNEL); | ||
1519 | } | ||
1520 | } | ||
1521 | |||
1331 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { | 1522 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { |
1332 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1523 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1333 | if (net_ratelimit()) { | 1524 | if (net_ratelimit()) { |
@@ -1506,7 +1697,8 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1506 | 1697 | ||
1507 | ieee80211_sta_process_chanswitch(sdata, | 1698 | ieee80211_sta_process_chanswitch(sdata, |
1508 | &mgmt->u.action.u.chan_switch.sw_elem, | 1699 | &mgmt->u.action.u.chan_switch.sw_elem, |
1509 | (void *)ifmgd->associated->priv); | 1700 | (void *)ifmgd->associated->priv, |
1701 | rx_status->mactime); | ||
1510 | break; | 1702 | break; |
1511 | } | 1703 | } |
1512 | mutex_unlock(&ifmgd->mtx); | 1704 | mutex_unlock(&ifmgd->mtx); |
@@ -1613,7 +1805,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1613 | printk(KERN_DEBUG "No probe response from AP %pM" | 1805 | printk(KERN_DEBUG "No probe response from AP %pM" |
1614 | " after %dms, disconnecting.\n", | 1806 | " after %dms, disconnecting.\n", |
1615 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1807 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1616 | ieee80211_set_disassoc(sdata); | 1808 | ieee80211_set_disassoc(sdata, true); |
1617 | ieee80211_recalc_idle(local); | 1809 | ieee80211_recalc_idle(local); |
1618 | mutex_unlock(&ifmgd->mtx); | 1810 | mutex_unlock(&ifmgd->mtx); |
1619 | /* | 1811 | /* |
@@ -1623,7 +1815,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1623 | ieee80211_send_deauth_disassoc(sdata, bssid, | 1815 | ieee80211_send_deauth_disassoc(sdata, bssid, |
1624 | IEEE80211_STYPE_DEAUTH, | 1816 | IEEE80211_STYPE_DEAUTH, |
1625 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1817 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
1626 | NULL); | 1818 | NULL, true); |
1627 | mutex_lock(&ifmgd->mtx); | 1819 | mutex_lock(&ifmgd->mtx); |
1628 | } | 1820 | } |
1629 | } | 1821 | } |
@@ -1640,7 +1832,8 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data) | |||
1640 | if (local->quiescing) | 1832 | if (local->quiescing) |
1641 | return; | 1833 | return; |
1642 | 1834 | ||
1643 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); | 1835 | ieee80211_queue_work(&sdata->local->hw, |
1836 | &sdata->u.mgd.beacon_connection_loss_work); | ||
1644 | } | 1837 | } |
1645 | 1838 | ||
1646 | static void ieee80211_sta_conn_mon_timer(unsigned long data) | 1839 | static void ieee80211_sta_conn_mon_timer(unsigned long data) |
@@ -1692,7 +1885,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
1692 | */ | 1885 | */ |
1693 | 1886 | ||
1694 | cancel_work_sync(&ifmgd->work); | 1887 | cancel_work_sync(&ifmgd->work); |
1695 | cancel_work_sync(&ifmgd->beacon_loss_work); | 1888 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
1696 | if (del_timer_sync(&ifmgd->timer)) | 1889 | if (del_timer_sync(&ifmgd->timer)) |
1697 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 1890 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
1698 | 1891 | ||
@@ -1726,7 +1919,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
1726 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); | 1919 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); |
1727 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); | 1920 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); |
1728 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 1921 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
1729 | INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); | 1922 | INIT_WORK(&ifmgd->beacon_connection_loss_work, |
1923 | ieee80211_beacon_connection_loss_work); | ||
1730 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 1924 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
1731 | (unsigned long) sdata); | 1925 | (unsigned long) sdata); |
1732 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 1926 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
@@ -1805,6 +1999,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
1805 | struct ieee80211_work *wk; | 1999 | struct ieee80211_work *wk; |
1806 | u16 auth_alg; | 2000 | u16 auth_alg; |
1807 | 2001 | ||
2002 | if (req->local_state_change) | ||
2003 | return 0; /* no need to update mac80211 state */ | ||
2004 | |||
1808 | switch (req->auth_type) { | 2005 | switch (req->auth_type) { |
1809 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | 2006 | case NL80211_AUTHTYPE_OPEN_SYSTEM: |
1810 | auth_alg = WLAN_AUTH_OPEN; | 2007 | auth_alg = WLAN_AUTH_OPEN; |
@@ -1913,7 +2110,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
1913 | } | 2110 | } |
1914 | 2111 | ||
1915 | /* Trying to reassociate - clear previous association state */ | 2112 | /* Trying to reassociate - clear previous association state */ |
1916 | ieee80211_set_disassoc(sdata); | 2113 | ieee80211_set_disassoc(sdata, true); |
1917 | } | 2114 | } |
1918 | mutex_unlock(&ifmgd->mtx); | 2115 | mutex_unlock(&ifmgd->mtx); |
1919 | 2116 | ||
@@ -2017,7 +2214,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2017 | 2214 | ||
2018 | if (ifmgd->associated == req->bss) { | 2215 | if (ifmgd->associated == req->bss) { |
2019 | bssid = req->bss->bssid; | 2216 | bssid = req->bss->bssid; |
2020 | ieee80211_set_disassoc(sdata); | 2217 | ieee80211_set_disassoc(sdata, true); |
2021 | mutex_unlock(&ifmgd->mtx); | 2218 | mutex_unlock(&ifmgd->mtx); |
2022 | } else { | 2219 | } else { |
2023 | bool not_auth_yet = false; | 2220 | bool not_auth_yet = false; |
@@ -2061,9 +2258,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2061 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 2258 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", |
2062 | sdata->name, bssid, req->reason_code); | 2259 | sdata->name, bssid, req->reason_code); |
2063 | 2260 | ||
2064 | ieee80211_send_deauth_disassoc(sdata, bssid, | 2261 | ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH, |
2065 | IEEE80211_STYPE_DEAUTH, req->reason_code, | 2262 | req->reason_code, cookie, |
2066 | cookie); | 2263 | !req->local_state_change); |
2067 | 2264 | ||
2068 | ieee80211_recalc_idle(sdata->local); | 2265 | ieee80211_recalc_idle(sdata->local); |
2069 | 2266 | ||
@@ -2075,6 +2272,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2075 | void *cookie) | 2272 | void *cookie) |
2076 | { | 2273 | { |
2077 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2274 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2275 | u8 bssid[ETH_ALEN]; | ||
2078 | 2276 | ||
2079 | mutex_lock(&ifmgd->mtx); | 2277 | mutex_lock(&ifmgd->mtx); |
2080 | 2278 | ||
@@ -2092,13 +2290,15 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2092 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 2290 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", |
2093 | sdata->name, req->bss->bssid, req->reason_code); | 2291 | sdata->name, req->bss->bssid, req->reason_code); |
2094 | 2292 | ||
2095 | ieee80211_set_disassoc(sdata); | 2293 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
2294 | ieee80211_set_disassoc(sdata, false); | ||
2096 | 2295 | ||
2097 | mutex_unlock(&ifmgd->mtx); | 2296 | mutex_unlock(&ifmgd->mtx); |
2098 | 2297 | ||
2099 | ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, | 2298 | ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, |
2100 | IEEE80211_STYPE_DISASSOC, req->reason_code, | 2299 | IEEE80211_STYPE_DISASSOC, req->reason_code, |
2101 | cookie); | 2300 | cookie, !req->local_state_change); |
2301 | sta_info_destroy_addr(sdata, bssid); | ||
2102 | 2302 | ||
2103 | ieee80211_recalc_idle(sdata->local); | 2303 | ieee80211_recalc_idle(sdata->local); |
2104 | 2304 | ||
@@ -2118,7 +2318,7 @@ int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | |||
2118 | if ((chan != local->tmp_channel || | 2318 | if ((chan != local->tmp_channel || |
2119 | channel_type != local->tmp_channel_type) && | 2319 | channel_type != local->tmp_channel_type) && |
2120 | (chan != local->oper_channel || | 2320 | (chan != local->oper_channel || |
2121 | channel_type != local->oper_channel_type)) | 2321 | channel_type != local->_oper_channel_type)) |
2122 | return -EBUSY; | 2322 | return -EBUSY; |
2123 | 2323 | ||
2124 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | 2324 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); |
@@ -2139,3 +2339,15 @@ int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | |||
2139 | *cookie = (unsigned long) skb; | 2339 | *cookie = (unsigned long) skb; |
2140 | return 0; | 2340 | return 0; |
2141 | } | 2341 | } |
2342 | |||
2343 | void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | ||
2344 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
2345 | gfp_t gfp) | ||
2346 | { | ||
2347 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
2348 | |||
2349 | trace_api_cqm_rssi_notify(sdata, rssi_event); | ||
2350 | |||
2351 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | ||
2352 | } | ||
2353 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 0e64484e861c..75202b295a4e 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -46,7 +46,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
46 | 46 | ||
47 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 47 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
48 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 48 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
49 | set_sta_flags(sta, WLAN_STA_SUSPEND); | 49 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
50 | ieee80211_sta_tear_down_BA_sessions(sta); | 50 | ieee80211_sta_tear_down_BA_sessions(sta); |
51 | } | 51 | } |
52 | } | 52 | } |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 818abfae9007..f65ce6dcc8e2 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -542,7 +542,7 @@ minstrel_free(void *priv) | |||
542 | kfree(priv); | 542 | kfree(priv); |
543 | } | 543 | } |
544 | 544 | ||
545 | static struct rate_control_ops mac80211_minstrel = { | 545 | struct rate_control_ops mac80211_minstrel = { |
546 | .name = "minstrel", | 546 | .name = "minstrel", |
547 | .tx_status = minstrel_tx_status, | 547 | .tx_status = minstrel_tx_status, |
548 | .get_rate = minstrel_get_rate, | 548 | .get_rate = minstrel_get_rate, |
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 38bf4168fc3a..0f5a83370aa6 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -80,7 +80,18 @@ struct minstrel_priv { | |||
80 | unsigned int lookaround_rate_mrr; | 80 | unsigned int lookaround_rate_mrr; |
81 | }; | 81 | }; |
82 | 82 | ||
83 | struct minstrel_debugfs_info { | ||
84 | size_t len; | ||
85 | char buf[]; | ||
86 | }; | ||
87 | |||
88 | extern struct rate_control_ops mac80211_minstrel; | ||
83 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | 89 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); |
84 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); | 90 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); |
85 | 91 | ||
92 | /* debugfs */ | ||
93 | int minstrel_stats_open(struct inode *inode, struct file *file); | ||
94 | ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); | ||
95 | int minstrel_stats_release(struct inode *inode, struct file *file); | ||
96 | |||
86 | #endif | 97 | #endif |
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index 0e1f12b1b6dd..241e76f3fdf2 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -53,21 +53,15 @@ | |||
53 | #include <net/mac80211.h> | 53 | #include <net/mac80211.h> |
54 | #include "rc80211_minstrel.h" | 54 | #include "rc80211_minstrel.h" |
55 | 55 | ||
56 | struct minstrel_stats_info { | 56 | int |
57 | struct minstrel_sta_info *mi; | ||
58 | char buf[4096]; | ||
59 | size_t len; | ||
60 | }; | ||
61 | |||
62 | static int | ||
63 | minstrel_stats_open(struct inode *inode, struct file *file) | 57 | minstrel_stats_open(struct inode *inode, struct file *file) |
64 | { | 58 | { |
65 | struct minstrel_sta_info *mi = inode->i_private; | 59 | struct minstrel_sta_info *mi = inode->i_private; |
66 | struct minstrel_stats_info *ms; | 60 | struct minstrel_debugfs_info *ms; |
67 | unsigned int i, tp, prob, eprob; | 61 | unsigned int i, tp, prob, eprob; |
68 | char *p; | 62 | char *p; |
69 | 63 | ||
70 | ms = kmalloc(sizeof(*ms), GFP_KERNEL); | 64 | ms = kmalloc(sizeof(*ms) + 4096, GFP_KERNEL); |
71 | if (!ms) | 65 | if (!ms) |
72 | return -ENOMEM; | 66 | return -ENOMEM; |
73 | 67 | ||
@@ -107,36 +101,19 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
107 | return 0; | 101 | return 0; |
108 | } | 102 | } |
109 | 103 | ||
110 | static ssize_t | 104 | ssize_t |
111 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *o) | 105 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) |
112 | { | 106 | { |
113 | struct minstrel_stats_info *ms; | 107 | struct minstrel_debugfs_info *ms; |
114 | char *src; | ||
115 | 108 | ||
116 | ms = file->private_data; | 109 | ms = file->private_data; |
117 | src = ms->buf; | 110 | return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); |
118 | |||
119 | len = min(len, ms->len); | ||
120 | if (len <= *o) | ||
121 | return 0; | ||
122 | |||
123 | src += *o; | ||
124 | len -= *o; | ||
125 | *o += len; | ||
126 | |||
127 | if (copy_to_user(buf, src, len)) | ||
128 | return -EFAULT; | ||
129 | |||
130 | return len; | ||
131 | } | 111 | } |
132 | 112 | ||
133 | static int | 113 | int |
134 | minstrel_stats_release(struct inode *inode, struct file *file) | 114 | minstrel_stats_release(struct inode *inode, struct file *file) |
135 | { | 115 | { |
136 | struct minstrel_stats_info *ms = file->private_data; | 116 | kfree(file->private_data); |
137 | |||
138 | kfree(ms); | ||
139 | |||
140 | return 0; | 117 | return 0; |
141 | } | 118 | } |
142 | 119 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 04ea07f0e78a..6e2a7bcd8cb8 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -39,7 +39,7 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
39 | { | 39 | { |
40 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 40 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
41 | if (likely(skb->len > FCS_LEN)) | 41 | if (likely(skb->len > FCS_LEN)) |
42 | skb_trim(skb, skb->len - FCS_LEN); | 42 | __pskb_trim(skb, skb->len - FCS_LEN); |
43 | else { | 43 | else { |
44 | /* driver bug */ | 44 | /* driver bug */ |
45 | WARN_ON(1); | 45 | WARN_ON(1); |
@@ -81,8 +81,6 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
81 | len += 8; | 81 | len += 8; |
82 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 82 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
83 | len += 1; | 83 | len += 1; |
84 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) | ||
85 | len += 1; | ||
86 | 84 | ||
87 | if (len & 1) /* padding for RX_FLAGS if necessary */ | 85 | if (len & 1) /* padding for RX_FLAGS if necessary */ |
88 | len++; | 86 | len++; |
@@ -179,14 +177,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
179 | pos++; | 177 | pos++; |
180 | } | 178 | } |
181 | 179 | ||
182 | /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ | ||
183 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) { | ||
184 | *pos = status->noise; | ||
185 | rthdr->it_present |= | ||
186 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE); | ||
187 | pos++; | ||
188 | } | ||
189 | |||
190 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ | 180 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ |
191 | 181 | ||
192 | /* IEEE80211_RADIOTAP_ANTENNA */ | 182 | /* IEEE80211_RADIOTAP_ANTENNA */ |
@@ -236,6 +226,12 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
236 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 226 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
237 | present_fcs_len = FCS_LEN; | 227 | present_fcs_len = FCS_LEN; |
238 | 228 | ||
229 | /* make sure hdr->frame_control is on the linear part */ | ||
230 | if (!pskb_may_pull(origskb, 2)) { | ||
231 | dev_kfree_skb(origskb); | ||
232 | return NULL; | ||
233 | } | ||
234 | |||
239 | if (!local->monitors) { | 235 | if (!local->monitors) { |
240 | if (should_drop_frame(origskb, present_fcs_len)) { | 236 | if (should_drop_frame(origskb, present_fcs_len)) { |
241 | dev_kfree_skb(origskb); | 237 | dev_kfree_skb(origskb); |
@@ -493,7 +489,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
493 | 489 | ||
494 | if (ieee80211_is_action(hdr->frame_control)) { | 490 | if (ieee80211_is_action(hdr->frame_control)) { |
495 | mgmt = (struct ieee80211_mgmt *)hdr; | 491 | mgmt = (struct ieee80211_mgmt *)hdr; |
496 | if (mgmt->u.action.category != MESH_PLINK_CATEGORY) | 492 | if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK) |
497 | return RX_DROP_MONITOR; | 493 | return RX_DROP_MONITOR; |
498 | return RX_CONTINUE; | 494 | return RX_CONTINUE; |
499 | } | 495 | } |
@@ -723,14 +719,16 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
723 | 719 | ||
724 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 720 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
725 | 721 | ||
726 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) | 722 | spin_lock(&sta->lock); |
727 | goto dont_reorder; | 723 | |
724 | if (!sta->ampdu_mlme.tid_active_rx[tid]) | ||
725 | goto dont_reorder_unlock; | ||
728 | 726 | ||
729 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | 727 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; |
730 | 728 | ||
731 | /* qos null data frames are excluded */ | 729 | /* qos null data frames are excluded */ |
732 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) | 730 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
733 | goto dont_reorder; | 731 | goto dont_reorder_unlock; |
734 | 732 | ||
735 | /* new, potentially un-ordered, ampdu frame - process it */ | 733 | /* new, potentially un-ordered, ampdu frame - process it */ |
736 | 734 | ||
@@ -742,15 +740,20 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
742 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 740 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
743 | sc = le16_to_cpu(hdr->seq_ctrl); | 741 | sc = le16_to_cpu(hdr->seq_ctrl); |
744 | if (sc & IEEE80211_SCTL_FRAG) { | 742 | if (sc & IEEE80211_SCTL_FRAG) { |
745 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | 743 | spin_unlock(&sta->lock); |
746 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); | 744 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
745 | WLAN_REASON_QSTA_REQUIRE_SETUP); | ||
747 | dev_kfree_skb(skb); | 746 | dev_kfree_skb(skb); |
748 | return; | 747 | return; |
749 | } | 748 | } |
750 | 749 | ||
751 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) | 750 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) { |
751 | spin_unlock(&sta->lock); | ||
752 | return; | 752 | return; |
753 | } | ||
753 | 754 | ||
755 | dont_reorder_unlock: | ||
756 | spin_unlock(&sta->lock); | ||
754 | dont_reorder: | 757 | dont_reorder: |
755 | __skb_queue_tail(frames, skb); | 758 | __skb_queue_tail(frames, skb); |
756 | } | 759 | } |
@@ -897,6 +900,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
897 | rx->key = key; | 900 | rx->key = key; |
898 | return RX_CONTINUE; | 901 | return RX_CONTINUE; |
899 | } else { | 902 | } else { |
903 | u8 keyid; | ||
900 | /* | 904 | /* |
901 | * The device doesn't give us the IV so we won't be | 905 | * The device doesn't give us the IV so we won't be |
902 | * able to look up the key. That's ok though, we | 906 | * able to look up the key. That's ok though, we |
@@ -919,7 +923,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
919 | * no need to call ieee80211_wep_get_keyidx, | 923 | * no need to call ieee80211_wep_get_keyidx, |
920 | * it verifies a bunch of things we've done already | 924 | * it verifies a bunch of things we've done already |
921 | */ | 925 | */ |
922 | keyidx = rx->skb->data[hdrlen + 3] >> 6; | 926 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); |
927 | keyidx = keyid >> 6; | ||
923 | 928 | ||
924 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); | 929 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); |
925 | 930 | ||
@@ -940,6 +945,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
940 | return RX_DROP_MONITOR; | 945 | return RX_DROP_MONITOR; |
941 | } | 946 | } |
942 | 947 | ||
948 | if (skb_linearize(rx->skb)) | ||
949 | return RX_DROP_UNUSABLE; | ||
950 | |||
951 | hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
952 | |||
943 | /* Check for weak IVs if possible */ | 953 | /* Check for weak IVs if possible */ |
944 | if (rx->sta && rx->key->conf.alg == ALG_WEP && | 954 | if (rx->sta && rx->key->conf.alg == ALG_WEP && |
945 | ieee80211_is_data(hdr->frame_control) && | 955 | ieee80211_is_data(hdr->frame_control) && |
@@ -1078,7 +1088,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1078 | sta->rx_fragments++; | 1088 | sta->rx_fragments++; |
1079 | sta->rx_bytes += rx->skb->len; | 1089 | sta->rx_bytes += rx->skb->len; |
1080 | sta->last_signal = status->signal; | 1090 | sta->last_signal = status->signal; |
1081 | sta->last_noise = status->noise; | ||
1082 | 1091 | ||
1083 | /* | 1092 | /* |
1084 | * Change STA power saving mode only at the end of a frame | 1093 | * Change STA power saving mode only at the end of a frame |
@@ -1241,6 +1250,15 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1241 | } | 1250 | } |
1242 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); | 1251 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); |
1243 | 1252 | ||
1253 | if (skb_linearize(rx->skb)) | ||
1254 | return RX_DROP_UNUSABLE; | ||
1255 | |||
1256 | /* | ||
1257 | * skb_linearize() might change the skb->data and | ||
1258 | * previously cached variables (in this case, hdr) need to | ||
1259 | * be refreshed with the new data. | ||
1260 | */ | ||
1261 | hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
1244 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; | 1262 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; |
1245 | 1263 | ||
1246 | if (frag == 0) { | 1264 | if (frag == 0) { |
@@ -1406,21 +1424,24 @@ static int | |||
1406 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | 1424 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) |
1407 | { | 1425 | { |
1408 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1426 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1427 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | ||
1409 | __le16 fc = hdr->frame_control; | 1428 | __le16 fc = hdr->frame_control; |
1410 | int res; | ||
1411 | 1429 | ||
1412 | res = ieee80211_drop_unencrypted(rx, fc); | 1430 | /* |
1413 | if (unlikely(res)) | 1431 | * Pass through unencrypted frames if the hardware has |
1414 | return res; | 1432 | * decrypted them already. |
1433 | */ | ||
1434 | if (status->flag & RX_FLAG_DECRYPTED) | ||
1435 | return 0; | ||
1415 | 1436 | ||
1416 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1437 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1417 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1438 | if (unlikely(!ieee80211_has_protected(fc) && |
1439 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1418 | rx->key)) | 1440 | rx->key)) |
1419 | return -EACCES; | 1441 | return -EACCES; |
1420 | /* BIP does not use Protected field, so need to check MMIE */ | 1442 | /* BIP does not use Protected field, so need to check MMIE */ |
1421 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | 1443 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && |
1422 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | 1444 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) |
1423 | rx->key)) | ||
1424 | return -EACCES; | 1445 | return -EACCES; |
1425 | /* | 1446 | /* |
1426 | * When using MFP, Action frames are not allowed prior to | 1447 | * When using MFP, Action frames are not allowed prior to |
@@ -1598,6 +1619,9 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1598 | skb->dev = dev; | 1619 | skb->dev = dev; |
1599 | __skb_queue_head_init(&frame_list); | 1620 | __skb_queue_head_init(&frame_list); |
1600 | 1621 | ||
1622 | if (skb_linearize(skb)) | ||
1623 | return RX_DROP_UNUSABLE; | ||
1624 | |||
1601 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, | 1625 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, |
1602 | rx->sdata->vif.type, | 1626 | rx->sdata->vif.type, |
1603 | rx->local->hw.extra_tx_headroom); | 1627 | rx->local->hw.extra_tx_headroom); |
@@ -1796,10 +1820,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1796 | if (ieee80211_is_back_req(bar->frame_control)) { | 1820 | if (ieee80211_is_back_req(bar->frame_control)) { |
1797 | if (!rx->sta) | 1821 | if (!rx->sta) |
1798 | return RX_DROP_MONITOR; | 1822 | return RX_DROP_MONITOR; |
1823 | spin_lock(&rx->sta->lock); | ||
1799 | tid = le16_to_cpu(bar->control) >> 12; | 1824 | tid = le16_to_cpu(bar->control) >> 12; |
1800 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] | 1825 | if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) { |
1801 | != HT_AGG_STATE_OPERATIONAL) | 1826 | spin_unlock(&rx->sta->lock); |
1802 | return RX_DROP_MONITOR; | 1827 | return RX_DROP_MONITOR; |
1828 | } | ||
1803 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; | 1829 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; |
1804 | 1830 | ||
1805 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; | 1831 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; |
@@ -1813,6 +1839,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1813 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, | 1839 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, |
1814 | frames); | 1840 | frames); |
1815 | kfree_skb(skb); | 1841 | kfree_skb(skb); |
1842 | spin_unlock(&rx->sta->lock); | ||
1816 | return RX_QUEUED; | 1843 | return RX_QUEUED; |
1817 | } | 1844 | } |
1818 | 1845 | ||
@@ -1974,8 +2001,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1974 | goto handled; | 2001 | goto handled; |
1975 | } | 2002 | } |
1976 | break; | 2003 | break; |
1977 | case MESH_PLINK_CATEGORY: | 2004 | case WLAN_CATEGORY_MESH_PLINK: |
1978 | case MESH_PATH_SEL_CATEGORY: | 2005 | case WLAN_CATEGORY_MESH_PATH_SEL: |
1979 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2006 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1980 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | 2007 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); |
1981 | break; | 2008 | break; |
@@ -2372,29 +2399,42 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2372 | struct ieee80211_local *local = hw_to_local(hw); | 2399 | struct ieee80211_local *local = hw_to_local(hw); |
2373 | struct ieee80211_sub_if_data *sdata; | 2400 | struct ieee80211_sub_if_data *sdata; |
2374 | struct ieee80211_hdr *hdr; | 2401 | struct ieee80211_hdr *hdr; |
2402 | __le16 fc; | ||
2375 | struct ieee80211_rx_data rx; | 2403 | struct ieee80211_rx_data rx; |
2376 | int prepares; | 2404 | int prepares; |
2377 | struct ieee80211_sub_if_data *prev = NULL; | 2405 | struct ieee80211_sub_if_data *prev = NULL; |
2378 | struct sk_buff *skb_new; | 2406 | struct sk_buff *skb_new; |
2379 | struct sta_info *sta, *tmp; | 2407 | struct sta_info *sta, *tmp; |
2380 | bool found_sta = false; | 2408 | bool found_sta = false; |
2409 | int err = 0; | ||
2381 | 2410 | ||
2382 | hdr = (struct ieee80211_hdr *)skb->data; | 2411 | fc = ((struct ieee80211_hdr *)skb->data)->frame_control; |
2383 | memset(&rx, 0, sizeof(rx)); | 2412 | memset(&rx, 0, sizeof(rx)); |
2384 | rx.skb = skb; | 2413 | rx.skb = skb; |
2385 | rx.local = local; | 2414 | rx.local = local; |
2386 | 2415 | ||
2387 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) | 2416 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
2388 | local->dot11ReceivedFragmentCount++; | 2417 | local->dot11ReceivedFragmentCount++; |
2389 | 2418 | ||
2390 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 2419 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
2391 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) | 2420 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) |
2392 | rx.flags |= IEEE80211_RX_IN_SCAN; | 2421 | rx.flags |= IEEE80211_RX_IN_SCAN; |
2393 | 2422 | ||
2423 | if (ieee80211_is_mgmt(fc)) | ||
2424 | err = skb_linearize(skb); | ||
2425 | else | ||
2426 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); | ||
2427 | |||
2428 | if (err) { | ||
2429 | dev_kfree_skb(skb); | ||
2430 | return; | ||
2431 | } | ||
2432 | |||
2433 | hdr = (struct ieee80211_hdr *)skb->data; | ||
2394 | ieee80211_parse_qos(&rx); | 2434 | ieee80211_parse_qos(&rx); |
2395 | ieee80211_verify_alignment(&rx); | 2435 | ieee80211_verify_alignment(&rx); |
2396 | 2436 | ||
2397 | if (ieee80211_is_data(hdr->frame_control)) { | 2437 | if (ieee80211_is_data(fc)) { |
2398 | for_each_sta_info(local, hdr->addr2, sta, tmp) { | 2438 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2399 | rx.sta = sta; | 2439 | rx.sta = sta; |
2400 | found_sta = true; | 2440 | found_sta = true; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 85507bd9e341..e1b0be7a57b9 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <linux/pm_qos_params.h> | ||
18 | #include <net/sch_generic.h> | ||
17 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
18 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
19 | 21 | ||
@@ -83,7 +85,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
83 | { | 85 | { |
84 | struct cfg80211_bss *cbss; | 86 | struct cfg80211_bss *cbss; |
85 | struct ieee80211_bss *bss; | 87 | struct ieee80211_bss *bss; |
86 | int clen; | 88 | int clen, srlen; |
87 | s32 signal = 0; | 89 | s32 signal = 0; |
88 | 90 | ||
89 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 91 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
@@ -112,23 +114,24 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
112 | bss->dtim_period = tim_ie->dtim_period; | 114 | bss->dtim_period = tim_ie->dtim_period; |
113 | } | 115 | } |
114 | 116 | ||
115 | bss->supp_rates_len = 0; | 117 | /* replace old supported rates if we get new values */ |
118 | srlen = 0; | ||
116 | if (elems->supp_rates) { | 119 | if (elems->supp_rates) { |
117 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | 120 | clen = IEEE80211_MAX_SUPP_RATES; |
118 | if (clen > elems->supp_rates_len) | 121 | if (clen > elems->supp_rates_len) |
119 | clen = elems->supp_rates_len; | 122 | clen = elems->supp_rates_len; |
120 | memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, | 123 | memcpy(bss->supp_rates, elems->supp_rates, clen); |
121 | clen); | 124 | srlen += clen; |
122 | bss->supp_rates_len += clen; | ||
123 | } | 125 | } |
124 | if (elems->ext_supp_rates) { | 126 | if (elems->ext_supp_rates) { |
125 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | 127 | clen = IEEE80211_MAX_SUPP_RATES - srlen; |
126 | if (clen > elems->ext_supp_rates_len) | 128 | if (clen > elems->ext_supp_rates_len) |
127 | clen = elems->ext_supp_rates_len; | 129 | clen = elems->ext_supp_rates_len; |
128 | memcpy(&bss->supp_rates[bss->supp_rates_len], | 130 | memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen); |
129 | elems->ext_supp_rates, clen); | 131 | srlen += clen; |
130 | bss->supp_rates_len += clen; | ||
131 | } | 132 | } |
133 | if (srlen) | ||
134 | bss->supp_rates_len = srlen; | ||
132 | 135 | ||
133 | bss->wmm_used = elems->wmm_param || elems->wmm_info; | 136 | bss->wmm_used = elems->wmm_param || elems->wmm_info; |
134 | bss->uapsd_supported = is_uapsd_supported(elems); | 137 | bss->uapsd_supported = is_uapsd_supported(elems); |
@@ -246,6 +249,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
246 | struct ieee80211_local *local = hw_to_local(hw); | 249 | struct ieee80211_local *local = hw_to_local(hw); |
247 | bool was_hw_scan; | 250 | bool was_hw_scan; |
248 | 251 | ||
252 | trace_api_scan_completed(local, aborted); | ||
253 | |||
249 | mutex_lock(&local->scan_mtx); | 254 | mutex_lock(&local->scan_mtx); |
250 | 255 | ||
251 | /* | 256 | /* |
@@ -322,6 +327,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
322 | 327 | ||
323 | ieee80211_offchannel_stop_beaconing(local); | 328 | ieee80211_offchannel_stop_beaconing(local); |
324 | 329 | ||
330 | local->leave_oper_channel_time = 0; | ||
325 | local->next_scan_state = SCAN_DECISION; | 331 | local->next_scan_state = SCAN_DECISION; |
326 | local->scan_channel_idx = 0; | 332 | local->scan_channel_idx = 0; |
327 | 333 | ||
@@ -406,7 +412,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
406 | 412 | ||
407 | if (local->ops->hw_scan) { | 413 | if (local->ops->hw_scan) { |
408 | WARN_ON(!ieee80211_prep_hw_scan(local)); | 414 | WARN_ON(!ieee80211_prep_hw_scan(local)); |
409 | rc = drv_hw_scan(local, local->hw_scan_req); | 415 | rc = drv_hw_scan(local, sdata, local->hw_scan_req); |
410 | } else | 416 | } else |
411 | rc = ieee80211_start_sw_scan(local); | 417 | rc = ieee80211_start_sw_scan(local); |
412 | 418 | ||
@@ -426,11 +432,28 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
426 | return rc; | 432 | return rc; |
427 | } | 433 | } |
428 | 434 | ||
435 | static unsigned long | ||
436 | ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) | ||
437 | { | ||
438 | /* | ||
439 | * TODO: channel switching also consumes quite some time, | ||
440 | * add that delay as well to get a better estimation | ||
441 | */ | ||
442 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) | ||
443 | return IEEE80211_PASSIVE_CHANNEL_TIME; | ||
444 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; | ||
445 | } | ||
446 | |||
429 | static int ieee80211_scan_state_decision(struct ieee80211_local *local, | 447 | static int ieee80211_scan_state_decision(struct ieee80211_local *local, |
430 | unsigned long *next_delay) | 448 | unsigned long *next_delay) |
431 | { | 449 | { |
432 | bool associated = false; | 450 | bool associated = false; |
451 | bool tx_empty = true; | ||
452 | bool bad_latency; | ||
453 | bool listen_int_exceeded; | ||
454 | unsigned long min_beacon_int = 0; | ||
433 | struct ieee80211_sub_if_data *sdata; | 455 | struct ieee80211_sub_if_data *sdata; |
456 | struct ieee80211_channel *next_chan; | ||
434 | 457 | ||
435 | /* if no more bands/channels left, complete scan and advance to the idle state */ | 458 | /* if no more bands/channels left, complete scan and advance to the idle state */ |
436 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | 459 | if (local->scan_channel_idx >= local->scan_req->n_channels) { |
@@ -438,7 +461,11 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
438 | return 1; | 461 | return 1; |
439 | } | 462 | } |
440 | 463 | ||
441 | /* check if at least one STA interface is associated */ | 464 | /* |
465 | * check if at least one STA interface is associated, | ||
466 | * check if at least one STA interface has pending tx frames | ||
467 | * and grab the lowest used beacon interval | ||
468 | */ | ||
442 | mutex_lock(&local->iflist_mtx); | 469 | mutex_lock(&local->iflist_mtx); |
443 | list_for_each_entry(sdata, &local->interfaces, list) { | 470 | list_for_each_entry(sdata, &local->interfaces, list) { |
444 | if (!ieee80211_sdata_running(sdata)) | 471 | if (!ieee80211_sdata_running(sdata)) |
@@ -447,7 +474,16 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
447 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 474 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
448 | if (sdata->u.mgd.associated) { | 475 | if (sdata->u.mgd.associated) { |
449 | associated = true; | 476 | associated = true; |
450 | break; | 477 | |
478 | if (sdata->vif.bss_conf.beacon_int < | ||
479 | min_beacon_int || min_beacon_int == 0) | ||
480 | min_beacon_int = | ||
481 | sdata->vif.bss_conf.beacon_int; | ||
482 | |||
483 | if (!qdisc_all_tx_empty(sdata->dev)) { | ||
484 | tx_empty = false; | ||
485 | break; | ||
486 | } | ||
451 | } | 487 | } |
452 | } | 488 | } |
453 | } | 489 | } |
@@ -456,11 +492,34 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
456 | if (local->scan_channel) { | 492 | if (local->scan_channel) { |
457 | /* | 493 | /* |
458 | * we're currently scanning a different channel, let's | 494 | * we're currently scanning a different channel, let's |
459 | * switch back to the operating channel now if at least | 495 | * see if we can scan another channel without interfering |
460 | * one interface is associated. Otherwise just scan the | 496 | * with the current traffic situation. |
461 | * next channel | 497 | * |
498 | * Since we don't know if the AP has pending frames for us | ||
499 | * we can only check for our tx queues and use the current | ||
500 | * pm_qos requirements for rx. Hence, if no tx traffic occurs | ||
501 | * at all we will scan as many channels in a row as the pm_qos | ||
502 | * latency allows us to. Additionally we also check for the | ||
503 | * currently negotiated listen interval to prevent losing | ||
504 | * frames unnecessarily. | ||
505 | * | ||
506 | * Otherwise switch back to the operating channel. | ||
462 | */ | 507 | */ |
463 | if (associated) | 508 | next_chan = local->scan_req->channels[local->scan_channel_idx]; |
509 | |||
510 | bad_latency = time_after(jiffies + | ||
511 | ieee80211_scan_get_channel_time(next_chan), | ||
512 | local->leave_oper_channel_time + | ||
513 | usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY))); | ||
514 | |||
515 | listen_int_exceeded = time_after(jiffies + | ||
516 | ieee80211_scan_get_channel_time(next_chan), | ||
517 | local->leave_oper_channel_time + | ||
518 | usecs_to_jiffies(min_beacon_int * 1024) * | ||
519 | local->hw.conf.listen_interval); | ||
520 | |||
521 | if (associated && ( !tx_empty || bad_latency || | ||
522 | listen_int_exceeded)) | ||
464 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; | 523 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; |
465 | else | 524 | else |
466 | local->next_scan_state = SCAN_SET_CHANNEL; | 525 | local->next_scan_state = SCAN_SET_CHANNEL; |
@@ -492,6 +551,9 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca | |||
492 | else | 551 | else |
493 | *next_delay = HZ / 10; | 552 | *next_delay = HZ / 10; |
494 | 553 | ||
554 | /* remember when we left the operating channel */ | ||
555 | local->leave_oper_channel_time = jiffies; | ||
556 | |||
495 | /* advance to the next channel to be scanned */ | 557 | /* advance to the next channel to be scanned */ |
496 | local->next_scan_state = SCAN_SET_CHANNEL; | 558 | local->next_scan_state = SCAN_SET_CHANNEL; |
497 | } | 559 | } |
@@ -594,7 +656,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
594 | } | 656 | } |
595 | 657 | ||
596 | if (local->hw_scan_req) { | 658 | if (local->hw_scan_req) { |
597 | int rc = drv_hw_scan(local, local->hw_scan_req); | 659 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); |
598 | mutex_unlock(&local->scan_mtx); | 660 | mutex_unlock(&local->scan_mtx); |
599 | if (rc) | 661 | if (rc) |
600 | ieee80211_scan_completed(&local->hw, true); | 662 | ieee80211_scan_completed(&local->hw, true); |
@@ -667,10 +729,12 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
667 | } | 729 | } |
668 | 730 | ||
669 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | 731 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, |
670 | const u8 *ssid, u8 ssid_len) | 732 | const u8 *ssid, u8 ssid_len, |
733 | struct ieee80211_channel *chan) | ||
671 | { | 734 | { |
672 | struct ieee80211_local *local = sdata->local; | 735 | struct ieee80211_local *local = sdata->local; |
673 | int ret = -EBUSY; | 736 | int ret = -EBUSY; |
737 | enum nl80211_band band; | ||
674 | 738 | ||
675 | mutex_lock(&local->scan_mtx); | 739 | mutex_lock(&local->scan_mtx); |
676 | 740 | ||
@@ -678,6 +742,30 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
678 | if (local->scan_req) | 742 | if (local->scan_req) |
679 | goto unlock; | 743 | goto unlock; |
680 | 744 | ||
745 | /* fill internal scan request */ | ||
746 | if (!chan) { | ||
747 | int i, nchan = 0; | ||
748 | |||
749 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
750 | if (!local->hw.wiphy->bands[band]) | ||
751 | continue; | ||
752 | for (i = 0; | ||
753 | i < local->hw.wiphy->bands[band]->n_channels; | ||
754 | i++) { | ||
755 | local->int_scan_req->channels[nchan] = | ||
756 | &local->hw.wiphy->bands[band]->channels[i]; | ||
757 | nchan++; | ||
758 | } | ||
759 | } | ||
760 | |||
761 | local->int_scan_req->n_channels = nchan; | ||
762 | } else { | ||
763 | local->int_scan_req->channels[0] = chan; | ||
764 | local->int_scan_req->n_channels = 1; | ||
765 | } | ||
766 | |||
767 | local->int_scan_req->ssids = &local->scan_ssid; | ||
768 | local->int_scan_req->n_ssids = 1; | ||
681 | memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); | 769 | memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); |
682 | local->int_scan_req->ssids[0].ssid_len = ssid_len; | 770 | local->int_scan_req->ssids[0].ssid_len = ssid_len; |
683 | 771 | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index fb12cec4d333..730197591ab5 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -250,9 +250,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
250 | * enable session_timer's data differentiation. refer to | 250 | * enable session_timer's data differentiation. refer to |
251 | * sta_rx_agg_session_timer_expired for useage */ | 251 | * sta_rx_agg_session_timer_expired for useage */ |
252 | sta->timer_to_tid[i] = i; | 252 | sta->timer_to_tid[i] = i; |
253 | /* rx */ | ||
254 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; | ||
255 | sta->ampdu_mlme.tid_rx[i] = NULL; | ||
256 | /* tx */ | 253 | /* tx */ |
257 | sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; | 254 | sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; |
258 | sta->ampdu_mlme.tid_tx[i] = NULL; | 255 | sta->ampdu_mlme.tid_tx[i] = NULL; |
@@ -578,7 +575,7 @@ static int sta_info_buffer_expired(struct sta_info *sta, | |||
578 | } | 575 | } |
579 | 576 | ||
580 | 577 | ||
581 | static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | 578 | static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, |
582 | struct sta_info *sta) | 579 | struct sta_info *sta) |
583 | { | 580 | { |
584 | unsigned long flags; | 581 | unsigned long flags; |
@@ -586,7 +583,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
586 | struct ieee80211_sub_if_data *sdata; | 583 | struct ieee80211_sub_if_data *sdata; |
587 | 584 | ||
588 | if (skb_queue_empty(&sta->ps_tx_buf)) | 585 | if (skb_queue_empty(&sta->ps_tx_buf)) |
589 | return; | 586 | return false; |
590 | 587 | ||
591 | for (;;) { | 588 | for (;;) { |
592 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); | 589 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); |
@@ -611,6 +608,8 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
611 | if (skb_queue_empty(&sta->ps_tx_buf)) | 608 | if (skb_queue_empty(&sta->ps_tx_buf)) |
612 | sta_info_clear_tim_bit(sta); | 609 | sta_info_clear_tim_bit(sta); |
613 | } | 610 | } |
611 | |||
612 | return true; | ||
614 | } | 613 | } |
615 | 614 | ||
616 | static int __must_check __sta_info_destroy(struct sta_info *sta) | 615 | static int __must_check __sta_info_destroy(struct sta_info *sta) |
@@ -619,7 +618,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
619 | struct ieee80211_sub_if_data *sdata; | 618 | struct ieee80211_sub_if_data *sdata; |
620 | struct sk_buff *skb; | 619 | struct sk_buff *skb; |
621 | unsigned long flags; | 620 | unsigned long flags; |
622 | int ret, i; | 621 | int ret; |
623 | 622 | ||
624 | might_sleep(); | 623 | might_sleep(); |
625 | 624 | ||
@@ -629,6 +628,15 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
629 | local = sta->local; | 628 | local = sta->local; |
630 | sdata = sta->sdata; | 629 | sdata = sta->sdata; |
631 | 630 | ||
631 | /* | ||
632 | * Before removing the station from the driver and | ||
633 | * rate control, it might still start new aggregation | ||
634 | * sessions -- block that to make sure the tear-down | ||
635 | * will be sufficient. | ||
636 | */ | ||
637 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | ||
638 | ieee80211_sta_tear_down_BA_sessions(sta); | ||
639 | |||
632 | spin_lock_irqsave(&local->sta_lock, flags); | 640 | spin_lock_irqsave(&local->sta_lock, flags); |
633 | ret = sta_info_hash_del(local, sta); | 641 | ret = sta_info_hash_del(local, sta); |
634 | /* this might still be the pending list ... which is fine */ | 642 | /* this might still be the pending list ... which is fine */ |
@@ -645,9 +653,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
645 | * may mean it is removed from hardware which requires that | 653 | * may mean it is removed from hardware which requires that |
646 | * the key->sta pointer is still valid, so flush the key todo | 654 | * the key->sta pointer is still valid, so flush the key todo |
647 | * list here. | 655 | * list here. |
648 | * | ||
649 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
650 | * nothing can reference this sta struct any more. | ||
651 | */ | 656 | */ |
652 | ieee80211_key_todo(); | 657 | ieee80211_key_todo(); |
653 | 658 | ||
@@ -679,11 +684,17 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
679 | sdata = sta->sdata; | 684 | sdata = sta->sdata; |
680 | } | 685 | } |
681 | 686 | ||
687 | /* | ||
688 | * At this point, after we wait for an RCU grace period, | ||
689 | * neither mac80211 nor the driver can reference this | ||
690 | * sta struct any more except by still existing timers | ||
691 | * associated with this station that we clean up below. | ||
692 | */ | ||
693 | synchronize_rcu(); | ||
694 | |||
682 | #ifdef CONFIG_MAC80211_MESH | 695 | #ifdef CONFIG_MAC80211_MESH |
683 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 696 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
684 | mesh_accept_plinks_update(sdata); | 697 | mesh_accept_plinks_update(sdata); |
685 | del_timer(&sta->plink_timer); | ||
686 | } | ||
687 | #endif | 698 | #endif |
688 | 699 | ||
689 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 700 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -710,50 +721,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
710 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | 721 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) |
711 | dev_kfree_skb_any(skb); | 722 | dev_kfree_skb_any(skb); |
712 | 723 | ||
713 | for (i = 0; i < STA_TID_NUM; i++) { | ||
714 | struct tid_ampdu_rx *tid_rx; | ||
715 | struct tid_ampdu_tx *tid_tx; | ||
716 | |||
717 | spin_lock_bh(&sta->lock); | ||
718 | tid_rx = sta->ampdu_mlme.tid_rx[i]; | ||
719 | /* Make sure timer won't free the tid_rx struct, see below */ | ||
720 | if (tid_rx) | ||
721 | tid_rx->shutdown = true; | ||
722 | |||
723 | spin_unlock_bh(&sta->lock); | ||
724 | |||
725 | /* | ||
726 | * Outside spinlock - shutdown is true now so that the timer | ||
727 | * won't free tid_rx, we have to do that now. Can't let the | ||
728 | * timer do it because we have to sync the timer outside the | ||
729 | * lock that it takes itself. | ||
730 | */ | ||
731 | if (tid_rx) { | ||
732 | del_timer_sync(&tid_rx->session_timer); | ||
733 | kfree(tid_rx); | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | * No need to do such complications for TX agg sessions, the | ||
738 | * path leading to freeing the tid_tx struct goes via a call | ||
739 | * from the driver, and thus needs to look up the sta struct | ||
740 | * again, which cannot be found when we get here. Hence, we | ||
741 | * just need to delete the timer and free the aggregation | ||
742 | * info; we won't be telling the peer about it then but that | ||
743 | * doesn't matter if we're not talking to it again anyway. | ||
744 | */ | ||
745 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
746 | if (tid_tx) { | ||
747 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
748 | /* | ||
749 | * STA removed while aggregation session being | ||
750 | * started? Bit odd, but purge frames anyway. | ||
751 | */ | ||
752 | skb_queue_purge(&tid_tx->pending); | ||
753 | kfree(tid_tx); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | __sta_info_free(local, sta); | 724 | __sta_info_free(local, sta); |
758 | 725 | ||
759 | return 0; | 726 | return 0; |
@@ -790,15 +757,20 @@ static void sta_info_cleanup(unsigned long data) | |||
790 | { | 757 | { |
791 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 758 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
792 | struct sta_info *sta; | 759 | struct sta_info *sta; |
760 | bool timer_needed = false; | ||
793 | 761 | ||
794 | rcu_read_lock(); | 762 | rcu_read_lock(); |
795 | list_for_each_entry_rcu(sta, &local->sta_list, list) | 763 | list_for_each_entry_rcu(sta, &local->sta_list, list) |
796 | sta_info_cleanup_expire_buffered(local, sta); | 764 | if (sta_info_cleanup_expire_buffered(local, sta)) |
765 | timer_needed = true; | ||
797 | rcu_read_unlock(); | 766 | rcu_read_unlock(); |
798 | 767 | ||
799 | if (local->quiescing) | 768 | if (local->quiescing) |
800 | return; | 769 | return; |
801 | 770 | ||
771 | if (!timer_needed) | ||
772 | return; | ||
773 | |||
802 | local->sta_cleanup.expires = | 774 | local->sta_cleanup.expires = |
803 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 775 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
804 | add_timer(&local->sta_cleanup); | 776 | add_timer(&local->sta_cleanup); |
@@ -883,8 +855,12 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, | |||
883 | struct sta_info *sta, *nxt; | 855 | struct sta_info *sta, *nxt; |
884 | 856 | ||
885 | /* Just return a random station ... first in list ... */ | 857 | /* Just return a random station ... first in list ... */ |
886 | for_each_sta_info(hw_to_local(hw), addr, sta, nxt) | 858 | for_each_sta_info(hw_to_local(hw), addr, sta, nxt) { |
859 | if (!sta->uploaded) | ||
860 | return NULL; | ||
887 | return &sta->sta; | 861 | return &sta->sta; |
862 | } | ||
863 | |||
888 | return NULL; | 864 | return NULL; |
889 | } | 865 | } |
890 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); | 866 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); |
@@ -892,14 +868,19 @@ EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); | |||
892 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, | 868 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, |
893 | const u8 *addr) | 869 | const u8 *addr) |
894 | { | 870 | { |
895 | struct ieee80211_sub_if_data *sdata; | 871 | struct sta_info *sta; |
896 | 872 | ||
897 | if (!vif) | 873 | if (!vif) |
898 | return NULL; | 874 | return NULL; |
899 | 875 | ||
900 | sdata = vif_to_sdata(vif); | 876 | sta = sta_info_get_bss(vif_to_sdata(vif), addr); |
877 | if (!sta) | ||
878 | return NULL; | ||
879 | |||
880 | if (!sta->uploaded) | ||
881 | return NULL; | ||
901 | 882 | ||
902 | return ieee80211_find_sta_by_hw(&sdata->local->hw, addr); | 883 | return &sta->sta; |
903 | } | 884 | } |
904 | EXPORT_SYMBOL(ieee80211_find_sta); | 885 | EXPORT_SYMBOL(ieee80211_find_sta); |
905 | 886 | ||
@@ -992,6 +973,8 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
992 | { | 973 | { |
993 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 974 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
994 | 975 | ||
976 | trace_api_sta_block_awake(sta->local, pubsta, block); | ||
977 | |||
995 | if (block) | 978 | if (block) |
996 | set_sta_flags(sta, WLAN_STA_PS_DRIVER); | 979 | set_sta_flags(sta, WLAN_STA_PS_DRIVER); |
997 | else | 980 | else |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 822d84522937..48a5e80957f0 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -35,8 +35,8 @@ | |||
35 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next | 35 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next |
36 | * frame to this station is transmitted. | 36 | * frame to this station is transmitted. |
37 | * @WLAN_STA_MFP: Management frame protection is used with this STA. | 37 | * @WLAN_STA_MFP: Management frame protection is used with this STA. |
38 | * @WLAN_STA_SUSPEND: Set/cleared during a suspend/resume cycle. | 38 | * @WLAN_STA_BLOCK_BA: Used to deny ADDBA requests (both TX and RX) |
39 | * Used to deny ADDBA requests (both TX and RX). | 39 | * during suspend/resume and station removal. |
40 | * @WLAN_STA_PS_DRIVER: driver requires keeping this station in | 40 | * @WLAN_STA_PS_DRIVER: driver requires keeping this station in |
41 | * power-save mode logically to flush frames that might still | 41 | * power-save mode logically to flush frames that might still |
42 | * be in the queues | 42 | * be in the queues |
@@ -57,7 +57,7 @@ enum ieee80211_sta_info_flags { | |||
57 | WLAN_STA_WDS = 1<<7, | 57 | WLAN_STA_WDS = 1<<7, |
58 | WLAN_STA_CLEAR_PS_FILT = 1<<9, | 58 | WLAN_STA_CLEAR_PS_FILT = 1<<9, |
59 | WLAN_STA_MFP = 1<<10, | 59 | WLAN_STA_MFP = 1<<10, |
60 | WLAN_STA_SUSPEND = 1<<11, | 60 | WLAN_STA_BLOCK_BA = 1<<11, |
61 | WLAN_STA_PS_DRIVER = 1<<12, | 61 | WLAN_STA_PS_DRIVER = 1<<12, |
62 | WLAN_STA_PSPOLL = 1<<13, | 62 | WLAN_STA_PSPOLL = 1<<13, |
63 | WLAN_STA_DISASSOC = 1<<14, | 63 | WLAN_STA_DISASSOC = 1<<14, |
@@ -106,7 +106,6 @@ struct tid_ampdu_tx { | |||
106 | * @buf_size: buffer size for incoming A-MPDUs | 106 | * @buf_size: buffer size for incoming A-MPDUs |
107 | * @timeout: reset timer value (in TUs). | 107 | * @timeout: reset timer value (in TUs). |
108 | * @dialog_token: dialog token for aggregation session | 108 | * @dialog_token: dialog token for aggregation session |
109 | * @shutdown: this session is being shut down due to STA removal | ||
110 | */ | 109 | */ |
111 | struct tid_ampdu_rx { | 110 | struct tid_ampdu_rx { |
112 | struct sk_buff **reorder_buf; | 111 | struct sk_buff **reorder_buf; |
@@ -118,7 +117,6 @@ struct tid_ampdu_rx { | |||
118 | u16 buf_size; | 117 | u16 buf_size; |
119 | u16 timeout; | 118 | u16 timeout; |
120 | u8 dialog_token; | 119 | u8 dialog_token; |
121 | bool shutdown; | ||
122 | }; | 120 | }; |
123 | 121 | ||
124 | /** | 122 | /** |
@@ -156,7 +154,7 @@ enum plink_state { | |||
156 | */ | 154 | */ |
157 | struct sta_ampdu_mlme { | 155 | struct sta_ampdu_mlme { |
158 | /* rx */ | 156 | /* rx */ |
159 | u8 tid_state_rx[STA_TID_NUM]; | 157 | bool tid_active_rx[STA_TID_NUM]; |
160 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; | 158 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; |
161 | /* tx */ | 159 | /* tx */ |
162 | u8 tid_state_tx[STA_TID_NUM]; | 160 | u8 tid_state_tx[STA_TID_NUM]; |
@@ -200,7 +198,6 @@ struct sta_ampdu_mlme { | |||
200 | * @rx_fragments: number of received MPDUs | 198 | * @rx_fragments: number of received MPDUs |
201 | * @rx_dropped: number of dropped MPDUs from this STA | 199 | * @rx_dropped: number of dropped MPDUs from this STA |
202 | * @last_signal: signal of last received frame from this STA | 200 | * @last_signal: signal of last received frame from this STA |
203 | * @last_noise: noise of last received frame from this STA | ||
204 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) | 201 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) |
205 | * @tx_filtered_count: number of frames the hardware filtered for this STA | 202 | * @tx_filtered_count: number of frames the hardware filtered for this STA |
206 | * @tx_retry_failed: number of frames that failed retry | 203 | * @tx_retry_failed: number of frames that failed retry |
@@ -267,7 +264,6 @@ struct sta_info { | |||
267 | unsigned long rx_fragments; | 264 | unsigned long rx_fragments; |
268 | unsigned long rx_dropped; | 265 | unsigned long rx_dropped; |
269 | int last_signal; | 266 | int last_signal; |
270 | int last_noise; | ||
271 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 267 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; |
272 | 268 | ||
273 | /* Updated from TX status path only, no locking requirements */ | 269 | /* Updated from TX status path only, no locking requirements */ |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 56d5b9a6ec5b..94613af009f3 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -171,13 +171,16 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
171 | struct net_device *prev_dev = NULL; | 171 | struct net_device *prev_dev = NULL; |
172 | struct sta_info *sta, *tmp; | 172 | struct sta_info *sta, *tmp; |
173 | int retry_count = -1, i; | 173 | int retry_count = -1, i; |
174 | bool injected; | 174 | int rates_idx = -1; |
175 | bool send_to_cooked; | ||
175 | 176 | ||
176 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 177 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
177 | /* the HW cannot have attempted that rate */ | 178 | /* the HW cannot have attempted that rate */ |
178 | if (i >= hw->max_rates) { | 179 | if (i >= hw->max_rates) { |
179 | info->status.rates[i].idx = -1; | 180 | info->status.rates[i].idx = -1; |
180 | info->status.rates[i].count = 0; | 181 | info->status.rates[i].count = 0; |
182 | } else if (info->status.rates[i].idx >= 0) { | ||
183 | rates_idx = i; | ||
181 | } | 184 | } |
182 | 185 | ||
183 | retry_count += info->status.rates[i].count; | 186 | retry_count += info->status.rates[i].count; |
@@ -206,6 +209,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
206 | return; | 209 | return; |
207 | } | 210 | } |
208 | 211 | ||
212 | if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && | ||
213 | (rates_idx != -1)) | ||
214 | sta->last_tx_rate = info->status.rates[rates_idx]; | ||
215 | |||
209 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | 216 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && |
210 | (ieee80211_is_data_qos(fc))) { | 217 | (ieee80211_is_data_qos(fc))) { |
211 | u16 tid, ssn; | 218 | u16 tid, ssn; |
@@ -296,11 +303,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
296 | /* this was a transmitted frame, but now we want to reuse it */ | 303 | /* this was a transmitted frame, but now we want to reuse it */ |
297 | skb_orphan(skb); | 304 | skb_orphan(skb); |
298 | 305 | ||
306 | /* Need to make a copy before skb->cb gets cleared */ | ||
307 | send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) || | ||
308 | (type != IEEE80211_FTYPE_DATA); | ||
309 | |||
299 | /* | 310 | /* |
300 | * This is a bit racy but we can avoid a lot of work | 311 | * This is a bit racy but we can avoid a lot of work |
301 | * with this test... | 312 | * with this test... |
302 | */ | 313 | */ |
303 | if (!local->monitors && !local->cooked_mntrs) { | 314 | if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) { |
304 | dev_kfree_skb(skb); | 315 | dev_kfree_skb(skb); |
305 | return; | 316 | return; |
306 | } | 317 | } |
@@ -345,9 +356,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
345 | /* for now report the total retry_count */ | 356 | /* for now report the total retry_count */ |
346 | rthdr->data_retries = retry_count; | 357 | rthdr->data_retries = retry_count; |
347 | 358 | ||
348 | /* Need to make a copy before skb->cb gets cleared */ | ||
349 | injected = !!(info->flags & IEEE80211_TX_CTL_INJECTED); | ||
350 | |||
351 | /* XXX: is this sufficient for BPF? */ | 359 | /* XXX: is this sufficient for BPF? */ |
352 | skb_set_mac_header(skb, 0); | 360 | skb_set_mac_header(skb, 0); |
353 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 361 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -362,8 +370,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
362 | continue; | 370 | continue; |
363 | 371 | ||
364 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && | 372 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && |
365 | !injected && | 373 | !send_to_cooked) |
366 | (type == IEEE80211_FTYPE_DATA)) | ||
367 | continue; | 374 | continue; |
368 | 375 | ||
369 | if (prev_dev) { | 376 | if (prev_dev) { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index cfc473e1b050..680bcb7093db 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -429,6 +429,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
429 | struct sta_info *sta = tx->sta; | 429 | struct sta_info *sta = tx->sta; |
430 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 430 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
431 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 431 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
432 | struct ieee80211_local *local = tx->local; | ||
432 | u32 staflags; | 433 | u32 staflags; |
433 | 434 | ||
434 | if (unlikely(!sta || | 435 | if (unlikely(!sta || |
@@ -476,6 +477,12 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
476 | info->control.vif = &tx->sdata->vif; | 477 | info->control.vif = &tx->sdata->vif; |
477 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 478 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
478 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); | 479 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); |
480 | |||
481 | if (!timer_pending(&local->sta_cleanup)) | ||
482 | mod_timer(&local->sta_cleanup, | ||
483 | round_jiffies(jiffies + | ||
484 | STA_INFO_CLEANUP_INTERVAL)); | ||
485 | |||
479 | return TX_QUEUED; | 486 | return TX_QUEUED; |
480 | } | 487 | } |
481 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 488 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
@@ -513,6 +520,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
513 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 520 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) |
514 | tx->key = key; | 521 | tx->key = key; |
515 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 522 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
523 | is_multicast_ether_addr(hdr->addr1) && | ||
524 | ieee80211_is_robust_mgmt_frame(hdr) && | ||
516 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | 525 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) |
517 | tx->key = key; | 526 | tx->key = key; |
518 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 527 | else if ((key = rcu_dereference(tx->sdata->default_key))) |
@@ -584,7 +593,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
584 | struct ieee80211_hdr *hdr = (void *)tx->skb->data; | 593 | struct ieee80211_hdr *hdr = (void *)tx->skb->data; |
585 | struct ieee80211_supported_band *sband; | 594 | struct ieee80211_supported_band *sband; |
586 | struct ieee80211_rate *rate; | 595 | struct ieee80211_rate *rate; |
587 | int i, len; | 596 | int i; |
597 | u32 len; | ||
588 | bool inval = false, rts = false, short_preamble = false; | 598 | bool inval = false, rts = false, short_preamble = false; |
589 | struct ieee80211_tx_rate_control txrc; | 599 | struct ieee80211_tx_rate_control txrc; |
590 | u32 sta_flags; | 600 | u32 sta_flags; |
@@ -593,7 +603,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
593 | 603 | ||
594 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 604 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
595 | 605 | ||
596 | len = min_t(int, tx->skb->len + FCS_LEN, | 606 | len = min_t(u32, tx->skb->len + FCS_LEN, |
597 | tx->local->hw.wiphy->frag_threshold); | 607 | tx->local->hw.wiphy->frag_threshold); |
598 | 608 | ||
599 | /* set up the tx rate control struct we give the RC algo */ | 609 | /* set up the tx rate control struct we give the RC algo */ |
@@ -1142,13 +1152,12 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1142 | 1152 | ||
1143 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && | 1153 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && |
1144 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { | 1154 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { |
1145 | unsigned long flags; | ||
1146 | struct tid_ampdu_tx *tid_tx; | 1155 | struct tid_ampdu_tx *tid_tx; |
1147 | 1156 | ||
1148 | qc = ieee80211_get_qos_ctl(hdr); | 1157 | qc = ieee80211_get_qos_ctl(hdr); |
1149 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 1158 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
1150 | 1159 | ||
1151 | spin_lock_irqsave(&tx->sta->lock, flags); | 1160 | spin_lock(&tx->sta->lock); |
1152 | /* | 1161 | /* |
1153 | * XXX: This spinlock could be fairly expensive, but see the | 1162 | * XXX: This spinlock could be fairly expensive, but see the |
1154 | * comment in agg-tx.c:ieee80211_agg_tx_operational(). | 1163 | * comment in agg-tx.c:ieee80211_agg_tx_operational(). |
@@ -1173,7 +1182,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1173 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1182 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1174 | __skb_queue_tail(&tid_tx->pending, skb); | 1183 | __skb_queue_tail(&tid_tx->pending, skb); |
1175 | } | 1184 | } |
1176 | spin_unlock_irqrestore(&tx->sta->lock, flags); | 1185 | spin_unlock(&tx->sta->lock); |
1177 | 1186 | ||
1178 | if (unlikely(queued)) | 1187 | if (unlikely(queued)) |
1179 | return TX_QUEUED; | 1188 | return TX_QUEUED; |
@@ -2011,14 +2020,12 @@ void ieee80211_tx_pending(unsigned long data) | |||
2011 | while (!skb_queue_empty(&local->pending[i])) { | 2020 | while (!skb_queue_empty(&local->pending[i])) { |
2012 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); | 2021 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); |
2013 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2022 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2014 | struct ieee80211_sub_if_data *sdata; | ||
2015 | 2023 | ||
2016 | if (WARN_ON(!info->control.vif)) { | 2024 | if (WARN_ON(!info->control.vif)) { |
2017 | kfree_skb(skb); | 2025 | kfree_skb(skb); |
2018 | continue; | 2026 | continue; |
2019 | } | 2027 | } |
2020 | 2028 | ||
2021 | sdata = vif_to_sdata(info->control.vif); | ||
2022 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 2029 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
2023 | flags); | 2030 | flags); |
2024 | 2031 | ||
@@ -2244,8 +2251,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2244 | 2251 | ||
2245 | info->control.vif = vif; | 2252 | info->control.vif = vif; |
2246 | 2253 | ||
2247 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 2254 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT | |
2248 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | 2255 | IEEE80211_TX_CTL_ASSIGN_SEQ | |
2256 | IEEE80211_TX_CTL_FIRST_FRAGMENT; | ||
2249 | out: | 2257 | out: |
2250 | rcu_read_unlock(); | 2258 | rcu_read_unlock(); |
2251 | return skb; | 2259 | return skb; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 53af57047435..5b79d552780a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -270,6 +270,8 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
270 | struct ieee80211_local *local = hw_to_local(hw); | 270 | struct ieee80211_local *local = hw_to_local(hw); |
271 | struct ieee80211_sub_if_data *sdata; | 271 | struct ieee80211_sub_if_data *sdata; |
272 | 272 | ||
273 | trace_wake_queue(local, queue, reason); | ||
274 | |||
273 | if (WARN_ON(queue >= hw->queues)) | 275 | if (WARN_ON(queue >= hw->queues)) |
274 | return; | 276 | return; |
275 | 277 | ||
@@ -312,6 +314,8 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
312 | struct ieee80211_local *local = hw_to_local(hw); | 314 | struct ieee80211_local *local = hw_to_local(hw); |
313 | struct ieee80211_sub_if_data *sdata; | 315 | struct ieee80211_sub_if_data *sdata; |
314 | 316 | ||
317 | trace_stop_queue(local, queue, reason); | ||
318 | |||
315 | if (WARN_ON(queue >= hw->queues)) | 319 | if (WARN_ON(queue >= hw->queues)) |
316 | return; | 320 | return; |
317 | 321 | ||
@@ -796,6 +800,11 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
796 | 800 | ||
797 | drv_conf_tx(local, queue, &qparam); | 801 | drv_conf_tx(local, queue, &qparam); |
798 | } | 802 | } |
803 | |||
804 | /* after reinitialize QoS TX queues setting to default, | ||
805 | * disable QoS at all */ | ||
806 | local->hw.conf.flags &= ~IEEE80211_CONF_QOS; | ||
807 | drv_config(local, IEEE80211_CONF_CHANGE_QOS); | ||
799 | } | 808 | } |
800 | 809 | ||
801 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 810 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
@@ -1135,7 +1144,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1135 | 1144 | ||
1136 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 1145 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
1137 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 1146 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
1138 | clear_sta_flags(sta, WLAN_STA_SUSPEND); | 1147 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); |
1139 | } | 1148 | } |
1140 | } | 1149 | } |
1141 | 1150 | ||
@@ -1151,18 +1160,33 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1151 | 1160 | ||
1152 | /* Finally also reconfigure all the BSS information */ | 1161 | /* Finally also reconfigure all the BSS information */ |
1153 | list_for_each_entry(sdata, &local->interfaces, list) { | 1162 | list_for_each_entry(sdata, &local->interfaces, list) { |
1154 | u32 changed = ~0; | 1163 | u32 changed; |
1164 | |||
1155 | if (!ieee80211_sdata_running(sdata)) | 1165 | if (!ieee80211_sdata_running(sdata)) |
1156 | continue; | 1166 | continue; |
1167 | |||
1168 | /* common change flags for all interface types */ | ||
1169 | changed = BSS_CHANGED_ERP_CTS_PROT | | ||
1170 | BSS_CHANGED_ERP_PREAMBLE | | ||
1171 | BSS_CHANGED_ERP_SLOT | | ||
1172 | BSS_CHANGED_HT | | ||
1173 | BSS_CHANGED_BASIC_RATES | | ||
1174 | BSS_CHANGED_BEACON_INT | | ||
1175 | BSS_CHANGED_BSSID | | ||
1176 | BSS_CHANGED_CQM; | ||
1177 | |||
1157 | switch (sdata->vif.type) { | 1178 | switch (sdata->vif.type) { |
1158 | case NL80211_IFTYPE_STATION: | 1179 | case NL80211_IFTYPE_STATION: |
1159 | /* disable beacon change bits */ | 1180 | changed |= BSS_CHANGED_ASSOC; |
1160 | changed &= ~(BSS_CHANGED_BEACON | | 1181 | ieee80211_bss_info_change_notify(sdata, changed); |
1161 | BSS_CHANGED_BEACON_ENABLED); | 1182 | break; |
1162 | /* fall through */ | ||
1163 | case NL80211_IFTYPE_ADHOC: | 1183 | case NL80211_IFTYPE_ADHOC: |
1184 | changed |= BSS_CHANGED_IBSS; | ||
1185 | /* fall through */ | ||
1164 | case NL80211_IFTYPE_AP: | 1186 | case NL80211_IFTYPE_AP: |
1165 | case NL80211_IFTYPE_MESH_POINT: | 1187 | case NL80211_IFTYPE_MESH_POINT: |
1188 | changed |= BSS_CHANGED_BEACON | | ||
1189 | BSS_CHANGED_BEACON_ENABLED; | ||
1166 | ieee80211_bss_info_change_notify(sdata, changed); | 1190 | ieee80211_bss_info_change_notify(sdata, changed); |
1167 | break; | 1191 | break; |
1168 | case NL80211_IFTYPE_WDS: | 1192 | case NL80211_IFTYPE_WDS: |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 15e1ba931b87..be3d4a698692 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #define IEEE80211_MAX_PROBE_TRIES 5 | 33 | #define IEEE80211_MAX_PROBE_TRIES 5 |
34 | 34 | ||
35 | enum work_action { | 35 | enum work_action { |
36 | WORK_ACT_MISMATCH, | ||
36 | WORK_ACT_NONE, | 37 | WORK_ACT_NONE, |
37 | WORK_ACT_TIMEOUT, | 38 | WORK_ACT_TIMEOUT, |
38 | WORK_ACT_DONE, | 39 | WORK_ACT_DONE, |
@@ -213,15 +214,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
213 | 214 | ||
214 | sband = local->hw.wiphy->bands[wk->chan->band]; | 215 | sband = local->hw.wiphy->bands[wk->chan->band]; |
215 | 216 | ||
216 | /* | 217 | if (wk->assoc.supp_rates_len) { |
217 | * Get all rates supported by the device and the AP as | 218 | /* |
218 | * some APs don't like getting a superset of their rates | 219 | * Get all rates supported by the device and the AP as |
219 | * in the association request (e.g. D-Link DAP 1353 in | 220 | * some APs don't like getting a superset of their rates |
220 | * b-only mode)... | 221 | * in the association request (e.g. D-Link DAP 1353 in |
221 | */ | 222 | * b-only mode)... |
222 | rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, | 223 | */ |
223 | wk->assoc.supp_rates_len, | 224 | rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, |
224 | sband, &rates); | 225 | wk->assoc.supp_rates_len, |
226 | sband, &rates); | ||
227 | } else { | ||
228 | /* | ||
229 | * In case AP not provide any supported rates information | ||
230 | * before association, we send information element(s) with | ||
231 | * all rates that we support. | ||
232 | */ | ||
233 | rates = ~0; | ||
234 | rates_len = sband->n_bitrates; | ||
235 | } | ||
225 | 236 | ||
226 | skb = alloc_skb(local->hw.extra_tx_headroom + | 237 | skb = alloc_skb(local->hw.extra_tx_headroom + |
227 | sizeof(*mgmt) + /* bit too much but doesn't matter */ | 238 | sizeof(*mgmt) + /* bit too much but doesn't matter */ |
@@ -575,7 +586,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, | |||
575 | u16 auth_alg, auth_transaction, status_code; | 586 | u16 auth_alg, auth_transaction, status_code; |
576 | 587 | ||
577 | if (wk->type != IEEE80211_WORK_AUTH) | 588 | if (wk->type != IEEE80211_WORK_AUTH) |
578 | return WORK_ACT_NONE; | 589 | return WORK_ACT_MISMATCH; |
579 | 590 | ||
580 | if (len < 24 + 6) | 591 | if (len < 24 + 6) |
581 | return WORK_ACT_NONE; | 592 | return WORK_ACT_NONE; |
@@ -626,6 +637,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, | |||
626 | struct ieee802_11_elems elems; | 637 | struct ieee802_11_elems elems; |
627 | u8 *pos; | 638 | u8 *pos; |
628 | 639 | ||
640 | if (wk->type != IEEE80211_WORK_ASSOC) | ||
641 | return WORK_ACT_MISMATCH; | ||
642 | |||
629 | /* | 643 | /* |
630 | * AssocResp and ReassocResp have identical structure, so process both | 644 | * AssocResp and ReassocResp have identical structure, so process both |
631 | * of them in this function. | 645 | * of them in this function. |
@@ -681,6 +695,12 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, | |||
681 | 695 | ||
682 | ASSERT_WORK_MTX(local); | 696 | ASSERT_WORK_MTX(local); |
683 | 697 | ||
698 | if (wk->type != IEEE80211_WORK_DIRECT_PROBE) | ||
699 | return WORK_ACT_MISMATCH; | ||
700 | |||
701 | if (len < 24 + 12) | ||
702 | return WORK_ACT_NONE; | ||
703 | |||
684 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 704 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
685 | if (baselen > len) | 705 | if (baselen > len) |
686 | return WORK_ACT_NONE; | 706 | return WORK_ACT_NONE; |
@@ -695,7 +715,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
695 | struct ieee80211_rx_status *rx_status; | 715 | struct ieee80211_rx_status *rx_status; |
696 | struct ieee80211_mgmt *mgmt; | 716 | struct ieee80211_mgmt *mgmt; |
697 | struct ieee80211_work *wk; | 717 | struct ieee80211_work *wk; |
698 | enum work_action rma = WORK_ACT_NONE; | 718 | enum work_action rma; |
699 | u16 fc; | 719 | u16 fc; |
700 | 720 | ||
701 | rx_status = (struct ieee80211_rx_status *) skb->cb; | 721 | rx_status = (struct ieee80211_rx_status *) skb->cb; |
@@ -742,7 +762,17 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
742 | break; | 762 | break; |
743 | default: | 763 | default: |
744 | WARN_ON(1); | 764 | WARN_ON(1); |
765 | rma = WORK_ACT_NONE; | ||
745 | } | 766 | } |
767 | |||
768 | /* | ||
769 | * We've either received an unexpected frame, or we have | ||
770 | * multiple work items and need to match the frame to the | ||
771 | * right one. | ||
772 | */ | ||
773 | if (rma == WORK_ACT_MISMATCH) | ||
774 | continue; | ||
775 | |||
746 | /* | 776 | /* |
747 | * We've processed this frame for that work, so it can't | 777 | * We've processed this frame for that work, so it can't |
748 | * belong to another work struct. | 778 | * belong to another work struct. |
@@ -752,6 +782,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
752 | } | 782 | } |
753 | 783 | ||
754 | switch (rma) { | 784 | switch (rma) { |
785 | case WORK_ACT_MISMATCH: | ||
786 | /* ignore this unmatched frame */ | ||
787 | break; | ||
755 | case WORK_ACT_NONE: | 788 | case WORK_ACT_NONE: |
756 | break; | 789 | break; |
757 | case WORK_ACT_DONE: | 790 | case WORK_ACT_DONE: |
@@ -920,11 +953,16 @@ static void ieee80211_work_work(struct work_struct *work) | |||
920 | run_again(local, jiffies + HZ/2); | 953 | run_again(local, jiffies + HZ/2); |
921 | } | 954 | } |
922 | 955 | ||
923 | if (list_empty(&local->work_list) && local->scan_req) | 956 | mutex_lock(&local->scan_mtx); |
957 | |||
958 | if (list_empty(&local->work_list) && local->scan_req && | ||
959 | !local->scanning) | ||
924 | ieee80211_queue_delayed_work(&local->hw, | 960 | ieee80211_queue_delayed_work(&local->hw, |
925 | &local->scan_work, | 961 | &local->scan_work, |
926 | round_jiffies_relative(0)); | 962 | round_jiffies_relative(0)); |
927 | 963 | ||
964 | mutex_unlock(&local->scan_mtx); | ||
965 | |||
928 | mutex_unlock(&local->work_mtx); | 966 | mutex_unlock(&local->work_mtx); |
929 | 967 | ||
930 | ieee80211_recalc_idle(local); | 968 | ieee80211_recalc_idle(local); |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 18d77b5c351a..8593a77cfea9 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -314,8 +314,39 @@ config NETFILTER_XTABLES | |||
314 | 314 | ||
315 | if NETFILTER_XTABLES | 315 | if NETFILTER_XTABLES |
316 | 316 | ||
317 | comment "Xtables combined modules" | ||
318 | |||
319 | config NETFILTER_XT_MARK | ||
320 | tristate 'nfmark target and match support' | ||
321 | default m if NETFILTER_ADVANCED=n | ||
322 | ---help--- | ||
323 | This option adds the "MARK" target and "mark" match. | ||
324 | |||
325 | Netfilter mark matching allows you to match packets based on the | ||
326 | "nfmark" value in the packet. | ||
327 | The target allows you to create rules in the "mangle" table which alter | ||
328 | the netfilter mark (nfmark) field associated with the packet. | ||
329 | |||
330 | Prior to routing, the nfmark can influence the routing method (see | ||
331 | "Use netfilter MARK value as routing key") and can also be used by | ||
332 | other subsystems to change their behavior. | ||
333 | |||
334 | config NETFILTER_XT_CONNMARK | ||
335 | tristate 'ctmark target and match support' | ||
336 | depends on NF_CONNTRACK | ||
337 | depends on NETFILTER_ADVANCED | ||
338 | select NF_CONNTRACK_MARK | ||
339 | ---help--- | ||
340 | This option adds the "CONNMARK" target and "connmark" match. | ||
341 | |||
342 | Netfilter allows you to store a mark value per connection (a.k.a. | ||
343 | ctmark), similarly to the packet mark (nfmark). Using this | ||
344 | target and match, you can set and match on this mark. | ||
345 | |||
317 | # alphabetically ordered list of targets | 346 | # alphabetically ordered list of targets |
318 | 347 | ||
348 | comment "Xtables targets" | ||
349 | |||
319 | config NETFILTER_XT_TARGET_CLASSIFY | 350 | config NETFILTER_XT_TARGET_CLASSIFY |
320 | tristate '"CLASSIFY" target support' | 351 | tristate '"CLASSIFY" target support' |
321 | depends on NETFILTER_ADVANCED | 352 | depends on NETFILTER_ADVANCED |
@@ -332,15 +363,11 @@ config NETFILTER_XT_TARGET_CONNMARK | |||
332 | tristate '"CONNMARK" target support' | 363 | tristate '"CONNMARK" target support' |
333 | depends on NF_CONNTRACK | 364 | depends on NF_CONNTRACK |
334 | depends on NETFILTER_ADVANCED | 365 | depends on NETFILTER_ADVANCED |
335 | select NF_CONNTRACK_MARK | 366 | select NETFILTER_XT_CONNMARK |
336 | help | 367 | ---help--- |
337 | This option adds a `CONNMARK' target, which allows one to manipulate | 368 | This is a backwards-compat option for the user's convenience |
338 | the connection mark value. Similar to the MARK target, but | 369 | (e.g. when running oldconfig). It selects |
339 | affects the connection mark value rather than the packet mark value. | 370 | CONFIG_NETFILTER_XT_CONNMARK (combined connmark/CONNMARK module). |
340 | |||
341 | If you want to compile it as a module, say M here and read | ||
342 | <file:Documentation/kbuild/modules.txt>. The module will be called | ||
343 | ipt_CONNMARK. If unsure, say `N'. | ||
344 | 371 | ||
345 | config NETFILTER_XT_TARGET_CONNSECMARK | 372 | config NETFILTER_XT_TARGET_CONNSECMARK |
346 | tristate '"CONNSECMARK" target support' | 373 | tristate '"CONNSECMARK" target support' |
@@ -423,16 +450,12 @@ config NETFILTER_XT_TARGET_LED | |||
423 | 450 | ||
424 | config NETFILTER_XT_TARGET_MARK | 451 | config NETFILTER_XT_TARGET_MARK |
425 | tristate '"MARK" target support' | 452 | tristate '"MARK" target support' |
426 | default m if NETFILTER_ADVANCED=n | 453 | depends on NETFILTER_ADVANCED |
427 | help | 454 | select NETFILTER_XT_MARK |
428 | This option adds a `MARK' target, which allows you to create rules | 455 | ---help--- |
429 | in the `mangle' table which alter the netfilter mark (nfmark) field | 456 | This is a backwards-compat option for the user's convenience |
430 | associated with the packet prior to routing. This can change | 457 | (e.g. when running oldconfig). It selects |
431 | the routing method (see `Use netfilter MARK value as routing | 458 | CONFIG_NETFILTER_XT_MARK (combined mark/MARK module). |
432 | key') and can also be used by other subsystems to change their | ||
433 | behavior. | ||
434 | |||
435 | To compile it as a module, choose M here. If unsure, say N. | ||
436 | 459 | ||
437 | config NETFILTER_XT_TARGET_NFLOG | 460 | config NETFILTER_XT_TARGET_NFLOG |
438 | tristate '"NFLOG" target support' | 461 | tristate '"NFLOG" target support' |
@@ -479,6 +502,15 @@ config NETFILTER_XT_TARGET_RATEEST | |||
479 | 502 | ||
480 | To compile it as a module, choose M here. If unsure, say N. | 503 | To compile it as a module, choose M here. If unsure, say N. |
481 | 504 | ||
505 | config NETFILTER_XT_TARGET_TEE | ||
506 | tristate '"TEE" - packet cloning to alternate destiantion' | ||
507 | depends on NETFILTER_ADVANCED | ||
508 | depends on (IPV6 || IPV6=n) | ||
509 | depends on !NF_CONNTRACK || NF_CONNTRACK | ||
510 | ---help--- | ||
511 | This option adds a "TEE" target with which a packet can be cloned and | ||
512 | this clone be rerouted to another nexthop. | ||
513 | |||
482 | config NETFILTER_XT_TARGET_TPROXY | 514 | config NETFILTER_XT_TARGET_TPROXY |
483 | tristate '"TPROXY" target support (EXPERIMENTAL)' | 515 | tristate '"TPROXY" target support (EXPERIMENTAL)' |
484 | depends on EXPERIMENTAL | 516 | depends on EXPERIMENTAL |
@@ -552,6 +584,10 @@ config NETFILTER_XT_TARGET_TCPOPTSTRIP | |||
552 | This option adds a "TCPOPTSTRIP" target, which allows you to strip | 584 | This option adds a "TCPOPTSTRIP" target, which allows you to strip |
553 | TCP options from TCP packets. | 585 | TCP options from TCP packets. |
554 | 586 | ||
587 | # alphabetically ordered list of matches | ||
588 | |||
589 | comment "Xtables matches" | ||
590 | |||
555 | config NETFILTER_XT_MATCH_CLUSTER | 591 | config NETFILTER_XT_MATCH_CLUSTER |
556 | tristate '"cluster" match support' | 592 | tristate '"cluster" match support' |
557 | depends on NF_CONNTRACK | 593 | depends on NF_CONNTRACK |
@@ -602,14 +638,11 @@ config NETFILTER_XT_MATCH_CONNMARK | |||
602 | tristate '"connmark" connection mark match support' | 638 | tristate '"connmark" connection mark match support' |
603 | depends on NF_CONNTRACK | 639 | depends on NF_CONNTRACK |
604 | depends on NETFILTER_ADVANCED | 640 | depends on NETFILTER_ADVANCED |
605 | select NF_CONNTRACK_MARK | 641 | select NETFILTER_XT_CONNMARK |
606 | help | 642 | ---help--- |
607 | This option adds a `connmark' match, which allows you to match the | 643 | This is a backwards-compat option for the user's convenience |
608 | connection mark value previously set for the session by `CONNMARK'. | 644 | (e.g. when running oldconfig). It selects |
609 | 645 | CONFIG_NETFILTER_XT_CONNMARK (combined connmark/CONNMARK module). | |
610 | If you want to compile it as a module, say M here and read | ||
611 | <file:Documentation/kbuild/modules.txt>. The module will be called | ||
612 | ipt_connmark. If unsure, say `N'. | ||
613 | 646 | ||
614 | config NETFILTER_XT_MATCH_CONNTRACK | 647 | config NETFILTER_XT_MATCH_CONNTRACK |
615 | tristate '"conntrack" connection tracking match support' | 648 | tristate '"conntrack" connection tracking match support' |
@@ -733,13 +766,12 @@ config NETFILTER_XT_MATCH_MAC | |||
733 | 766 | ||
734 | config NETFILTER_XT_MATCH_MARK | 767 | config NETFILTER_XT_MATCH_MARK |
735 | tristate '"mark" match support' | 768 | tristate '"mark" match support' |
736 | default m if NETFILTER_ADVANCED=n | 769 | depends on NETFILTER_ADVANCED |
737 | help | 770 | select NETFILTER_XT_MARK |
738 | Netfilter mark matching allows you to match packets based on the | 771 | ---help--- |
739 | `nfmark' value in the packet. This can be set by the MARK target | 772 | This is a backwards-compat option for the user's convenience |
740 | (see below). | 773 | (e.g. when running oldconfig). It selects |
741 | 774 | CONFIG_NETFILTER_XT_MARK (combined mark/MARK module). | |
742 | To compile it as a module, choose M here. If unsure, say N. | ||
743 | 775 | ||
744 | config NETFILTER_XT_MATCH_MULTIPORT | 776 | config NETFILTER_XT_MATCH_MULTIPORT |
745 | tristate '"multiport" Multiple port match support' | 777 | tristate '"multiport" Multiple port match support' |
@@ -751,6 +783,19 @@ config NETFILTER_XT_MATCH_MULTIPORT | |||
751 | 783 | ||
752 | To compile it as a module, choose M here. If unsure, say N. | 784 | To compile it as a module, choose M here. If unsure, say N. |
753 | 785 | ||
786 | config NETFILTER_XT_MATCH_OSF | ||
787 | tristate '"osf" Passive OS fingerprint match' | ||
788 | depends on NETFILTER_ADVANCED && NETFILTER_NETLINK | ||
789 | help | ||
790 | This option selects the Passive OS Fingerprinting match module | ||
791 | that allows to passively match the remote operating system by | ||
792 | analyzing incoming TCP SYN packets. | ||
793 | |||
794 | Rules and loading software can be downloaded from | ||
795 | http://www.ioremap.net/projects/osf | ||
796 | |||
797 | To compile it as a module, choose M here. If unsure, say N. | ||
798 | |||
754 | config NETFILTER_XT_MATCH_OWNER | 799 | config NETFILTER_XT_MATCH_OWNER |
755 | tristate '"owner" match support' | 800 | tristate '"owner" match support' |
756 | depends on NETFILTER_ADVANCED | 801 | depends on NETFILTER_ADVANCED |
@@ -836,13 +881,6 @@ config NETFILTER_XT_MATCH_RECENT | |||
836 | Short options are available by using 'iptables -m recent -h' | 881 | Short options are available by using 'iptables -m recent -h' |
837 | Official Website: <http://snowman.net/projects/ipt_recent/> | 882 | Official Website: <http://snowman.net/projects/ipt_recent/> |
838 | 883 | ||
839 | config NETFILTER_XT_MATCH_RECENT_PROC_COMPAT | ||
840 | bool 'Enable obsolete /proc/net/ipt_recent' | ||
841 | depends on NETFILTER_XT_MATCH_RECENT && PROC_FS | ||
842 | ---help--- | ||
843 | This option enables the old /proc/net/ipt_recent interface, | ||
844 | which has been obsoleted by /proc/net/xt_recent. | ||
845 | |||
846 | config NETFILTER_XT_MATCH_SCTP | 884 | config NETFILTER_XT_MATCH_SCTP |
847 | tristate '"sctp" protocol match support (EXPERIMENTAL)' | 885 | tristate '"sctp" protocol match support (EXPERIMENTAL)' |
848 | depends on EXPERIMENTAL | 886 | depends on EXPERIMENTAL |
@@ -942,19 +980,6 @@ config NETFILTER_XT_MATCH_U32 | |||
942 | 980 | ||
943 | Details and examples are in the kernel module source. | 981 | Details and examples are in the kernel module source. |
944 | 982 | ||
945 | config NETFILTER_XT_MATCH_OSF | ||
946 | tristate '"osf" Passive OS fingerprint match' | ||
947 | depends on NETFILTER_ADVANCED && NETFILTER_NETLINK | ||
948 | help | ||
949 | This option selects the Passive OS Fingerprinting match module | ||
950 | that allows to passively match the remote operating system by | ||
951 | analyzing incoming TCP SYN packets. | ||
952 | |||
953 | Rules and loading software can be downloaded from | ||
954 | http://www.ioremap.net/projects/osf | ||
955 | |||
956 | To compile it as a module, choose M here. If unsure, say N. | ||
957 | |||
958 | endif # NETFILTER_XTABLES | 983 | endif # NETFILTER_XTABLES |
959 | 984 | ||
960 | endmenu | 985 | endmenu |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index f873644f02f6..14e3a8fd8180 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -40,15 +40,17 @@ obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o | |||
40 | # generic X tables | 40 | # generic X tables |
41 | obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o | 41 | obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o |
42 | 42 | ||
43 | # combos | ||
44 | obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o | ||
45 | obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o | ||
46 | |||
43 | # targets | 47 | # targets |
44 | obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o | 48 | obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o |
45 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o | ||
46 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o | 49 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o |
47 | obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o | 50 | obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o |
48 | obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o | 51 | obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o |
49 | obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o | 52 | obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o |
50 | obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o | 53 | obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o |
51 | obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o | ||
52 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o | 54 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o |
53 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | 55 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o |
54 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o | 56 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o |
@@ -57,6 +59,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o | |||
57 | obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o | 59 | obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o |
58 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o | 60 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o |
59 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o | 61 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o |
62 | obj-$(CONFIG_NETFILTER_XT_TARGET_TEE) += xt_TEE.o | ||
60 | obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o | 63 | obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o |
61 | 64 | ||
62 | # matches | 65 | # matches |
@@ -64,7 +67,6 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CLUSTER) += xt_cluster.o | |||
64 | obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o | 67 | obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o |
65 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o | 68 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o |
66 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o | 69 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o |
67 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o | ||
68 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o | 70 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o |
69 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o | 71 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o |
70 | obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o | 72 | obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o |
@@ -76,7 +78,6 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o | |||
76 | obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o | 78 | obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o |
77 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o | 79 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o |
78 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o | 80 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o |
79 | obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o | ||
80 | obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o | 81 | obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o |
81 | obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o | 82 | obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o |
82 | obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o | 83 | obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o |
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index 2c7f185dfae4..2ae747a376a5 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c | |||
@@ -209,8 +209,14 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
209 | */ | 209 | */ |
210 | from.ip = n_cp->vaddr.ip; | 210 | from.ip = n_cp->vaddr.ip; |
211 | port = n_cp->vport; | 211 | port = n_cp->vport; |
212 | sprintf(buf, "%u,%u,%u,%u,%u,%u", NIPQUAD(from.ip), | 212 | snprintf(buf, sizeof(buf), "%u,%u,%u,%u,%u,%u", |
213 | (ntohs(port)>>8)&255, ntohs(port)&255); | 213 | ((unsigned char *)&from.ip)[0], |
214 | ((unsigned char *)&from.ip)[1], | ||
215 | ((unsigned char *)&from.ip)[2], | ||
216 | ((unsigned char *)&from.ip)[3], | ||
217 | ntohs(port) >> 8, | ||
218 | ntohs(port) & 0xFF); | ||
219 | |||
214 | buf_len = strlen(buf); | 220 | buf_len = strlen(buf); |
215 | 221 | ||
216 | /* | 222 | /* |
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index 7fc49f4cf5ad..2d3d5e4b35f8 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c | |||
@@ -167,26 +167,24 @@ ip_vs_tcpudp_debug_packet_v4(struct ip_vs_protocol *pp, | |||
167 | 167 | ||
168 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); | 168 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); |
169 | if (ih == NULL) | 169 | if (ih == NULL) |
170 | sprintf(buf, "%s TRUNCATED", pp->name); | 170 | sprintf(buf, "TRUNCATED"); |
171 | else if (ih->frag_off & htons(IP_OFFSET)) | 171 | else if (ih->frag_off & htons(IP_OFFSET)) |
172 | sprintf(buf, "%s %pI4->%pI4 frag", | 172 | sprintf(buf, "%pI4->%pI4 frag", &ih->saddr, &ih->daddr); |
173 | pp->name, &ih->saddr, &ih->daddr); | ||
174 | else { | 173 | else { |
175 | __be16 _ports[2], *pptr | 174 | __be16 _ports[2], *pptr |
176 | ; | 175 | ; |
177 | pptr = skb_header_pointer(skb, offset + ih->ihl*4, | 176 | pptr = skb_header_pointer(skb, offset + ih->ihl*4, |
178 | sizeof(_ports), _ports); | 177 | sizeof(_ports), _ports); |
179 | if (pptr == NULL) | 178 | if (pptr == NULL) |
180 | sprintf(buf, "%s TRUNCATED %pI4->%pI4", | 179 | sprintf(buf, "TRUNCATED %pI4->%pI4", |
181 | pp->name, &ih->saddr, &ih->daddr); | 180 | &ih->saddr, &ih->daddr); |
182 | else | 181 | else |
183 | sprintf(buf, "%s %pI4:%u->%pI4:%u", | 182 | sprintf(buf, "%pI4:%u->%pI4:%u", |
184 | pp->name, | ||
185 | &ih->saddr, ntohs(pptr[0]), | 183 | &ih->saddr, ntohs(pptr[0]), |
186 | &ih->daddr, ntohs(pptr[1])); | 184 | &ih->daddr, ntohs(pptr[1])); |
187 | } | 185 | } |
188 | 186 | ||
189 | pr_debug("%s: %s\n", msg, buf); | 187 | pr_debug("%s: %s %s\n", msg, pp->name, buf); |
190 | } | 188 | } |
191 | 189 | ||
192 | #ifdef CONFIG_IP_VS_IPV6 | 190 | #ifdef CONFIG_IP_VS_IPV6 |
@@ -201,26 +199,24 @@ ip_vs_tcpudp_debug_packet_v6(struct ip_vs_protocol *pp, | |||
201 | 199 | ||
202 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); | 200 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); |
203 | if (ih == NULL) | 201 | if (ih == NULL) |
204 | sprintf(buf, "%s TRUNCATED", pp->name); | 202 | sprintf(buf, "TRUNCATED"); |
205 | else if (ih->nexthdr == IPPROTO_FRAGMENT) | 203 | else if (ih->nexthdr == IPPROTO_FRAGMENT) |
206 | sprintf(buf, "%s %pI6->%pI6 frag", | 204 | sprintf(buf, "%pI6->%pI6 frag", &ih->saddr, &ih->daddr); |
207 | pp->name, &ih->saddr, &ih->daddr); | ||
208 | else { | 205 | else { |
209 | __be16 _ports[2], *pptr; | 206 | __be16 _ports[2], *pptr; |
210 | 207 | ||
211 | pptr = skb_header_pointer(skb, offset + sizeof(struct ipv6hdr), | 208 | pptr = skb_header_pointer(skb, offset + sizeof(struct ipv6hdr), |
212 | sizeof(_ports), _ports); | 209 | sizeof(_ports), _ports); |
213 | if (pptr == NULL) | 210 | if (pptr == NULL) |
214 | sprintf(buf, "%s TRUNCATED %pI6->%pI6", | 211 | sprintf(buf, "TRUNCATED %pI6->%pI6", |
215 | pp->name, &ih->saddr, &ih->daddr); | 212 | &ih->saddr, &ih->daddr); |
216 | else | 213 | else |
217 | sprintf(buf, "%s %pI6:%u->%pI6:%u", | 214 | sprintf(buf, "%pI6:%u->%pI6:%u", |
218 | pp->name, | ||
219 | &ih->saddr, ntohs(pptr[0]), | 215 | &ih->saddr, ntohs(pptr[0]), |
220 | &ih->daddr, ntohs(pptr[1])); | 216 | &ih->daddr, ntohs(pptr[1])); |
221 | } | 217 | } |
222 | 218 | ||
223 | pr_debug("%s: %s\n", msg, buf); | 219 | pr_debug("%s: %s %s\n", msg, pp->name, buf); |
224 | } | 220 | } |
225 | #endif | 221 | #endif |
226 | 222 | ||
diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c index c30b43c36cd7..1892dfc12fdd 100644 --- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c +++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c | |||
@@ -136,12 +136,11 @@ ah_esp_debug_packet_v4(struct ip_vs_protocol *pp, const struct sk_buff *skb, | |||
136 | 136 | ||
137 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); | 137 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); |
138 | if (ih == NULL) | 138 | if (ih == NULL) |
139 | sprintf(buf, "%s TRUNCATED", pp->name); | 139 | sprintf(buf, "TRUNCATED"); |
140 | else | 140 | else |
141 | sprintf(buf, "%s %pI4->%pI4", | 141 | sprintf(buf, "%pI4->%pI4", &ih->saddr, &ih->daddr); |
142 | pp->name, &ih->saddr, &ih->daddr); | ||
143 | 142 | ||
144 | pr_debug("%s: %s\n", msg, buf); | 143 | pr_debug("%s: %s %s\n", msg, pp->name, buf); |
145 | } | 144 | } |
146 | 145 | ||
147 | #ifdef CONFIG_IP_VS_IPV6 | 146 | #ifdef CONFIG_IP_VS_IPV6 |
@@ -154,12 +153,11 @@ ah_esp_debug_packet_v6(struct ip_vs_protocol *pp, const struct sk_buff *skb, | |||
154 | 153 | ||
155 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); | 154 | ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); |
156 | if (ih == NULL) | 155 | if (ih == NULL) |
157 | sprintf(buf, "%s TRUNCATED", pp->name); | 156 | sprintf(buf, "TRUNCATED"); |
158 | else | 157 | else |
159 | sprintf(buf, "%s %pI6->%pI6", | 158 | sprintf(buf, "%pI6->%pI6", &ih->saddr, &ih->daddr); |
160 | pp->name, &ih->saddr, &ih->daddr); | ||
161 | 159 | ||
162 | pr_debug("%s: %s\n", msg, buf); | 160 | pr_debug("%s: %s %s\n", msg, pp->name, buf); |
163 | } | 161 | } |
164 | #endif | 162 | #endif |
165 | 163 | ||
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 8fb0ae616761..7ba06939829f 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -802,7 +802,7 @@ static int sync_thread_backup(void *data) | |||
802 | ip_vs_backup_mcast_ifn, ip_vs_backup_syncid); | 802 | ip_vs_backup_mcast_ifn, ip_vs_backup_syncid); |
803 | 803 | ||
804 | while (!kthread_should_stop()) { | 804 | while (!kthread_should_stop()) { |
805 | wait_event_interruptible(*tinfo->sock->sk->sk_sleep, | 805 | wait_event_interruptible(*sk_sleep(tinfo->sock->sk), |
806 | !skb_queue_empty(&tinfo->sock->sk->sk_receive_queue) | 806 | !skb_queue_empty(&tinfo->sock->sk->sk_receive_queue) |
807 | || kthread_should_stop()); | 807 | || kthread_should_stop()); |
808 | 808 | ||
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index e450cd6f4eb5..93c15a107b2c 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
@@ -270,7 +270,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
270 | /* Another hack: avoid icmp_send in ip_fragment */ | 270 | /* Another hack: avoid icmp_send in ip_fragment */ |
271 | skb->local_df = 1; | 271 | skb->local_df = 1; |
272 | 272 | ||
273 | IP_VS_XMIT(PF_INET, skb, rt); | 273 | IP_VS_XMIT(NFPROTO_IPV4, skb, rt); |
274 | 274 | ||
275 | LeaveFunction(10); | 275 | LeaveFunction(10); |
276 | return NF_STOLEN; | 276 | return NF_STOLEN; |
@@ -334,7 +334,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
334 | /* Another hack: avoid icmp_send in ip_fragment */ | 334 | /* Another hack: avoid icmp_send in ip_fragment */ |
335 | skb->local_df = 1; | 335 | skb->local_df = 1; |
336 | 336 | ||
337 | IP_VS_XMIT(PF_INET6, skb, rt); | 337 | IP_VS_XMIT(NFPROTO_IPV6, skb, rt); |
338 | 338 | ||
339 | LeaveFunction(10); | 339 | LeaveFunction(10); |
340 | return NF_STOLEN; | 340 | return NF_STOLEN; |
@@ -410,7 +410,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
410 | /* Another hack: avoid icmp_send in ip_fragment */ | 410 | /* Another hack: avoid icmp_send in ip_fragment */ |
411 | skb->local_df = 1; | 411 | skb->local_df = 1; |
412 | 412 | ||
413 | IP_VS_XMIT(PF_INET, skb, rt); | 413 | IP_VS_XMIT(NFPROTO_IPV4, skb, rt); |
414 | 414 | ||
415 | LeaveFunction(10); | 415 | LeaveFunction(10); |
416 | return NF_STOLEN; | 416 | return NF_STOLEN; |
@@ -486,7 +486,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
486 | /* Another hack: avoid icmp_send in ip_fragment */ | 486 | /* Another hack: avoid icmp_send in ip_fragment */ |
487 | skb->local_df = 1; | 487 | skb->local_df = 1; |
488 | 488 | ||
489 | IP_VS_XMIT(PF_INET6, skb, rt); | 489 | IP_VS_XMIT(NFPROTO_IPV6, skb, rt); |
490 | 490 | ||
491 | LeaveFunction(10); | 491 | LeaveFunction(10); |
492 | return NF_STOLEN; | 492 | return NF_STOLEN; |
@@ -785,7 +785,7 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
785 | /* Another hack: avoid icmp_send in ip_fragment */ | 785 | /* Another hack: avoid icmp_send in ip_fragment */ |
786 | skb->local_df = 1; | 786 | skb->local_df = 1; |
787 | 787 | ||
788 | IP_VS_XMIT(PF_INET, skb, rt); | 788 | IP_VS_XMIT(NFPROTO_IPV4, skb, rt); |
789 | 789 | ||
790 | LeaveFunction(10); | 790 | LeaveFunction(10); |
791 | return NF_STOLEN; | 791 | return NF_STOLEN; |
@@ -838,7 +838,7 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
838 | /* Another hack: avoid icmp_send in ip_fragment */ | 838 | /* Another hack: avoid icmp_send in ip_fragment */ |
839 | skb->local_df = 1; | 839 | skb->local_df = 1; |
840 | 840 | ||
841 | IP_VS_XMIT(PF_INET6, skb, rt); | 841 | IP_VS_XMIT(NFPROTO_IPV6, skb, rt); |
842 | 842 | ||
843 | LeaveFunction(10); | 843 | LeaveFunction(10); |
844 | return NF_STOLEN; | 844 | return NF_STOLEN; |
@@ -912,7 +912,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
912 | /* Another hack: avoid icmp_send in ip_fragment */ | 912 | /* Another hack: avoid icmp_send in ip_fragment */ |
913 | skb->local_df = 1; | 913 | skb->local_df = 1; |
914 | 914 | ||
915 | IP_VS_XMIT(PF_INET, skb, rt); | 915 | IP_VS_XMIT(NFPROTO_IPV4, skb, rt); |
916 | 916 | ||
917 | rc = NF_STOLEN; | 917 | rc = NF_STOLEN; |
918 | goto out; | 918 | goto out; |
@@ -987,7 +987,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
987 | /* Another hack: avoid icmp_send in ip_fragment */ | 987 | /* Another hack: avoid icmp_send in ip_fragment */ |
988 | skb->local_df = 1; | 988 | skb->local_df = 1; |
989 | 989 | ||
990 | IP_VS_XMIT(PF_INET6, skb, rt); | 990 | IP_VS_XMIT(NFPROTO_IPV6, skb, rt); |
991 | 991 | ||
992 | rc = NF_STOLEN; | 992 | rc = NF_STOLEN; |
993 | goto out; | 993 | goto out; |
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index 372e80f07a81..13fd2c55e329 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c | |||
@@ -108,7 +108,7 @@ static int amanda_help(struct sk_buff *skb, | |||
108 | dataoff = protoff + sizeof(struct udphdr); | 108 | dataoff = protoff + sizeof(struct udphdr); |
109 | if (dataoff >= skb->len) { | 109 | if (dataoff >= skb->len) { |
110 | if (net_ratelimit()) | 110 | if (net_ratelimit()) |
111 | printk("amanda_help: skblen = %u\n", skb->len); | 111 | printk(KERN_ERR "amanda_help: skblen = %u\n", skb->len); |
112 | return NF_ACCEPT; | 112 | return NF_ACCEPT; |
113 | } | 113 | } |
114 | 114 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0c9bbe93cc16..b83c530c5e0a 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -319,8 +319,10 @@ begin: | |||
319 | * not the expected one, we must restart lookup. | 319 | * not the expected one, we must restart lookup. |
320 | * We probably met an item that was moved to another chain. | 320 | * We probably met an item that was moved to another chain. |
321 | */ | 321 | */ |
322 | if (get_nulls_value(n) != hash) | 322 | if (get_nulls_value(n) != hash) { |
323 | NF_CT_STAT_INC(net, search_restart); | ||
323 | goto begin; | 324 | goto begin; |
325 | } | ||
324 | local_bh_enable(); | 326 | local_bh_enable(); |
325 | 327 | ||
326 | return NULL; | 328 | return NULL; |
@@ -1333,7 +1335,7 @@ static int nf_conntrack_init_init_net(void) | |||
1333 | } | 1335 | } |
1334 | nf_conntrack_max = max_factor * nf_conntrack_htable_size; | 1336 | nf_conntrack_max = max_factor * nf_conntrack_htable_size; |
1335 | 1337 | ||
1336 | printk("nf_conntrack version %s (%u buckets, %d max)\n", | 1338 | printk(KERN_INFO "nf_conntrack version %s (%u buckets, %d max)\n", |
1337 | NF_CONNTRACK_VERSION, nf_conntrack_htable_size, | 1339 | NF_CONNTRACK_VERSION, nf_conntrack_htable_size, |
1338 | nf_conntrack_max); | 1340 | nf_conntrack_max); |
1339 | 1341 | ||
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index f516961a83b4..cdcc7649476b 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c | |||
@@ -85,7 +85,8 @@ int nf_conntrack_register_notifier(struct nf_ct_event_notifier *new) | |||
85 | struct nf_ct_event_notifier *notify; | 85 | struct nf_ct_event_notifier *notify; |
86 | 86 | ||
87 | mutex_lock(&nf_ct_ecache_mutex); | 87 | mutex_lock(&nf_ct_ecache_mutex); |
88 | notify = rcu_dereference(nf_conntrack_event_cb); | 88 | notify = rcu_dereference_protected(nf_conntrack_event_cb, |
89 | lockdep_is_held(&nf_ct_ecache_mutex)); | ||
89 | if (notify != NULL) { | 90 | if (notify != NULL) { |
90 | ret = -EBUSY; | 91 | ret = -EBUSY; |
91 | goto out_unlock; | 92 | goto out_unlock; |
@@ -105,7 +106,8 @@ void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *new) | |||
105 | struct nf_ct_event_notifier *notify; | 106 | struct nf_ct_event_notifier *notify; |
106 | 107 | ||
107 | mutex_lock(&nf_ct_ecache_mutex); | 108 | mutex_lock(&nf_ct_ecache_mutex); |
108 | notify = rcu_dereference(nf_conntrack_event_cb); | 109 | notify = rcu_dereference_protected(nf_conntrack_event_cb, |
110 | lockdep_is_held(&nf_ct_ecache_mutex)); | ||
109 | BUG_ON(notify != new); | 111 | BUG_ON(notify != new); |
110 | rcu_assign_pointer(nf_conntrack_event_cb, NULL); | 112 | rcu_assign_pointer(nf_conntrack_event_cb, NULL); |
111 | mutex_unlock(&nf_ct_ecache_mutex); | 113 | mutex_unlock(&nf_ct_ecache_mutex); |
@@ -118,7 +120,8 @@ int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *new) | |||
118 | struct nf_exp_event_notifier *notify; | 120 | struct nf_exp_event_notifier *notify; |
119 | 121 | ||
120 | mutex_lock(&nf_ct_ecache_mutex); | 122 | mutex_lock(&nf_ct_ecache_mutex); |
121 | notify = rcu_dereference(nf_expect_event_cb); | 123 | notify = rcu_dereference_protected(nf_expect_event_cb, |
124 | lockdep_is_held(&nf_ct_ecache_mutex)); | ||
122 | if (notify != NULL) { | 125 | if (notify != NULL) { |
123 | ret = -EBUSY; | 126 | ret = -EBUSY; |
124 | goto out_unlock; | 127 | goto out_unlock; |
@@ -138,7 +141,8 @@ void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *new) | |||
138 | struct nf_exp_event_notifier *notify; | 141 | struct nf_exp_event_notifier *notify; |
139 | 142 | ||
140 | mutex_lock(&nf_ct_ecache_mutex); | 143 | mutex_lock(&nf_ct_ecache_mutex); |
141 | notify = rcu_dereference(nf_expect_event_cb); | 144 | notify = rcu_dereference_protected(nf_expect_event_cb, |
145 | lockdep_is_held(&nf_ct_ecache_mutex)); | ||
142 | BUG_ON(notify != new); | 146 | BUG_ON(notify != new); |
143 | rcu_assign_pointer(nf_expect_event_cb, NULL); | 147 | rcu_assign_pointer(nf_expect_event_cb, NULL); |
144 | mutex_unlock(&nf_ct_ecache_mutex); | 148 | mutex_unlock(&nf_ct_ecache_mutex); |
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 2ae3169e7633..e17cb7c7dd8f 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -573,8 +573,8 @@ static int __init nf_conntrack_ftp_init(void) | |||
573 | ftp[i][j].tuple.src.l3num, ports[i]); | 573 | ftp[i][j].tuple.src.l3num, ports[i]); |
574 | ret = nf_conntrack_helper_register(&ftp[i][j]); | 574 | ret = nf_conntrack_helper_register(&ftp[i][j]); |
575 | if (ret) { | 575 | if (ret) { |
576 | printk("nf_ct_ftp: failed to register helper " | 576 | printk(KERN_ERR "nf_ct_ftp: failed to register" |
577 | " for pf: %d port: %d\n", | 577 | " helper for pf: %d port: %d\n", |
578 | ftp[i][j].tuple.src.l3num, ports[i]); | 578 | ftp[i][j].tuple.src.l3num, ports[i]); |
579 | nf_conntrack_ftp_fini(); | 579 | nf_conntrack_ftp_fini(); |
580 | return ret; | 580 | return ret; |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index a487c8038044..6eaee7c8a337 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -194,8 +194,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff, | |||
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
196 | 196 | ||
197 | if (net_ratelimit()) | 197 | pr_debug("nf_ct_h323: incomplete TPKT (fragmented?)\n"); |
198 | printk("nf_ct_h323: incomplete TPKT (fragmented?)\n"); | ||
199 | goto clear_out; | 198 | goto clear_out; |
200 | } | 199 | } |
201 | 200 | ||
@@ -608,7 +607,7 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff, | |||
608 | drop: | 607 | drop: |
609 | spin_unlock_bh(&nf_h323_lock); | 608 | spin_unlock_bh(&nf_h323_lock); |
610 | if (net_ratelimit()) | 609 | if (net_ratelimit()) |
611 | printk("nf_ct_h245: packet dropped\n"); | 610 | pr_info("nf_ct_h245: packet dropped\n"); |
612 | return NF_DROP; | 611 | return NF_DROP; |
613 | } | 612 | } |
614 | 613 | ||
@@ -1153,7 +1152,7 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff, | |||
1153 | drop: | 1152 | drop: |
1154 | spin_unlock_bh(&nf_h323_lock); | 1153 | spin_unlock_bh(&nf_h323_lock); |
1155 | if (net_ratelimit()) | 1154 | if (net_ratelimit()) |
1156 | printk("nf_ct_q931: packet dropped\n"); | 1155 | pr_info("nf_ct_q931: packet dropped\n"); |
1157 | return NF_DROP; | 1156 | return NF_DROP; |
1158 | } | 1157 | } |
1159 | 1158 | ||
@@ -1728,7 +1727,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff, | |||
1728 | drop: | 1727 | drop: |
1729 | spin_unlock_bh(&nf_h323_lock); | 1728 | spin_unlock_bh(&nf_h323_lock); |
1730 | if (net_ratelimit()) | 1729 | if (net_ratelimit()) |
1731 | printk("nf_ct_ras: packet dropped\n"); | 1730 | pr_info("nf_ct_ras: packet dropped\n"); |
1732 | return NF_DROP; | 1731 | return NF_DROP; |
1733 | } | 1732 | } |
1734 | 1733 | ||
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 7673930ca342..b394aa318776 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c | |||
@@ -235,7 +235,7 @@ static int __init nf_conntrack_irc_init(void) | |||
235 | char *tmpname; | 235 | char *tmpname; |
236 | 236 | ||
237 | if (max_dcc_channels < 1) { | 237 | if (max_dcc_channels < 1) { |
238 | printk("nf_ct_irc: max_dcc_channels must not be zero\n"); | 238 | printk(KERN_ERR "nf_ct_irc: max_dcc_channels must not be zero\n"); |
239 | return -EINVAL; | 239 | return -EINVAL; |
240 | } | 240 | } |
241 | 241 | ||
@@ -267,7 +267,7 @@ static int __init nf_conntrack_irc_init(void) | |||
267 | 267 | ||
268 | ret = nf_conntrack_helper_register(&irc[i]); | 268 | ret = nf_conntrack_helper_register(&irc[i]); |
269 | if (ret) { | 269 | if (ret) { |
270 | printk("nf_ct_irc: failed to register helper " | 270 | printk(KERN_ERR "nf_ct_irc: failed to register helper " |
271 | "for pf: %u port: %u\n", | 271 | "for pf: %u port: %u\n", |
272 | irc[i].tuple.src.l3num, ports[i]); | 272 | irc[i].tuple.src.l3num, ports[i]); |
273 | nf_conntrack_irc_fini(); | 273 | nf_conntrack_irc_fini(); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index afc52f2ee4ac..c42ff6aa441d 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -427,6 +427,17 @@ ctnetlink_proto_size(const struct nf_conn *ct) | |||
427 | } | 427 | } |
428 | 428 | ||
429 | static inline size_t | 429 | static inline size_t |
430 | ctnetlink_counters_size(const struct nf_conn *ct) | ||
431 | { | ||
432 | if (!nf_ct_ext_exist(ct, NF_CT_EXT_ACCT)) | ||
433 | return 0; | ||
434 | return 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ | ||
435 | + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_PACKETS */ | ||
436 | + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_BYTES */ | ||
437 | ; | ||
438 | } | ||
439 | |||
440 | static inline size_t | ||
430 | ctnetlink_nlmsg_size(const struct nf_conn *ct) | 441 | ctnetlink_nlmsg_size(const struct nf_conn *ct) |
431 | { | 442 | { |
432 | return NLMSG_ALIGN(sizeof(struct nfgenmsg)) | 443 | return NLMSG_ALIGN(sizeof(struct nfgenmsg)) |
@@ -436,11 +447,7 @@ ctnetlink_nlmsg_size(const struct nf_conn *ct) | |||
436 | + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */ | 447 | + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */ |
437 | + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */ | 448 | + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */ |
438 | + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */ | 449 | + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */ |
439 | #ifdef CONFIG_NF_CT_ACCT | 450 | + ctnetlink_counters_size(ct) |
440 | + 2 * nla_total_size(0) /* CTA_COUNTERS_ORIG|REPL */ | ||
441 | + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_PACKETS */ | ||
442 | + 2 * nla_total_size(sizeof(uint64_t)) /* CTA_COUNTERS_BYTES */ | ||
443 | #endif | ||
444 | + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */ | 451 | + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */ |
445 | + nla_total_size(0) /* CTA_PROTOINFO */ | 452 | + nla_total_size(0) /* CTA_PROTOINFO */ |
446 | + nla_total_size(0) /* CTA_HELP */ | 453 | + nla_total_size(0) /* CTA_HELP */ |
@@ -2050,29 +2057,29 @@ static int __init ctnetlink_init(void) | |||
2050 | { | 2057 | { |
2051 | int ret; | 2058 | int ret; |
2052 | 2059 | ||
2053 | printk("ctnetlink v%s: registering with nfnetlink.\n", version); | 2060 | pr_info("ctnetlink v%s: registering with nfnetlink.\n", version); |
2054 | ret = nfnetlink_subsys_register(&ctnl_subsys); | 2061 | ret = nfnetlink_subsys_register(&ctnl_subsys); |
2055 | if (ret < 0) { | 2062 | if (ret < 0) { |
2056 | printk("ctnetlink_init: cannot register with nfnetlink.\n"); | 2063 | pr_err("ctnetlink_init: cannot register with nfnetlink.\n"); |
2057 | goto err_out; | 2064 | goto err_out; |
2058 | } | 2065 | } |
2059 | 2066 | ||
2060 | ret = nfnetlink_subsys_register(&ctnl_exp_subsys); | 2067 | ret = nfnetlink_subsys_register(&ctnl_exp_subsys); |
2061 | if (ret < 0) { | 2068 | if (ret < 0) { |
2062 | printk("ctnetlink_init: cannot register exp with nfnetlink.\n"); | 2069 | pr_err("ctnetlink_init: cannot register exp with nfnetlink.\n"); |
2063 | goto err_unreg_subsys; | 2070 | goto err_unreg_subsys; |
2064 | } | 2071 | } |
2065 | 2072 | ||
2066 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 2073 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
2067 | ret = nf_conntrack_register_notifier(&ctnl_notifier); | 2074 | ret = nf_conntrack_register_notifier(&ctnl_notifier); |
2068 | if (ret < 0) { | 2075 | if (ret < 0) { |
2069 | printk("ctnetlink_init: cannot register notifier.\n"); | 2076 | pr_err("ctnetlink_init: cannot register notifier.\n"); |
2070 | goto err_unreg_exp_subsys; | 2077 | goto err_unreg_exp_subsys; |
2071 | } | 2078 | } |
2072 | 2079 | ||
2073 | ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp); | 2080 | ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp); |
2074 | if (ret < 0) { | 2081 | if (ret < 0) { |
2075 | printk("ctnetlink_init: cannot expect register notifier.\n"); | 2082 | pr_err("ctnetlink_init: cannot expect register notifier.\n"); |
2076 | goto err_unreg_notifier; | 2083 | goto err_unreg_notifier; |
2077 | } | 2084 | } |
2078 | #endif | 2085 | #endif |
@@ -2093,7 +2100,7 @@ err_out: | |||
2093 | 2100 | ||
2094 | static void __exit ctnetlink_exit(void) | 2101 | static void __exit ctnetlink_exit(void) |
2095 | { | 2102 | { |
2096 | printk("ctnetlink: unregistering from nfnetlink.\n"); | 2103 | pr_info("ctnetlink: unregistering from nfnetlink.\n"); |
2097 | 2104 | ||
2098 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 2105 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
2099 | nf_ct_expect_unregister_notifier(&ctnl_notifier_exp); | 2106 | nf_ct_expect_unregister_notifier(&ctnl_notifier_exp); |
@@ -2102,7 +2109,6 @@ static void __exit ctnetlink_exit(void) | |||
2102 | 2109 | ||
2103 | nfnetlink_subsys_unregister(&ctnl_exp_subsys); | 2110 | nfnetlink_subsys_unregister(&ctnl_exp_subsys); |
2104 | nfnetlink_subsys_unregister(&ctnl_subsys); | 2111 | nfnetlink_subsys_unregister(&ctnl_subsys); |
2105 | return; | ||
2106 | } | 2112 | } |
2107 | 2113 | ||
2108 | module_init(ctnetlink_init); | 2114 | module_init(ctnetlink_init); |
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index a44fa75b5178..5886ba1d52a0 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c | |||
@@ -14,12 +14,10 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
17 | #include <linux/skbuff.h> | ||
18 | #include <linux/vmalloc.h> | 17 | #include <linux/vmalloc.h> |
19 | #include <linux/stddef.h> | 18 | #include <linux/stddef.h> |
20 | #include <linux/err.h> | 19 | #include <linux/err.h> |
21 | #include <linux/percpu.h> | 20 | #include <linux/percpu.h> |
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/notifier.h> | 21 | #include <linux/notifier.h> |
24 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
25 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
@@ -119,9 +117,13 @@ void nf_ct_l3proto_module_put(unsigned short l3proto) | |||
119 | { | 117 | { |
120 | struct nf_conntrack_l3proto *p; | 118 | struct nf_conntrack_l3proto *p; |
121 | 119 | ||
122 | /* rcu_read_lock not necessary since the caller holds a reference */ | 120 | /* rcu_read_lock not necessary since the caller holds a reference, but |
121 | * taken anyways to avoid lockdep warnings in __nf_ct_l3proto_find() | ||
122 | */ | ||
123 | rcu_read_lock(); | ||
123 | p = __nf_ct_l3proto_find(l3proto); | 124 | p = __nf_ct_l3proto_find(l3proto); |
124 | module_put(p->me); | 125 | module_put(p->me); |
126 | rcu_read_unlock(); | ||
125 | } | 127 | } |
126 | EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); | 128 | EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); |
127 | 129 | ||
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index b68ff15ed979..c6049c2d5ea8 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -717,12 +717,12 @@ static int __init nf_conntrack_proto_sctp_init(void) | |||
717 | 717 | ||
718 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4); | 718 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4); |
719 | if (ret) { | 719 | if (ret) { |
720 | printk("nf_conntrack_l4proto_sctp4: protocol register failed\n"); | 720 | pr_err("nf_conntrack_l4proto_sctp4: protocol register failed\n"); |
721 | goto out; | 721 | goto out; |
722 | } | 722 | } |
723 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6); | 723 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6); |
724 | if (ret) { | 724 | if (ret) { |
725 | printk("nf_conntrack_l4proto_sctp6: protocol register failed\n"); | 725 | pr_err("nf_conntrack_l4proto_sctp6: protocol register failed\n"); |
726 | goto cleanup_sctp4; | 726 | goto cleanup_sctp4; |
727 | } | 727 | } |
728 | 728 | ||
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index c6cd1b84eddd..b20f4275893c 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -1549,8 +1549,8 @@ static int __init nf_conntrack_sip_init(void) | |||
1549 | 1549 | ||
1550 | ret = nf_conntrack_helper_register(&sip[i][j]); | 1550 | ret = nf_conntrack_helper_register(&sip[i][j]); |
1551 | if (ret) { | 1551 | if (ret) { |
1552 | printk("nf_ct_sip: failed to register helper " | 1552 | printk(KERN_ERR "nf_ct_sip: failed to register" |
1553 | "for pf: %u port: %u\n", | 1553 | " helper for pf: %u port: %u\n", |
1554 | sip[i][j].tuple.src.l3num, ports[i]); | 1554 | sip[i][j].tuple.src.l3num, ports[i]); |
1555 | nf_conntrack_sip_fini(); | 1555 | nf_conntrack_sip_fini(); |
1556 | return ret; | 1556 | return ret; |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index faa8eb3722b9..eb973fcd67ab 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -252,12 +252,12 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v) | |||
252 | const struct ip_conntrack_stat *st = v; | 252 | const struct ip_conntrack_stat *st = v; |
253 | 253 | ||
254 | if (v == SEQ_START_TOKEN) { | 254 | if (v == SEQ_START_TOKEN) { |
255 | seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n"); | 255 | seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete search_restart\n"); |
256 | return 0; | 256 | return 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x " | 259 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x " |
260 | "%08x %08x %08x %08x %08x %08x %08x %08x \n", | 260 | "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n", |
261 | nr_conntracks, | 261 | nr_conntracks, |
262 | st->searched, | 262 | st->searched, |
263 | st->found, | 263 | st->found, |
@@ -274,7 +274,8 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v) | |||
274 | 274 | ||
275 | st->expect_new, | 275 | st->expect_new, |
276 | st->expect_create, | 276 | st->expect_create, |
277 | st->expect_delete | 277 | st->expect_delete, |
278 | st->search_restart | ||
278 | ); | 279 | ); |
279 | return 0; | 280 | return 0; |
280 | } | 281 | } |
@@ -445,7 +446,7 @@ out_kmemdup: | |||
445 | if (net_eq(net, &init_net)) | 446 | if (net_eq(net, &init_net)) |
446 | unregister_sysctl_table(nf_ct_netfilter_header); | 447 | unregister_sysctl_table(nf_ct_netfilter_header); |
447 | out: | 448 | out: |
448 | printk("nf_conntrack: can't register to sysctl.\n"); | 449 | printk(KERN_ERR "nf_conntrack: can't register to sysctl.\n"); |
449 | return -ENOMEM; | 450 | return -ENOMEM; |
450 | } | 451 | } |
451 | 452 | ||
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index 46e646b2e9b9..75466fd72f4f 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c | |||
@@ -138,8 +138,8 @@ static int __init nf_conntrack_tftp_init(void) | |||
138 | 138 | ||
139 | ret = nf_conntrack_helper_register(&tftp[i][j]); | 139 | ret = nf_conntrack_helper_register(&tftp[i][j]); |
140 | if (ret) { | 140 | if (ret) { |
141 | printk("nf_ct_tftp: failed to register helper " | 141 | printk(KERN_ERR "nf_ct_tftp: failed to register" |
142 | "for pf: %u port: %u\n", | 142 | " helper for pf: %u port: %u\n", |
143 | tftp[i][j].tuple.src.l3num, ports[i]); | 143 | tftp[i][j].tuple.src.l3num, ports[i]); |
144 | nf_conntrack_tftp_fini(); | 144 | nf_conntrack_tftp_fini(); |
145 | return ret; | 145 | return ret; |
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h index bf6609978af7..770f76432ad0 100644 --- a/net/netfilter/nf_internals.h +++ b/net/netfilter/nf_internals.h | |||
@@ -6,7 +6,7 @@ | |||
6 | #include <linux/netdevice.h> | 6 | #include <linux/netdevice.h> |
7 | 7 | ||
8 | #ifdef CONFIG_NETFILTER_DEBUG | 8 | #ifdef CONFIG_NETFILTER_DEBUG |
9 | #define NFDEBUG(format, args...) printk(format , ## args) | 9 | #define NFDEBUG(format, args...) printk(KERN_DEBUG format , ## args) |
10 | #else | 10 | #else |
11 | #define NFDEBUG(format, args...) | 11 | #define NFDEBUG(format, args...) |
12 | #endif | 12 | #endif |
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 015725a5cd50..7df37fd786bc 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c | |||
@@ -52,7 +52,8 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) | |||
52 | } else { | 52 | } else { |
53 | /* register at end of list to honor first register win */ | 53 | /* register at end of list to honor first register win */ |
54 | list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); | 54 | list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); |
55 | llog = rcu_dereference(nf_loggers[pf]); | 55 | llog = rcu_dereference_protected(nf_loggers[pf], |
56 | lockdep_is_held(&nf_log_mutex)); | ||
56 | if (llog == NULL) | 57 | if (llog == NULL) |
57 | rcu_assign_pointer(nf_loggers[pf], logger); | 58 | rcu_assign_pointer(nf_loggers[pf], logger); |
58 | } | 59 | } |
@@ -70,7 +71,8 @@ void nf_log_unregister(struct nf_logger *logger) | |||
70 | 71 | ||
71 | mutex_lock(&nf_log_mutex); | 72 | mutex_lock(&nf_log_mutex); |
72 | for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) { | 73 | for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) { |
73 | c_logger = rcu_dereference(nf_loggers[i]); | 74 | c_logger = rcu_dereference_protected(nf_loggers[i], |
75 | lockdep_is_held(&nf_log_mutex)); | ||
74 | if (c_logger == logger) | 76 | if (c_logger == logger) |
75 | rcu_assign_pointer(nf_loggers[i], NULL); | 77 | rcu_assign_pointer(nf_loggers[i], NULL); |
76 | list_del(&logger->list[i]); | 78 | list_del(&logger->list[i]); |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index c49ef219899e..78b3cf9c519c 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/rcupdate.h> | 9 | #include <linux/rcupdate.h> |
10 | #include <net/protocol.h> | 10 | #include <net/protocol.h> |
11 | #include <net/netfilter/nf_queue.h> | 11 | #include <net/netfilter/nf_queue.h> |
12 | #include <net/dst.h> | ||
12 | 13 | ||
13 | #include "nf_internals.h" | 14 | #include "nf_internals.h" |
14 | 15 | ||
@@ -170,6 +171,7 @@ static int __nf_queue(struct sk_buff *skb, | |||
170 | dev_hold(physoutdev); | 171 | dev_hold(physoutdev); |
171 | } | 172 | } |
172 | #endif | 173 | #endif |
174 | skb_dst_force(skb); | ||
173 | afinfo->saveroute(skb, entry); | 175 | afinfo->saveroute(skb, entry); |
174 | status = qh->outfn(entry, queuenum); | 176 | status = qh->outfn(entry, queuenum); |
175 | 177 | ||
@@ -279,7 +281,6 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) | |||
279 | } | 281 | } |
280 | rcu_read_unlock(); | 282 | rcu_read_unlock(); |
281 | kfree(entry); | 283 | kfree(entry); |
282 | return; | ||
283 | } | 284 | } |
284 | EXPORT_SYMBOL(nf_reinject); | 285 | EXPORT_SYMBOL(nf_reinject); |
285 | 286 | ||
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 6afa3d52ea5f..b4a4532823e8 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -18,12 +18,9 @@ | |||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/socket.h> | 19 | #include <linux/socket.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/major.h> | ||
22 | #include <linux/timer.h> | ||
23 | #include <linux/string.h> | 21 | #include <linux/string.h> |
24 | #include <linux/sockios.h> | 22 | #include <linux/sockios.h> |
25 | #include <linux/net.h> | 23 | #include <linux/net.h> |
26 | #include <linux/fcntl.h> | ||
27 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
28 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
29 | #include <asm/system.h> | 26 | #include <asm/system.h> |
@@ -215,13 +212,13 @@ static struct pernet_operations nfnetlink_net_ops = { | |||
215 | 212 | ||
216 | static int __init nfnetlink_init(void) | 213 | static int __init nfnetlink_init(void) |
217 | { | 214 | { |
218 | printk("Netfilter messages via NETLINK v%s.\n", nfversion); | 215 | pr_info("Netfilter messages via NETLINK v%s.\n", nfversion); |
219 | return register_pernet_subsys(&nfnetlink_net_ops); | 216 | return register_pernet_subsys(&nfnetlink_net_ops); |
220 | } | 217 | } |
221 | 218 | ||
222 | static void __exit nfnetlink_exit(void) | 219 | static void __exit nfnetlink_exit(void) |
223 | { | 220 | { |
224 | printk("Removing netfilter NETLINK layer.\n"); | 221 | pr_info("Removing netfilter NETLINK layer.\n"); |
225 | unregister_pernet_subsys(&nfnetlink_net_ops); | 222 | unregister_pernet_subsys(&nfnetlink_net_ops); |
226 | } | 223 | } |
227 | module_init(nfnetlink_init); | 224 | module_init(nfnetlink_init); |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 203643fb2c52..fc9a211e629e 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -297,7 +297,7 @@ nfulnl_alloc_skb(unsigned int inst_size, unsigned int pkt_size) | |||
297 | n = max(inst_size, pkt_size); | 297 | n = max(inst_size, pkt_size); |
298 | skb = alloc_skb(n, GFP_ATOMIC); | 298 | skb = alloc_skb(n, GFP_ATOMIC); |
299 | if (!skb) { | 299 | if (!skb) { |
300 | PRINTR("nfnetlink_log: can't alloc whole buffer (%u bytes)\n", | 300 | pr_notice("nfnetlink_log: can't alloc whole buffer (%u bytes)\n", |
301 | inst_size); | 301 | inst_size); |
302 | 302 | ||
303 | if (n > pkt_size) { | 303 | if (n > pkt_size) { |
@@ -306,7 +306,7 @@ nfulnl_alloc_skb(unsigned int inst_size, unsigned int pkt_size) | |||
306 | 306 | ||
307 | skb = alloc_skb(pkt_size, GFP_ATOMIC); | 307 | skb = alloc_skb(pkt_size, GFP_ATOMIC); |
308 | if (!skb) | 308 | if (!skb) |
309 | PRINTR("nfnetlink_log: can't even alloc %u " | 309 | pr_err("nfnetlink_log: can't even alloc %u " |
310 | "bytes\n", pkt_size); | 310 | "bytes\n", pkt_size); |
311 | } | 311 | } |
312 | } | 312 | } |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index e70a6ef1f4f2..12e1ab37fcd8 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -246,8 +246,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
246 | break; | 246 | break; |
247 | 247 | ||
248 | case NFQNL_COPY_PACKET: | 248 | case NFQNL_COPY_PACKET: |
249 | if ((entskb->ip_summed == CHECKSUM_PARTIAL || | 249 | if (entskb->ip_summed == CHECKSUM_PARTIAL && |
250 | entskb->ip_summed == CHECKSUM_COMPLETE) && | ||
251 | skb_checksum_help(entskb)) { | 250 | skb_checksum_help(entskb)) { |
252 | spin_unlock_bh(&queue->lock); | 251 | spin_unlock_bh(&queue->lock); |
253 | return NULL; | 252 | return NULL; |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 665f5beef6ad..445de702b8b7 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/socket.h> | 17 | #include <linux/socket.h> |
18 | #include <linux/net.h> | 18 | #include <linux/net.h> |
@@ -55,12 +55,6 @@ struct xt_af { | |||
55 | 55 | ||
56 | static struct xt_af *xt; | 56 | static struct xt_af *xt; |
57 | 57 | ||
58 | #ifdef DEBUG_IP_FIREWALL_USER | ||
59 | #define duprintf(format, args...) printk(format , ## args) | ||
60 | #else | ||
61 | #define duprintf(format, args...) | ||
62 | #endif | ||
63 | |||
64 | static const char *const xt_prefix[NFPROTO_NUMPROTO] = { | 58 | static const char *const xt_prefix[NFPROTO_NUMPROTO] = { |
65 | [NFPROTO_UNSPEC] = "x", | 59 | [NFPROTO_UNSPEC] = "x", |
66 | [NFPROTO_IPV4] = "ip", | 60 | [NFPROTO_IPV4] = "ip", |
@@ -69,6 +63,9 @@ static const char *const xt_prefix[NFPROTO_NUMPROTO] = { | |||
69 | [NFPROTO_IPV6] = "ip6", | 63 | [NFPROTO_IPV6] = "ip6", |
70 | }; | 64 | }; |
71 | 65 | ||
66 | /* Allow this many total (re)entries. */ | ||
67 | static const unsigned int xt_jumpstack_multiplier = 2; | ||
68 | |||
72 | /* Registration hooks for targets. */ | 69 | /* Registration hooks for targets. */ |
73 | int | 70 | int |
74 | xt_register_target(struct xt_target *target) | 71 | xt_register_target(struct xt_target *target) |
@@ -221,6 +218,17 @@ struct xt_match *xt_find_match(u8 af, const char *name, u8 revision) | |||
221 | } | 218 | } |
222 | EXPORT_SYMBOL(xt_find_match); | 219 | EXPORT_SYMBOL(xt_find_match); |
223 | 220 | ||
221 | struct xt_match * | ||
222 | xt_request_find_match(uint8_t nfproto, const char *name, uint8_t revision) | ||
223 | { | ||
224 | struct xt_match *match; | ||
225 | |||
226 | match = try_then_request_module(xt_find_match(nfproto, name, revision), | ||
227 | "%st_%s", xt_prefix[nfproto], name); | ||
228 | return (match != NULL) ? match : ERR_PTR(-ENOENT); | ||
229 | } | ||
230 | EXPORT_SYMBOL_GPL(xt_request_find_match); | ||
231 | |||
224 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ | 232 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ |
225 | struct xt_target *xt_find_target(u8 af, const char *name, u8 revision) | 233 | struct xt_target *xt_find_target(u8 af, const char *name, u8 revision) |
226 | { | 234 | { |
@@ -257,9 +265,7 @@ struct xt_target *xt_request_find_target(u8 af, const char *name, u8 revision) | |||
257 | 265 | ||
258 | target = try_then_request_module(xt_find_target(af, name, revision), | 266 | target = try_then_request_module(xt_find_target(af, name, revision), |
259 | "%st_%s", xt_prefix[af], name); | 267 | "%st_%s", xt_prefix[af], name); |
260 | if (IS_ERR(target) || !target) | 268 | return (target != NULL) ? target : ERR_PTR(-ENOENT); |
261 | return NULL; | ||
262 | return target; | ||
263 | } | 269 | } |
264 | EXPORT_SYMBOL_GPL(xt_request_find_target); | 270 | EXPORT_SYMBOL_GPL(xt_request_find_target); |
265 | 271 | ||
@@ -361,6 +367,8 @@ static char *textify_hooks(char *buf, size_t size, unsigned int mask) | |||
361 | int xt_check_match(struct xt_mtchk_param *par, | 367 | int xt_check_match(struct xt_mtchk_param *par, |
362 | unsigned int size, u_int8_t proto, bool inv_proto) | 368 | unsigned int size, u_int8_t proto, bool inv_proto) |
363 | { | 369 | { |
370 | int ret; | ||
371 | |||
364 | if (XT_ALIGN(par->match->matchsize) != size && | 372 | if (XT_ALIGN(par->match->matchsize) != size && |
365 | par->match->matchsize != -1) { | 373 | par->match->matchsize != -1) { |
366 | /* | 374 | /* |
@@ -397,8 +405,14 @@ int xt_check_match(struct xt_mtchk_param *par, | |||
397 | par->match->proto); | 405 | par->match->proto); |
398 | return -EINVAL; | 406 | return -EINVAL; |
399 | } | 407 | } |
400 | if (par->match->checkentry != NULL && !par->match->checkentry(par)) | 408 | if (par->match->checkentry != NULL) { |
401 | return -EINVAL; | 409 | ret = par->match->checkentry(par); |
410 | if (ret < 0) | ||
411 | return ret; | ||
412 | else if (ret > 0) | ||
413 | /* Flag up potential errors. */ | ||
414 | return -EIO; | ||
415 | } | ||
402 | return 0; | 416 | return 0; |
403 | } | 417 | } |
404 | EXPORT_SYMBOL_GPL(xt_check_match); | 418 | EXPORT_SYMBOL_GPL(xt_check_match); |
@@ -518,6 +532,8 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user); | |||
518 | int xt_check_target(struct xt_tgchk_param *par, | 532 | int xt_check_target(struct xt_tgchk_param *par, |
519 | unsigned int size, u_int8_t proto, bool inv_proto) | 533 | unsigned int size, u_int8_t proto, bool inv_proto) |
520 | { | 534 | { |
535 | int ret; | ||
536 | |||
521 | if (XT_ALIGN(par->target->targetsize) != size) { | 537 | if (XT_ALIGN(par->target->targetsize) != size) { |
522 | pr_err("%s_tables: %s.%u target: invalid size " | 538 | pr_err("%s_tables: %s.%u target: invalid size " |
523 | "%u (kernel) != (user) %u\n", | 539 | "%u (kernel) != (user) %u\n", |
@@ -549,8 +565,14 @@ int xt_check_target(struct xt_tgchk_param *par, | |||
549 | par->target->proto); | 565 | par->target->proto); |
550 | return -EINVAL; | 566 | return -EINVAL; |
551 | } | 567 | } |
552 | if (par->target->checkentry != NULL && !par->target->checkentry(par)) | 568 | if (par->target->checkentry != NULL) { |
553 | return -EINVAL; | 569 | ret = par->target->checkentry(par); |
570 | if (ret < 0) | ||
571 | return ret; | ||
572 | else if (ret > 0) | ||
573 | /* Flag up potential errors. */ | ||
574 | return -EIO; | ||
575 | } | ||
554 | return 0; | 576 | return 0; |
555 | } | 577 | } |
556 | EXPORT_SYMBOL_GPL(xt_check_target); | 578 | EXPORT_SYMBOL_GPL(xt_check_target); |
@@ -662,6 +684,26 @@ void xt_free_table_info(struct xt_table_info *info) | |||
662 | else | 684 | else |
663 | vfree(info->entries[cpu]); | 685 | vfree(info->entries[cpu]); |
664 | } | 686 | } |
687 | |||
688 | if (info->jumpstack != NULL) { | ||
689 | if (sizeof(void *) * info->stacksize > PAGE_SIZE) { | ||
690 | for_each_possible_cpu(cpu) | ||
691 | vfree(info->jumpstack[cpu]); | ||
692 | } else { | ||
693 | for_each_possible_cpu(cpu) | ||
694 | kfree(info->jumpstack[cpu]); | ||
695 | } | ||
696 | } | ||
697 | |||
698 | if (sizeof(void **) * nr_cpu_ids > PAGE_SIZE) | ||
699 | vfree(info->jumpstack); | ||
700 | else | ||
701 | kfree(info->jumpstack); | ||
702 | if (sizeof(unsigned int) * nr_cpu_ids > PAGE_SIZE) | ||
703 | vfree(info->stackptr); | ||
704 | else | ||
705 | kfree(info->stackptr); | ||
706 | |||
665 | kfree(info); | 707 | kfree(info); |
666 | } | 708 | } |
667 | EXPORT_SYMBOL(xt_free_table_info); | 709 | EXPORT_SYMBOL(xt_free_table_info); |
@@ -706,6 +748,49 @@ EXPORT_SYMBOL_GPL(xt_compat_unlock); | |||
706 | DEFINE_PER_CPU(struct xt_info_lock, xt_info_locks); | 748 | DEFINE_PER_CPU(struct xt_info_lock, xt_info_locks); |
707 | EXPORT_PER_CPU_SYMBOL_GPL(xt_info_locks); | 749 | EXPORT_PER_CPU_SYMBOL_GPL(xt_info_locks); |
708 | 750 | ||
751 | static int xt_jumpstack_alloc(struct xt_table_info *i) | ||
752 | { | ||
753 | unsigned int size; | ||
754 | int cpu; | ||
755 | |||
756 | size = sizeof(unsigned int) * nr_cpu_ids; | ||
757 | if (size > PAGE_SIZE) | ||
758 | i->stackptr = vmalloc(size); | ||
759 | else | ||
760 | i->stackptr = kmalloc(size, GFP_KERNEL); | ||
761 | if (i->stackptr == NULL) | ||
762 | return -ENOMEM; | ||
763 | memset(i->stackptr, 0, size); | ||
764 | |||
765 | size = sizeof(void **) * nr_cpu_ids; | ||
766 | if (size > PAGE_SIZE) | ||
767 | i->jumpstack = vmalloc(size); | ||
768 | else | ||
769 | i->jumpstack = kmalloc(size, GFP_KERNEL); | ||
770 | if (i->jumpstack == NULL) | ||
771 | return -ENOMEM; | ||
772 | memset(i->jumpstack, 0, size); | ||
773 | |||
774 | i->stacksize *= xt_jumpstack_multiplier; | ||
775 | size = sizeof(void *) * i->stacksize; | ||
776 | for_each_possible_cpu(cpu) { | ||
777 | if (size > PAGE_SIZE) | ||
778 | i->jumpstack[cpu] = vmalloc_node(size, | ||
779 | cpu_to_node(cpu)); | ||
780 | else | ||
781 | i->jumpstack[cpu] = kmalloc_node(size, | ||
782 | GFP_KERNEL, cpu_to_node(cpu)); | ||
783 | if (i->jumpstack[cpu] == NULL) | ||
784 | /* | ||
785 | * Freeing will be done later on by the callers. The | ||
786 | * chain is: xt_replace_table -> __do_replace -> | ||
787 | * do_replace -> xt_free_table_info. | ||
788 | */ | ||
789 | return -ENOMEM; | ||
790 | } | ||
791 | |||
792 | return 0; | ||
793 | } | ||
709 | 794 | ||
710 | struct xt_table_info * | 795 | struct xt_table_info * |
711 | xt_replace_table(struct xt_table *table, | 796 | xt_replace_table(struct xt_table *table, |
@@ -714,6 +799,13 @@ xt_replace_table(struct xt_table *table, | |||
714 | int *error) | 799 | int *error) |
715 | { | 800 | { |
716 | struct xt_table_info *private; | 801 | struct xt_table_info *private; |
802 | int ret; | ||
803 | |||
804 | ret = xt_jumpstack_alloc(newinfo); | ||
805 | if (ret < 0) { | ||
806 | *error = ret; | ||
807 | return NULL; | ||
808 | } | ||
717 | 809 | ||
718 | /* Do the substitution. */ | 810 | /* Do the substitution. */ |
719 | local_bh_disable(); | 811 | local_bh_disable(); |
@@ -721,7 +813,7 @@ xt_replace_table(struct xt_table *table, | |||
721 | 813 | ||
722 | /* Check inside lock: is the old number correct? */ | 814 | /* Check inside lock: is the old number correct? */ |
723 | if (num_counters != private->number) { | 815 | if (num_counters != private->number) { |
724 | duprintf("num_counters != table->private->number (%u/%u)\n", | 816 | pr_debug("num_counters != table->private->number (%u/%u)\n", |
725 | num_counters, private->number); | 817 | num_counters, private->number); |
726 | local_bh_enable(); | 818 | local_bh_enable(); |
727 | *error = -EAGAIN; | 819 | *error = -EAGAIN; |
@@ -752,6 +844,10 @@ struct xt_table *xt_register_table(struct net *net, | |||
752 | struct xt_table_info *private; | 844 | struct xt_table_info *private; |
753 | struct xt_table *t, *table; | 845 | struct xt_table *t, *table; |
754 | 846 | ||
847 | ret = xt_jumpstack_alloc(newinfo); | ||
848 | if (ret < 0) | ||
849 | return ERR_PTR(ret); | ||
850 | |||
755 | /* Don't add one object to multiple lists. */ | 851 | /* Don't add one object to multiple lists. */ |
756 | table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL); | 852 | table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL); |
757 | if (!table) { | 853 | if (!table) { |
@@ -778,7 +874,7 @@ struct xt_table *xt_register_table(struct net *net, | |||
778 | goto unlock; | 874 | goto unlock; |
779 | 875 | ||
780 | private = table->private; | 876 | private = table->private; |
781 | duprintf("table->private->number = %u\n", private->number); | 877 | pr_debug("table->private->number = %u\n", private->number); |
782 | 878 | ||
783 | /* save number of initial entries */ | 879 | /* save number of initial entries */ |
784 | private->initial_entries = private->number; | 880 | private->initial_entries = private->number; |
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c index 011bc80dd2a1..c2c0e4abeb99 100644 --- a/net/netfilter/xt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c | |||
@@ -27,7 +27,7 @@ MODULE_ALIAS("ipt_CLASSIFY"); | |||
27 | MODULE_ALIAS("ip6t_CLASSIFY"); | 27 | MODULE_ALIAS("ip6t_CLASSIFY"); |
28 | 28 | ||
29 | static unsigned int | 29 | static unsigned int |
30 | classify_tg(struct sk_buff *skb, const struct xt_target_param *par) | 30 | classify_tg(struct sk_buff *skb, const struct xt_action_param *par) |
31 | { | 31 | { |
32 | const struct xt_classify_target_info *clinfo = par->targinfo; | 32 | const struct xt_classify_target_info *clinfo = par->targinfo; |
33 | 33 | ||
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c deleted file mode 100644 index 593457068ae1..000000000000 --- a/net/netfilter/xt_CONNMARK.c +++ /dev/null | |||
@@ -1,113 +0,0 @@ | |||
1 | /* | ||
2 | * xt_CONNMARK - Netfilter module to modify the connection mark values | ||
3 | * | ||
4 | * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | ||
5 | * by Henrik Nordstrom <hno@marasystems.com> | ||
6 | * Copyright © CC Computer Consultants GmbH, 2007 - 2008 | ||
7 | * Jan Engelhardt <jengelh@computergmbh.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/skbuff.h> | ||
25 | #include <linux/ip.h> | ||
26 | #include <net/checksum.h> | ||
27 | |||
28 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); | ||
29 | MODULE_DESCRIPTION("Xtables: connection mark modification"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | MODULE_ALIAS("ipt_CONNMARK"); | ||
32 | MODULE_ALIAS("ip6t_CONNMARK"); | ||
33 | |||
34 | #include <linux/netfilter/x_tables.h> | ||
35 | #include <linux/netfilter/xt_CONNMARK.h> | ||
36 | #include <net/netfilter/nf_conntrack_ecache.h> | ||
37 | |||
38 | static unsigned int | ||
39 | connmark_tg(struct sk_buff *skb, const struct xt_target_param *par) | ||
40 | { | ||
41 | const struct xt_connmark_tginfo1 *info = par->targinfo; | ||
42 | enum ip_conntrack_info ctinfo; | ||
43 | struct nf_conn *ct; | ||
44 | u_int32_t newmark; | ||
45 | |||
46 | ct = nf_ct_get(skb, &ctinfo); | ||
47 | if (ct == NULL) | ||
48 | return XT_CONTINUE; | ||
49 | |||
50 | switch (info->mode) { | ||
51 | case XT_CONNMARK_SET: | ||
52 | newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; | ||
53 | if (ct->mark != newmark) { | ||
54 | ct->mark = newmark; | ||
55 | nf_conntrack_event_cache(IPCT_MARK, ct); | ||
56 | } | ||
57 | break; | ||
58 | case XT_CONNMARK_SAVE: | ||
59 | newmark = (ct->mark & ~info->ctmask) ^ | ||
60 | (skb->mark & info->nfmask); | ||
61 | if (ct->mark != newmark) { | ||
62 | ct->mark = newmark; | ||
63 | nf_conntrack_event_cache(IPCT_MARK, ct); | ||
64 | } | ||
65 | break; | ||
66 | case XT_CONNMARK_RESTORE: | ||
67 | newmark = (skb->mark & ~info->nfmask) ^ | ||
68 | (ct->mark & info->ctmask); | ||
69 | skb->mark = newmark; | ||
70 | break; | ||
71 | } | ||
72 | |||
73 | return XT_CONTINUE; | ||
74 | } | ||
75 | |||
76 | static bool connmark_tg_check(const struct xt_tgchk_param *par) | ||
77 | { | ||
78 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { | ||
79 | printk(KERN_WARNING "cannot load conntrack support for " | ||
80 | "proto=%u\n", par->family); | ||
81 | return false; | ||
82 | } | ||
83 | return true; | ||
84 | } | ||
85 | |||
86 | static void connmark_tg_destroy(const struct xt_tgdtor_param *par) | ||
87 | { | ||
88 | nf_ct_l3proto_module_put(par->family); | ||
89 | } | ||
90 | |||
91 | static struct xt_target connmark_tg_reg __read_mostly = { | ||
92 | .name = "CONNMARK", | ||
93 | .revision = 1, | ||
94 | .family = NFPROTO_UNSPEC, | ||
95 | .checkentry = connmark_tg_check, | ||
96 | .target = connmark_tg, | ||
97 | .targetsize = sizeof(struct xt_connmark_tginfo1), | ||
98 | .destroy = connmark_tg_destroy, | ||
99 | .me = THIS_MODULE, | ||
100 | }; | ||
101 | |||
102 | static int __init connmark_tg_init(void) | ||
103 | { | ||
104 | return xt_register_target(&connmark_tg_reg); | ||
105 | } | ||
106 | |||
107 | static void __exit connmark_tg_exit(void) | ||
108 | { | ||
109 | xt_unregister_target(&connmark_tg_reg); | ||
110 | } | ||
111 | |||
112 | module_init(connmark_tg_init); | ||
113 | module_exit(connmark_tg_exit); | ||
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c index b54c3756fdc3..e04dc282e3bb 100644 --- a/net/netfilter/xt_CONNSECMARK.c +++ b/net/netfilter/xt_CONNSECMARK.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * published by the Free Software Foundation. | 15 | * published by the Free Software Foundation. |
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
20 | #include <linux/netfilter/x_tables.h> | 21 | #include <linux/netfilter/x_tables.h> |
@@ -22,8 +23,6 @@ | |||
22 | #include <net/netfilter/nf_conntrack.h> | 23 | #include <net/netfilter/nf_conntrack.h> |
23 | #include <net/netfilter/nf_conntrack_ecache.h> | 24 | #include <net/netfilter/nf_conntrack_ecache.h> |
24 | 25 | ||
25 | #define PFX "CONNSECMARK: " | ||
26 | |||
27 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
28 | MODULE_AUTHOR("James Morris <jmorris@redhat.com>"); | 27 | MODULE_AUTHOR("James Morris <jmorris@redhat.com>"); |
29 | MODULE_DESCRIPTION("Xtables: target for copying between connection and security mark"); | 28 | MODULE_DESCRIPTION("Xtables: target for copying between connection and security mark"); |
@@ -65,7 +64,7 @@ static void secmark_restore(struct sk_buff *skb) | |||
65 | } | 64 | } |
66 | 65 | ||
67 | static unsigned int | 66 | static unsigned int |
68 | connsecmark_tg(struct sk_buff *skb, const struct xt_target_param *par) | 67 | connsecmark_tg(struct sk_buff *skb, const struct xt_action_param *par) |
69 | { | 68 | { |
70 | const struct xt_connsecmark_target_info *info = par->targinfo; | 69 | const struct xt_connsecmark_target_info *info = par->targinfo; |
71 | 70 | ||
@@ -85,15 +84,16 @@ connsecmark_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
85 | return XT_CONTINUE; | 84 | return XT_CONTINUE; |
86 | } | 85 | } |
87 | 86 | ||
88 | static bool connsecmark_tg_check(const struct xt_tgchk_param *par) | 87 | static int connsecmark_tg_check(const struct xt_tgchk_param *par) |
89 | { | 88 | { |
90 | const struct xt_connsecmark_target_info *info = par->targinfo; | 89 | const struct xt_connsecmark_target_info *info = par->targinfo; |
90 | int ret; | ||
91 | 91 | ||
92 | if (strcmp(par->table, "mangle") != 0 && | 92 | if (strcmp(par->table, "mangle") != 0 && |
93 | strcmp(par->table, "security") != 0) { | 93 | strcmp(par->table, "security") != 0) { |
94 | printk(KERN_INFO PFX "target only valid in the \'mangle\' " | 94 | pr_info("target only valid in the \'mangle\' " |
95 | "or \'security\' tables, not \'%s\'.\n", par->table); | 95 | "or \'security\' tables, not \'%s\'.\n", par->table); |
96 | return false; | 96 | return -EINVAL; |
97 | } | 97 | } |
98 | 98 | ||
99 | switch (info->mode) { | 99 | switch (info->mode) { |
@@ -102,16 +102,15 @@ static bool connsecmark_tg_check(const struct xt_tgchk_param *par) | |||
102 | break; | 102 | break; |
103 | 103 | ||
104 | default: | 104 | default: |
105 | printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); | 105 | pr_info("invalid mode: %hu\n", info->mode); |
106 | return false; | 106 | return -EINVAL; |
107 | } | 107 | } |
108 | 108 | ||
109 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { | 109 | ret = nf_ct_l3proto_try_module_get(par->family); |
110 | printk(KERN_WARNING "can't load conntrack support for " | 110 | if (ret < 0) |
111 | "proto=%u\n", par->family); | 111 | pr_info("cannot load conntrack support for proto=%u\n", |
112 | return false; | 112 | par->family); |
113 | } | 113 | return ret; |
114 | return true; | ||
115 | } | 114 | } |
116 | 115 | ||
117 | static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par) | 116 | static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par) |
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index ee18b231b950..562bf3266e04 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <net/netfilter/nf_conntrack_zones.h> | 20 | #include <net/netfilter/nf_conntrack_zones.h> |
21 | 21 | ||
22 | static unsigned int xt_ct_target(struct sk_buff *skb, | 22 | static unsigned int xt_ct_target(struct sk_buff *skb, |
23 | const struct xt_target_param *par) | 23 | const struct xt_action_param *par) |
24 | { | 24 | { |
25 | const struct xt_ct_target_info *info = par->targinfo; | 25 | const struct xt_ct_target_info *info = par->targinfo; |
26 | struct nf_conn *ct = info->ct; | 26 | struct nf_conn *ct = info->ct; |
@@ -38,13 +38,13 @@ static unsigned int xt_ct_target(struct sk_buff *skb, | |||
38 | 38 | ||
39 | static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) | 39 | static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) |
40 | { | 40 | { |
41 | if (par->family == AF_INET) { | 41 | if (par->family == NFPROTO_IPV4) { |
42 | const struct ipt_entry *e = par->entryinfo; | 42 | const struct ipt_entry *e = par->entryinfo; |
43 | 43 | ||
44 | if (e->ip.invflags & IPT_INV_PROTO) | 44 | if (e->ip.invflags & IPT_INV_PROTO) |
45 | return 0; | 45 | return 0; |
46 | return e->ip.proto; | 46 | return e->ip.proto; |
47 | } else if (par->family == AF_INET6) { | 47 | } else if (par->family == NFPROTO_IPV6) { |
48 | const struct ip6t_entry *e = par->entryinfo; | 48 | const struct ip6t_entry *e = par->entryinfo; |
49 | 49 | ||
50 | if (e->ipv6.invflags & IP6T_INV_PROTO) | 50 | if (e->ipv6.invflags & IP6T_INV_PROTO) |
@@ -54,16 +54,17 @@ static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) | |||
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
56 | 56 | ||
57 | static bool xt_ct_tg_check(const struct xt_tgchk_param *par) | 57 | static int xt_ct_tg_check(const struct xt_tgchk_param *par) |
58 | { | 58 | { |
59 | struct xt_ct_target_info *info = par->targinfo; | 59 | struct xt_ct_target_info *info = par->targinfo; |
60 | struct nf_conntrack_tuple t; | 60 | struct nf_conntrack_tuple t; |
61 | struct nf_conn_help *help; | 61 | struct nf_conn_help *help; |
62 | struct nf_conn *ct; | 62 | struct nf_conn *ct; |
63 | int ret = 0; | ||
63 | u8 proto; | 64 | u8 proto; |
64 | 65 | ||
65 | if (info->flags & ~XT_CT_NOTRACK) | 66 | if (info->flags & ~XT_CT_NOTRACK) |
66 | return false; | 67 | return -EINVAL; |
67 | 68 | ||
68 | if (info->flags & XT_CT_NOTRACK) { | 69 | if (info->flags & XT_CT_NOTRACK) { |
69 | ct = &nf_conntrack_untracked; | 70 | ct = &nf_conntrack_untracked; |
@@ -76,28 +77,34 @@ static bool xt_ct_tg_check(const struct xt_tgchk_param *par) | |||
76 | goto err1; | 77 | goto err1; |
77 | #endif | 78 | #endif |
78 | 79 | ||
79 | if (nf_ct_l3proto_try_module_get(par->family) < 0) | 80 | ret = nf_ct_l3proto_try_module_get(par->family); |
81 | if (ret < 0) | ||
80 | goto err1; | 82 | goto err1; |
81 | 83 | ||
82 | memset(&t, 0, sizeof(t)); | 84 | memset(&t, 0, sizeof(t)); |
83 | ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); | 85 | ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); |
86 | ret = PTR_ERR(ct); | ||
84 | if (IS_ERR(ct)) | 87 | if (IS_ERR(ct)) |
85 | goto err2; | 88 | goto err2; |
86 | 89 | ||
90 | ret = 0; | ||
87 | if ((info->ct_events || info->exp_events) && | 91 | if ((info->ct_events || info->exp_events) && |
88 | !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, | 92 | !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, |
89 | GFP_KERNEL)) | 93 | GFP_KERNEL)) |
90 | goto err3; | 94 | goto err3; |
91 | 95 | ||
92 | if (info->helper[0]) { | 96 | if (info->helper[0]) { |
97 | ret = -ENOENT; | ||
93 | proto = xt_ct_find_proto(par); | 98 | proto = xt_ct_find_proto(par); |
94 | if (!proto) | 99 | if (!proto) |
95 | goto err3; | 100 | goto err3; |
96 | 101 | ||
102 | ret = -ENOMEM; | ||
97 | help = nf_ct_helper_ext_add(ct, GFP_KERNEL); | 103 | help = nf_ct_helper_ext_add(ct, GFP_KERNEL); |
98 | if (help == NULL) | 104 | if (help == NULL) |
99 | goto err3; | 105 | goto err3; |
100 | 106 | ||
107 | ret = -ENOENT; | ||
101 | help->helper = nf_conntrack_helper_try_module_get(info->helper, | 108 | help->helper = nf_conntrack_helper_try_module_get(info->helper, |
102 | par->family, | 109 | par->family, |
103 | proto); | 110 | proto); |
@@ -109,14 +116,14 @@ static bool xt_ct_tg_check(const struct xt_tgchk_param *par) | |||
109 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | 116 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); |
110 | out: | 117 | out: |
111 | info->ct = ct; | 118 | info->ct = ct; |
112 | return true; | 119 | return 0; |
113 | 120 | ||
114 | err3: | 121 | err3: |
115 | nf_conntrack_free(ct); | 122 | nf_conntrack_free(ct); |
116 | err2: | 123 | err2: |
117 | nf_ct_l3proto_module_put(par->family); | 124 | nf_ct_l3proto_module_put(par->family); |
118 | err1: | 125 | err1: |
119 | return false; | 126 | return ret; |
120 | } | 127 | } |
121 | 128 | ||
122 | static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par) | 129 | static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par) |
@@ -138,7 +145,7 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par) | |||
138 | static struct xt_target xt_ct_tg __read_mostly = { | 145 | static struct xt_target xt_ct_tg __read_mostly = { |
139 | .name = "CT", | 146 | .name = "CT", |
140 | .family = NFPROTO_UNSPEC, | 147 | .family = NFPROTO_UNSPEC, |
141 | .targetsize = XT_ALIGN(sizeof(struct xt_ct_target_info)), | 148 | .targetsize = sizeof(struct xt_ct_target_info), |
142 | .checkentry = xt_ct_tg_check, | 149 | .checkentry = xt_ct_tg_check, |
143 | .destroy = xt_ct_tg_destroy, | 150 | .destroy = xt_ct_tg_destroy, |
144 | .target = xt_ct_target, | 151 | .target = xt_ct_target, |
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index 74ce89260056..0a229191e55b 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * | 9 | * |
10 | * See RFC2474 for a description of the DSCP field within the IP Header. | 10 | * See RFC2474 for a description of the DSCP field within the IP Header. |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/ip.h> | 15 | #include <linux/ip.h> |
@@ -28,7 +28,7 @@ MODULE_ALIAS("ipt_TOS"); | |||
28 | MODULE_ALIAS("ip6t_TOS"); | 28 | MODULE_ALIAS("ip6t_TOS"); |
29 | 29 | ||
30 | static unsigned int | 30 | static unsigned int |
31 | dscp_tg(struct sk_buff *skb, const struct xt_target_param *par) | 31 | dscp_tg(struct sk_buff *skb, const struct xt_action_param *par) |
32 | { | 32 | { |
33 | const struct xt_DSCP_info *dinfo = par->targinfo; | 33 | const struct xt_DSCP_info *dinfo = par->targinfo; |
34 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; | 34 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; |
@@ -45,7 +45,7 @@ dscp_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
45 | } | 45 | } |
46 | 46 | ||
47 | static unsigned int | 47 | static unsigned int |
48 | dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par) | 48 | dscp_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
49 | { | 49 | { |
50 | const struct xt_DSCP_info *dinfo = par->targinfo; | 50 | const struct xt_DSCP_info *dinfo = par->targinfo; |
51 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; | 51 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; |
@@ -60,19 +60,19 @@ dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par) | |||
60 | return XT_CONTINUE; | 60 | return XT_CONTINUE; |
61 | } | 61 | } |
62 | 62 | ||
63 | static bool dscp_tg_check(const struct xt_tgchk_param *par) | 63 | static int dscp_tg_check(const struct xt_tgchk_param *par) |
64 | { | 64 | { |
65 | const struct xt_DSCP_info *info = par->targinfo; | 65 | const struct xt_DSCP_info *info = par->targinfo; |
66 | 66 | ||
67 | if (info->dscp > XT_DSCP_MAX) { | 67 | if (info->dscp > XT_DSCP_MAX) { |
68 | printk(KERN_WARNING "DSCP: dscp %x out of range\n", info->dscp); | 68 | pr_info("dscp %x out of range\n", info->dscp); |
69 | return false; | 69 | return -EDOM; |
70 | } | 70 | } |
71 | return true; | 71 | return 0; |
72 | } | 72 | } |
73 | 73 | ||
74 | static unsigned int | 74 | static unsigned int |
75 | tos_tg(struct sk_buff *skb, const struct xt_target_param *par) | 75 | tos_tg(struct sk_buff *skb, const struct xt_action_param *par) |
76 | { | 76 | { |
77 | const struct xt_tos_target_info *info = par->targinfo; | 77 | const struct xt_tos_target_info *info = par->targinfo; |
78 | struct iphdr *iph = ip_hdr(skb); | 78 | struct iphdr *iph = ip_hdr(skb); |
@@ -92,7 +92,7 @@ tos_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
92 | } | 92 | } |
93 | 93 | ||
94 | static unsigned int | 94 | static unsigned int |
95 | tos_tg6(struct sk_buff *skb, const struct xt_target_param *par) | 95 | tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
96 | { | 96 | { |
97 | const struct xt_tos_target_info *info = par->targinfo; | 97 | const struct xt_tos_target_info *info = par->targinfo; |
98 | struct ipv6hdr *iph = ipv6_hdr(skb); | 98 | struct ipv6hdr *iph = ipv6_hdr(skb); |
diff --git a/net/netfilter/xt_HL.c b/net/netfilter/xt_HL.c index 10e789e2d12a..95b084800fcc 100644 --- a/net/netfilter/xt_HL.c +++ b/net/netfilter/xt_HL.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/ip.h> | 15 | #include <linux/ip.h> |
@@ -26,7 +26,7 @@ MODULE_DESCRIPTION("Xtables: Hoplimit/TTL Limit field modification target"); | |||
26 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
27 | 27 | ||
28 | static unsigned int | 28 | static unsigned int |
29 | ttl_tg(struct sk_buff *skb, const struct xt_target_param *par) | 29 | ttl_tg(struct sk_buff *skb, const struct xt_action_param *par) |
30 | { | 30 | { |
31 | struct iphdr *iph; | 31 | struct iphdr *iph; |
32 | const struct ipt_TTL_info *info = par->targinfo; | 32 | const struct ipt_TTL_info *info = par->targinfo; |
@@ -66,7 +66,7 @@ ttl_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
66 | } | 66 | } |
67 | 67 | ||
68 | static unsigned int | 68 | static unsigned int |
69 | hl_tg6(struct sk_buff *skb, const struct xt_target_param *par) | 69 | hl_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
70 | { | 70 | { |
71 | struct ipv6hdr *ip6h; | 71 | struct ipv6hdr *ip6h; |
72 | const struct ip6t_HL_info *info = par->targinfo; | 72 | const struct ip6t_HL_info *info = par->targinfo; |
@@ -101,35 +101,33 @@ hl_tg6(struct sk_buff *skb, const struct xt_target_param *par) | |||
101 | return XT_CONTINUE; | 101 | return XT_CONTINUE; |
102 | } | 102 | } |
103 | 103 | ||
104 | static bool ttl_tg_check(const struct xt_tgchk_param *par) | 104 | static int ttl_tg_check(const struct xt_tgchk_param *par) |
105 | { | 105 | { |
106 | const struct ipt_TTL_info *info = par->targinfo; | 106 | const struct ipt_TTL_info *info = par->targinfo; |
107 | 107 | ||
108 | if (info->mode > IPT_TTL_MAXMODE) { | 108 | if (info->mode > IPT_TTL_MAXMODE) { |
109 | printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", | 109 | pr_info("TTL: invalid or unknown mode %u\n", info->mode); |
110 | info->mode); | 110 | return -EINVAL; |
111 | return false; | ||
112 | } | 111 | } |
113 | if (info->mode != IPT_TTL_SET && info->ttl == 0) | 112 | if (info->mode != IPT_TTL_SET && info->ttl == 0) |
114 | return false; | 113 | return -EINVAL; |
115 | return true; | 114 | return 0; |
116 | } | 115 | } |
117 | 116 | ||
118 | static bool hl_tg6_check(const struct xt_tgchk_param *par) | 117 | static int hl_tg6_check(const struct xt_tgchk_param *par) |
119 | { | 118 | { |
120 | const struct ip6t_HL_info *info = par->targinfo; | 119 | const struct ip6t_HL_info *info = par->targinfo; |
121 | 120 | ||
122 | if (info->mode > IP6T_HL_MAXMODE) { | 121 | if (info->mode > IP6T_HL_MAXMODE) { |
123 | printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", | 122 | pr_info("invalid or unknown mode %u\n", info->mode); |
124 | info->mode); | 123 | return -EINVAL; |
125 | return false; | ||
126 | } | 124 | } |
127 | if (info->mode != IP6T_HL_SET && info->hop_limit == 0) { | 125 | if (info->mode != IP6T_HL_SET && info->hop_limit == 0) { |
128 | printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't " | 126 | pr_info("increment/decrement does not " |
129 | "make sense with value 0\n"); | 127 | "make sense with value 0\n"); |
130 | return false; | 128 | return -EINVAL; |
131 | } | 129 | } |
132 | return true; | 130 | return 0; |
133 | } | 131 | } |
134 | 132 | ||
135 | static struct xt_target hl_tg_reg[] __read_mostly = { | 133 | static struct xt_target hl_tg_reg[] __read_mostly = { |
diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c index 3271c8e52153..a4140509eea1 100644 --- a/net/netfilter/xt_LED.c +++ b/net/netfilter/xt_LED.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * 02110-1301 USA. | 18 | * 02110-1301 USA. |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <linux/netfilter/x_tables.h> | 24 | #include <linux/netfilter/x_tables.h> |
@@ -32,18 +32,24 @@ MODULE_LICENSE("GPL"); | |||
32 | MODULE_AUTHOR("Adam Nielsen <a.nielsen@shikadi.net>"); | 32 | MODULE_AUTHOR("Adam Nielsen <a.nielsen@shikadi.net>"); |
33 | MODULE_DESCRIPTION("Xtables: trigger LED devices on packet match"); | 33 | MODULE_DESCRIPTION("Xtables: trigger LED devices on packet match"); |
34 | 34 | ||
35 | static LIST_HEAD(xt_led_triggers); | ||
36 | static DEFINE_MUTEX(xt_led_mutex); | ||
37 | |||
35 | /* | 38 | /* |
36 | * This is declared in here (the kernel module) only, to avoid having these | 39 | * This is declared in here (the kernel module) only, to avoid having these |
37 | * dependencies in userspace code. This is what xt_led_info.internal_data | 40 | * dependencies in userspace code. This is what xt_led_info.internal_data |
38 | * points to. | 41 | * points to. |
39 | */ | 42 | */ |
40 | struct xt_led_info_internal { | 43 | struct xt_led_info_internal { |
44 | struct list_head list; | ||
45 | int refcnt; | ||
46 | char *trigger_id; | ||
41 | struct led_trigger netfilter_led_trigger; | 47 | struct led_trigger netfilter_led_trigger; |
42 | struct timer_list timer; | 48 | struct timer_list timer; |
43 | }; | 49 | }; |
44 | 50 | ||
45 | static unsigned int | 51 | static unsigned int |
46 | led_tg(struct sk_buff *skb, const struct xt_target_param *par) | 52 | led_tg(struct sk_buff *skb, const struct xt_action_param *par) |
47 | { | 53 | { |
48 | const struct xt_led_info *ledinfo = par->targinfo; | 54 | const struct xt_led_info *ledinfo = par->targinfo; |
49 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; | 55 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; |
@@ -54,7 +60,7 @@ led_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
54 | */ | 60 | */ |
55 | if ((ledinfo->delay > 0) && ledinfo->always_blink && | 61 | if ((ledinfo->delay > 0) && ledinfo->always_blink && |
56 | timer_pending(&ledinternal->timer)) | 62 | timer_pending(&ledinternal->timer)) |
57 | led_trigger_event(&ledinternal->netfilter_led_trigger,LED_OFF); | 63 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF); |
58 | 64 | ||
59 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_FULL); | 65 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_FULL); |
60 | 66 | ||
@@ -75,54 +81,86 @@ led_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
75 | 81 | ||
76 | static void led_timeout_callback(unsigned long data) | 82 | static void led_timeout_callback(unsigned long data) |
77 | { | 83 | { |
78 | struct xt_led_info *ledinfo = (struct xt_led_info *)data; | 84 | struct xt_led_info_internal *ledinternal = (struct xt_led_info_internal *)data; |
79 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; | ||
80 | 85 | ||
81 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF); | 86 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF); |
82 | } | 87 | } |
83 | 88 | ||
84 | static bool led_tg_check(const struct xt_tgchk_param *par) | 89 | static struct xt_led_info_internal *led_trigger_lookup(const char *name) |
90 | { | ||
91 | struct xt_led_info_internal *ledinternal; | ||
92 | |||
93 | list_for_each_entry(ledinternal, &xt_led_triggers, list) { | ||
94 | if (!strcmp(name, ledinternal->netfilter_led_trigger.name)) { | ||
95 | return ledinternal; | ||
96 | } | ||
97 | } | ||
98 | return NULL; | ||
99 | } | ||
100 | |||
101 | static int led_tg_check(const struct xt_tgchk_param *par) | ||
85 | { | 102 | { |
86 | struct xt_led_info *ledinfo = par->targinfo; | 103 | struct xt_led_info *ledinfo = par->targinfo; |
87 | struct xt_led_info_internal *ledinternal; | 104 | struct xt_led_info_internal *ledinternal; |
88 | int err; | 105 | int err; |
89 | 106 | ||
90 | if (ledinfo->id[0] == '\0') { | 107 | if (ledinfo->id[0] == '\0') { |
91 | printk(KERN_ERR KBUILD_MODNAME ": No 'id' parameter given.\n"); | 108 | pr_info("No 'id' parameter given.\n"); |
92 | return false; | 109 | return -EINVAL; |
93 | } | 110 | } |
94 | 111 | ||
95 | ledinternal = kzalloc(sizeof(struct xt_led_info_internal), GFP_KERNEL); | 112 | mutex_lock(&xt_led_mutex); |
96 | if (!ledinternal) { | 113 | |
97 | printk(KERN_CRIT KBUILD_MODNAME ": out of memory\n"); | 114 | ledinternal = led_trigger_lookup(ledinfo->id); |
98 | return false; | 115 | if (ledinternal) { |
116 | ledinternal->refcnt++; | ||
117 | goto out; | ||
99 | } | 118 | } |
100 | 119 | ||
101 | ledinternal->netfilter_led_trigger.name = ledinfo->id; | 120 | err = -ENOMEM; |
121 | ledinternal = kzalloc(sizeof(struct xt_led_info_internal), GFP_KERNEL); | ||
122 | if (!ledinternal) | ||
123 | goto exit_mutex_only; | ||
124 | |||
125 | ledinternal->trigger_id = kstrdup(ledinfo->id, GFP_KERNEL); | ||
126 | if (!ledinternal->trigger_id) | ||
127 | goto exit_internal_alloc; | ||
128 | |||
129 | ledinternal->refcnt = 1; | ||
130 | ledinternal->netfilter_led_trigger.name = ledinternal->trigger_id; | ||
102 | 131 | ||
103 | err = led_trigger_register(&ledinternal->netfilter_led_trigger); | 132 | err = led_trigger_register(&ledinternal->netfilter_led_trigger); |
104 | if (err) { | 133 | if (err) { |
105 | printk(KERN_CRIT KBUILD_MODNAME | 134 | pr_warning("led_trigger_register() failed\n"); |
106 | ": led_trigger_register() failed\n"); | ||
107 | if (err == -EEXIST) | 135 | if (err == -EEXIST) |
108 | printk(KERN_ERR KBUILD_MODNAME | 136 | pr_warning("Trigger name is already in use.\n"); |
109 | ": Trigger name is already in use.\n"); | ||
110 | goto exit_alloc; | 137 | goto exit_alloc; |
111 | } | 138 | } |
112 | 139 | ||
113 | /* See if we need to set up a timer */ | 140 | /* See if we need to set up a timer */ |
114 | if (ledinfo->delay > 0) | 141 | if (ledinfo->delay > 0) |
115 | setup_timer(&ledinternal->timer, led_timeout_callback, | 142 | setup_timer(&ledinternal->timer, led_timeout_callback, |
116 | (unsigned long)ledinfo); | 143 | (unsigned long)ledinternal); |
144 | |||
145 | list_add_tail(&ledinternal->list, &xt_led_triggers); | ||
146 | |||
147 | out: | ||
148 | mutex_unlock(&xt_led_mutex); | ||
117 | 149 | ||
118 | ledinfo->internal_data = ledinternal; | 150 | ledinfo->internal_data = ledinternal; |
119 | 151 | ||
120 | return true; | 152 | return 0; |
121 | 153 | ||
122 | exit_alloc: | 154 | exit_alloc: |
155 | kfree(ledinternal->trigger_id); | ||
156 | |||
157 | exit_internal_alloc: | ||
123 | kfree(ledinternal); | 158 | kfree(ledinternal); |
124 | 159 | ||
125 | return false; | 160 | exit_mutex_only: |
161 | mutex_unlock(&xt_led_mutex); | ||
162 | |||
163 | return err; | ||
126 | } | 164 | } |
127 | 165 | ||
128 | static void led_tg_destroy(const struct xt_tgdtor_param *par) | 166 | static void led_tg_destroy(const struct xt_tgdtor_param *par) |
@@ -130,10 +168,23 @@ static void led_tg_destroy(const struct xt_tgdtor_param *par) | |||
130 | const struct xt_led_info *ledinfo = par->targinfo; | 168 | const struct xt_led_info *ledinfo = par->targinfo; |
131 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; | 169 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; |
132 | 170 | ||
171 | mutex_lock(&xt_led_mutex); | ||
172 | |||
173 | if (--ledinternal->refcnt) { | ||
174 | mutex_unlock(&xt_led_mutex); | ||
175 | return; | ||
176 | } | ||
177 | |||
178 | list_del(&ledinternal->list); | ||
179 | |||
133 | if (ledinfo->delay > 0) | 180 | if (ledinfo->delay > 0) |
134 | del_timer_sync(&ledinternal->timer); | 181 | del_timer_sync(&ledinternal->timer); |
135 | 182 | ||
136 | led_trigger_unregister(&ledinternal->netfilter_led_trigger); | 183 | led_trigger_unregister(&ledinternal->netfilter_led_trigger); |
184 | |||
185 | mutex_unlock(&xt_led_mutex); | ||
186 | |||
187 | kfree(ledinternal->trigger_id); | ||
137 | kfree(ledinternal); | 188 | kfree(ledinternal); |
138 | } | 189 | } |
139 | 190 | ||
@@ -142,7 +193,7 @@ static struct xt_target led_tg_reg __read_mostly = { | |||
142 | .revision = 0, | 193 | .revision = 0, |
143 | .family = NFPROTO_UNSPEC, | 194 | .family = NFPROTO_UNSPEC, |
144 | .target = led_tg, | 195 | .target = led_tg, |
145 | .targetsize = XT_ALIGN(sizeof(struct xt_led_info)), | 196 | .targetsize = sizeof(struct xt_led_info), |
146 | .checkentry = led_tg_check, | 197 | .checkentry = led_tg_check, |
147 | .destroy = led_tg_destroy, | 198 | .destroy = led_tg_destroy, |
148 | .me = THIS_MODULE, | 199 | .me = THIS_MODULE, |
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c deleted file mode 100644 index 225f8d11e173..000000000000 --- a/net/netfilter/xt_MARK.c +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | /* | ||
2 | * xt_MARK - Netfilter module to modify the NFMARK field of an skb | ||
3 | * | ||
4 | * (C) 1999-2001 Marc Boucher <marc@mbsi.ca> | ||
5 | * Copyright © CC Computer Consultants GmbH, 2007 - 2008 | ||
6 | * Jan Engelhardt <jengelh@computergmbh.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/ip.h> | ||
16 | #include <net/checksum.h> | ||
17 | |||
18 | #include <linux/netfilter/x_tables.h> | ||
19 | #include <linux/netfilter/xt_MARK.h> | ||
20 | |||
21 | MODULE_LICENSE("GPL"); | ||
22 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | ||
23 | MODULE_DESCRIPTION("Xtables: packet mark modification"); | ||
24 | MODULE_ALIAS("ipt_MARK"); | ||
25 | MODULE_ALIAS("ip6t_MARK"); | ||
26 | |||
27 | static unsigned int | ||
28 | mark_tg(struct sk_buff *skb, const struct xt_target_param *par) | ||
29 | { | ||
30 | const struct xt_mark_tginfo2 *info = par->targinfo; | ||
31 | |||
32 | skb->mark = (skb->mark & ~info->mask) ^ info->mark; | ||
33 | return XT_CONTINUE; | ||
34 | } | ||
35 | |||
36 | static struct xt_target mark_tg_reg __read_mostly = { | ||
37 | .name = "MARK", | ||
38 | .revision = 2, | ||
39 | .family = NFPROTO_UNSPEC, | ||
40 | .target = mark_tg, | ||
41 | .targetsize = sizeof(struct xt_mark_tginfo2), | ||
42 | .me = THIS_MODULE, | ||
43 | }; | ||
44 | |||
45 | static int __init mark_tg_init(void) | ||
46 | { | ||
47 | return xt_register_target(&mark_tg_reg); | ||
48 | } | ||
49 | |||
50 | static void __exit mark_tg_exit(void) | ||
51 | { | ||
52 | xt_unregister_target(&mark_tg_reg); | ||
53 | } | ||
54 | |||
55 | module_init(mark_tg_init); | ||
56 | module_exit(mark_tg_exit); | ||
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c index a57c5cf018ec..a17dd0f589b2 100644 --- a/net/netfilter/xt_NFLOG.c +++ b/net/netfilter/xt_NFLOG.c | |||
@@ -22,7 +22,7 @@ MODULE_ALIAS("ipt_NFLOG"); | |||
22 | MODULE_ALIAS("ip6t_NFLOG"); | 22 | MODULE_ALIAS("ip6t_NFLOG"); |
23 | 23 | ||
24 | static unsigned int | 24 | static unsigned int |
25 | nflog_tg(struct sk_buff *skb, const struct xt_target_param *par) | 25 | nflog_tg(struct sk_buff *skb, const struct xt_action_param *par) |
26 | { | 26 | { |
27 | const struct xt_nflog_info *info = par->targinfo; | 27 | const struct xt_nflog_info *info = par->targinfo; |
28 | struct nf_loginfo li; | 28 | struct nf_loginfo li; |
@@ -37,15 +37,15 @@ nflog_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
37 | return XT_CONTINUE; | 37 | return XT_CONTINUE; |
38 | } | 38 | } |
39 | 39 | ||
40 | static bool nflog_tg_check(const struct xt_tgchk_param *par) | 40 | static int nflog_tg_check(const struct xt_tgchk_param *par) |
41 | { | 41 | { |
42 | const struct xt_nflog_info *info = par->targinfo; | 42 | const struct xt_nflog_info *info = par->targinfo; |
43 | 43 | ||
44 | if (info->flags & ~XT_NFLOG_MASK) | 44 | if (info->flags & ~XT_NFLOG_MASK) |
45 | return false; | 45 | return -EINVAL; |
46 | if (info->prefix[sizeof(info->prefix) - 1] != '\0') | 46 | if (info->prefix[sizeof(info->prefix) - 1] != '\0') |
47 | return false; | 47 | return -EINVAL; |
48 | return true; | 48 | return 0; |
49 | } | 49 | } |
50 | 50 | ||
51 | static struct xt_target nflog_tg_reg __read_mostly = { | 51 | static struct xt_target nflog_tg_reg __read_mostly = { |
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 12dcd7007c3e..039cce1bde3d 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c | |||
@@ -31,7 +31,7 @@ static u32 jhash_initval __read_mostly; | |||
31 | static bool rnd_inited __read_mostly; | 31 | static bool rnd_inited __read_mostly; |
32 | 32 | ||
33 | static unsigned int | 33 | static unsigned int |
34 | nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par) | 34 | nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par) |
35 | { | 35 | { |
36 | const struct xt_NFQ_info *tinfo = par->targinfo; | 36 | const struct xt_NFQ_info *tinfo = par->targinfo; |
37 | 37 | ||
@@ -49,17 +49,6 @@ static u32 hash_v4(const struct sk_buff *skb) | |||
49 | return jhash_2words((__force u32)ipaddr, iph->protocol, jhash_initval); | 49 | return jhash_2words((__force u32)ipaddr, iph->protocol, jhash_initval); |
50 | } | 50 | } |
51 | 51 | ||
52 | static unsigned int | ||
53 | nfqueue_tg4_v1(struct sk_buff *skb, const struct xt_target_param *par) | ||
54 | { | ||
55 | const struct xt_NFQ_info_v1 *info = par->targinfo; | ||
56 | u32 queue = info->queuenum; | ||
57 | |||
58 | if (info->queues_total > 1) | ||
59 | queue = hash_v4(skb) % info->queues_total + queue; | ||
60 | return NF_QUEUE_NR(queue); | ||
61 | } | ||
62 | |||
63 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 52 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
64 | static u32 hash_v6(const struct sk_buff *skb) | 53 | static u32 hash_v6(const struct sk_buff *skb) |
65 | { | 54 | { |
@@ -73,20 +62,26 @@ static u32 hash_v6(const struct sk_buff *skb) | |||
73 | 62 | ||
74 | return jhash2((__force u32 *)addr, ARRAY_SIZE(addr), jhash_initval); | 63 | return jhash2((__force u32 *)addr, ARRAY_SIZE(addr), jhash_initval); |
75 | } | 64 | } |
65 | #endif | ||
76 | 66 | ||
77 | static unsigned int | 67 | static unsigned int |
78 | nfqueue_tg6_v1(struct sk_buff *skb, const struct xt_target_param *par) | 68 | nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par) |
79 | { | 69 | { |
80 | const struct xt_NFQ_info_v1 *info = par->targinfo; | 70 | const struct xt_NFQ_info_v1 *info = par->targinfo; |
81 | u32 queue = info->queuenum; | 71 | u32 queue = info->queuenum; |
82 | 72 | ||
83 | if (info->queues_total > 1) | 73 | if (info->queues_total > 1) { |
84 | queue = hash_v6(skb) % info->queues_total + queue; | 74 | if (par->family == NFPROTO_IPV4) |
75 | queue = hash_v4(skb) % info->queues_total + queue; | ||
76 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | ||
77 | else if (par->family == NFPROTO_IPV6) | ||
78 | queue = hash_v6(skb) % info->queues_total + queue; | ||
79 | #endif | ||
80 | } | ||
85 | return NF_QUEUE_NR(queue); | 81 | return NF_QUEUE_NR(queue); |
86 | } | 82 | } |
87 | #endif | ||
88 | 83 | ||
89 | static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par) | 84 | static int nfqueue_tg_v1_check(const struct xt_tgchk_param *par) |
90 | { | 85 | { |
91 | const struct xt_NFQ_info_v1 *info = par->targinfo; | 86 | const struct xt_NFQ_info_v1 *info = par->targinfo; |
92 | u32 maxid; | 87 | u32 maxid; |
@@ -97,15 +92,15 @@ static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par) | |||
97 | } | 92 | } |
98 | if (info->queues_total == 0) { | 93 | if (info->queues_total == 0) { |
99 | pr_err("NFQUEUE: number of total queues is 0\n"); | 94 | pr_err("NFQUEUE: number of total queues is 0\n"); |
100 | return false; | 95 | return -EINVAL; |
101 | } | 96 | } |
102 | maxid = info->queues_total - 1 + info->queuenum; | 97 | maxid = info->queues_total - 1 + info->queuenum; |
103 | if (maxid > 0xffff) { | 98 | if (maxid > 0xffff) { |
104 | pr_err("NFQUEUE: number of queues (%u) out of range (got %u)\n", | 99 | pr_err("NFQUEUE: number of queues (%u) out of range (got %u)\n", |
105 | info->queues_total, maxid); | 100 | info->queues_total, maxid); |
106 | return false; | 101 | return -ERANGE; |
107 | } | 102 | } |
108 | return true; | 103 | return 0; |
109 | } | 104 | } |
110 | 105 | ||
111 | static struct xt_target nfqueue_tg_reg[] __read_mostly = { | 106 | static struct xt_target nfqueue_tg_reg[] __read_mostly = { |
@@ -119,23 +114,12 @@ static struct xt_target nfqueue_tg_reg[] __read_mostly = { | |||
119 | { | 114 | { |
120 | .name = "NFQUEUE", | 115 | .name = "NFQUEUE", |
121 | .revision = 1, | 116 | .revision = 1, |
122 | .family = NFPROTO_IPV4, | 117 | .family = NFPROTO_UNSPEC, |
123 | .checkentry = nfqueue_tg_v1_check, | ||
124 | .target = nfqueue_tg4_v1, | ||
125 | .targetsize = sizeof(struct xt_NFQ_info_v1), | ||
126 | .me = THIS_MODULE, | ||
127 | }, | ||
128 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | ||
129 | { | ||
130 | .name = "NFQUEUE", | ||
131 | .revision = 1, | ||
132 | .family = NFPROTO_IPV6, | ||
133 | .checkentry = nfqueue_tg_v1_check, | 118 | .checkentry = nfqueue_tg_v1_check, |
134 | .target = nfqueue_tg6_v1, | 119 | .target = nfqueue_tg_v1, |
135 | .targetsize = sizeof(struct xt_NFQ_info_v1), | 120 | .targetsize = sizeof(struct xt_NFQ_info_v1), |
136 | .me = THIS_MODULE, | 121 | .me = THIS_MODULE, |
137 | }, | 122 | }, |
138 | #endif | ||
139 | }; | 123 | }; |
140 | 124 | ||
141 | static int __init nfqueue_tg_init(void) | 125 | static int __init nfqueue_tg_init(void) |
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c index e7a0a54fd4ea..512b9123252f 100644 --- a/net/netfilter/xt_NOTRACK.c +++ b/net/netfilter/xt_NOTRACK.c | |||
@@ -13,7 +13,7 @@ MODULE_ALIAS("ipt_NOTRACK"); | |||
13 | MODULE_ALIAS("ip6t_NOTRACK"); | 13 | MODULE_ALIAS("ip6t_NOTRACK"); |
14 | 14 | ||
15 | static unsigned int | 15 | static unsigned int |
16 | notrack_tg(struct sk_buff *skb, const struct xt_target_param *par) | 16 | notrack_tg(struct sk_buff *skb, const struct xt_action_param *par) |
17 | { | 17 | { |
18 | /* Previously seen (loopback)? Ignore. */ | 18 | /* Previously seen (loopback)? Ignore. */ |
19 | if (skb->nfct != NULL) | 19 | if (skb->nfct != NULL) |
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index d16d55df4f61..69c01e10f8af 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c | |||
@@ -73,7 +73,7 @@ void xt_rateest_put(struct xt_rateest *est) | |||
73 | EXPORT_SYMBOL_GPL(xt_rateest_put); | 73 | EXPORT_SYMBOL_GPL(xt_rateest_put); |
74 | 74 | ||
75 | static unsigned int | 75 | static unsigned int |
76 | xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par) | 76 | xt_rateest_tg(struct sk_buff *skb, const struct xt_action_param *par) |
77 | { | 77 | { |
78 | const struct xt_rateest_target_info *info = par->targinfo; | 78 | const struct xt_rateest_target_info *info = par->targinfo; |
79 | struct gnet_stats_basic_packed *stats = &info->est->bstats; | 79 | struct gnet_stats_basic_packed *stats = &info->est->bstats; |
@@ -86,7 +86,7 @@ xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
86 | return XT_CONTINUE; | 86 | return XT_CONTINUE; |
87 | } | 87 | } |
88 | 88 | ||
89 | static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) | 89 | static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) |
90 | { | 90 | { |
91 | struct xt_rateest_target_info *info = par->targinfo; | 91 | struct xt_rateest_target_info *info = par->targinfo; |
92 | struct xt_rateest *est; | 92 | struct xt_rateest *est; |
@@ -94,6 +94,7 @@ static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) | |||
94 | struct nlattr opt; | 94 | struct nlattr opt; |
95 | struct gnet_estimator est; | 95 | struct gnet_estimator est; |
96 | } cfg; | 96 | } cfg; |
97 | int ret; | ||
97 | 98 | ||
98 | if (unlikely(!rnd_inited)) { | 99 | if (unlikely(!rnd_inited)) { |
99 | get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); | 100 | get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); |
@@ -110,12 +111,13 @@ static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) | |||
110 | (info->interval != est->params.interval || | 111 | (info->interval != est->params.interval || |
111 | info->ewma_log != est->params.ewma_log)) { | 112 | info->ewma_log != est->params.ewma_log)) { |
112 | xt_rateest_put(est); | 113 | xt_rateest_put(est); |
113 | return false; | 114 | return -EINVAL; |
114 | } | 115 | } |
115 | info->est = est; | 116 | info->est = est; |
116 | return true; | 117 | return 0; |
117 | } | 118 | } |
118 | 119 | ||
120 | ret = -ENOMEM; | ||
119 | est = kzalloc(sizeof(*est), GFP_KERNEL); | 121 | est = kzalloc(sizeof(*est), GFP_KERNEL); |
120 | if (!est) | 122 | if (!est) |
121 | goto err1; | 123 | goto err1; |
@@ -131,19 +133,19 @@ static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) | |||
131 | cfg.est.interval = info->interval; | 133 | cfg.est.interval = info->interval; |
132 | cfg.est.ewma_log = info->ewma_log; | 134 | cfg.est.ewma_log = info->ewma_log; |
133 | 135 | ||
134 | if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock, | 136 | ret = gen_new_estimator(&est->bstats, &est->rstats, |
135 | &cfg.opt) < 0) | 137 | &est->lock, &cfg.opt); |
138 | if (ret < 0) | ||
136 | goto err2; | 139 | goto err2; |
137 | 140 | ||
138 | info->est = est; | 141 | info->est = est; |
139 | xt_rateest_hash_insert(est); | 142 | xt_rateest_hash_insert(est); |
140 | 143 | return 0; | |
141 | return true; | ||
142 | 144 | ||
143 | err2: | 145 | err2: |
144 | kfree(est); | 146 | kfree(est); |
145 | err1: | 147 | err1: |
146 | return false; | 148 | return ret; |
147 | } | 149 | } |
148 | 150 | ||
149 | static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) | 151 | static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) |
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index 7a6f9e6f5dfa..23b2d6c486b5 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
17 | #include <linux/selinux.h> | 18 | #include <linux/selinux.h> |
@@ -29,7 +30,7 @@ MODULE_ALIAS("ip6t_SECMARK"); | |||
29 | static u8 mode; | 30 | static u8 mode; |
30 | 31 | ||
31 | static unsigned int | 32 | static unsigned int |
32 | secmark_tg(struct sk_buff *skb, const struct xt_target_param *par) | 33 | secmark_tg(struct sk_buff *skb, const struct xt_action_param *par) |
33 | { | 34 | { |
34 | u32 secmark = 0; | 35 | u32 secmark = 0; |
35 | const struct xt_secmark_target_info *info = par->targinfo; | 36 | const struct xt_secmark_target_info *info = par->targinfo; |
@@ -49,7 +50,7 @@ secmark_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
49 | return XT_CONTINUE; | 50 | return XT_CONTINUE; |
50 | } | 51 | } |
51 | 52 | ||
52 | static bool checkentry_selinux(struct xt_secmark_target_info *info) | 53 | static int checkentry_selinux(struct xt_secmark_target_info *info) |
53 | { | 54 | { |
54 | int err; | 55 | int err; |
55 | struct xt_secmark_target_selinux_info *sel = &info->u.sel; | 56 | struct xt_secmark_target_selinux_info *sel = &info->u.sel; |
@@ -59,58 +60,59 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info) | |||
59 | err = selinux_string_to_sid(sel->selctx, &sel->selsid); | 60 | err = selinux_string_to_sid(sel->selctx, &sel->selsid); |
60 | if (err) { | 61 | if (err) { |
61 | if (err == -EINVAL) | 62 | if (err == -EINVAL) |
62 | printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n", | 63 | pr_info("invalid SELinux context \'%s\'\n", |
63 | sel->selctx); | 64 | sel->selctx); |
64 | return false; | 65 | return err; |
65 | } | 66 | } |
66 | 67 | ||
67 | if (!sel->selsid) { | 68 | if (!sel->selsid) { |
68 | printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n", | 69 | pr_info("unable to map SELinux context \'%s\'\n", sel->selctx); |
69 | sel->selctx); | 70 | return -ENOENT; |
70 | return false; | ||
71 | } | 71 | } |
72 | 72 | ||
73 | err = selinux_secmark_relabel_packet_permission(sel->selsid); | 73 | err = selinux_secmark_relabel_packet_permission(sel->selsid); |
74 | if (err) { | 74 | if (err) { |
75 | printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); | 75 | pr_info("unable to obtain relabeling permission\n"); |
76 | return false; | 76 | return err; |
77 | } | 77 | } |
78 | 78 | ||
79 | selinux_secmark_refcount_inc(); | 79 | selinux_secmark_refcount_inc(); |
80 | return true; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | static bool secmark_tg_check(const struct xt_tgchk_param *par) | 83 | static int secmark_tg_check(const struct xt_tgchk_param *par) |
84 | { | 84 | { |
85 | struct xt_secmark_target_info *info = par->targinfo; | 85 | struct xt_secmark_target_info *info = par->targinfo; |
86 | int err; | ||
86 | 87 | ||
87 | if (strcmp(par->table, "mangle") != 0 && | 88 | if (strcmp(par->table, "mangle") != 0 && |
88 | strcmp(par->table, "security") != 0) { | 89 | strcmp(par->table, "security") != 0) { |
89 | printk(KERN_INFO PFX "target only valid in the \'mangle\' " | 90 | pr_info("target only valid in the \'mangle\' " |
90 | "or \'security\' tables, not \'%s\'.\n", par->table); | 91 | "or \'security\' tables, not \'%s\'.\n", par->table); |
91 | return false; | 92 | return -EINVAL; |
92 | } | 93 | } |
93 | 94 | ||
94 | if (mode && mode != info->mode) { | 95 | if (mode && mode != info->mode) { |
95 | printk(KERN_INFO PFX "mode already set to %hu cannot mix with " | 96 | pr_info("mode already set to %hu cannot mix with " |
96 | "rules for mode %hu\n", mode, info->mode); | 97 | "rules for mode %hu\n", mode, info->mode); |
97 | return false; | 98 | return -EINVAL; |
98 | } | 99 | } |
99 | 100 | ||
100 | switch (info->mode) { | 101 | switch (info->mode) { |
101 | case SECMARK_MODE_SEL: | 102 | case SECMARK_MODE_SEL: |
102 | if (!checkentry_selinux(info)) | 103 | err = checkentry_selinux(info); |
103 | return false; | 104 | if (err <= 0) |
105 | return err; | ||
104 | break; | 106 | break; |
105 | 107 | ||
106 | default: | 108 | default: |
107 | printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); | 109 | pr_info("invalid mode: %hu\n", info->mode); |
108 | return false; | 110 | return -EINVAL; |
109 | } | 111 | } |
110 | 112 | ||
111 | if (!mode) | 113 | if (!mode) |
112 | mode = info->mode; | 114 | mode = info->mode; |
113 | return true; | 115 | return 0; |
114 | } | 116 | } |
115 | 117 | ||
116 | static void secmark_tg_destroy(const struct xt_tgdtor_param *par) | 118 | static void secmark_tg_destroy(const struct xt_tgdtor_param *par) |
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index c5f4b9919e9a..62ec021fbd50 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <linux/ip.h> | 13 | #include <linux/ip.h> |
@@ -68,15 +68,14 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
68 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { | 68 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { |
69 | if (dst_mtu(skb_dst(skb)) <= minlen) { | 69 | if (dst_mtu(skb_dst(skb)) <= minlen) { |
70 | if (net_ratelimit()) | 70 | if (net_ratelimit()) |
71 | printk(KERN_ERR "xt_TCPMSS: " | 71 | pr_err("unknown or invalid path-MTU (%u)\n", |
72 | "unknown or invalid path-MTU (%u)\n", | ||
73 | dst_mtu(skb_dst(skb))); | 72 | dst_mtu(skb_dst(skb))); |
74 | return -1; | 73 | return -1; |
75 | } | 74 | } |
76 | if (in_mtu <= minlen) { | 75 | if (in_mtu <= minlen) { |
77 | if (net_ratelimit()) | 76 | if (net_ratelimit()) |
78 | printk(KERN_ERR "xt_TCPMSS: unknown or " | 77 | pr_err("unknown or invalid path-MTU (%u)\n", |
79 | "invalid path-MTU (%u)\n", in_mtu); | 78 | in_mtu); |
80 | return -1; | 79 | return -1; |
81 | } | 80 | } |
82 | newmss = min(dst_mtu(skb_dst(skb)), in_mtu) - minlen; | 81 | newmss = min(dst_mtu(skb_dst(skb)), in_mtu) - minlen; |
@@ -173,7 +172,7 @@ static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb, | |||
173 | } | 172 | } |
174 | 173 | ||
175 | static unsigned int | 174 | static unsigned int |
176 | tcpmss_tg4(struct sk_buff *skb, const struct xt_target_param *par) | 175 | tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par) |
177 | { | 176 | { |
178 | struct iphdr *iph = ip_hdr(skb); | 177 | struct iphdr *iph = ip_hdr(skb); |
179 | __be16 newlen; | 178 | __be16 newlen; |
@@ -196,7 +195,7 @@ tcpmss_tg4(struct sk_buff *skb, const struct xt_target_param *par) | |||
196 | 195 | ||
197 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 196 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
198 | static unsigned int | 197 | static unsigned int |
199 | tcpmss_tg6(struct sk_buff *skb, const struct xt_target_param *par) | 198 | tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
200 | { | 199 | { |
201 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 200 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
202 | u8 nexthdr; | 201 | u8 nexthdr; |
@@ -236,7 +235,7 @@ static inline bool find_syn_match(const struct xt_entry_match *m) | |||
236 | return false; | 235 | return false; |
237 | } | 236 | } |
238 | 237 | ||
239 | static bool tcpmss_tg4_check(const struct xt_tgchk_param *par) | 238 | static int tcpmss_tg4_check(const struct xt_tgchk_param *par) |
240 | { | 239 | { |
241 | const struct xt_tcpmss_info *info = par->targinfo; | 240 | const struct xt_tcpmss_info *info = par->targinfo; |
242 | const struct ipt_entry *e = par->entryinfo; | 241 | const struct ipt_entry *e = par->entryinfo; |
@@ -246,19 +245,19 @@ static bool tcpmss_tg4_check(const struct xt_tgchk_param *par) | |||
246 | (par->hook_mask & ~((1 << NF_INET_FORWARD) | | 245 | (par->hook_mask & ~((1 << NF_INET_FORWARD) | |
247 | (1 << NF_INET_LOCAL_OUT) | | 246 | (1 << NF_INET_LOCAL_OUT) | |
248 | (1 << NF_INET_POST_ROUTING))) != 0) { | 247 | (1 << NF_INET_POST_ROUTING))) != 0) { |
249 | printk("xt_TCPMSS: path-MTU clamping only supported in " | 248 | pr_info("path-MTU clamping only supported in " |
250 | "FORWARD, OUTPUT and POSTROUTING hooks\n"); | 249 | "FORWARD, OUTPUT and POSTROUTING hooks\n"); |
251 | return false; | 250 | return -EINVAL; |
252 | } | 251 | } |
253 | xt_ematch_foreach(ematch, e) | 252 | xt_ematch_foreach(ematch, e) |
254 | if (find_syn_match(ematch)) | 253 | if (find_syn_match(ematch)) |
255 | return true; | 254 | return 0; |
256 | printk("xt_TCPMSS: Only works on TCP SYN packets\n"); | 255 | pr_info("Only works on TCP SYN packets\n"); |
257 | return false; | 256 | return -EINVAL; |
258 | } | 257 | } |
259 | 258 | ||
260 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 259 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
261 | static bool tcpmss_tg6_check(const struct xt_tgchk_param *par) | 260 | static int tcpmss_tg6_check(const struct xt_tgchk_param *par) |
262 | { | 261 | { |
263 | const struct xt_tcpmss_info *info = par->targinfo; | 262 | const struct xt_tcpmss_info *info = par->targinfo; |
264 | const struct ip6t_entry *e = par->entryinfo; | 263 | const struct ip6t_entry *e = par->entryinfo; |
@@ -268,15 +267,15 @@ static bool tcpmss_tg6_check(const struct xt_tgchk_param *par) | |||
268 | (par->hook_mask & ~((1 << NF_INET_FORWARD) | | 267 | (par->hook_mask & ~((1 << NF_INET_FORWARD) | |
269 | (1 << NF_INET_LOCAL_OUT) | | 268 | (1 << NF_INET_LOCAL_OUT) | |
270 | (1 << NF_INET_POST_ROUTING))) != 0) { | 269 | (1 << NF_INET_POST_ROUTING))) != 0) { |
271 | printk("xt_TCPMSS: path-MTU clamping only supported in " | 270 | pr_info("path-MTU clamping only supported in " |
272 | "FORWARD, OUTPUT and POSTROUTING hooks\n"); | 271 | "FORWARD, OUTPUT and POSTROUTING hooks\n"); |
273 | return false; | 272 | return -EINVAL; |
274 | } | 273 | } |
275 | xt_ematch_foreach(ematch, e) | 274 | xt_ematch_foreach(ematch, e) |
276 | if (find_syn_match(ematch)) | 275 | if (find_syn_match(ematch)) |
277 | return true; | 276 | return 0; |
278 | printk("xt_TCPMSS: Only works on TCP SYN packets\n"); | 277 | pr_info("Only works on TCP SYN packets\n"); |
279 | return false; | 278 | return -EINVAL; |
280 | } | 279 | } |
281 | #endif | 280 | #endif |
282 | 281 | ||
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c index 9dd8c8ef63eb..9dc9ecfdd546 100644 --- a/net/netfilter/xt_TCPOPTSTRIP.c +++ b/net/netfilter/xt_TCPOPTSTRIP.c | |||
@@ -3,7 +3,6 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2007 Sven Schnelle <svens@bitebene.org> | 4 | * Copyright (C) 2007 Sven Schnelle <svens@bitebene.org> |
5 | * Copyright © CC Computer Consultants GmbH, 2007 | 5 | * Copyright © CC Computer Consultants GmbH, 2007 |
6 | * Contact: Jan Engelhardt <jengelh@computergmbh.de> | ||
7 | * | 6 | * |
8 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -75,7 +74,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, | |||
75 | } | 74 | } |
76 | 75 | ||
77 | static unsigned int | 76 | static unsigned int |
78 | tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_target_param *par) | 77 | tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par) |
79 | { | 78 | { |
80 | return tcpoptstrip_mangle_packet(skb, par->targinfo, ip_hdrlen(skb), | 79 | return tcpoptstrip_mangle_packet(skb, par->targinfo, ip_hdrlen(skb), |
81 | sizeof(struct iphdr) + sizeof(struct tcphdr)); | 80 | sizeof(struct iphdr) + sizeof(struct tcphdr)); |
@@ -83,7 +82,7 @@ tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_target_param *par) | |||
83 | 82 | ||
84 | #if defined(CONFIG_IP6_NF_MANGLE) || defined(CONFIG_IP6_NF_MANGLE_MODULE) | 83 | #if defined(CONFIG_IP6_NF_MANGLE) || defined(CONFIG_IP6_NF_MANGLE_MODULE) |
85 | static unsigned int | 84 | static unsigned int |
86 | tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_target_param *par) | 85 | tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
87 | { | 86 | { |
88 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 87 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
89 | int tcphoff; | 88 | int tcphoff; |
@@ -136,7 +135,7 @@ static void __exit tcpoptstrip_tg_exit(void) | |||
136 | 135 | ||
137 | module_init(tcpoptstrip_tg_init); | 136 | module_init(tcpoptstrip_tg_init); |
138 | module_exit(tcpoptstrip_tg_exit); | 137 | module_exit(tcpoptstrip_tg_exit); |
139 | MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>, Jan Engelhardt <jengelh@computergmbh.de>"); | 138 | MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>, Jan Engelhardt <jengelh@medozas.de>"); |
140 | MODULE_DESCRIPTION("Xtables: TCP option stripping"); | 139 | MODULE_DESCRIPTION("Xtables: TCP option stripping"); |
141 | MODULE_LICENSE("GPL"); | 140 | MODULE_LICENSE("GPL"); |
142 | MODULE_ALIAS("ipt_TCPOPTSTRIP"); | 141 | MODULE_ALIAS("ipt_TCPOPTSTRIP"); |
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c new file mode 100644 index 000000000000..d7920d9f49e9 --- /dev/null +++ b/net/netfilter/xt_TEE.c | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * "TEE" target extension for Xtables | ||
3 | * Copyright © Sebastian Claßen, 2007 | ||
4 | * Jan Engelhardt, 2007-2010 | ||
5 | * | ||
6 | * based on ipt_ROUTE.c from Cédric de Launois | ||
7 | * <delaunois@info.ucl.be> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 or later, as published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/ip.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/percpu.h> | ||
16 | #include <linux/route.h> | ||
17 | #include <linux/skbuff.h> | ||
18 | #include <linux/notifier.h> | ||
19 | #include <net/checksum.h> | ||
20 | #include <net/icmp.h> | ||
21 | #include <net/ip.h> | ||
22 | #include <net/ipv6.h> | ||
23 | #include <net/ip6_route.h> | ||
24 | #include <net/route.h> | ||
25 | #include <linux/netfilter/x_tables.h> | ||
26 | #include <linux/netfilter/xt_TEE.h> | ||
27 | |||
28 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
29 | # define WITH_CONNTRACK 1 | ||
30 | # include <net/netfilter/nf_conntrack.h> | ||
31 | #endif | ||
32 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
33 | # define WITH_IPV6 1 | ||
34 | #endif | ||
35 | |||
36 | struct xt_tee_priv { | ||
37 | struct notifier_block notifier; | ||
38 | struct xt_tee_tginfo *tginfo; | ||
39 | int oif; | ||
40 | }; | ||
41 | |||
42 | static const union nf_inet_addr tee_zero_address; | ||
43 | static DEFINE_PER_CPU(bool, tee_active); | ||
44 | |||
45 | static struct net *pick_net(struct sk_buff *skb) | ||
46 | { | ||
47 | #ifdef CONFIG_NET_NS | ||
48 | const struct dst_entry *dst; | ||
49 | |||
50 | if (skb->dev != NULL) | ||
51 | return dev_net(skb->dev); | ||
52 | dst = skb_dst(skb); | ||
53 | if (dst != NULL && dst->dev != NULL) | ||
54 | return dev_net(dst->dev); | ||
55 | #endif | ||
56 | return &init_net; | ||
57 | } | ||
58 | |||
59 | static bool | ||
60 | tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info) | ||
61 | { | ||
62 | const struct iphdr *iph = ip_hdr(skb); | ||
63 | struct net *net = pick_net(skb); | ||
64 | struct rtable *rt; | ||
65 | struct flowi fl; | ||
66 | |||
67 | memset(&fl, 0, sizeof(fl)); | ||
68 | if (info->priv) { | ||
69 | if (info->priv->oif == -1) | ||
70 | return false; | ||
71 | fl.oif = info->priv->oif; | ||
72 | } | ||
73 | fl.nl_u.ip4_u.daddr = info->gw.ip; | ||
74 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | ||
75 | fl.nl_u.ip4_u.scope = RT_SCOPE_UNIVERSE; | ||
76 | if (ip_route_output_key(net, &rt, &fl) != 0) | ||
77 | return false; | ||
78 | |||
79 | dst_release(skb_dst(skb)); | ||
80 | skb_dst_set(skb, &rt->u.dst); | ||
81 | skb->dev = rt->u.dst.dev; | ||
82 | skb->protocol = htons(ETH_P_IP); | ||
83 | return true; | ||
84 | } | ||
85 | |||
86 | static unsigned int | ||
87 | tee_tg4(struct sk_buff *skb, const struct xt_action_param *par) | ||
88 | { | ||
89 | const struct xt_tee_tginfo *info = par->targinfo; | ||
90 | struct iphdr *iph; | ||
91 | |||
92 | if (percpu_read(tee_active)) | ||
93 | return XT_CONTINUE; | ||
94 | /* | ||
95 | * Copy the skb, and route the copy. Will later return %XT_CONTINUE for | ||
96 | * the original skb, which should continue on its way as if nothing has | ||
97 | * happened. The copy should be independently delivered to the TEE | ||
98 | * --gateway. | ||
99 | */ | ||
100 | skb = pskb_copy(skb, GFP_ATOMIC); | ||
101 | if (skb == NULL) | ||
102 | return XT_CONTINUE; | ||
103 | |||
104 | #ifdef WITH_CONNTRACK | ||
105 | /* Avoid counting cloned packets towards the original connection. */ | ||
106 | nf_conntrack_put(skb->nfct); | ||
107 | skb->nfct = &nf_conntrack_untracked.ct_general; | ||
108 | skb->nfctinfo = IP_CT_NEW; | ||
109 | nf_conntrack_get(skb->nfct); | ||
110 | #endif | ||
111 | /* | ||
112 | * If we are in PREROUTING/INPUT, the checksum must be recalculated | ||
113 | * since the length could have changed as a result of defragmentation. | ||
114 | * | ||
115 | * We also decrease the TTL to mitigate potential TEE loops | ||
116 | * between two hosts. | ||
117 | * | ||
118 | * Set %IP_DF so that the original source is notified of a potentially | ||
119 | * decreased MTU on the clone route. IPv6 does this too. | ||
120 | */ | ||
121 | iph = ip_hdr(skb); | ||
122 | iph->frag_off |= htons(IP_DF); | ||
123 | if (par->hooknum == NF_INET_PRE_ROUTING || | ||
124 | par->hooknum == NF_INET_LOCAL_IN) | ||
125 | --iph->ttl; | ||
126 | ip_send_check(iph); | ||
127 | |||
128 | if (tee_tg_route4(skb, info)) { | ||
129 | percpu_write(tee_active, true); | ||
130 | ip_local_out(skb); | ||
131 | percpu_write(tee_active, false); | ||
132 | } else { | ||
133 | kfree_skb(skb); | ||
134 | } | ||
135 | return XT_CONTINUE; | ||
136 | } | ||
137 | |||
138 | #ifdef WITH_IPV6 | ||
139 | static bool | ||
140 | tee_tg_route6(struct sk_buff *skb, const struct xt_tee_tginfo *info) | ||
141 | { | ||
142 | const struct ipv6hdr *iph = ipv6_hdr(skb); | ||
143 | struct net *net = pick_net(skb); | ||
144 | struct dst_entry *dst; | ||
145 | struct flowi fl; | ||
146 | |||
147 | memset(&fl, 0, sizeof(fl)); | ||
148 | if (info->priv) { | ||
149 | if (info->priv->oif == -1) | ||
150 | return false; | ||
151 | fl.oif = info->priv->oif; | ||
152 | } | ||
153 | fl.nl_u.ip6_u.daddr = info->gw.in6; | ||
154 | fl.nl_u.ip6_u.flowlabel = ((iph->flow_lbl[0] & 0xF) << 16) | | ||
155 | (iph->flow_lbl[1] << 8) | iph->flow_lbl[2]; | ||
156 | dst = ip6_route_output(net, NULL, &fl); | ||
157 | if (dst == NULL) | ||
158 | return false; | ||
159 | |||
160 | dst_release(skb_dst(skb)); | ||
161 | skb_dst_set(skb, dst); | ||
162 | skb->dev = dst->dev; | ||
163 | skb->protocol = htons(ETH_P_IPV6); | ||
164 | return true; | ||
165 | } | ||
166 | |||
167 | static unsigned int | ||
168 | tee_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
169 | { | ||
170 | const struct xt_tee_tginfo *info = par->targinfo; | ||
171 | |||
172 | if (percpu_read(tee_active)) | ||
173 | return XT_CONTINUE; | ||
174 | skb = pskb_copy(skb, GFP_ATOMIC); | ||
175 | if (skb == NULL) | ||
176 | return XT_CONTINUE; | ||
177 | |||
178 | #ifdef WITH_CONNTRACK | ||
179 | nf_conntrack_put(skb->nfct); | ||
180 | skb->nfct = &nf_conntrack_untracked.ct_general; | ||
181 | skb->nfctinfo = IP_CT_NEW; | ||
182 | nf_conntrack_get(skb->nfct); | ||
183 | #endif | ||
184 | if (par->hooknum == NF_INET_PRE_ROUTING || | ||
185 | par->hooknum == NF_INET_LOCAL_IN) { | ||
186 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
187 | --iph->hop_limit; | ||
188 | } | ||
189 | if (tee_tg_route6(skb, info)) { | ||
190 | percpu_write(tee_active, true); | ||
191 | ip6_local_out(skb); | ||
192 | percpu_write(tee_active, false); | ||
193 | } else { | ||
194 | kfree_skb(skb); | ||
195 | } | ||
196 | return XT_CONTINUE; | ||
197 | } | ||
198 | #endif /* WITH_IPV6 */ | ||
199 | |||
200 | static int tee_netdev_event(struct notifier_block *this, unsigned long event, | ||
201 | void *ptr) | ||
202 | { | ||
203 | struct net_device *dev = ptr; | ||
204 | struct xt_tee_priv *priv; | ||
205 | |||
206 | priv = container_of(this, struct xt_tee_priv, notifier); | ||
207 | switch (event) { | ||
208 | case NETDEV_REGISTER: | ||
209 | if (!strcmp(dev->name, priv->tginfo->oif)) | ||
210 | priv->oif = dev->ifindex; | ||
211 | break; | ||
212 | case NETDEV_UNREGISTER: | ||
213 | if (dev->ifindex == priv->oif) | ||
214 | priv->oif = -1; | ||
215 | break; | ||
216 | case NETDEV_CHANGENAME: | ||
217 | if (!strcmp(dev->name, priv->tginfo->oif)) | ||
218 | priv->oif = dev->ifindex; | ||
219 | else if (dev->ifindex == priv->oif) | ||
220 | priv->oif = -1; | ||
221 | break; | ||
222 | } | ||
223 | |||
224 | return NOTIFY_DONE; | ||
225 | } | ||
226 | |||
227 | static int tee_tg_check(const struct xt_tgchk_param *par) | ||
228 | { | ||
229 | struct xt_tee_tginfo *info = par->targinfo; | ||
230 | struct xt_tee_priv *priv; | ||
231 | |||
232 | /* 0.0.0.0 and :: not allowed */ | ||
233 | if (memcmp(&info->gw, &tee_zero_address, | ||
234 | sizeof(tee_zero_address)) == 0) | ||
235 | return -EINVAL; | ||
236 | |||
237 | if (info->oif[0]) { | ||
238 | if (info->oif[sizeof(info->oif)-1] != '\0') | ||
239 | return -EINVAL; | ||
240 | |||
241 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
242 | if (priv == NULL) | ||
243 | return -ENOMEM; | ||
244 | |||
245 | priv->tginfo = info; | ||
246 | priv->oif = -1; | ||
247 | priv->notifier.notifier_call = tee_netdev_event; | ||
248 | info->priv = priv; | ||
249 | |||
250 | register_netdevice_notifier(&priv->notifier); | ||
251 | } else | ||
252 | info->priv = NULL; | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static void tee_tg_destroy(const struct xt_tgdtor_param *par) | ||
258 | { | ||
259 | struct xt_tee_tginfo *info = par->targinfo; | ||
260 | |||
261 | if (info->priv) { | ||
262 | unregister_netdevice_notifier(&info->priv->notifier); | ||
263 | kfree(info->priv); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static struct xt_target tee_tg_reg[] __read_mostly = { | ||
268 | { | ||
269 | .name = "TEE", | ||
270 | .revision = 1, | ||
271 | .family = NFPROTO_IPV4, | ||
272 | .target = tee_tg4, | ||
273 | .targetsize = sizeof(struct xt_tee_tginfo), | ||
274 | .checkentry = tee_tg_check, | ||
275 | .destroy = tee_tg_destroy, | ||
276 | .me = THIS_MODULE, | ||
277 | }, | ||
278 | #ifdef WITH_IPV6 | ||
279 | { | ||
280 | .name = "TEE", | ||
281 | .revision = 1, | ||
282 | .family = NFPROTO_IPV6, | ||
283 | .target = tee_tg6, | ||
284 | .targetsize = sizeof(struct xt_tee_tginfo), | ||
285 | .checkentry = tee_tg_check, | ||
286 | .destroy = tee_tg_destroy, | ||
287 | .me = THIS_MODULE, | ||
288 | }, | ||
289 | #endif | ||
290 | }; | ||
291 | |||
292 | static int __init tee_tg_init(void) | ||
293 | { | ||
294 | return xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); | ||
295 | } | ||
296 | |||
297 | static void __exit tee_tg_exit(void) | ||
298 | { | ||
299 | xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); | ||
300 | } | ||
301 | |||
302 | module_init(tee_tg_init); | ||
303 | module_exit(tee_tg_exit); | ||
304 | MODULE_AUTHOR("Sebastian Claßen <sebastian.classen@freenet.ag>"); | ||
305 | MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); | ||
306 | MODULE_DESCRIPTION("Xtables: Reroute packet copy"); | ||
307 | MODULE_LICENSE("GPL"); | ||
308 | MODULE_ALIAS("ipt_TEE"); | ||
309 | MODULE_ALIAS("ip6t_TEE"); | ||
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c index 1340c2fa3621..e1a0dedac258 100644 --- a/net/netfilter/xt_TPROXY.c +++ b/net/netfilter/xt_TPROXY.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/ip.h> | 15 | #include <linux/ip.h> |
@@ -25,7 +25,7 @@ | |||
25 | #include <net/netfilter/nf_tproxy_core.h> | 25 | #include <net/netfilter/nf_tproxy_core.h> |
26 | 26 | ||
27 | static unsigned int | 27 | static unsigned int |
28 | tproxy_tg(struct sk_buff *skb, const struct xt_target_param *par) | 28 | tproxy_tg(struct sk_buff *skb, const struct xt_action_param *par) |
29 | { | 29 | { |
30 | const struct iphdr *iph = ip_hdr(skb); | 30 | const struct iphdr *iph = ip_hdr(skb); |
31 | const struct xt_tproxy_target_info *tgi = par->targinfo; | 31 | const struct xt_tproxy_target_info *tgi = par->targinfo; |
@@ -59,17 +59,17 @@ tproxy_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
59 | return NF_DROP; | 59 | return NF_DROP; |
60 | } | 60 | } |
61 | 61 | ||
62 | static bool tproxy_tg_check(const struct xt_tgchk_param *par) | 62 | static int tproxy_tg_check(const struct xt_tgchk_param *par) |
63 | { | 63 | { |
64 | const struct ipt_ip *i = par->entryinfo; | 64 | const struct ipt_ip *i = par->entryinfo; |
65 | 65 | ||
66 | if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) | 66 | if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) |
67 | && !(i->invflags & IPT_INV_PROTO)) | 67 | && !(i->invflags & IPT_INV_PROTO)) |
68 | return true; | 68 | return 0; |
69 | 69 | ||
70 | pr_info("xt_TPROXY: Can be used only in combination with " | 70 | pr_info("Can be used only in combination with " |
71 | "either -p tcp or -p udp\n"); | 71 | "either -p tcp or -p udp\n"); |
72 | return false; | 72 | return -EINVAL; |
73 | } | 73 | } |
74 | 74 | ||
75 | static struct xt_target tproxy_tg_reg __read_mostly = { | 75 | static struct xt_target tproxy_tg_reg __read_mostly = { |
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c index fbb04b86c46b..df48967af382 100644 --- a/net/netfilter/xt_TRACE.c +++ b/net/netfilter/xt_TRACE.c | |||
@@ -11,7 +11,7 @@ MODULE_ALIAS("ipt_TRACE"); | |||
11 | MODULE_ALIAS("ip6t_TRACE"); | 11 | MODULE_ALIAS("ip6t_TRACE"); |
12 | 12 | ||
13 | static unsigned int | 13 | static unsigned int |
14 | trace_tg(struct sk_buff *skb, const struct xt_target_param *par) | 14 | trace_tg(struct sk_buff *skb, const struct xt_action_param *par) |
15 | { | 15 | { |
16 | skb->nf_trace = 1; | 16 | skb->nf_trace = 1; |
17 | return XT_CONTINUE; | 17 | return XT_CONTINUE; |
diff --git a/net/netfilter/xt_cluster.c b/net/netfilter/xt_cluster.c index 225ee3ecd69d..30b95a1c1c89 100644 --- a/net/netfilter/xt_cluster.c +++ b/net/netfilter/xt_cluster.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
8 | #include <linux/module.h> | 9 | #include <linux/module.h> |
9 | #include <linux/skbuff.h> | 10 | #include <linux/skbuff.h> |
10 | #include <linux/jhash.h> | 11 | #include <linux/jhash.h> |
@@ -85,7 +86,7 @@ xt_cluster_is_multicast_addr(const struct sk_buff *skb, u_int8_t family) | |||
85 | } | 86 | } |
86 | 87 | ||
87 | static bool | 88 | static bool |
88 | xt_cluster_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 89 | xt_cluster_mt(const struct sk_buff *skb, struct xt_action_param *par) |
89 | { | 90 | { |
90 | struct sk_buff *pskb = (struct sk_buff *)skb; | 91 | struct sk_buff *pskb = (struct sk_buff *)skb; |
91 | const struct xt_cluster_match_info *info = par->matchinfo; | 92 | const struct xt_cluster_match_info *info = par->matchinfo; |
@@ -131,22 +132,22 @@ xt_cluster_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
131 | !!(info->flags & XT_CLUSTER_F_INV); | 132 | !!(info->flags & XT_CLUSTER_F_INV); |
132 | } | 133 | } |
133 | 134 | ||
134 | static bool xt_cluster_mt_checkentry(const struct xt_mtchk_param *par) | 135 | static int xt_cluster_mt_checkentry(const struct xt_mtchk_param *par) |
135 | { | 136 | { |
136 | struct xt_cluster_match_info *info = par->matchinfo; | 137 | struct xt_cluster_match_info *info = par->matchinfo; |
137 | 138 | ||
138 | if (info->total_nodes > XT_CLUSTER_NODES_MAX) { | 139 | if (info->total_nodes > XT_CLUSTER_NODES_MAX) { |
139 | printk(KERN_ERR "xt_cluster: you have exceeded the maximum " | 140 | pr_info("you have exceeded the maximum " |
140 | "number of cluster nodes (%u > %u)\n", | 141 | "number of cluster nodes (%u > %u)\n", |
141 | info->total_nodes, XT_CLUSTER_NODES_MAX); | 142 | info->total_nodes, XT_CLUSTER_NODES_MAX); |
142 | return false; | 143 | return -EINVAL; |
143 | } | 144 | } |
144 | if (info->node_mask >= (1ULL << info->total_nodes)) { | 145 | if (info->node_mask >= (1ULL << info->total_nodes)) { |
145 | printk(KERN_ERR "xt_cluster: this node mask cannot be " | 146 | pr_info("this node mask cannot be " |
146 | "higher than the total number of nodes\n"); | 147 | "higher than the total number of nodes\n"); |
147 | return false; | 148 | return -EDOM; |
148 | } | 149 | } |
149 | return true; | 150 | return 0; |
150 | } | 151 | } |
151 | 152 | ||
152 | static struct xt_match xt_cluster_match __read_mostly = { | 153 | static struct xt_match xt_cluster_match __read_mostly = { |
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c index e82179832acd..5c861d2f21ca 100644 --- a/net/netfilter/xt_comment.c +++ b/net/netfilter/xt_comment.c | |||
@@ -16,7 +16,7 @@ MODULE_ALIAS("ipt_comment"); | |||
16 | MODULE_ALIAS("ip6t_comment"); | 16 | MODULE_ALIAS("ip6t_comment"); |
17 | 17 | ||
18 | static bool | 18 | static bool |
19 | comment_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 19 | comment_mt(const struct sk_buff *skb, struct xt_action_param *par) |
20 | { | 20 | { |
21 | /* We always match */ | 21 | /* We always match */ |
22 | return true; | 22 | return true; |
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c index 955e6598a7f0..73517835303d 100644 --- a/net/netfilter/xt_connbytes.c +++ b/net/netfilter/xt_connbytes.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* Kernel module to match connection tracking byte counter. | 1 | /* Kernel module to match connection tracking byte counter. |
2 | * GPL (C) 2002 Martin Devera (devik@cdi.cz). | 2 | * GPL (C) 2002 Martin Devera (devik@cdi.cz). |
3 | */ | 3 | */ |
4 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
4 | #include <linux/module.h> | 5 | #include <linux/module.h> |
5 | #include <linux/bitops.h> | 6 | #include <linux/bitops.h> |
6 | #include <linux/skbuff.h> | 7 | #include <linux/skbuff.h> |
@@ -17,7 +18,7 @@ MODULE_ALIAS("ipt_connbytes"); | |||
17 | MODULE_ALIAS("ip6t_connbytes"); | 18 | MODULE_ALIAS("ip6t_connbytes"); |
18 | 19 | ||
19 | static bool | 20 | static bool |
20 | connbytes_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 21 | connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par) |
21 | { | 22 | { |
22 | const struct xt_connbytes_info *sinfo = par->matchinfo; | 23 | const struct xt_connbytes_info *sinfo = par->matchinfo; |
23 | const struct nf_conn *ct; | 24 | const struct nf_conn *ct; |
@@ -92,27 +93,26 @@ connbytes_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
92 | return what >= sinfo->count.from; | 93 | return what >= sinfo->count.from; |
93 | } | 94 | } |
94 | 95 | ||
95 | static bool connbytes_mt_check(const struct xt_mtchk_param *par) | 96 | static int connbytes_mt_check(const struct xt_mtchk_param *par) |
96 | { | 97 | { |
97 | const struct xt_connbytes_info *sinfo = par->matchinfo; | 98 | const struct xt_connbytes_info *sinfo = par->matchinfo; |
99 | int ret; | ||
98 | 100 | ||
99 | if (sinfo->what != XT_CONNBYTES_PKTS && | 101 | if (sinfo->what != XT_CONNBYTES_PKTS && |
100 | sinfo->what != XT_CONNBYTES_BYTES && | 102 | sinfo->what != XT_CONNBYTES_BYTES && |
101 | sinfo->what != XT_CONNBYTES_AVGPKT) | 103 | sinfo->what != XT_CONNBYTES_AVGPKT) |
102 | return false; | 104 | return -EINVAL; |
103 | 105 | ||
104 | if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && | 106 | if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && |
105 | sinfo->direction != XT_CONNBYTES_DIR_REPLY && | 107 | sinfo->direction != XT_CONNBYTES_DIR_REPLY && |
106 | sinfo->direction != XT_CONNBYTES_DIR_BOTH) | 108 | sinfo->direction != XT_CONNBYTES_DIR_BOTH) |
107 | return false; | 109 | return -EINVAL; |
108 | |||
109 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { | ||
110 | printk(KERN_WARNING "can't load conntrack support for " | ||
111 | "proto=%u\n", par->family); | ||
112 | return false; | ||
113 | } | ||
114 | 110 | ||
115 | return true; | 111 | ret = nf_ct_l3proto_try_module_get(par->family); |
112 | if (ret < 0) | ||
113 | pr_info("cannot load conntrack support for proto=%u\n", | ||
114 | par->family); | ||
115 | return ret; | ||
116 | } | 116 | } |
117 | 117 | ||
118 | static void connbytes_mt_destroy(const struct xt_mtdtor_param *par) | 118 | static void connbytes_mt_destroy(const struct xt_mtdtor_param *par) |
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 388ca4596098..5c5b6b921b84 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c | |||
@@ -5,13 +5,13 @@ | |||
5 | * Nov 2002: Martin Bene <martin.bene@icomedias.com>: | 5 | * Nov 2002: Martin Bene <martin.bene@icomedias.com>: |
6 | * only ignore TIME_WAIT or gone connections | 6 | * only ignore TIME_WAIT or gone connections |
7 | * (C) CC Computer Consultants GmbH, 2007 | 7 | * (C) CC Computer Consultants GmbH, 2007 |
8 | * Contact: <jengelh@computergmbh.de> | ||
9 | * | 8 | * |
10 | * based on ... | 9 | * based on ... |
11 | * | 10 | * |
12 | * Kernel module to match connection tracking information. | 11 | * Kernel module to match connection tracking information. |
13 | * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au). | 12 | * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au). |
14 | */ | 13 | */ |
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
15 | #include <linux/in.h> | 15 | #include <linux/in.h> |
16 | #include <linux/in6.h> | 16 | #include <linux/in6.h> |
17 | #include <linux/ip.h> | 17 | #include <linux/ip.h> |
@@ -173,7 +173,7 @@ static int count_them(struct net *net, | |||
173 | } | 173 | } |
174 | 174 | ||
175 | static bool | 175 | static bool |
176 | connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 176 | connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) |
177 | { | 177 | { |
178 | struct net *net = dev_net(par->in ? par->in : par->out); | 178 | struct net *net = dev_net(par->in ? par->in : par->out); |
179 | const struct xt_connlimit_info *info = par->matchinfo; | 179 | const struct xt_connlimit_info *info = par->matchinfo; |
@@ -206,44 +206,46 @@ connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
206 | 206 | ||
207 | if (connections < 0) { | 207 | if (connections < 0) { |
208 | /* kmalloc failed, drop it entirely */ | 208 | /* kmalloc failed, drop it entirely */ |
209 | *par->hotdrop = true; | 209 | par->hotdrop = true; |
210 | return false; | 210 | return false; |
211 | } | 211 | } |
212 | 212 | ||
213 | return (connections > info->limit) ^ info->inverse; | 213 | return (connections > info->limit) ^ info->inverse; |
214 | 214 | ||
215 | hotdrop: | 215 | hotdrop: |
216 | *par->hotdrop = true; | 216 | par->hotdrop = true; |
217 | return false; | 217 | return false; |
218 | } | 218 | } |
219 | 219 | ||
220 | static bool connlimit_mt_check(const struct xt_mtchk_param *par) | 220 | static int connlimit_mt_check(const struct xt_mtchk_param *par) |
221 | { | 221 | { |
222 | struct xt_connlimit_info *info = par->matchinfo; | 222 | struct xt_connlimit_info *info = par->matchinfo; |
223 | unsigned int i; | 223 | unsigned int i; |
224 | int ret; | ||
224 | 225 | ||
225 | if (unlikely(!connlimit_rnd_inited)) { | 226 | if (unlikely(!connlimit_rnd_inited)) { |
226 | get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd)); | 227 | get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd)); |
227 | connlimit_rnd_inited = true; | 228 | connlimit_rnd_inited = true; |
228 | } | 229 | } |
229 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { | 230 | ret = nf_ct_l3proto_try_module_get(par->family); |
230 | printk(KERN_WARNING "cannot load conntrack support for " | 231 | if (ret < 0) { |
231 | "address family %u\n", par->family); | 232 | pr_info("cannot load conntrack support for " |
232 | return false; | 233 | "address family %u\n", par->family); |
234 | return ret; | ||
233 | } | 235 | } |
234 | 236 | ||
235 | /* init private data */ | 237 | /* init private data */ |
236 | info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL); | 238 | info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL); |
237 | if (info->data == NULL) { | 239 | if (info->data == NULL) { |
238 | nf_ct_l3proto_module_put(par->family); | 240 | nf_ct_l3proto_module_put(par->family); |
239 | return false; | 241 | return -ENOMEM; |
240 | } | 242 | } |
241 | 243 | ||
242 | spin_lock_init(&info->data->lock); | 244 | spin_lock_init(&info->data->lock); |
243 | for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) | 245 | for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) |
244 | INIT_LIST_HEAD(&info->data->iphash[i]); | 246 | INIT_LIST_HEAD(&info->data->iphash[i]); |
245 | 247 | ||
246 | return true; | 248 | return 0; |
247 | } | 249 | } |
248 | 250 | ||
249 | static void connlimit_mt_destroy(const struct xt_mtdtor_param *par) | 251 | static void connlimit_mt_destroy(const struct xt_mtdtor_param *par) |
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index 122aa8b0147b..7278145e6a68 100644 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c | |||
@@ -1,10 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * xt_connmark - Netfilter module to match connection mark values | 2 | * xt_connmark - Netfilter module to operate on connection marks |
3 | * | 3 | * |
4 | * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | 4 | * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> |
5 | * by Henrik Nordstrom <hno@marasystems.com> | 5 | * by Henrik Nordstrom <hno@marasystems.com> |
6 | * Copyright © CC Computer Consultants GmbH, 2007 - 2008 | 6 | * Copyright © CC Computer Consultants GmbH, 2007 - 2008 |
7 | * Jan Engelhardt <jengelh@computergmbh.de> | 7 | * Jan Engelhardt <jengelh@medozas.de> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -24,17 +24,74 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/skbuff.h> | 25 | #include <linux/skbuff.h> |
26 | #include <net/netfilter/nf_conntrack.h> | 26 | #include <net/netfilter/nf_conntrack.h> |
27 | #include <net/netfilter/nf_conntrack_ecache.h> | ||
27 | #include <linux/netfilter/x_tables.h> | 28 | #include <linux/netfilter/x_tables.h> |
28 | #include <linux/netfilter/xt_connmark.h> | 29 | #include <linux/netfilter/xt_connmark.h> |
29 | 30 | ||
30 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); | 31 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>"); |
31 | MODULE_DESCRIPTION("Xtables: connection mark match"); | 32 | MODULE_DESCRIPTION("Xtables: connection mark operations"); |
32 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | MODULE_ALIAS("ipt_CONNMARK"); | ||
35 | MODULE_ALIAS("ip6t_CONNMARK"); | ||
33 | MODULE_ALIAS("ipt_connmark"); | 36 | MODULE_ALIAS("ipt_connmark"); |
34 | MODULE_ALIAS("ip6t_connmark"); | 37 | MODULE_ALIAS("ip6t_connmark"); |
35 | 38 | ||
39 | static unsigned int | ||
40 | connmark_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
41 | { | ||
42 | const struct xt_connmark_tginfo1 *info = par->targinfo; | ||
43 | enum ip_conntrack_info ctinfo; | ||
44 | struct nf_conn *ct; | ||
45 | u_int32_t newmark; | ||
46 | |||
47 | ct = nf_ct_get(skb, &ctinfo); | ||
48 | if (ct == NULL) | ||
49 | return XT_CONTINUE; | ||
50 | |||
51 | switch (info->mode) { | ||
52 | case XT_CONNMARK_SET: | ||
53 | newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; | ||
54 | if (ct->mark != newmark) { | ||
55 | ct->mark = newmark; | ||
56 | nf_conntrack_event_cache(IPCT_MARK, ct); | ||
57 | } | ||
58 | break; | ||
59 | case XT_CONNMARK_SAVE: | ||
60 | newmark = (ct->mark & ~info->ctmask) ^ | ||
61 | (skb->mark & info->nfmask); | ||
62 | if (ct->mark != newmark) { | ||
63 | ct->mark = newmark; | ||
64 | nf_conntrack_event_cache(IPCT_MARK, ct); | ||
65 | } | ||
66 | break; | ||
67 | case XT_CONNMARK_RESTORE: | ||
68 | newmark = (skb->mark & ~info->nfmask) ^ | ||
69 | (ct->mark & info->ctmask); | ||
70 | skb->mark = newmark; | ||
71 | break; | ||
72 | } | ||
73 | |||
74 | return XT_CONTINUE; | ||
75 | } | ||
76 | |||
77 | static int connmark_tg_check(const struct xt_tgchk_param *par) | ||
78 | { | ||
79 | int ret; | ||
80 | |||
81 | ret = nf_ct_l3proto_try_module_get(par->family); | ||
82 | if (ret < 0) | ||
83 | pr_info("cannot load conntrack support for proto=%u\n", | ||
84 | par->family); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | static void connmark_tg_destroy(const struct xt_tgdtor_param *par) | ||
89 | { | ||
90 | nf_ct_l3proto_module_put(par->family); | ||
91 | } | ||
92 | |||
36 | static bool | 93 | static bool |
37 | connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 94 | connmark_mt(const struct sk_buff *skb, struct xt_action_param *par) |
38 | { | 95 | { |
39 | const struct xt_connmark_mtinfo1 *info = par->matchinfo; | 96 | const struct xt_connmark_mtinfo1 *info = par->matchinfo; |
40 | enum ip_conntrack_info ctinfo; | 97 | enum ip_conntrack_info ctinfo; |
@@ -47,14 +104,15 @@ connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
47 | return ((ct->mark & info->mask) == info->mark) ^ info->invert; | 104 | return ((ct->mark & info->mask) == info->mark) ^ info->invert; |
48 | } | 105 | } |
49 | 106 | ||
50 | static bool connmark_mt_check(const struct xt_mtchk_param *par) | 107 | static int connmark_mt_check(const struct xt_mtchk_param *par) |
51 | { | 108 | { |
52 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { | 109 | int ret; |
53 | printk(KERN_WARNING "cannot load conntrack support for " | 110 | |
54 | "proto=%u\n", par->family); | 111 | ret = nf_ct_l3proto_try_module_get(par->family); |
55 | return false; | 112 | if (ret < 0) |
56 | } | 113 | pr_info("cannot load conntrack support for proto=%u\n", |
57 | return true; | 114 | par->family); |
115 | return ret; | ||
58 | } | 116 | } |
59 | 117 | ||
60 | static void connmark_mt_destroy(const struct xt_mtdtor_param *par) | 118 | static void connmark_mt_destroy(const struct xt_mtdtor_param *par) |
@@ -62,6 +120,17 @@ static void connmark_mt_destroy(const struct xt_mtdtor_param *par) | |||
62 | nf_ct_l3proto_module_put(par->family); | 120 | nf_ct_l3proto_module_put(par->family); |
63 | } | 121 | } |
64 | 122 | ||
123 | static struct xt_target connmark_tg_reg __read_mostly = { | ||
124 | .name = "CONNMARK", | ||
125 | .revision = 1, | ||
126 | .family = NFPROTO_UNSPEC, | ||
127 | .checkentry = connmark_tg_check, | ||
128 | .target = connmark_tg, | ||
129 | .targetsize = sizeof(struct xt_connmark_tginfo1), | ||
130 | .destroy = connmark_tg_destroy, | ||
131 | .me = THIS_MODULE, | ||
132 | }; | ||
133 | |||
65 | static struct xt_match connmark_mt_reg __read_mostly = { | 134 | static struct xt_match connmark_mt_reg __read_mostly = { |
66 | .name = "connmark", | 135 | .name = "connmark", |
67 | .revision = 1, | 136 | .revision = 1, |
@@ -75,12 +144,23 @@ static struct xt_match connmark_mt_reg __read_mostly = { | |||
75 | 144 | ||
76 | static int __init connmark_mt_init(void) | 145 | static int __init connmark_mt_init(void) |
77 | { | 146 | { |
78 | return xt_register_match(&connmark_mt_reg); | 147 | int ret; |
148 | |||
149 | ret = xt_register_target(&connmark_tg_reg); | ||
150 | if (ret < 0) | ||
151 | return ret; | ||
152 | ret = xt_register_match(&connmark_mt_reg); | ||
153 | if (ret < 0) { | ||
154 | xt_unregister_target(&connmark_tg_reg); | ||
155 | return ret; | ||
156 | } | ||
157 | return 0; | ||
79 | } | 158 | } |
80 | 159 | ||
81 | static void __exit connmark_mt_exit(void) | 160 | static void __exit connmark_mt_exit(void) |
82 | { | 161 | { |
83 | xt_unregister_match(&connmark_mt_reg); | 162 | xt_unregister_match(&connmark_mt_reg); |
163 | xt_unregister_target(&connmark_tg_reg); | ||
84 | } | 164 | } |
85 | 165 | ||
86 | module_init(connmark_mt_init); | 166 | module_init(connmark_mt_init); |
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index ae66305f0fe5..39681f10291c 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <net/ipv6.h> | 15 | #include <net/ipv6.h> |
@@ -113,7 +113,7 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info, | |||
113 | } | 113 | } |
114 | 114 | ||
115 | static bool | 115 | static bool |
116 | conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par, | 116 | conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par, |
117 | u16 state_mask, u16 status_mask) | 117 | u16 state_mask, u16 status_mask) |
118 | { | 118 | { |
119 | const struct xt_conntrack_mtinfo2 *info = par->matchinfo; | 119 | const struct xt_conntrack_mtinfo2 *info = par->matchinfo; |
@@ -191,7 +191,7 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par, | |||
191 | } | 191 | } |
192 | 192 | ||
193 | static bool | 193 | static bool |
194 | conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | 194 | conntrack_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) |
195 | { | 195 | { |
196 | const struct xt_conntrack_mtinfo1 *info = par->matchinfo; | 196 | const struct xt_conntrack_mtinfo1 *info = par->matchinfo; |
197 | 197 | ||
@@ -199,21 +199,22 @@ conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | static bool | 201 | static bool |
202 | conntrack_mt_v2(const struct sk_buff *skb, const struct xt_match_param *par) | 202 | conntrack_mt_v2(const struct sk_buff *skb, struct xt_action_param *par) |
203 | { | 203 | { |
204 | const struct xt_conntrack_mtinfo2 *info = par->matchinfo; | 204 | const struct xt_conntrack_mtinfo2 *info = par->matchinfo; |
205 | 205 | ||
206 | return conntrack_mt(skb, par, info->state_mask, info->status_mask); | 206 | return conntrack_mt(skb, par, info->state_mask, info->status_mask); |
207 | } | 207 | } |
208 | 208 | ||
209 | static bool conntrack_mt_check(const struct xt_mtchk_param *par) | 209 | static int conntrack_mt_check(const struct xt_mtchk_param *par) |
210 | { | 210 | { |
211 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { | 211 | int ret; |
212 | printk(KERN_WARNING "can't load conntrack support for " | 212 | |
213 | "proto=%u\n", par->family); | 213 | ret = nf_ct_l3proto_try_module_get(par->family); |
214 | return false; | 214 | if (ret < 0) |
215 | } | 215 | pr_info("cannot load conntrack support for proto=%u\n", |
216 | return true; | 216 | par->family); |
217 | return ret; | ||
217 | } | 218 | } |
218 | 219 | ||
219 | static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) | 220 | static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) |
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c index 395af5943ffd..b63d2a3d80ba 100644 --- a/net/netfilter/xt_dccp.c +++ b/net/netfilter/xt_dccp.c | |||
@@ -96,7 +96,7 @@ match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff, | |||
96 | } | 96 | } |
97 | 97 | ||
98 | static bool | 98 | static bool |
99 | dccp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 99 | dccp_mt(const struct sk_buff *skb, struct xt_action_param *par) |
100 | { | 100 | { |
101 | const struct xt_dccp_info *info = par->matchinfo; | 101 | const struct xt_dccp_info *info = par->matchinfo; |
102 | const struct dccp_hdr *dh; | 102 | const struct dccp_hdr *dh; |
@@ -107,7 +107,7 @@ dccp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
107 | 107 | ||
108 | dh = skb_header_pointer(skb, par->thoff, sizeof(_dh), &_dh); | 108 | dh = skb_header_pointer(skb, par->thoff, sizeof(_dh), &_dh); |
109 | if (dh == NULL) { | 109 | if (dh == NULL) { |
110 | *par->hotdrop = true; | 110 | par->hotdrop = true; |
111 | return false; | 111 | return false; |
112 | } | 112 | } |
113 | 113 | ||
@@ -120,17 +120,21 @@ dccp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
120 | && DCCHECK(match_types(dh, info->typemask), | 120 | && DCCHECK(match_types(dh, info->typemask), |
121 | XT_DCCP_TYPE, info->flags, info->invflags) | 121 | XT_DCCP_TYPE, info->flags, info->invflags) |
122 | && DCCHECK(match_option(info->option, skb, par->thoff, dh, | 122 | && DCCHECK(match_option(info->option, skb, par->thoff, dh, |
123 | par->hotdrop), | 123 | &par->hotdrop), |
124 | XT_DCCP_OPTION, info->flags, info->invflags); | 124 | XT_DCCP_OPTION, info->flags, info->invflags); |
125 | } | 125 | } |
126 | 126 | ||
127 | static bool dccp_mt_check(const struct xt_mtchk_param *par) | 127 | static int dccp_mt_check(const struct xt_mtchk_param *par) |
128 | { | 128 | { |
129 | const struct xt_dccp_info *info = par->matchinfo; | 129 | const struct xt_dccp_info *info = par->matchinfo; |
130 | 130 | ||
131 | return !(info->flags & ~XT_DCCP_VALID_FLAGS) | 131 | if (info->flags & ~XT_DCCP_VALID_FLAGS) |
132 | && !(info->invflags & ~XT_DCCP_VALID_FLAGS) | 132 | return -EINVAL; |
133 | && !(info->invflags & ~info->flags); | 133 | if (info->invflags & ~XT_DCCP_VALID_FLAGS) |
134 | return -EINVAL; | ||
135 | if (info->invflags & ~info->flags) | ||
136 | return -EINVAL; | ||
137 | return 0; | ||
134 | } | 138 | } |
135 | 139 | ||
136 | static struct xt_match dccp_mt_reg[] __read_mostly = { | 140 | static struct xt_match dccp_mt_reg[] __read_mostly = { |
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c index 0280d3a8c161..64670fc5d0e1 100644 --- a/net/netfilter/xt_dscp.c +++ b/net/netfilter/xt_dscp.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/ip.h> | 12 | #include <linux/ip.h> |
@@ -25,7 +25,7 @@ MODULE_ALIAS("ipt_tos"); | |||
25 | MODULE_ALIAS("ip6t_tos"); | 25 | MODULE_ALIAS("ip6t_tos"); |
26 | 26 | ||
27 | static bool | 27 | static bool |
28 | dscp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 28 | dscp_mt(const struct sk_buff *skb, struct xt_action_param *par) |
29 | { | 29 | { |
30 | const struct xt_dscp_info *info = par->matchinfo; | 30 | const struct xt_dscp_info *info = par->matchinfo; |
31 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; | 31 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; |
@@ -34,7 +34,7 @@ dscp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
34 | } | 34 | } |
35 | 35 | ||
36 | static bool | 36 | static bool |
37 | dscp_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 37 | dscp_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
38 | { | 38 | { |
39 | const struct xt_dscp_info *info = par->matchinfo; | 39 | const struct xt_dscp_info *info = par->matchinfo; |
40 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; | 40 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; |
@@ -42,23 +42,23 @@ dscp_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
42 | return (dscp == info->dscp) ^ !!info->invert; | 42 | return (dscp == info->dscp) ^ !!info->invert; |
43 | } | 43 | } |
44 | 44 | ||
45 | static bool dscp_mt_check(const struct xt_mtchk_param *par) | 45 | static int dscp_mt_check(const struct xt_mtchk_param *par) |
46 | { | 46 | { |
47 | const struct xt_dscp_info *info = par->matchinfo; | 47 | const struct xt_dscp_info *info = par->matchinfo; |
48 | 48 | ||
49 | if (info->dscp > XT_DSCP_MAX) { | 49 | if (info->dscp > XT_DSCP_MAX) { |
50 | printk(KERN_ERR "xt_dscp: dscp %x out of range\n", info->dscp); | 50 | pr_info("dscp %x out of range\n", info->dscp); |
51 | return false; | 51 | return -EDOM; |
52 | } | 52 | } |
53 | 53 | ||
54 | return true; | 54 | return 0; |
55 | } | 55 | } |
56 | 56 | ||
57 | static bool tos_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 57 | static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par) |
58 | { | 58 | { |
59 | const struct xt_tos_match_info *info = par->matchinfo; | 59 | const struct xt_tos_match_info *info = par->matchinfo; |
60 | 60 | ||
61 | if (par->match->family == NFPROTO_IPV4) | 61 | if (par->family == NFPROTO_IPV4) |
62 | return ((ip_hdr(skb)->tos & info->tos_mask) == | 62 | return ((ip_hdr(skb)->tos & info->tos_mask) == |
63 | info->tos_value) ^ !!info->invert; | 63 | info->tos_value) ^ !!info->invert; |
64 | else | 64 | else |
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c index 609439967c2c..171ba82b5902 100644 --- a/net/netfilter/xt_esp.c +++ b/net/netfilter/xt_esp.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/in.h> | 12 | #include <linux/in.h> |
@@ -24,25 +24,19 @@ MODULE_DESCRIPTION("Xtables: IPsec-ESP packet match"); | |||
24 | MODULE_ALIAS("ipt_esp"); | 24 | MODULE_ALIAS("ipt_esp"); |
25 | MODULE_ALIAS("ip6t_esp"); | 25 | MODULE_ALIAS("ip6t_esp"); |
26 | 26 | ||
27 | #if 0 | ||
28 | #define duprintf(format, args...) printk(format , ## args) | ||
29 | #else | ||
30 | #define duprintf(format, args...) | ||
31 | #endif | ||
32 | |||
33 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ | 27 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ |
34 | static inline bool | 28 | static inline bool |
35 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) | 29 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) |
36 | { | 30 | { |
37 | bool r; | 31 | bool r; |
38 | duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', | 32 | pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n", |
39 | min, spi, max); | 33 | invert ? '!' : ' ', min, spi, max); |
40 | r = (spi >= min && spi <= max) ^ invert; | 34 | r = (spi >= min && spi <= max) ^ invert; |
41 | duprintf(" result %s\n", r ? "PASS" : "FAILED"); | 35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
42 | return r; | 36 | return r; |
43 | } | 37 | } |
44 | 38 | ||
45 | static bool esp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 39 | static bool esp_mt(const struct sk_buff *skb, struct xt_action_param *par) |
46 | { | 40 | { |
47 | const struct ip_esp_hdr *eh; | 41 | const struct ip_esp_hdr *eh; |
48 | struct ip_esp_hdr _esp; | 42 | struct ip_esp_hdr _esp; |
@@ -57,8 +51,8 @@ static bool esp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
57 | /* We've been asked to examine this packet, and we | 51 | /* We've been asked to examine this packet, and we |
58 | * can't. Hence, no choice but to drop. | 52 | * can't. Hence, no choice but to drop. |
59 | */ | 53 | */ |
60 | duprintf("Dropping evil ESP tinygram.\n"); | 54 | pr_debug("Dropping evil ESP tinygram.\n"); |
61 | *par->hotdrop = true; | 55 | par->hotdrop = true; |
62 | return false; | 56 | return false; |
63 | } | 57 | } |
64 | 58 | ||
@@ -66,16 +60,16 @@ static bool esp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
66 | !!(espinfo->invflags & XT_ESP_INV_SPI)); | 60 | !!(espinfo->invflags & XT_ESP_INV_SPI)); |
67 | } | 61 | } |
68 | 62 | ||
69 | static bool esp_mt_check(const struct xt_mtchk_param *par) | 63 | static int esp_mt_check(const struct xt_mtchk_param *par) |
70 | { | 64 | { |
71 | const struct xt_esp *espinfo = par->matchinfo; | 65 | const struct xt_esp *espinfo = par->matchinfo; |
72 | 66 | ||
73 | if (espinfo->invflags & ~XT_ESP_INV_MASK) { | 67 | if (espinfo->invflags & ~XT_ESP_INV_MASK) { |
74 | duprintf("xt_esp: unknown flags %X\n", espinfo->invflags); | 68 | pr_debug("unknown flags %X\n", espinfo->invflags); |
75 | return false; | 69 | return -EINVAL; |
76 | } | 70 | } |
77 | 71 | ||
78 | return true; | 72 | return 0; |
79 | } | 73 | } |
80 | 74 | ||
81 | static struct xt_match esp_mt_reg[] __read_mostly = { | 75 | static struct xt_match esp_mt_reg[] __read_mostly = { |
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 215a64835de8..b46a8390896d 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Development of this code was funded by Astaro AG, http://www.astaro.com/ | 8 | * Development of this code was funded by Astaro AG, http://www.astaro.com/ |
9 | */ | 9 | */ |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
10 | #include <linux/module.h> | 11 | #include <linux/module.h> |
11 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
12 | #include <linux/random.h> | 13 | #include <linux/random.h> |
@@ -36,7 +37,7 @@ | |||
36 | 37 | ||
37 | MODULE_LICENSE("GPL"); | 38 | MODULE_LICENSE("GPL"); |
38 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | 39 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
39 | MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>"); | 40 | MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); |
40 | MODULE_DESCRIPTION("Xtables: per hash-bucket rate-limit match"); | 41 | MODULE_DESCRIPTION("Xtables: per hash-bucket rate-limit match"); |
41 | MODULE_ALIAS("ipt_hashlimit"); | 42 | MODULE_ALIAS("ipt_hashlimit"); |
42 | MODULE_ALIAS("ip6t_hashlimit"); | 43 | MODULE_ALIAS("ip6t_hashlimit"); |
@@ -80,12 +81,14 @@ struct dsthash_ent { | |||
80 | struct dsthash_dst dst; | 81 | struct dsthash_dst dst; |
81 | 82 | ||
82 | /* modified structure members in the end */ | 83 | /* modified structure members in the end */ |
84 | spinlock_t lock; | ||
83 | unsigned long expires; /* precalculated expiry time */ | 85 | unsigned long expires; /* precalculated expiry time */ |
84 | struct { | 86 | struct { |
85 | unsigned long prev; /* last modification */ | 87 | unsigned long prev; /* last modification */ |
86 | u_int32_t credit; | 88 | u_int32_t credit; |
87 | u_int32_t credit_cap, cost; | 89 | u_int32_t credit_cap, cost; |
88 | } rateinfo; | 90 | } rateinfo; |
91 | struct rcu_head rcu; | ||
89 | }; | 92 | }; |
90 | 93 | ||
91 | struct xt_hashlimit_htable { | 94 | struct xt_hashlimit_htable { |
@@ -142,9 +145,11 @@ dsthash_find(const struct xt_hashlimit_htable *ht, | |||
142 | u_int32_t hash = hash_dst(ht, dst); | 145 | u_int32_t hash = hash_dst(ht, dst); |
143 | 146 | ||
144 | if (!hlist_empty(&ht->hash[hash])) { | 147 | if (!hlist_empty(&ht->hash[hash])) { |
145 | hlist_for_each_entry(ent, pos, &ht->hash[hash], node) | 148 | hlist_for_each_entry_rcu(ent, pos, &ht->hash[hash], node) |
146 | if (dst_cmp(ent, dst)) | 149 | if (dst_cmp(ent, dst)) { |
150 | spin_lock(&ent->lock); | ||
147 | return ent; | 151 | return ent; |
152 | } | ||
148 | } | 153 | } |
149 | return NULL; | 154 | return NULL; |
150 | } | 155 | } |
@@ -156,9 +161,10 @@ dsthash_alloc_init(struct xt_hashlimit_htable *ht, | |||
156 | { | 161 | { |
157 | struct dsthash_ent *ent; | 162 | struct dsthash_ent *ent; |
158 | 163 | ||
164 | spin_lock(&ht->lock); | ||
159 | /* initialize hash with random val at the time we allocate | 165 | /* initialize hash with random val at the time we allocate |
160 | * the first hashtable entry */ | 166 | * the first hashtable entry */ |
161 | if (!ht->rnd_initialized) { | 167 | if (unlikely(!ht->rnd_initialized)) { |
162 | get_random_bytes(&ht->rnd, sizeof(ht->rnd)); | 168 | get_random_bytes(&ht->rnd, sizeof(ht->rnd)); |
163 | ht->rnd_initialized = true; | 169 | ht->rnd_initialized = true; |
164 | } | 170 | } |
@@ -166,106 +172,40 @@ dsthash_alloc_init(struct xt_hashlimit_htable *ht, | |||
166 | if (ht->cfg.max && ht->count >= ht->cfg.max) { | 172 | if (ht->cfg.max && ht->count >= ht->cfg.max) { |
167 | /* FIXME: do something. question is what.. */ | 173 | /* FIXME: do something. question is what.. */ |
168 | if (net_ratelimit()) | 174 | if (net_ratelimit()) |
169 | printk(KERN_WARNING | 175 | pr_err("max count of %u reached\n", ht->cfg.max); |
170 | "xt_hashlimit: max count of %u reached\n", | 176 | ent = NULL; |
171 | ht->cfg.max); | 177 | } else |
172 | return NULL; | 178 | ent = kmem_cache_alloc(hashlimit_cachep, GFP_ATOMIC); |
173 | } | ||
174 | |||
175 | ent = kmem_cache_alloc(hashlimit_cachep, GFP_ATOMIC); | ||
176 | if (!ent) { | 179 | if (!ent) { |
177 | if (net_ratelimit()) | 180 | if (net_ratelimit()) |
178 | printk(KERN_ERR | 181 | pr_err("cannot allocate dsthash_ent\n"); |
179 | "xt_hashlimit: can't allocate dsthash_ent\n"); | 182 | } else { |
180 | return NULL; | 183 | memcpy(&ent->dst, dst, sizeof(ent->dst)); |
181 | } | 184 | spin_lock_init(&ent->lock); |
182 | memcpy(&ent->dst, dst, sizeof(ent->dst)); | ||
183 | 185 | ||
184 | hlist_add_head(&ent->node, &ht->hash[hash_dst(ht, dst)]); | 186 | spin_lock(&ent->lock); |
185 | ht->count++; | 187 | hlist_add_head_rcu(&ent->node, &ht->hash[hash_dst(ht, dst)]); |
188 | ht->count++; | ||
189 | } | ||
190 | spin_unlock(&ht->lock); | ||
186 | return ent; | 191 | return ent; |
187 | } | 192 | } |
188 | 193 | ||
189 | static inline void | 194 | static void dsthash_free_rcu(struct rcu_head *head) |
190 | dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent) | ||
191 | { | 195 | { |
192 | hlist_del(&ent->node); | 196 | struct dsthash_ent *ent = container_of(head, struct dsthash_ent, rcu); |
197 | |||
193 | kmem_cache_free(hashlimit_cachep, ent); | 198 | kmem_cache_free(hashlimit_cachep, ent); |
194 | ht->count--; | ||
195 | } | 199 | } |
196 | static void htable_gc(unsigned long htlong); | ||
197 | 200 | ||
198 | static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_int8_t family) | 201 | static inline void |
202 | dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent) | ||
199 | { | 203 | { |
200 | struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); | 204 | hlist_del_rcu(&ent->node); |
201 | struct xt_hashlimit_htable *hinfo; | 205 | call_rcu_bh(&ent->rcu, dsthash_free_rcu); |
202 | unsigned int size; | 206 | ht->count--; |
203 | unsigned int i; | ||
204 | |||
205 | if (minfo->cfg.size) | ||
206 | size = minfo->cfg.size; | ||
207 | else { | ||
208 | size = ((totalram_pages << PAGE_SHIFT) / 16384) / | ||
209 | sizeof(struct list_head); | ||
210 | if (totalram_pages > (1024 * 1024 * 1024 / PAGE_SIZE)) | ||
211 | size = 8192; | ||
212 | if (size < 16) | ||
213 | size = 16; | ||
214 | } | ||
215 | /* FIXME: don't use vmalloc() here or anywhere else -HW */ | ||
216 | hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) + | ||
217 | sizeof(struct list_head) * size); | ||
218 | if (!hinfo) { | ||
219 | printk(KERN_ERR "xt_hashlimit: unable to create hashtable\n"); | ||
220 | return -1; | ||
221 | } | ||
222 | minfo->hinfo = hinfo; | ||
223 | |||
224 | /* copy match config into hashtable config */ | ||
225 | hinfo->cfg.mode = minfo->cfg.mode; | ||
226 | hinfo->cfg.avg = minfo->cfg.avg; | ||
227 | hinfo->cfg.burst = minfo->cfg.burst; | ||
228 | hinfo->cfg.max = minfo->cfg.max; | ||
229 | hinfo->cfg.gc_interval = minfo->cfg.gc_interval; | ||
230 | hinfo->cfg.expire = minfo->cfg.expire; | ||
231 | |||
232 | if (family == NFPROTO_IPV4) | ||
233 | hinfo->cfg.srcmask = hinfo->cfg.dstmask = 32; | ||
234 | else | ||
235 | hinfo->cfg.srcmask = hinfo->cfg.dstmask = 128; | ||
236 | |||
237 | hinfo->cfg.size = size; | ||
238 | if (!hinfo->cfg.max) | ||
239 | hinfo->cfg.max = 8 * hinfo->cfg.size; | ||
240 | else if (hinfo->cfg.max < hinfo->cfg.size) | ||
241 | hinfo->cfg.max = hinfo->cfg.size; | ||
242 | |||
243 | for (i = 0; i < hinfo->cfg.size; i++) | ||
244 | INIT_HLIST_HEAD(&hinfo->hash[i]); | ||
245 | |||
246 | hinfo->use = 1; | ||
247 | hinfo->count = 0; | ||
248 | hinfo->family = family; | ||
249 | hinfo->rnd_initialized = false; | ||
250 | spin_lock_init(&hinfo->lock); | ||
251 | hinfo->pde = proc_create_data(minfo->name, 0, | ||
252 | (family == NFPROTO_IPV4) ? | ||
253 | hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit, | ||
254 | &dl_file_ops, hinfo); | ||
255 | if (!hinfo->pde) { | ||
256 | vfree(hinfo); | ||
257 | return -1; | ||
258 | } | ||
259 | hinfo->net = net; | ||
260 | |||
261 | setup_timer(&hinfo->timer, htable_gc, (unsigned long )hinfo); | ||
262 | hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); | ||
263 | add_timer(&hinfo->timer); | ||
264 | |||
265 | hlist_add_head(&hinfo->node, &hashlimit_net->htables); | ||
266 | |||
267 | return 0; | ||
268 | } | 207 | } |
208 | static void htable_gc(unsigned long htlong); | ||
269 | 209 | ||
270 | static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, | 210 | static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, |
271 | u_int8_t family) | 211 | u_int8_t family) |
@@ -288,10 +228,8 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, | |||
288 | /* FIXME: don't use vmalloc() here or anywhere else -HW */ | 228 | /* FIXME: don't use vmalloc() here or anywhere else -HW */ |
289 | hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) + | 229 | hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) + |
290 | sizeof(struct list_head) * size); | 230 | sizeof(struct list_head) * size); |
291 | if (hinfo == NULL) { | 231 | if (hinfo == NULL) |
292 | printk(KERN_ERR "xt_hashlimit: unable to create hashtable\n"); | 232 | return -ENOMEM; |
293 | return -1; | ||
294 | } | ||
295 | minfo->hinfo = hinfo; | 233 | minfo->hinfo = hinfo; |
296 | 234 | ||
297 | /* copy match config into hashtable config */ | 235 | /* copy match config into hashtable config */ |
@@ -317,7 +255,7 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, | |||
317 | &dl_file_ops, hinfo); | 255 | &dl_file_ops, hinfo); |
318 | if (hinfo->pde == NULL) { | 256 | if (hinfo->pde == NULL) { |
319 | vfree(hinfo); | 257 | vfree(hinfo); |
320 | return -1; | 258 | return -ENOMEM; |
321 | } | 259 | } |
322 | hinfo->net = net; | 260 | hinfo->net = net; |
323 | 261 | ||
@@ -578,58 +516,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, | |||
578 | } | 516 | } |
579 | 517 | ||
580 | static bool | 518 | static bool |
581 | hashlimit_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) | 519 | hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) |
582 | { | ||
583 | const struct xt_hashlimit_info *r = par->matchinfo; | ||
584 | struct xt_hashlimit_htable *hinfo = r->hinfo; | ||
585 | unsigned long now = jiffies; | ||
586 | struct dsthash_ent *dh; | ||
587 | struct dsthash_dst dst; | ||
588 | |||
589 | if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0) | ||
590 | goto hotdrop; | ||
591 | |||
592 | spin_lock_bh(&hinfo->lock); | ||
593 | dh = dsthash_find(hinfo, &dst); | ||
594 | if (!dh) { | ||
595 | dh = dsthash_alloc_init(hinfo, &dst); | ||
596 | if (!dh) { | ||
597 | spin_unlock_bh(&hinfo->lock); | ||
598 | goto hotdrop; | ||
599 | } | ||
600 | |||
601 | dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire); | ||
602 | dh->rateinfo.prev = jiffies; | ||
603 | dh->rateinfo.credit = user2credits(hinfo->cfg.avg * | ||
604 | hinfo->cfg.burst); | ||
605 | dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * | ||
606 | hinfo->cfg.burst); | ||
607 | dh->rateinfo.cost = user2credits(hinfo->cfg.avg); | ||
608 | } else { | ||
609 | /* update expiration timeout */ | ||
610 | dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); | ||
611 | rateinfo_recalc(dh, now); | ||
612 | } | ||
613 | |||
614 | if (dh->rateinfo.credit >= dh->rateinfo.cost) { | ||
615 | /* We're underlimit. */ | ||
616 | dh->rateinfo.credit -= dh->rateinfo.cost; | ||
617 | spin_unlock_bh(&hinfo->lock); | ||
618 | return true; | ||
619 | } | ||
620 | |||
621 | spin_unlock_bh(&hinfo->lock); | ||
622 | |||
623 | /* default case: we're overlimit, thus don't match */ | ||
624 | return false; | ||
625 | |||
626 | hotdrop: | ||
627 | *par->hotdrop = true; | ||
628 | return false; | ||
629 | } | ||
630 | |||
631 | static bool | ||
632 | hashlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) | ||
633 | { | 520 | { |
634 | const struct xt_hashlimit_mtinfo1 *info = par->matchinfo; | 521 | const struct xt_hashlimit_mtinfo1 *info = par->matchinfo; |
635 | struct xt_hashlimit_htable *hinfo = info->hinfo; | 522 | struct xt_hashlimit_htable *hinfo = info->hinfo; |
@@ -640,15 +527,14 @@ hashlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
640 | if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0) | 527 | if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0) |
641 | goto hotdrop; | 528 | goto hotdrop; |
642 | 529 | ||
643 | spin_lock_bh(&hinfo->lock); | 530 | rcu_read_lock_bh(); |
644 | dh = dsthash_find(hinfo, &dst); | 531 | dh = dsthash_find(hinfo, &dst); |
645 | if (dh == NULL) { | 532 | if (dh == NULL) { |
646 | dh = dsthash_alloc_init(hinfo, &dst); | 533 | dh = dsthash_alloc_init(hinfo, &dst); |
647 | if (dh == NULL) { | 534 | if (dh == NULL) { |
648 | spin_unlock_bh(&hinfo->lock); | 535 | rcu_read_unlock_bh(); |
649 | goto hotdrop; | 536 | goto hotdrop; |
650 | } | 537 | } |
651 | |||
652 | dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire); | 538 | dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire); |
653 | dh->rateinfo.prev = jiffies; | 539 | dh->rateinfo.prev = jiffies; |
654 | dh->rateinfo.credit = user2credits(hinfo->cfg.avg * | 540 | dh->rateinfo.credit = user2credits(hinfo->cfg.avg * |
@@ -665,96 +551,58 @@ hashlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
665 | if (dh->rateinfo.credit >= dh->rateinfo.cost) { | 551 | if (dh->rateinfo.credit >= dh->rateinfo.cost) { |
666 | /* below the limit */ | 552 | /* below the limit */ |
667 | dh->rateinfo.credit -= dh->rateinfo.cost; | 553 | dh->rateinfo.credit -= dh->rateinfo.cost; |
668 | spin_unlock_bh(&hinfo->lock); | 554 | spin_unlock(&dh->lock); |
555 | rcu_read_unlock_bh(); | ||
669 | return !(info->cfg.mode & XT_HASHLIMIT_INVERT); | 556 | return !(info->cfg.mode & XT_HASHLIMIT_INVERT); |
670 | } | 557 | } |
671 | 558 | ||
672 | spin_unlock_bh(&hinfo->lock); | 559 | spin_unlock(&dh->lock); |
560 | rcu_read_unlock_bh(); | ||
673 | /* default match is underlimit - so over the limit, we need to invert */ | 561 | /* default match is underlimit - so over the limit, we need to invert */ |
674 | return info->cfg.mode & XT_HASHLIMIT_INVERT; | 562 | return info->cfg.mode & XT_HASHLIMIT_INVERT; |
675 | 563 | ||
676 | hotdrop: | 564 | hotdrop: |
677 | *par->hotdrop = true; | 565 | par->hotdrop = true; |
678 | return false; | 566 | return false; |
679 | } | 567 | } |
680 | 568 | ||
681 | static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par) | 569 | static int hashlimit_mt_check(const struct xt_mtchk_param *par) |
682 | { | ||
683 | struct net *net = par->net; | ||
684 | struct xt_hashlimit_info *r = par->matchinfo; | ||
685 | |||
686 | /* Check for overflow. */ | ||
687 | if (r->cfg.burst == 0 || | ||
688 | user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) { | ||
689 | printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n", | ||
690 | r->cfg.avg, r->cfg.burst); | ||
691 | return false; | ||
692 | } | ||
693 | if (r->cfg.mode == 0 || | ||
694 | r->cfg.mode > (XT_HASHLIMIT_HASH_DPT | | ||
695 | XT_HASHLIMIT_HASH_DIP | | ||
696 | XT_HASHLIMIT_HASH_SIP | | ||
697 | XT_HASHLIMIT_HASH_SPT)) | ||
698 | return false; | ||
699 | if (!r->cfg.gc_interval) | ||
700 | return false; | ||
701 | if (!r->cfg.expire) | ||
702 | return false; | ||
703 | if (r->name[sizeof(r->name) - 1] != '\0') | ||
704 | return false; | ||
705 | |||
706 | mutex_lock(&hashlimit_mutex); | ||
707 | r->hinfo = htable_find_get(net, r->name, par->match->family); | ||
708 | if (!r->hinfo && htable_create_v0(net, r, par->match->family) != 0) { | ||
709 | mutex_unlock(&hashlimit_mutex); | ||
710 | return false; | ||
711 | } | ||
712 | mutex_unlock(&hashlimit_mutex); | ||
713 | |||
714 | return true; | ||
715 | } | ||
716 | |||
717 | static bool hashlimit_mt_check(const struct xt_mtchk_param *par) | ||
718 | { | 570 | { |
719 | struct net *net = par->net; | 571 | struct net *net = par->net; |
720 | struct xt_hashlimit_mtinfo1 *info = par->matchinfo; | 572 | struct xt_hashlimit_mtinfo1 *info = par->matchinfo; |
573 | int ret; | ||
721 | 574 | ||
722 | /* Check for overflow. */ | 575 | /* Check for overflow. */ |
723 | if (info->cfg.burst == 0 || | 576 | if (info->cfg.burst == 0 || |
724 | user2credits(info->cfg.avg * info->cfg.burst) < | 577 | user2credits(info->cfg.avg * info->cfg.burst) < |
725 | user2credits(info->cfg.avg)) { | 578 | user2credits(info->cfg.avg)) { |
726 | printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n", | 579 | pr_info("overflow, try lower: %u/%u\n", |
727 | info->cfg.avg, info->cfg.burst); | 580 | info->cfg.avg, info->cfg.burst); |
728 | return false; | 581 | return -ERANGE; |
729 | } | 582 | } |
730 | if (info->cfg.gc_interval == 0 || info->cfg.expire == 0) | 583 | if (info->cfg.gc_interval == 0 || info->cfg.expire == 0) |
731 | return false; | 584 | return -EINVAL; |
732 | if (info->name[sizeof(info->name)-1] != '\0') | 585 | if (info->name[sizeof(info->name)-1] != '\0') |
733 | return false; | 586 | return -EINVAL; |
734 | if (par->match->family == NFPROTO_IPV4) { | 587 | if (par->family == NFPROTO_IPV4) { |
735 | if (info->cfg.srcmask > 32 || info->cfg.dstmask > 32) | 588 | if (info->cfg.srcmask > 32 || info->cfg.dstmask > 32) |
736 | return false; | 589 | return -EINVAL; |
737 | } else { | 590 | } else { |
738 | if (info->cfg.srcmask > 128 || info->cfg.dstmask > 128) | 591 | if (info->cfg.srcmask > 128 || info->cfg.dstmask > 128) |
739 | return false; | 592 | return -EINVAL; |
740 | } | 593 | } |
741 | 594 | ||
742 | mutex_lock(&hashlimit_mutex); | 595 | mutex_lock(&hashlimit_mutex); |
743 | info->hinfo = htable_find_get(net, info->name, par->match->family); | 596 | info->hinfo = htable_find_get(net, info->name, par->family); |
744 | if (!info->hinfo && htable_create(net, info, par->match->family) != 0) { | 597 | if (info->hinfo == NULL) { |
745 | mutex_unlock(&hashlimit_mutex); | 598 | ret = htable_create(net, info, par->family); |
746 | return false; | 599 | if (ret < 0) { |
600 | mutex_unlock(&hashlimit_mutex); | ||
601 | return ret; | ||
602 | } | ||
747 | } | 603 | } |
748 | mutex_unlock(&hashlimit_mutex); | 604 | mutex_unlock(&hashlimit_mutex); |
749 | return true; | 605 | return 0; |
750 | } | ||
751 | |||
752 | static void | ||
753 | hashlimit_mt_destroy_v0(const struct xt_mtdtor_param *par) | ||
754 | { | ||
755 | const struct xt_hashlimit_info *r = par->matchinfo; | ||
756 | |||
757 | htable_put(r->hinfo); | ||
758 | } | 606 | } |
759 | 607 | ||
760 | static void hashlimit_mt_destroy(const struct xt_mtdtor_param *par) | 608 | static void hashlimit_mt_destroy(const struct xt_mtdtor_param *par) |
@@ -764,47 +612,8 @@ static void hashlimit_mt_destroy(const struct xt_mtdtor_param *par) | |||
764 | htable_put(info->hinfo); | 612 | htable_put(info->hinfo); |
765 | } | 613 | } |
766 | 614 | ||
767 | #ifdef CONFIG_COMPAT | ||
768 | struct compat_xt_hashlimit_info { | ||
769 | char name[IFNAMSIZ]; | ||
770 | struct hashlimit_cfg cfg; | ||
771 | compat_uptr_t hinfo; | ||
772 | compat_uptr_t master; | ||
773 | }; | ||
774 | |||
775 | static void hashlimit_mt_compat_from_user(void *dst, const void *src) | ||
776 | { | ||
777 | int off = offsetof(struct compat_xt_hashlimit_info, hinfo); | ||
778 | |||
779 | memcpy(dst, src, off); | ||
780 | memset(dst + off, 0, sizeof(struct compat_xt_hashlimit_info) - off); | ||
781 | } | ||
782 | |||
783 | static int hashlimit_mt_compat_to_user(void __user *dst, const void *src) | ||
784 | { | ||
785 | int off = offsetof(struct compat_xt_hashlimit_info, hinfo); | ||
786 | |||
787 | return copy_to_user(dst, src, off) ? -EFAULT : 0; | ||
788 | } | ||
789 | #endif | ||
790 | |||
791 | static struct xt_match hashlimit_mt_reg[] __read_mostly = { | 615 | static struct xt_match hashlimit_mt_reg[] __read_mostly = { |
792 | { | 616 | { |
793 | .name = "hashlimit", | ||
794 | .revision = 0, | ||
795 | .family = NFPROTO_IPV4, | ||
796 | .match = hashlimit_mt_v0, | ||
797 | .matchsize = sizeof(struct xt_hashlimit_info), | ||
798 | #ifdef CONFIG_COMPAT | ||
799 | .compatsize = sizeof(struct compat_xt_hashlimit_info), | ||
800 | .compat_from_user = hashlimit_mt_compat_from_user, | ||
801 | .compat_to_user = hashlimit_mt_compat_to_user, | ||
802 | #endif | ||
803 | .checkentry = hashlimit_mt_check_v0, | ||
804 | .destroy = hashlimit_mt_destroy_v0, | ||
805 | .me = THIS_MODULE | ||
806 | }, | ||
807 | { | ||
808 | .name = "hashlimit", | 617 | .name = "hashlimit", |
809 | .revision = 1, | 618 | .revision = 1, |
810 | .family = NFPROTO_IPV4, | 619 | .family = NFPROTO_IPV4, |
@@ -816,20 +625,6 @@ static struct xt_match hashlimit_mt_reg[] __read_mostly = { | |||
816 | }, | 625 | }, |
817 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 626 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
818 | { | 627 | { |
819 | .name = "hashlimit", | ||
820 | .family = NFPROTO_IPV6, | ||
821 | .match = hashlimit_mt_v0, | ||
822 | .matchsize = sizeof(struct xt_hashlimit_info), | ||
823 | #ifdef CONFIG_COMPAT | ||
824 | .compatsize = sizeof(struct compat_xt_hashlimit_info), | ||
825 | .compat_from_user = hashlimit_mt_compat_from_user, | ||
826 | .compat_to_user = hashlimit_mt_compat_to_user, | ||
827 | #endif | ||
828 | .checkentry = hashlimit_mt_check_v0, | ||
829 | .destroy = hashlimit_mt_destroy_v0, | ||
830 | .me = THIS_MODULE | ||
831 | }, | ||
832 | { | ||
833 | .name = "hashlimit", | 628 | .name = "hashlimit", |
834 | .revision = 1, | 629 | .revision = 1, |
835 | .family = NFPROTO_IPV6, | 630 | .family = NFPROTO_IPV6, |
@@ -888,12 +683,15 @@ static void dl_seq_stop(struct seq_file *s, void *v) | |||
888 | static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family, | 683 | static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family, |
889 | struct seq_file *s) | 684 | struct seq_file *s) |
890 | { | 685 | { |
686 | int res; | ||
687 | |||
688 | spin_lock(&ent->lock); | ||
891 | /* recalculate to show accurate numbers */ | 689 | /* recalculate to show accurate numbers */ |
892 | rateinfo_recalc(ent, jiffies); | 690 | rateinfo_recalc(ent, jiffies); |
893 | 691 | ||
894 | switch (family) { | 692 | switch (family) { |
895 | case NFPROTO_IPV4: | 693 | case NFPROTO_IPV4: |
896 | return seq_printf(s, "%ld %pI4:%u->%pI4:%u %u %u %u\n", | 694 | res = seq_printf(s, "%ld %pI4:%u->%pI4:%u %u %u %u\n", |
897 | (long)(ent->expires - jiffies)/HZ, | 695 | (long)(ent->expires - jiffies)/HZ, |
898 | &ent->dst.ip.src, | 696 | &ent->dst.ip.src, |
899 | ntohs(ent->dst.src_port), | 697 | ntohs(ent->dst.src_port), |
@@ -901,9 +699,10 @@ static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family, | |||
901 | ntohs(ent->dst.dst_port), | 699 | ntohs(ent->dst.dst_port), |
902 | ent->rateinfo.credit, ent->rateinfo.credit_cap, | 700 | ent->rateinfo.credit, ent->rateinfo.credit_cap, |
903 | ent->rateinfo.cost); | 701 | ent->rateinfo.cost); |
702 | break; | ||
904 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 703 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
905 | case NFPROTO_IPV6: | 704 | case NFPROTO_IPV6: |
906 | return seq_printf(s, "%ld %pI6:%u->%pI6:%u %u %u %u\n", | 705 | res = seq_printf(s, "%ld %pI6:%u->%pI6:%u %u %u %u\n", |
907 | (long)(ent->expires - jiffies)/HZ, | 706 | (long)(ent->expires - jiffies)/HZ, |
908 | &ent->dst.ip6.src, | 707 | &ent->dst.ip6.src, |
909 | ntohs(ent->dst.src_port), | 708 | ntohs(ent->dst.src_port), |
@@ -911,11 +710,14 @@ static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family, | |||
911 | ntohs(ent->dst.dst_port), | 710 | ntohs(ent->dst.dst_port), |
912 | ent->rateinfo.credit, ent->rateinfo.credit_cap, | 711 | ent->rateinfo.credit, ent->rateinfo.credit_cap, |
913 | ent->rateinfo.cost); | 712 | ent->rateinfo.cost); |
713 | break; | ||
914 | #endif | 714 | #endif |
915 | default: | 715 | default: |
916 | BUG(); | 716 | BUG(); |
917 | return 0; | 717 | res = 0; |
918 | } | 718 | } |
719 | spin_unlock(&ent->lock); | ||
720 | return res; | ||
919 | } | 721 | } |
920 | 722 | ||
921 | static int dl_seq_show(struct seq_file *s, void *v) | 723 | static int dl_seq_show(struct seq_file *s, void *v) |
@@ -1024,7 +826,7 @@ static int __init hashlimit_mt_init(void) | |||
1024 | sizeof(struct dsthash_ent), 0, 0, | 826 | sizeof(struct dsthash_ent), 0, 0, |
1025 | NULL); | 827 | NULL); |
1026 | if (!hashlimit_cachep) { | 828 | if (!hashlimit_cachep) { |
1027 | printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n"); | 829 | pr_warning("unable to create slab cache\n"); |
1028 | goto err2; | 830 | goto err2; |
1029 | } | 831 | } |
1030 | return 0; | 832 | return 0; |
@@ -1039,9 +841,11 @@ err1: | |||
1039 | 841 | ||
1040 | static void __exit hashlimit_mt_exit(void) | 842 | static void __exit hashlimit_mt_exit(void) |
1041 | { | 843 | { |
1042 | kmem_cache_destroy(hashlimit_cachep); | ||
1043 | xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg)); | 844 | xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg)); |
1044 | unregister_pernet_subsys(&hashlimit_net_ops); | 845 | unregister_pernet_subsys(&hashlimit_net_ops); |
846 | |||
847 | rcu_barrier_bh(); | ||
848 | kmem_cache_destroy(hashlimit_cachep); | ||
1045 | } | 849 | } |
1046 | 850 | ||
1047 | module_init(hashlimit_mt_init); | 851 | module_init(hashlimit_mt_init); |
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c index 64fc7f277221..9f4ab00c8050 100644 --- a/net/netfilter/xt_helper.c +++ b/net/netfilter/xt_helper.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/netfilter.h> | 12 | #include <linux/netfilter.h> |
@@ -24,7 +24,7 @@ MODULE_ALIAS("ip6t_helper"); | |||
24 | 24 | ||
25 | 25 | ||
26 | static bool | 26 | static bool |
27 | helper_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 27 | helper_mt(const struct sk_buff *skb, struct xt_action_param *par) |
28 | { | 28 | { |
29 | const struct xt_helper_info *info = par->matchinfo; | 29 | const struct xt_helper_info *info = par->matchinfo; |
30 | const struct nf_conn *ct; | 30 | const struct nf_conn *ct; |
@@ -54,17 +54,19 @@ helper_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
54 | return ret; | 54 | return ret; |
55 | } | 55 | } |
56 | 56 | ||
57 | static bool helper_mt_check(const struct xt_mtchk_param *par) | 57 | static int helper_mt_check(const struct xt_mtchk_param *par) |
58 | { | 58 | { |
59 | struct xt_helper_info *info = par->matchinfo; | 59 | struct xt_helper_info *info = par->matchinfo; |
60 | int ret; | ||
60 | 61 | ||
61 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { | 62 | ret = nf_ct_l3proto_try_module_get(par->family); |
62 | printk(KERN_WARNING "can't load conntrack support for " | 63 | if (ret < 0) { |
63 | "proto=%u\n", par->family); | 64 | pr_info("cannot load conntrack support for proto=%u\n", |
64 | return false; | 65 | par->family); |
66 | return ret; | ||
65 | } | 67 | } |
66 | info->name[29] = '\0'; | 68 | info->name[29] = '\0'; |
67 | return true; | 69 | return 0; |
68 | } | 70 | } |
69 | 71 | ||
70 | static void helper_mt_destroy(const struct xt_mtdtor_param *par) | 72 | static void helper_mt_destroy(const struct xt_mtdtor_param *par) |
diff --git a/net/netfilter/xt_hl.c b/net/netfilter/xt_hl.c index 7726154c87b2..7d12221ead89 100644 --- a/net/netfilter/xt_hl.c +++ b/net/netfilter/xt_hl.c | |||
@@ -25,7 +25,7 @@ MODULE_LICENSE("GPL"); | |||
25 | MODULE_ALIAS("ipt_ttl"); | 25 | MODULE_ALIAS("ipt_ttl"); |
26 | MODULE_ALIAS("ip6t_hl"); | 26 | MODULE_ALIAS("ip6t_hl"); |
27 | 27 | ||
28 | static bool ttl_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 28 | static bool ttl_mt(const struct sk_buff *skb, struct xt_action_param *par) |
29 | { | 29 | { |
30 | const struct ipt_ttl_info *info = par->matchinfo; | 30 | const struct ipt_ttl_info *info = par->matchinfo; |
31 | const u8 ttl = ip_hdr(skb)->ttl; | 31 | const u8 ttl = ip_hdr(skb)->ttl; |
@@ -39,16 +39,12 @@ static bool ttl_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
39 | return ttl < info->ttl; | 39 | return ttl < info->ttl; |
40 | case IPT_TTL_GT: | 40 | case IPT_TTL_GT: |
41 | return ttl > info->ttl; | 41 | return ttl > info->ttl; |
42 | default: | ||
43 | printk(KERN_WARNING "ipt_ttl: unknown mode %d\n", | ||
44 | info->mode); | ||
45 | return false; | ||
46 | } | 42 | } |
47 | 43 | ||
48 | return false; | 44 | return false; |
49 | } | 45 | } |
50 | 46 | ||
51 | static bool hl_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 47 | static bool hl_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
52 | { | 48 | { |
53 | const struct ip6t_hl_info *info = par->matchinfo; | 49 | const struct ip6t_hl_info *info = par->matchinfo; |
54 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | 50 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
@@ -56,20 +52,12 @@ static bool hl_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
56 | switch (info->mode) { | 52 | switch (info->mode) { |
57 | case IP6T_HL_EQ: | 53 | case IP6T_HL_EQ: |
58 | return ip6h->hop_limit == info->hop_limit; | 54 | return ip6h->hop_limit == info->hop_limit; |
59 | break; | ||
60 | case IP6T_HL_NE: | 55 | case IP6T_HL_NE: |
61 | return ip6h->hop_limit != info->hop_limit; | 56 | return ip6h->hop_limit != info->hop_limit; |
62 | break; | ||
63 | case IP6T_HL_LT: | 57 | case IP6T_HL_LT: |
64 | return ip6h->hop_limit < info->hop_limit; | 58 | return ip6h->hop_limit < info->hop_limit; |
65 | break; | ||
66 | case IP6T_HL_GT: | 59 | case IP6T_HL_GT: |
67 | return ip6h->hop_limit > info->hop_limit; | 60 | return ip6h->hop_limit > info->hop_limit; |
68 | break; | ||
69 | default: | ||
70 | printk(KERN_WARNING "ip6t_hl: unknown mode %d\n", | ||
71 | info->mode); | ||
72 | return false; | ||
73 | } | 61 | } |
74 | 62 | ||
75 | return false; | 63 | return false; |
diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c index ffc96387d556..88f7c3511c72 100644 --- a/net/netfilter/xt_iprange.c +++ b/net/netfilter/xt_iprange.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
11 | #include <linux/module.h> | 12 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 13 | #include <linux/skbuff.h> |
13 | #include <linux/ip.h> | 14 | #include <linux/ip.h> |
@@ -16,7 +17,7 @@ | |||
16 | #include <linux/netfilter/xt_iprange.h> | 17 | #include <linux/netfilter/xt_iprange.h> |
17 | 18 | ||
18 | static bool | 19 | static bool |
19 | iprange_mt4(const struct sk_buff *skb, const struct xt_match_param *par) | 20 | iprange_mt4(const struct sk_buff *skb, struct xt_action_param *par) |
20 | { | 21 | { |
21 | const struct xt_iprange_mtinfo *info = par->matchinfo; | 22 | const struct xt_iprange_mtinfo *info = par->matchinfo; |
22 | const struct iphdr *iph = ip_hdr(skb); | 23 | const struct iphdr *iph = ip_hdr(skb); |
@@ -67,7 +68,7 @@ iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b) | |||
67 | } | 68 | } |
68 | 69 | ||
69 | static bool | 70 | static bool |
70 | iprange_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 71 | iprange_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
71 | { | 72 | { |
72 | const struct xt_iprange_mtinfo *info = par->matchinfo; | 73 | const struct xt_iprange_mtinfo *info = par->matchinfo; |
73 | const struct ipv6hdr *iph = ipv6_hdr(skb); | 74 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c index c4871ca6c86d..176e5570a999 100644 --- a/net/netfilter/xt_length.c +++ b/net/netfilter/xt_length.c | |||
@@ -21,7 +21,7 @@ MODULE_ALIAS("ipt_length"); | |||
21 | MODULE_ALIAS("ip6t_length"); | 21 | MODULE_ALIAS("ip6t_length"); |
22 | 22 | ||
23 | static bool | 23 | static bool |
24 | length_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 24 | length_mt(const struct sk_buff *skb, struct xt_action_param *par) |
25 | { | 25 | { |
26 | const struct xt_length_info *info = par->matchinfo; | 26 | const struct xt_length_info *info = par->matchinfo; |
27 | u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len); | 27 | u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len); |
@@ -30,7 +30,7 @@ length_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
30 | } | 30 | } |
31 | 31 | ||
32 | static bool | 32 | static bool |
33 | length_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 33 | length_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
34 | { | 34 | { |
35 | const struct xt_length_info *info = par->matchinfo; | 35 | const struct xt_length_info *info = par->matchinfo; |
36 | const u_int16_t pktlen = ntohs(ipv6_hdr(skb)->payload_len) + | 36 | const u_int16_t pktlen = ntohs(ipv6_hdr(skb)->payload_len) + |
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index e5d7e1ffb1a4..32b7a579a032 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
8 | 9 | ||
9 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
10 | #include <linux/module.h> | 11 | #include <linux/module.h> |
@@ -64,7 +65,7 @@ static DEFINE_SPINLOCK(limit_lock); | |||
64 | #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) | 65 | #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) |
65 | 66 | ||
66 | static bool | 67 | static bool |
67 | limit_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 68 | limit_mt(const struct sk_buff *skb, struct xt_action_param *par) |
68 | { | 69 | { |
69 | const struct xt_rateinfo *r = par->matchinfo; | 70 | const struct xt_rateinfo *r = par->matchinfo; |
70 | struct xt_limit_priv *priv = r->master; | 71 | struct xt_limit_priv *priv = r->master; |
@@ -98,7 +99,7 @@ user2credits(u_int32_t user) | |||
98 | return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE; | 99 | return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE; |
99 | } | 100 | } |
100 | 101 | ||
101 | static bool limit_mt_check(const struct xt_mtchk_param *par) | 102 | static int limit_mt_check(const struct xt_mtchk_param *par) |
102 | { | 103 | { |
103 | struct xt_rateinfo *r = par->matchinfo; | 104 | struct xt_rateinfo *r = par->matchinfo; |
104 | struct xt_limit_priv *priv; | 105 | struct xt_limit_priv *priv; |
@@ -106,14 +107,14 @@ static bool limit_mt_check(const struct xt_mtchk_param *par) | |||
106 | /* Check for overflow. */ | 107 | /* Check for overflow. */ |
107 | if (r->burst == 0 | 108 | if (r->burst == 0 |
108 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { | 109 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { |
109 | printk("Overflow in xt_limit, try lower: %u/%u\n", | 110 | pr_info("Overflow, try lower: %u/%u\n", |
110 | r->avg, r->burst); | 111 | r->avg, r->burst); |
111 | return false; | 112 | return -ERANGE; |
112 | } | 113 | } |
113 | 114 | ||
114 | priv = kmalloc(sizeof(*priv), GFP_KERNEL); | 115 | priv = kmalloc(sizeof(*priv), GFP_KERNEL); |
115 | if (priv == NULL) | 116 | if (priv == NULL) |
116 | return false; | 117 | return -ENOMEM; |
117 | 118 | ||
118 | /* For SMP, we only want to use one set of state. */ | 119 | /* For SMP, we only want to use one set of state. */ |
119 | r->master = priv; | 120 | r->master = priv; |
@@ -125,7 +126,7 @@ static bool limit_mt_check(const struct xt_mtchk_param *par) | |||
125 | r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ | 126 | r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ |
126 | r->cost = user2credits(r->avg); | 127 | r->cost = user2credits(r->avg); |
127 | } | 128 | } |
128 | return true; | 129 | return 0; |
129 | } | 130 | } |
130 | 131 | ||
131 | static void limit_mt_destroy(const struct xt_mtdtor_param *par) | 132 | static void limit_mt_destroy(const struct xt_mtdtor_param *par) |
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c index c2007116ce5b..8160f6b1435d 100644 --- a/net/netfilter/xt_mac.c +++ b/net/netfilter/xt_mac.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <linux/if_arp.h> | ||
13 | #include <linux/if_ether.h> | 14 | #include <linux/if_ether.h> |
14 | #include <linux/etherdevice.h> | 15 | #include <linux/etherdevice.h> |
15 | 16 | ||
@@ -24,16 +25,20 @@ MODULE_DESCRIPTION("Xtables: MAC address match"); | |||
24 | MODULE_ALIAS("ipt_mac"); | 25 | MODULE_ALIAS("ipt_mac"); |
25 | MODULE_ALIAS("ip6t_mac"); | 26 | MODULE_ALIAS("ip6t_mac"); |
26 | 27 | ||
27 | static bool mac_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 28 | static bool mac_mt(const struct sk_buff *skb, struct xt_action_param *par) |
28 | { | 29 | { |
29 | const struct xt_mac_info *info = par->matchinfo; | 30 | const struct xt_mac_info *info = par->matchinfo; |
30 | 31 | bool ret; | |
31 | /* Is mac pointer valid? */ | 32 | |
32 | return skb_mac_header(skb) >= skb->head && | 33 | if (skb->dev == NULL || skb->dev->type != ARPHRD_ETHER) |
33 | skb_mac_header(skb) + ETH_HLEN <= skb->data | 34 | return false; |
34 | /* If so, compare... */ | 35 | if (skb_mac_header(skb) < skb->head) |
35 | && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr)) | 36 | return false; |
36 | ^ info->invert); | 37 | if (skb_mac_header(skb) + ETH_HLEN > skb->data) |
38 | return false; | ||
39 | ret = compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr) == 0; | ||
40 | ret ^= info->invert; | ||
41 | return ret; | ||
37 | } | 42 | } |
38 | 43 | ||
39 | static struct xt_match mac_mt_reg __read_mostly = { | 44 | static struct xt_match mac_mt_reg __read_mostly = { |
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c index 1db07d8125f8..23345238711b 100644 --- a/net/netfilter/xt_mark.c +++ b/net/netfilter/xt_mark.c | |||
@@ -18,18 +18,38 @@ | |||
18 | 18 | ||
19 | MODULE_LICENSE("GPL"); | 19 | MODULE_LICENSE("GPL"); |
20 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 20 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
21 | MODULE_DESCRIPTION("Xtables: packet mark match"); | 21 | MODULE_DESCRIPTION("Xtables: packet mark operations"); |
22 | MODULE_ALIAS("ipt_mark"); | 22 | MODULE_ALIAS("ipt_mark"); |
23 | MODULE_ALIAS("ip6t_mark"); | 23 | MODULE_ALIAS("ip6t_mark"); |
24 | MODULE_ALIAS("ipt_MARK"); | ||
25 | MODULE_ALIAS("ip6t_MARK"); | ||
26 | |||
27 | static unsigned int | ||
28 | mark_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
29 | { | ||
30 | const struct xt_mark_tginfo2 *info = par->targinfo; | ||
31 | |||
32 | skb->mark = (skb->mark & ~info->mask) ^ info->mark; | ||
33 | return XT_CONTINUE; | ||
34 | } | ||
24 | 35 | ||
25 | static bool | 36 | static bool |
26 | mark_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 37 | mark_mt(const struct sk_buff *skb, struct xt_action_param *par) |
27 | { | 38 | { |
28 | const struct xt_mark_mtinfo1 *info = par->matchinfo; | 39 | const struct xt_mark_mtinfo1 *info = par->matchinfo; |
29 | 40 | ||
30 | return ((skb->mark & info->mask) == info->mark) ^ info->invert; | 41 | return ((skb->mark & info->mask) == info->mark) ^ info->invert; |
31 | } | 42 | } |
32 | 43 | ||
44 | static struct xt_target mark_tg_reg __read_mostly = { | ||
45 | .name = "MARK", | ||
46 | .revision = 2, | ||
47 | .family = NFPROTO_UNSPEC, | ||
48 | .target = mark_tg, | ||
49 | .targetsize = sizeof(struct xt_mark_tginfo2), | ||
50 | .me = THIS_MODULE, | ||
51 | }; | ||
52 | |||
33 | static struct xt_match mark_mt_reg __read_mostly = { | 53 | static struct xt_match mark_mt_reg __read_mostly = { |
34 | .name = "mark", | 54 | .name = "mark", |
35 | .revision = 1, | 55 | .revision = 1, |
@@ -41,12 +61,23 @@ static struct xt_match mark_mt_reg __read_mostly = { | |||
41 | 61 | ||
42 | static int __init mark_mt_init(void) | 62 | static int __init mark_mt_init(void) |
43 | { | 63 | { |
44 | return xt_register_match(&mark_mt_reg); | 64 | int ret; |
65 | |||
66 | ret = xt_register_target(&mark_tg_reg); | ||
67 | if (ret < 0) | ||
68 | return ret; | ||
69 | ret = xt_register_match(&mark_mt_reg); | ||
70 | if (ret < 0) { | ||
71 | xt_unregister_target(&mark_tg_reg); | ||
72 | return ret; | ||
73 | } | ||
74 | return 0; | ||
45 | } | 75 | } |
46 | 76 | ||
47 | static void __exit mark_mt_exit(void) | 77 | static void __exit mark_mt_exit(void) |
48 | { | 78 | { |
49 | xt_unregister_match(&mark_mt_reg); | 79 | xt_unregister_match(&mark_mt_reg); |
80 | xt_unregister_target(&mark_tg_reg); | ||
50 | } | 81 | } |
51 | 82 | ||
52 | module_init(mark_mt_init); | 83 | module_init(mark_mt_init); |
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c index d06bb2dd3900..ac1d3c3d09e7 100644 --- a/net/netfilter/xt_multiport.c +++ b/net/netfilter/xt_multiport.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/udp.h> | 14 | #include <linux/udp.h> |
@@ -26,29 +26,6 @@ MODULE_DESCRIPTION("Xtables: multiple port matching for TCP, UDP, UDP-Lite, SCTP | |||
26 | MODULE_ALIAS("ipt_multiport"); | 26 | MODULE_ALIAS("ipt_multiport"); |
27 | MODULE_ALIAS("ip6t_multiport"); | 27 | MODULE_ALIAS("ip6t_multiport"); |
28 | 28 | ||
29 | #if 0 | ||
30 | #define duprintf(format, args...) printk(format , ## args) | ||
31 | #else | ||
32 | #define duprintf(format, args...) | ||
33 | #endif | ||
34 | |||
35 | /* Returns 1 if the port is matched by the test, 0 otherwise. */ | ||
36 | static inline bool | ||
37 | ports_match_v0(const u_int16_t *portlist, enum xt_multiport_flags flags, | ||
38 | u_int8_t count, u_int16_t src, u_int16_t dst) | ||
39 | { | ||
40 | unsigned int i; | ||
41 | for (i = 0; i < count; i++) { | ||
42 | if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src) | ||
43 | return true; | ||
44 | |||
45 | if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst) | ||
46 | return true; | ||
47 | } | ||
48 | |||
49 | return false; | ||
50 | } | ||
51 | |||
52 | /* Returns 1 if the port is matched by the test, 0 otherwise. */ | 29 | /* Returns 1 if the port is matched by the test, 0 otherwise. */ |
53 | static inline bool | 30 | static inline bool |
54 | ports_match_v1(const struct xt_multiport_v1 *minfo, | 31 | ports_match_v1(const struct xt_multiport_v1 *minfo, |
@@ -63,7 +40,7 @@ ports_match_v1(const struct xt_multiport_v1 *minfo, | |||
63 | if (minfo->pflags[i]) { | 40 | if (minfo->pflags[i]) { |
64 | /* range port matching */ | 41 | /* range port matching */ |
65 | e = minfo->ports[++i]; | 42 | e = minfo->ports[++i]; |
66 | duprintf("src or dst matches with %d-%d?\n", s, e); | 43 | pr_debug("src or dst matches with %d-%d?\n", s, e); |
67 | 44 | ||
68 | if (minfo->flags == XT_MULTIPORT_SOURCE | 45 | if (minfo->flags == XT_MULTIPORT_SOURCE |
69 | && src >= s && src <= e) | 46 | && src >= s && src <= e) |
@@ -77,7 +54,7 @@ ports_match_v1(const struct xt_multiport_v1 *minfo, | |||
77 | return true ^ minfo->invert; | 54 | return true ^ minfo->invert; |
78 | } else { | 55 | } else { |
79 | /* exact port matching */ | 56 | /* exact port matching */ |
80 | duprintf("src or dst matches with %d?\n", s); | 57 | pr_debug("src or dst matches with %d?\n", s); |
81 | 58 | ||
82 | if (minfo->flags == XT_MULTIPORT_SOURCE | 59 | if (minfo->flags == XT_MULTIPORT_SOURCE |
83 | && src == s) | 60 | && src == s) |
@@ -95,31 +72,7 @@ ports_match_v1(const struct xt_multiport_v1 *minfo, | |||
95 | } | 72 | } |
96 | 73 | ||
97 | static bool | 74 | static bool |
98 | multiport_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) | 75 | multiport_mt(const struct sk_buff *skb, struct xt_action_param *par) |
99 | { | ||
100 | const __be16 *pptr; | ||
101 | __be16 _ports[2]; | ||
102 | const struct xt_multiport *multiinfo = par->matchinfo; | ||
103 | |||
104 | if (par->fragoff != 0) | ||
105 | return false; | ||
106 | |||
107 | pptr = skb_header_pointer(skb, par->thoff, sizeof(_ports), _ports); | ||
108 | if (pptr == NULL) { | ||
109 | /* We've been asked to examine this packet, and we | ||
110 | * can't. Hence, no choice but to drop. | ||
111 | */ | ||
112 | duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); | ||
113 | *par->hotdrop = true; | ||
114 | return false; | ||
115 | } | ||
116 | |||
117 | return ports_match_v0(multiinfo->ports, multiinfo->flags, | ||
118 | multiinfo->count, ntohs(pptr[0]), ntohs(pptr[1])); | ||
119 | } | ||
120 | |||
121 | static bool | ||
122 | multiport_mt(const struct sk_buff *skb, const struct xt_match_param *par) | ||
123 | { | 76 | { |
124 | const __be16 *pptr; | 77 | const __be16 *pptr; |
125 | __be16 _ports[2]; | 78 | __be16 _ports[2]; |
@@ -133,8 +86,8 @@ multiport_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
133 | /* We've been asked to examine this packet, and we | 86 | /* We've been asked to examine this packet, and we |
134 | * can't. Hence, no choice but to drop. | 87 | * can't. Hence, no choice but to drop. |
135 | */ | 88 | */ |
136 | duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); | 89 | pr_debug("Dropping evil offset=0 tinygram.\n"); |
137 | *par->hotdrop = true; | 90 | par->hotdrop = true; |
138 | return false; | 91 | return false; |
139 | } | 92 | } |
140 | 93 | ||
@@ -158,55 +111,28 @@ check(u_int16_t proto, | |||
158 | && count <= XT_MULTI_PORTS; | 111 | && count <= XT_MULTI_PORTS; |
159 | } | 112 | } |
160 | 113 | ||
161 | static bool multiport_mt_check_v0(const struct xt_mtchk_param *par) | 114 | static int multiport_mt_check(const struct xt_mtchk_param *par) |
162 | { | ||
163 | const struct ipt_ip *ip = par->entryinfo; | ||
164 | const struct xt_multiport *multiinfo = par->matchinfo; | ||
165 | |||
166 | return check(ip->proto, ip->invflags, multiinfo->flags, | ||
167 | multiinfo->count); | ||
168 | } | ||
169 | |||
170 | static bool multiport_mt_check(const struct xt_mtchk_param *par) | ||
171 | { | 115 | { |
172 | const struct ipt_ip *ip = par->entryinfo; | 116 | const struct ipt_ip *ip = par->entryinfo; |
173 | const struct xt_multiport_v1 *multiinfo = par->matchinfo; | 117 | const struct xt_multiport_v1 *multiinfo = par->matchinfo; |
174 | 118 | ||
175 | return check(ip->proto, ip->invflags, multiinfo->flags, | 119 | return check(ip->proto, ip->invflags, multiinfo->flags, |
176 | multiinfo->count); | 120 | multiinfo->count) ? 0 : -EINVAL; |
177 | } | 121 | } |
178 | 122 | ||
179 | static bool multiport_mt6_check_v0(const struct xt_mtchk_param *par) | 123 | static int multiport_mt6_check(const struct xt_mtchk_param *par) |
180 | { | ||
181 | const struct ip6t_ip6 *ip = par->entryinfo; | ||
182 | const struct xt_multiport *multiinfo = par->matchinfo; | ||
183 | |||
184 | return check(ip->proto, ip->invflags, multiinfo->flags, | ||
185 | multiinfo->count); | ||
186 | } | ||
187 | |||
188 | static bool multiport_mt6_check(const struct xt_mtchk_param *par) | ||
189 | { | 124 | { |
190 | const struct ip6t_ip6 *ip = par->entryinfo; | 125 | const struct ip6t_ip6 *ip = par->entryinfo; |
191 | const struct xt_multiport_v1 *multiinfo = par->matchinfo; | 126 | const struct xt_multiport_v1 *multiinfo = par->matchinfo; |
192 | 127 | ||
193 | return check(ip->proto, ip->invflags, multiinfo->flags, | 128 | return check(ip->proto, ip->invflags, multiinfo->flags, |
194 | multiinfo->count); | 129 | multiinfo->count) ? 0 : -EINVAL; |
195 | } | 130 | } |
196 | 131 | ||
197 | static struct xt_match multiport_mt_reg[] __read_mostly = { | 132 | static struct xt_match multiport_mt_reg[] __read_mostly = { |
198 | { | 133 | { |
199 | .name = "multiport", | 134 | .name = "multiport", |
200 | .family = NFPROTO_IPV4, | 135 | .family = NFPROTO_IPV4, |
201 | .revision = 0, | ||
202 | .checkentry = multiport_mt_check_v0, | ||
203 | .match = multiport_mt_v0, | ||
204 | .matchsize = sizeof(struct xt_multiport), | ||
205 | .me = THIS_MODULE, | ||
206 | }, | ||
207 | { | ||
208 | .name = "multiport", | ||
209 | .family = NFPROTO_IPV4, | ||
210 | .revision = 1, | 136 | .revision = 1, |
211 | .checkentry = multiport_mt_check, | 137 | .checkentry = multiport_mt_check, |
212 | .match = multiport_mt, | 138 | .match = multiport_mt, |
@@ -216,15 +142,6 @@ static struct xt_match multiport_mt_reg[] __read_mostly = { | |||
216 | { | 142 | { |
217 | .name = "multiport", | 143 | .name = "multiport", |
218 | .family = NFPROTO_IPV6, | 144 | .family = NFPROTO_IPV6, |
219 | .revision = 0, | ||
220 | .checkentry = multiport_mt6_check_v0, | ||
221 | .match = multiport_mt_v0, | ||
222 | .matchsize = sizeof(struct xt_multiport), | ||
223 | .me = THIS_MODULE, | ||
224 | }, | ||
225 | { | ||
226 | .name = "multiport", | ||
227 | .family = NFPROTO_IPV6, | ||
228 | .revision = 1, | 145 | .revision = 1, |
229 | .checkentry = multiport_mt6_check, | 146 | .checkentry = multiport_mt6_check, |
230 | .match = multiport_mt, | 147 | .match = multiport_mt, |
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 4169e200588d..4327e101c047 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | 22 | ||
@@ -193,8 +193,8 @@ static inline int xt_osf_ttl(const struct sk_buff *skb, const struct xt_osf_info | |||
193 | return ip->ttl == f_ttl; | 193 | return ip->ttl == f_ttl; |
194 | } | 194 | } |
195 | 195 | ||
196 | static bool xt_osf_match_packet(const struct sk_buff *skb, | 196 | static bool |
197 | const struct xt_match_param *p) | 197 | xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) |
198 | { | 198 | { |
199 | const struct xt_osf_info *info = p->matchinfo; | 199 | const struct xt_osf_info *info = p->matchinfo; |
200 | const struct iphdr *ip = ip_hdr(skb); | 200 | const struct iphdr *ip = ip_hdr(skb); |
@@ -382,14 +382,14 @@ static int __init xt_osf_init(void) | |||
382 | 382 | ||
383 | err = nfnetlink_subsys_register(&xt_osf_nfnetlink); | 383 | err = nfnetlink_subsys_register(&xt_osf_nfnetlink); |
384 | if (err < 0) { | 384 | if (err < 0) { |
385 | printk(KERN_ERR "Failed (%d) to register OSF nsfnetlink helper.\n", err); | 385 | pr_err("Failed to register OSF nsfnetlink helper (%d)\n", err); |
386 | goto err_out_exit; | 386 | goto err_out_exit; |
387 | } | 387 | } |
388 | 388 | ||
389 | err = xt_register_match(&xt_osf_match); | 389 | err = xt_register_match(&xt_osf_match); |
390 | if (err) { | 390 | if (err) { |
391 | printk(KERN_ERR "Failed (%d) to register OS fingerprint " | 391 | pr_err("Failed to register OS fingerprint " |
392 | "matching module.\n", err); | 392 | "matching module (%d)\n", err); |
393 | goto err_out_remove; | 393 | goto err_out_remove; |
394 | } | 394 | } |
395 | 395 | ||
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c index d24c76dffee2..772d7389b337 100644 --- a/net/netfilter/xt_owner.c +++ b/net/netfilter/xt_owner.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/netfilter/xt_owner.h> | 18 | #include <linux/netfilter/xt_owner.h> |
19 | 19 | ||
20 | static bool | 20 | static bool |
21 | owner_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 21 | owner_mt(const struct sk_buff *skb, struct xt_action_param *par) |
22 | { | 22 | { |
23 | const struct xt_owner_match_info *info = par->matchinfo; | 23 | const struct xt_owner_match_info *info = par->matchinfo; |
24 | const struct file *filp; | 24 | const struct file *filp; |
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c index 8d28ca5848bc..d7ca16b8b8df 100644 --- a/net/netfilter/xt_physdev.c +++ b/net/netfilter/xt_physdev.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <linux/netfilter_bridge.h> | 13 | #include <linux/netfilter_bridge.h> |
@@ -22,7 +22,7 @@ MODULE_ALIAS("ip6t_physdev"); | |||
22 | 22 | ||
23 | 23 | ||
24 | static bool | 24 | static bool |
25 | physdev_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 25 | physdev_mt(const struct sk_buff *skb, struct xt_action_param *par) |
26 | { | 26 | { |
27 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 27 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
28 | const struct xt_physdev_info *info = par->matchinfo; | 28 | const struct xt_physdev_info *info = par->matchinfo; |
@@ -83,25 +83,25 @@ match_outdev: | |||
83 | return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT)); | 83 | return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT)); |
84 | } | 84 | } |
85 | 85 | ||
86 | static bool physdev_mt_check(const struct xt_mtchk_param *par) | 86 | static int physdev_mt_check(const struct xt_mtchk_param *par) |
87 | { | 87 | { |
88 | const struct xt_physdev_info *info = par->matchinfo; | 88 | const struct xt_physdev_info *info = par->matchinfo; |
89 | 89 | ||
90 | if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || | 90 | if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || |
91 | info->bitmask & ~XT_PHYSDEV_OP_MASK) | 91 | info->bitmask & ~XT_PHYSDEV_OP_MASK) |
92 | return false; | 92 | return -EINVAL; |
93 | if (info->bitmask & XT_PHYSDEV_OP_OUT && | 93 | if (info->bitmask & XT_PHYSDEV_OP_OUT && |
94 | (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || | 94 | (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || |
95 | info->invert & XT_PHYSDEV_OP_BRIDGED) && | 95 | info->invert & XT_PHYSDEV_OP_BRIDGED) && |
96 | par->hook_mask & ((1 << NF_INET_LOCAL_OUT) | | 96 | par->hook_mask & ((1 << NF_INET_LOCAL_OUT) | |
97 | (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) { | 97 | (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) { |
98 | printk(KERN_WARNING "physdev match: using --physdev-out in the " | 98 | pr_info("using --physdev-out in the OUTPUT, FORWARD and " |
99 | "OUTPUT, FORWARD and POSTROUTING chains for non-bridged " | 99 | "POSTROUTING chains for non-bridged traffic is not " |
100 | "traffic is not supported anymore.\n"); | 100 | "supported anymore.\n"); |
101 | if (par->hook_mask & (1 << NF_INET_LOCAL_OUT)) | 101 | if (par->hook_mask & (1 << NF_INET_LOCAL_OUT)) |
102 | return false; | 102 | return -EINVAL; |
103 | } | 103 | } |
104 | return true; | 104 | return 0; |
105 | } | 105 | } |
106 | 106 | ||
107 | static struct xt_match physdev_mt_reg __read_mostly = { | 107 | static struct xt_match physdev_mt_reg __read_mostly = { |
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c index 69da1d3a1d85..5b645cb598fc 100644 --- a/net/netfilter/xt_pkttype.c +++ b/net/netfilter/xt_pkttype.c | |||
@@ -23,7 +23,7 @@ MODULE_ALIAS("ipt_pkttype"); | |||
23 | MODULE_ALIAS("ip6t_pkttype"); | 23 | MODULE_ALIAS("ip6t_pkttype"); |
24 | 24 | ||
25 | static bool | 25 | static bool |
26 | pkttype_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 26 | pkttype_mt(const struct sk_buff *skb, struct xt_action_param *par) |
27 | { | 27 | { |
28 | const struct xt_pkttype_info *info = par->matchinfo; | 28 | const struct xt_pkttype_info *info = par->matchinfo; |
29 | u_int8_t type; | 29 | u_int8_t type; |
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c index 4cbfebda8fa1..f23e97bb42d7 100644 --- a/net/netfilter/xt_policy.c +++ b/net/netfilter/xt_policy.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
@@ -110,15 +110,15 @@ match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info, | |||
110 | } | 110 | } |
111 | 111 | ||
112 | static bool | 112 | static bool |
113 | policy_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 113 | policy_mt(const struct sk_buff *skb, struct xt_action_param *par) |
114 | { | 114 | { |
115 | const struct xt_policy_info *info = par->matchinfo; | 115 | const struct xt_policy_info *info = par->matchinfo; |
116 | int ret; | 116 | int ret; |
117 | 117 | ||
118 | if (info->flags & XT_POLICY_MATCH_IN) | 118 | if (info->flags & XT_POLICY_MATCH_IN) |
119 | ret = match_policy_in(skb, info, par->match->family); | 119 | ret = match_policy_in(skb, info, par->family); |
120 | else | 120 | else |
121 | ret = match_policy_out(skb, info, par->match->family); | 121 | ret = match_policy_out(skb, info, par->family); |
122 | 122 | ||
123 | if (ret < 0) | 123 | if (ret < 0) |
124 | ret = info->flags & XT_POLICY_MATCH_NONE ? true : false; | 124 | ret = info->flags & XT_POLICY_MATCH_NONE ? true : false; |
@@ -128,32 +128,29 @@ policy_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
128 | return ret; | 128 | return ret; |
129 | } | 129 | } |
130 | 130 | ||
131 | static bool policy_mt_check(const struct xt_mtchk_param *par) | 131 | static int policy_mt_check(const struct xt_mtchk_param *par) |
132 | { | 132 | { |
133 | const struct xt_policy_info *info = par->matchinfo; | 133 | const struct xt_policy_info *info = par->matchinfo; |
134 | 134 | ||
135 | if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) { | 135 | if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) { |
136 | printk(KERN_ERR "xt_policy: neither incoming nor " | 136 | pr_info("neither incoming nor outgoing policy selected\n"); |
137 | "outgoing policy selected\n"); | 137 | return -EINVAL; |
138 | return false; | ||
139 | } | 138 | } |
140 | if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) | | 139 | if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) | |
141 | (1 << NF_INET_LOCAL_IN)) && info->flags & XT_POLICY_MATCH_OUT) { | 140 | (1 << NF_INET_LOCAL_IN)) && info->flags & XT_POLICY_MATCH_OUT) { |
142 | printk(KERN_ERR "xt_policy: output policy not valid in " | 141 | pr_info("output policy not valid in PREROUTING and INPUT\n"); |
143 | "PRE_ROUTING and INPUT\n"); | 142 | return -EINVAL; |
144 | return false; | ||
145 | } | 143 | } |
146 | if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) | | 144 | if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) | |
147 | (1 << NF_INET_LOCAL_OUT)) && info->flags & XT_POLICY_MATCH_IN) { | 145 | (1 << NF_INET_LOCAL_OUT)) && info->flags & XT_POLICY_MATCH_IN) { |
148 | printk(KERN_ERR "xt_policy: input policy not valid in " | 146 | pr_info("input policy not valid in POSTROUTING and OUTPUT\n"); |
149 | "POST_ROUTING and OUTPUT\n"); | 147 | return -EINVAL; |
150 | return false; | ||
151 | } | 148 | } |
152 | if (info->len > XT_POLICY_MAX_ELEM) { | 149 | if (info->len > XT_POLICY_MAX_ELEM) { |
153 | printk(KERN_ERR "xt_policy: too many policy elements\n"); | 150 | pr_info("too many policy elements\n"); |
154 | return false; | 151 | return -EINVAL; |
155 | } | 152 | } |
156 | return true; | 153 | return 0; |
157 | } | 154 | } |
158 | 155 | ||
159 | static struct xt_match policy_mt_reg[] __read_mostly = { | 156 | static struct xt_match policy_mt_reg[] __read_mostly = { |
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c index 2d5562498c43..b4f7dfea5980 100644 --- a/net/netfilter/xt_quota.c +++ b/net/netfilter/xt_quota.c | |||
@@ -23,7 +23,7 @@ MODULE_ALIAS("ip6t_quota"); | |||
23 | static DEFINE_SPINLOCK(quota_lock); | 23 | static DEFINE_SPINLOCK(quota_lock); |
24 | 24 | ||
25 | static bool | 25 | static bool |
26 | quota_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 26 | quota_mt(const struct sk_buff *skb, struct xt_action_param *par) |
27 | { | 27 | { |
28 | struct xt_quota_info *q = (void *)par->matchinfo; | 28 | struct xt_quota_info *q = (void *)par->matchinfo; |
29 | struct xt_quota_priv *priv = q->master; | 29 | struct xt_quota_priv *priv = q->master; |
@@ -44,19 +44,19 @@ quota_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
44 | return ret; | 44 | return ret; |
45 | } | 45 | } |
46 | 46 | ||
47 | static bool quota_mt_check(const struct xt_mtchk_param *par) | 47 | static int quota_mt_check(const struct xt_mtchk_param *par) |
48 | { | 48 | { |
49 | struct xt_quota_info *q = par->matchinfo; | 49 | struct xt_quota_info *q = par->matchinfo; |
50 | 50 | ||
51 | if (q->flags & ~XT_QUOTA_MASK) | 51 | if (q->flags & ~XT_QUOTA_MASK) |
52 | return false; | 52 | return -EINVAL; |
53 | 53 | ||
54 | q->master = kmalloc(sizeof(*q->master), GFP_KERNEL); | 54 | q->master = kmalloc(sizeof(*q->master), GFP_KERNEL); |
55 | if (q->master == NULL) | 55 | if (q->master == NULL) |
56 | return false; | 56 | return -ENOMEM; |
57 | 57 | ||
58 | q->master->quota = q->quota; | 58 | q->master->quota = q->quota; |
59 | return true; | 59 | return 0; |
60 | } | 60 | } |
61 | 61 | ||
62 | static void quota_mt_destroy(const struct xt_mtdtor_param *par) | 62 | static void quota_mt_destroy(const struct xt_mtdtor_param *par) |
diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c index 4fc6a917f6de..76a083184d8e 100644 --- a/net/netfilter/xt_rateest.c +++ b/net/netfilter/xt_rateest.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | 16 | ||
17 | static bool | 17 | static bool |
18 | xt_rateest_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 18 | xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par) |
19 | { | 19 | { |
20 | const struct xt_rateest_match_info *info = par->matchinfo; | 20 | const struct xt_rateest_match_info *info = par->matchinfo; |
21 | struct gnet_stats_rate_est *r; | 21 | struct gnet_stats_rate_est *r; |
@@ -74,10 +74,11 @@ xt_rateest_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
74 | return ret; | 74 | return ret; |
75 | } | 75 | } |
76 | 76 | ||
77 | static bool xt_rateest_mt_checkentry(const struct xt_mtchk_param *par) | 77 | static int xt_rateest_mt_checkentry(const struct xt_mtchk_param *par) |
78 | { | 78 | { |
79 | struct xt_rateest_match_info *info = par->matchinfo; | 79 | struct xt_rateest_match_info *info = par->matchinfo; |
80 | struct xt_rateest *est1, *est2; | 80 | struct xt_rateest *est1, *est2; |
81 | int ret = false; | ||
81 | 82 | ||
82 | if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS | | 83 | if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS | |
83 | XT_RATEEST_MATCH_REL)) != 1) | 84 | XT_RATEEST_MATCH_REL)) != 1) |
@@ -95,6 +96,7 @@ static bool xt_rateest_mt_checkentry(const struct xt_mtchk_param *par) | |||
95 | goto err1; | 96 | goto err1; |
96 | } | 97 | } |
97 | 98 | ||
99 | ret = -ENOENT; | ||
98 | est1 = xt_rateest_lookup(info->name1); | 100 | est1 = xt_rateest_lookup(info->name1); |
99 | if (!est1) | 101 | if (!est1) |
100 | goto err1; | 102 | goto err1; |
@@ -109,12 +111,12 @@ static bool xt_rateest_mt_checkentry(const struct xt_mtchk_param *par) | |||
109 | 111 | ||
110 | info->est1 = est1; | 112 | info->est1 = est1; |
111 | info->est2 = est2; | 113 | info->est2 = est2; |
112 | return true; | 114 | return 0; |
113 | 115 | ||
114 | err2: | 116 | err2: |
115 | xt_rateest_put(est1); | 117 | xt_rateest_put(est1); |
116 | err1: | 118 | err1: |
117 | return false; | 119 | return -EINVAL; |
118 | } | 120 | } |
119 | 121 | ||
120 | static void xt_rateest_mt_destroy(const struct xt_mtdtor_param *par) | 122 | static void xt_rateest_mt_destroy(const struct xt_mtdtor_param *par) |
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c index 484d1689bfde..459a7b256eb2 100644 --- a/net/netfilter/xt_realm.c +++ b/net/netfilter/xt_realm.c | |||
@@ -22,7 +22,7 @@ MODULE_DESCRIPTION("Xtables: Routing realm match"); | |||
22 | MODULE_ALIAS("ipt_realm"); | 22 | MODULE_ALIAS("ipt_realm"); |
23 | 23 | ||
24 | static bool | 24 | static bool |
25 | realm_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 25 | realm_mt(const struct sk_buff *skb, struct xt_action_param *par) |
26 | { | 26 | { |
27 | const struct xt_realm_info *info = par->matchinfo; | 27 | const struct xt_realm_info *info = par->matchinfo; |
28 | const struct dst_entry *dst = skb_dst(skb); | 28 | const struct dst_entry *dst = skb_dst(skb); |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 834b736857cb..76aec6a44762 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * Author: Stephen Frost <sfrost@snowman.net> | 12 | * Author: Stephen Frost <sfrost@snowman.net> |
13 | * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org | 13 | * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org |
14 | */ | 14 | */ |
15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
16 | #include <linux/ip.h> | 17 | #include <linux/ip.h> |
17 | #include <linux/ipv6.h> | 18 | #include <linux/ipv6.h> |
@@ -35,8 +36,8 @@ | |||
35 | #include <linux/netfilter/xt_recent.h> | 36 | #include <linux/netfilter/xt_recent.h> |
36 | 37 | ||
37 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 38 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
38 | MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>"); | 39 | MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); |
39 | MODULE_DESCRIPTION("Xtables: \"recently-seen\" host matching for IPv4"); | 40 | MODULE_DESCRIPTION("Xtables: \"recently-seen\" host matching"); |
40 | MODULE_LICENSE("GPL"); | 41 | MODULE_LICENSE("GPL"); |
41 | MODULE_ALIAS("ipt_recent"); | 42 | MODULE_ALIAS("ipt_recent"); |
42 | MODULE_ALIAS("ip6t_recent"); | 43 | MODULE_ALIAS("ip6t_recent"); |
@@ -51,14 +52,14 @@ module_param(ip_list_tot, uint, 0400); | |||
51 | module_param(ip_pkt_list_tot, uint, 0400); | 52 | module_param(ip_pkt_list_tot, uint, 0400); |
52 | module_param(ip_list_hash_size, uint, 0400); | 53 | module_param(ip_list_hash_size, uint, 0400); |
53 | module_param(ip_list_perms, uint, 0400); | 54 | module_param(ip_list_perms, uint, 0400); |
54 | module_param(ip_list_uid, uint, 0400); | 55 | module_param(ip_list_uid, uint, S_IRUGO | S_IWUSR); |
55 | module_param(ip_list_gid, uint, 0400); | 56 | module_param(ip_list_gid, uint, S_IRUGO | S_IWUSR); |
56 | MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list"); | 57 | MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list"); |
57 | MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP address to remember (max. 255)"); | 58 | MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP address to remember (max. 255)"); |
58 | MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); | 59 | MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); |
59 | MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files"); | 60 | MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files"); |
60 | MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/xt_recent/* files"); | 61 | MODULE_PARM_DESC(ip_list_uid, "default owner of /proc/net/xt_recent/* files"); |
61 | MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/xt_recent/* files"); | 62 | MODULE_PARM_DESC(ip_list_gid, "default owning group of /proc/net/xt_recent/* files"); |
62 | 63 | ||
63 | struct recent_entry { | 64 | struct recent_entry { |
64 | struct list_head list; | 65 | struct list_head list; |
@@ -84,9 +85,6 @@ struct recent_net { | |||
84 | struct list_head tables; | 85 | struct list_head tables; |
85 | #ifdef CONFIG_PROC_FS | 86 | #ifdef CONFIG_PROC_FS |
86 | struct proc_dir_entry *xt_recent; | 87 | struct proc_dir_entry *xt_recent; |
87 | #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT | ||
88 | struct proc_dir_entry *ipt_recent; | ||
89 | #endif | ||
90 | #endif | 88 | #endif |
91 | }; | 89 | }; |
92 | 90 | ||
@@ -147,6 +145,25 @@ static void recent_entry_remove(struct recent_table *t, struct recent_entry *e) | |||
147 | t->entries--; | 145 | t->entries--; |
148 | } | 146 | } |
149 | 147 | ||
148 | /* | ||
149 | * Drop entries with timestamps older then 'time'. | ||
150 | */ | ||
151 | static void recent_entry_reap(struct recent_table *t, unsigned long time) | ||
152 | { | ||
153 | struct recent_entry *e; | ||
154 | |||
155 | /* | ||
156 | * The head of the LRU list is always the oldest entry. | ||
157 | */ | ||
158 | e = list_entry(t->lru_list.next, struct recent_entry, lru_list); | ||
159 | |||
160 | /* | ||
161 | * The last time stamp is the most recent. | ||
162 | */ | ||
163 | if (time_after(time, e->stamps[e->index-1])) | ||
164 | recent_entry_remove(t, e); | ||
165 | } | ||
166 | |||
150 | static struct recent_entry * | 167 | static struct recent_entry * |
151 | recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr, | 168 | recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr, |
152 | u_int16_t family, u_int8_t ttl) | 169 | u_int16_t family, u_int8_t ttl) |
@@ -207,7 +224,7 @@ static void recent_table_flush(struct recent_table *t) | |||
207 | } | 224 | } |
208 | 225 | ||
209 | static bool | 226 | static bool |
210 | recent_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 227 | recent_mt(const struct sk_buff *skb, struct xt_action_param *par) |
211 | { | 228 | { |
212 | struct net *net = dev_net(par->in ? par->in : par->out); | 229 | struct net *net = dev_net(par->in ? par->in : par->out); |
213 | struct recent_net *recent_net = recent_pernet(net); | 230 | struct recent_net *recent_net = recent_pernet(net); |
@@ -218,7 +235,7 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
218 | u_int8_t ttl; | 235 | u_int8_t ttl; |
219 | bool ret = info->invert; | 236 | bool ret = info->invert; |
220 | 237 | ||
221 | if (par->match->family == NFPROTO_IPV4) { | 238 | if (par->family == NFPROTO_IPV4) { |
222 | const struct iphdr *iph = ip_hdr(skb); | 239 | const struct iphdr *iph = ip_hdr(skb); |
223 | 240 | ||
224 | if (info->side == XT_RECENT_DEST) | 241 | if (info->side == XT_RECENT_DEST) |
@@ -244,14 +261,14 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
244 | 261 | ||
245 | spin_lock_bh(&recent_lock); | 262 | spin_lock_bh(&recent_lock); |
246 | t = recent_table_lookup(recent_net, info->name); | 263 | t = recent_table_lookup(recent_net, info->name); |
247 | e = recent_entry_lookup(t, &addr, par->match->family, | 264 | e = recent_entry_lookup(t, &addr, par->family, |
248 | (info->check_set & XT_RECENT_TTL) ? ttl : 0); | 265 | (info->check_set & XT_RECENT_TTL) ? ttl : 0); |
249 | if (e == NULL) { | 266 | if (e == NULL) { |
250 | if (!(info->check_set & XT_RECENT_SET)) | 267 | if (!(info->check_set & XT_RECENT_SET)) |
251 | goto out; | 268 | goto out; |
252 | e = recent_entry_init(t, &addr, par->match->family, ttl); | 269 | e = recent_entry_init(t, &addr, par->family, ttl); |
253 | if (e == NULL) | 270 | if (e == NULL) |
254 | *par->hotdrop = true; | 271 | par->hotdrop = true; |
255 | ret = !ret; | 272 | ret = !ret; |
256 | goto out; | 273 | goto out; |
257 | } | 274 | } |
@@ -273,6 +290,10 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
273 | break; | 290 | break; |
274 | } | 291 | } |
275 | } | 292 | } |
293 | |||
294 | /* info->seconds must be non-zero */ | ||
295 | if (info->check_set & XT_RECENT_REAP) | ||
296 | recent_entry_reap(t, time); | ||
276 | } | 297 | } |
277 | 298 | ||
278 | if (info->check_set & XT_RECENT_SET || | 299 | if (info->check_set & XT_RECENT_SET || |
@@ -285,7 +306,7 @@ out: | |||
285 | return ret; | 306 | return ret; |
286 | } | 307 | } |
287 | 308 | ||
288 | static bool recent_mt_check(const struct xt_mtchk_param *par) | 309 | static int recent_mt_check(const struct xt_mtchk_param *par) |
289 | { | 310 | { |
290 | struct recent_net *recent_net = recent_pernet(par->net); | 311 | struct recent_net *recent_net = recent_pernet(par->net); |
291 | const struct xt_recent_mtinfo *info = par->matchinfo; | 312 | const struct xt_recent_mtinfo *info = par->matchinfo; |
@@ -294,41 +315,51 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) | |||
294 | struct proc_dir_entry *pde; | 315 | struct proc_dir_entry *pde; |
295 | #endif | 316 | #endif |
296 | unsigned i; | 317 | unsigned i; |
297 | bool ret = false; | 318 | int ret = -EINVAL; |
298 | 319 | ||
299 | if (unlikely(!hash_rnd_inited)) { | 320 | if (unlikely(!hash_rnd_inited)) { |
300 | get_random_bytes(&hash_rnd, sizeof(hash_rnd)); | 321 | get_random_bytes(&hash_rnd, sizeof(hash_rnd)); |
301 | hash_rnd_inited = true; | 322 | hash_rnd_inited = true; |
302 | } | 323 | } |
324 | if (info->check_set & ~XT_RECENT_VALID_FLAGS) { | ||
325 | pr_info("Unsupported user space flags (%08x)\n", | ||
326 | info->check_set); | ||
327 | return -EINVAL; | ||
328 | } | ||
303 | if (hweight8(info->check_set & | 329 | if (hweight8(info->check_set & |
304 | (XT_RECENT_SET | XT_RECENT_REMOVE | | 330 | (XT_RECENT_SET | XT_RECENT_REMOVE | |
305 | XT_RECENT_CHECK | XT_RECENT_UPDATE)) != 1) | 331 | XT_RECENT_CHECK | XT_RECENT_UPDATE)) != 1) |
306 | return false; | 332 | return -EINVAL; |
307 | if ((info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE)) && | 333 | if ((info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE)) && |
308 | (info->seconds || info->hit_count)) | 334 | (info->seconds || info->hit_count || |
309 | return false; | 335 | (info->check_set & XT_RECENT_MODIFIERS))) |
336 | return -EINVAL; | ||
337 | if ((info->check_set & XT_RECENT_REAP) && !info->seconds) | ||
338 | return -EINVAL; | ||
310 | if (info->hit_count > ip_pkt_list_tot) { | 339 | if (info->hit_count > ip_pkt_list_tot) { |
311 | pr_info(KBUILD_MODNAME ": hitcount (%u) is larger than " | 340 | pr_info("hitcount (%u) is larger than " |
312 | "packets to be remembered (%u)\n", | 341 | "packets to be remembered (%u)\n", |
313 | info->hit_count, ip_pkt_list_tot); | 342 | info->hit_count, ip_pkt_list_tot); |
314 | return false; | 343 | return -EINVAL; |
315 | } | 344 | } |
316 | if (info->name[0] == '\0' || | 345 | if (info->name[0] == '\0' || |
317 | strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN) | 346 | strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN) |
318 | return false; | 347 | return -EINVAL; |
319 | 348 | ||
320 | mutex_lock(&recent_mutex); | 349 | mutex_lock(&recent_mutex); |
321 | t = recent_table_lookup(recent_net, info->name); | 350 | t = recent_table_lookup(recent_net, info->name); |
322 | if (t != NULL) { | 351 | if (t != NULL) { |
323 | t->refcnt++; | 352 | t->refcnt++; |
324 | ret = true; | 353 | ret = 0; |
325 | goto out; | 354 | goto out; |
326 | } | 355 | } |
327 | 356 | ||
328 | t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size, | 357 | t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size, |
329 | GFP_KERNEL); | 358 | GFP_KERNEL); |
330 | if (t == NULL) | 359 | if (t == NULL) { |
360 | ret = -ENOMEM; | ||
331 | goto out; | 361 | goto out; |
362 | } | ||
332 | t->refcnt = 1; | 363 | t->refcnt = 1; |
333 | strcpy(t->name, info->name); | 364 | strcpy(t->name, info->name); |
334 | INIT_LIST_HEAD(&t->lru_list); | 365 | INIT_LIST_HEAD(&t->lru_list); |
@@ -339,26 +370,16 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) | |||
339 | &recent_mt_fops, t); | 370 | &recent_mt_fops, t); |
340 | if (pde == NULL) { | 371 | if (pde == NULL) { |
341 | kfree(t); | 372 | kfree(t); |
342 | goto out; | 373 | ret = -ENOMEM; |
343 | } | ||
344 | pde->uid = ip_list_uid; | ||
345 | pde->gid = ip_list_gid; | ||
346 | #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT | ||
347 | pde = proc_create_data(t->name, ip_list_perms, recent_net->ipt_recent, | ||
348 | &recent_old_fops, t); | ||
349 | if (pde == NULL) { | ||
350 | remove_proc_entry(t->name, recent_net->xt_recent); | ||
351 | kfree(t); | ||
352 | goto out; | 374 | goto out; |
353 | } | 375 | } |
354 | pde->uid = ip_list_uid; | 376 | pde->uid = ip_list_uid; |
355 | pde->gid = ip_list_gid; | 377 | pde->gid = ip_list_gid; |
356 | #endif | 378 | #endif |
357 | #endif | ||
358 | spin_lock_bh(&recent_lock); | 379 | spin_lock_bh(&recent_lock); |
359 | list_add_tail(&t->list, &recent_net->tables); | 380 | list_add_tail(&t->list, &recent_net->tables); |
360 | spin_unlock_bh(&recent_lock); | 381 | spin_unlock_bh(&recent_lock); |
361 | ret = true; | 382 | ret = 0; |
362 | out: | 383 | out: |
363 | mutex_unlock(&recent_mutex); | 384 | mutex_unlock(&recent_mutex); |
364 | return ret; | 385 | return ret; |
@@ -377,9 +398,6 @@ static void recent_mt_destroy(const struct xt_mtdtor_param *par) | |||
377 | list_del(&t->list); | 398 | list_del(&t->list); |
378 | spin_unlock_bh(&recent_lock); | 399 | spin_unlock_bh(&recent_lock); |
379 | #ifdef CONFIG_PROC_FS | 400 | #ifdef CONFIG_PROC_FS |
380 | #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT | ||
381 | remove_proc_entry(t->name, recent_net->ipt_recent); | ||
382 | #endif | ||
383 | remove_proc_entry(t->name, recent_net->xt_recent); | 401 | remove_proc_entry(t->name, recent_net->xt_recent); |
384 | #endif | 402 | #endif |
385 | recent_table_flush(t); | 403 | recent_table_flush(t); |
@@ -471,84 +489,6 @@ static int recent_seq_open(struct inode *inode, struct file *file) | |||
471 | return 0; | 489 | return 0; |
472 | } | 490 | } |
473 | 491 | ||
474 | #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT | ||
475 | static int recent_old_seq_open(struct inode *inode, struct file *filp) | ||
476 | { | ||
477 | static bool warned_of_old; | ||
478 | |||
479 | if (unlikely(!warned_of_old)) { | ||
480 | printk(KERN_INFO KBUILD_MODNAME ": Use of /proc/net/ipt_recent" | ||
481 | " is deprecated; use /proc/net/xt_recent.\n"); | ||
482 | warned_of_old = true; | ||
483 | } | ||
484 | return recent_seq_open(inode, filp); | ||
485 | } | ||
486 | |||
487 | static ssize_t recent_old_proc_write(struct file *file, | ||
488 | const char __user *input, | ||
489 | size_t size, loff_t *loff) | ||
490 | { | ||
491 | const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); | ||
492 | struct recent_table *t = pde->data; | ||
493 | struct recent_entry *e; | ||
494 | char buf[sizeof("+255.255.255.255")], *c = buf; | ||
495 | union nf_inet_addr addr = {}; | ||
496 | int add; | ||
497 | |||
498 | if (size > sizeof(buf)) | ||
499 | size = sizeof(buf); | ||
500 | if (copy_from_user(buf, input, size)) | ||
501 | return -EFAULT; | ||
502 | |||
503 | c = skip_spaces(c); | ||
504 | |||
505 | if (size - (c - buf) < 5) | ||
506 | return c - buf; | ||
507 | if (!strncmp(c, "clear", 5)) { | ||
508 | c += 5; | ||
509 | spin_lock_bh(&recent_lock); | ||
510 | recent_table_flush(t); | ||
511 | spin_unlock_bh(&recent_lock); | ||
512 | return c - buf; | ||
513 | } | ||
514 | |||
515 | switch (*c) { | ||
516 | case '-': | ||
517 | add = 0; | ||
518 | c++; | ||
519 | break; | ||
520 | case '+': | ||
521 | c++; | ||
522 | default: | ||
523 | add = 1; | ||
524 | break; | ||
525 | } | ||
526 | addr.ip = in_aton(c); | ||
527 | |||
528 | spin_lock_bh(&recent_lock); | ||
529 | e = recent_entry_lookup(t, &addr, NFPROTO_IPV4, 0); | ||
530 | if (e == NULL) { | ||
531 | if (add) | ||
532 | recent_entry_init(t, &addr, NFPROTO_IPV4, 0); | ||
533 | } else { | ||
534 | if (add) | ||
535 | recent_entry_update(t, e); | ||
536 | else | ||
537 | recent_entry_remove(t, e); | ||
538 | } | ||
539 | spin_unlock_bh(&recent_lock); | ||
540 | return size; | ||
541 | } | ||
542 | |||
543 | static const struct file_operations recent_old_fops = { | ||
544 | .open = recent_old_seq_open, | ||
545 | .read = seq_read, | ||
546 | .write = recent_old_proc_write, | ||
547 | .release = seq_release_private, | ||
548 | .owner = THIS_MODULE, | ||
549 | }; | ||
550 | #endif | ||
551 | |||
552 | static ssize_t | 492 | static ssize_t |
553 | recent_mt_proc_write(struct file *file, const char __user *input, | 493 | recent_mt_proc_write(struct file *file, const char __user *input, |
554 | size_t size, loff_t *loff) | 494 | size_t size, loff_t *loff) |
@@ -585,7 +525,7 @@ recent_mt_proc_write(struct file *file, const char __user *input, | |||
585 | add = true; | 525 | add = true; |
586 | break; | 526 | break; |
587 | default: | 527 | default: |
588 | printk(KERN_INFO KBUILD_MODNAME ": Need +ip, -ip or /\n"); | 528 | pr_info("Need \"+ip\", \"-ip\" or \"/\"\n"); |
589 | return -EINVAL; | 529 | return -EINVAL; |
590 | } | 530 | } |
591 | 531 | ||
@@ -600,8 +540,7 @@ recent_mt_proc_write(struct file *file, const char __user *input, | |||
600 | } | 540 | } |
601 | 541 | ||
602 | if (!succ) { | 542 | if (!succ) { |
603 | printk(KERN_INFO KBUILD_MODNAME ": illegal address written " | 543 | pr_info("illegal address written to procfs\n"); |
604 | "to procfs\n"); | ||
605 | return -EINVAL; | 544 | return -EINVAL; |
606 | } | 545 | } |
607 | 546 | ||
@@ -637,21 +576,11 @@ static int __net_init recent_proc_net_init(struct net *net) | |||
637 | recent_net->xt_recent = proc_mkdir("xt_recent", net->proc_net); | 576 | recent_net->xt_recent = proc_mkdir("xt_recent", net->proc_net); |
638 | if (!recent_net->xt_recent) | 577 | if (!recent_net->xt_recent) |
639 | return -ENOMEM; | 578 | return -ENOMEM; |
640 | #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT | ||
641 | recent_net->ipt_recent = proc_mkdir("ipt_recent", net->proc_net); | ||
642 | if (!recent_net->ipt_recent) { | ||
643 | proc_net_remove(net, "xt_recent"); | ||
644 | return -ENOMEM; | ||
645 | } | ||
646 | #endif | ||
647 | return 0; | 579 | return 0; |
648 | } | 580 | } |
649 | 581 | ||
650 | static void __net_exit recent_proc_net_exit(struct net *net) | 582 | static void __net_exit recent_proc_net_exit(struct net *net) |
651 | { | 583 | { |
652 | #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT | ||
653 | proc_net_remove(net, "ipt_recent"); | ||
654 | #endif | ||
655 | proc_net_remove(net, "xt_recent"); | 584 | proc_net_remove(net, "xt_recent"); |
656 | } | 585 | } |
657 | #else | 586 | #else |
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c index a189ada9128f..c04fcf385c59 100644 --- a/net/netfilter/xt_sctp.c +++ b/net/netfilter/xt_sctp.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
1 | #include <linux/module.h> | 2 | #include <linux/module.h> |
2 | #include <linux/skbuff.h> | 3 | #include <linux/skbuff.h> |
3 | #include <net/ip.h> | 4 | #include <net/ip.h> |
@@ -15,12 +16,6 @@ MODULE_DESCRIPTION("Xtables: SCTP protocol packet match"); | |||
15 | MODULE_ALIAS("ipt_sctp"); | 16 | MODULE_ALIAS("ipt_sctp"); |
16 | MODULE_ALIAS("ip6t_sctp"); | 17 | MODULE_ALIAS("ip6t_sctp"); |
17 | 18 | ||
18 | #ifdef DEBUG_SCTP | ||
19 | #define duprintf(format, args...) printk(format , ## args) | ||
20 | #else | ||
21 | #define duprintf(format, args...) | ||
22 | #endif | ||
23 | |||
24 | #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ | 19 | #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ |
25 | || (!!((invflag) & (option)) ^ (cond))) | 20 | || (!!((invflag) & (option)) ^ (cond))) |
26 | 21 | ||
@@ -52,7 +47,7 @@ match_packet(const struct sk_buff *skb, | |||
52 | const struct xt_sctp_flag_info *flag_info = info->flag_info; | 47 | const struct xt_sctp_flag_info *flag_info = info->flag_info; |
53 | int flag_count = info->flag_count; | 48 | int flag_count = info->flag_count; |
54 | 49 | ||
55 | #ifdef DEBUG_SCTP | 50 | #ifdef DEBUG |
56 | int i = 0; | 51 | int i = 0; |
57 | #endif | 52 | #endif |
58 | 53 | ||
@@ -62,17 +57,19 @@ match_packet(const struct sk_buff *skb, | |||
62 | do { | 57 | do { |
63 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); | 58 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); |
64 | if (sch == NULL || sch->length == 0) { | 59 | if (sch == NULL || sch->length == 0) { |
65 | duprintf("Dropping invalid SCTP packet.\n"); | 60 | pr_debug("Dropping invalid SCTP packet.\n"); |
66 | *hotdrop = true; | 61 | *hotdrop = true; |
67 | return false; | 62 | return false; |
68 | } | 63 | } |
69 | 64 | #ifdef DEBUG | |
70 | duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", | 65 | pr_debug("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d" |
71 | ++i, offset, sch->type, htons(sch->length), sch->flags); | 66 | "\tflags: %x\n", |
72 | 67 | ++i, offset, sch->type, htons(sch->length), | |
68 | sch->flags); | ||
69 | #endif | ||
73 | offset += (ntohs(sch->length) + 3) & ~3; | 70 | offset += (ntohs(sch->length) + 3) & ~3; |
74 | 71 | ||
75 | duprintf("skb->len: %d\toffset: %d\n", skb->len, offset); | 72 | pr_debug("skb->len: %d\toffset: %d\n", skb->len, offset); |
76 | 73 | ||
77 | if (SCTP_CHUNKMAP_IS_SET(info->chunkmap, sch->type)) { | 74 | if (SCTP_CHUNKMAP_IS_SET(info->chunkmap, sch->type)) { |
78 | switch (chunk_match_type) { | 75 | switch (chunk_match_type) { |
@@ -117,24 +114,24 @@ match_packet(const struct sk_buff *skb, | |||
117 | } | 114 | } |
118 | 115 | ||
119 | static bool | 116 | static bool |
120 | sctp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 117 | sctp_mt(const struct sk_buff *skb, struct xt_action_param *par) |
121 | { | 118 | { |
122 | const struct xt_sctp_info *info = par->matchinfo; | 119 | const struct xt_sctp_info *info = par->matchinfo; |
123 | const sctp_sctphdr_t *sh; | 120 | const sctp_sctphdr_t *sh; |
124 | sctp_sctphdr_t _sh; | 121 | sctp_sctphdr_t _sh; |
125 | 122 | ||
126 | if (par->fragoff != 0) { | 123 | if (par->fragoff != 0) { |
127 | duprintf("Dropping non-first fragment.. FIXME\n"); | 124 | pr_debug("Dropping non-first fragment.. FIXME\n"); |
128 | return false; | 125 | return false; |
129 | } | 126 | } |
130 | 127 | ||
131 | sh = skb_header_pointer(skb, par->thoff, sizeof(_sh), &_sh); | 128 | sh = skb_header_pointer(skb, par->thoff, sizeof(_sh), &_sh); |
132 | if (sh == NULL) { | 129 | if (sh == NULL) { |
133 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | 130 | pr_debug("Dropping evil TCP offset=0 tinygram.\n"); |
134 | *par->hotdrop = true; | 131 | par->hotdrop = true; |
135 | return false; | 132 | return false; |
136 | } | 133 | } |
137 | duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest)); | 134 | pr_debug("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest)); |
138 | 135 | ||
139 | return SCCHECK(ntohs(sh->source) >= info->spts[0] | 136 | return SCCHECK(ntohs(sh->source) >= info->spts[0] |
140 | && ntohs(sh->source) <= info->spts[1], | 137 | && ntohs(sh->source) <= info->spts[1], |
@@ -143,22 +140,26 @@ sctp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
143 | && ntohs(sh->dest) <= info->dpts[1], | 140 | && ntohs(sh->dest) <= info->dpts[1], |
144 | XT_SCTP_DEST_PORTS, info->flags, info->invflags) | 141 | XT_SCTP_DEST_PORTS, info->flags, info->invflags) |
145 | && SCCHECK(match_packet(skb, par->thoff + sizeof(sctp_sctphdr_t), | 142 | && SCCHECK(match_packet(skb, par->thoff + sizeof(sctp_sctphdr_t), |
146 | info, par->hotdrop), | 143 | info, &par->hotdrop), |
147 | XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); | 144 | XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); |
148 | } | 145 | } |
149 | 146 | ||
150 | static bool sctp_mt_check(const struct xt_mtchk_param *par) | 147 | static int sctp_mt_check(const struct xt_mtchk_param *par) |
151 | { | 148 | { |
152 | const struct xt_sctp_info *info = par->matchinfo; | 149 | const struct xt_sctp_info *info = par->matchinfo; |
153 | 150 | ||
154 | return !(info->flags & ~XT_SCTP_VALID_FLAGS) | 151 | if (info->flags & ~XT_SCTP_VALID_FLAGS) |
155 | && !(info->invflags & ~XT_SCTP_VALID_FLAGS) | 152 | return -EINVAL; |
156 | && !(info->invflags & ~info->flags) | 153 | if (info->invflags & ~XT_SCTP_VALID_FLAGS) |
157 | && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || | 154 | return -EINVAL; |
158 | (info->chunk_match_type & | 155 | if (info->invflags & ~info->flags) |
159 | (SCTP_CHUNK_MATCH_ALL | 156 | return -EINVAL; |
160 | | SCTP_CHUNK_MATCH_ANY | 157 | if (!(info->flags & XT_SCTP_CHUNK_TYPES)) |
161 | | SCTP_CHUNK_MATCH_ONLY))); | 158 | return 0; |
159 | if (info->chunk_match_type & (SCTP_CHUNK_MATCH_ALL | | ||
160 | SCTP_CHUNK_MATCH_ANY | SCTP_CHUNK_MATCH_ONLY)) | ||
161 | return 0; | ||
162 | return -EINVAL; | ||
162 | } | 163 | } |
163 | 164 | ||
164 | static struct xt_match sctp_mt_reg[] __read_mostly = { | 165 | static struct xt_match sctp_mt_reg[] __read_mostly = { |
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 6a902564d24f..3d54c236a1ba 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/netfilter/x_tables.h> | 15 | #include <linux/netfilter/x_tables.h> |
@@ -88,7 +88,7 @@ extract_icmp_fields(const struct sk_buff *skb, | |||
88 | 88 | ||
89 | 89 | ||
90 | static bool | 90 | static bool |
91 | socket_match(const struct sk_buff *skb, const struct xt_match_param *par, | 91 | socket_match(const struct sk_buff *skb, struct xt_action_param *par, |
92 | const struct xt_socket_mtinfo1 *info) | 92 | const struct xt_socket_mtinfo1 *info) |
93 | { | 93 | { |
94 | const struct iphdr *iph = ip_hdr(skb); | 94 | const struct iphdr *iph = ip_hdr(skb); |
@@ -165,8 +165,7 @@ socket_match(const struct sk_buff *skb, const struct xt_match_param *par, | |||
165 | sk = NULL; | 165 | sk = NULL; |
166 | } | 166 | } |
167 | 167 | ||
168 | pr_debug("socket match: proto %u %08x:%u -> %08x:%u " | 168 | pr_debug("proto %u %08x:%u -> %08x:%u (orig %08x:%u) sock %p\n", |
169 | "(orig %08x:%u) sock %p\n", | ||
170 | protocol, ntohl(saddr), ntohs(sport), | 169 | protocol, ntohl(saddr), ntohs(sport), |
171 | ntohl(daddr), ntohs(dport), | 170 | ntohl(daddr), ntohs(dport), |
172 | ntohl(iph->daddr), hp ? ntohs(hp->dest) : 0, sk); | 171 | ntohl(iph->daddr), hp ? ntohs(hp->dest) : 0, sk); |
@@ -175,13 +174,13 @@ socket_match(const struct sk_buff *skb, const struct xt_match_param *par, | |||
175 | } | 174 | } |
176 | 175 | ||
177 | static bool | 176 | static bool |
178 | socket_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) | 177 | socket_mt_v0(const struct sk_buff *skb, struct xt_action_param *par) |
179 | { | 178 | { |
180 | return socket_match(skb, par, NULL); | 179 | return socket_match(skb, par, NULL); |
181 | } | 180 | } |
182 | 181 | ||
183 | static bool | 182 | static bool |
184 | socket_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | 183 | socket_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) |
185 | { | 184 | { |
186 | return socket_match(skb, par, par->matchinfo); | 185 | return socket_match(skb, par, par->matchinfo); |
187 | } | 186 | } |
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c index 4c946cbd731f..e12e053d3782 100644 --- a/net/netfilter/xt_state.c +++ b/net/netfilter/xt_state.c | |||
@@ -21,7 +21,7 @@ MODULE_ALIAS("ipt_state"); | |||
21 | MODULE_ALIAS("ip6t_state"); | 21 | MODULE_ALIAS("ip6t_state"); |
22 | 22 | ||
23 | static bool | 23 | static bool |
24 | state_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 24 | state_mt(const struct sk_buff *skb, struct xt_action_param *par) |
25 | { | 25 | { |
26 | const struct xt_state_info *sinfo = par->matchinfo; | 26 | const struct xt_state_info *sinfo = par->matchinfo; |
27 | enum ip_conntrack_info ctinfo; | 27 | enum ip_conntrack_info ctinfo; |
@@ -37,50 +37,40 @@ state_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
37 | return (sinfo->statemask & statebit); | 37 | return (sinfo->statemask & statebit); |
38 | } | 38 | } |
39 | 39 | ||
40 | static bool state_mt_check(const struct xt_mtchk_param *par) | 40 | static int state_mt_check(const struct xt_mtchk_param *par) |
41 | { | 41 | { |
42 | if (nf_ct_l3proto_try_module_get(par->match->family) < 0) { | 42 | int ret; |
43 | printk(KERN_WARNING "can't load conntrack support for " | 43 | |
44 | "proto=%u\n", par->match->family); | 44 | ret = nf_ct_l3proto_try_module_get(par->family); |
45 | return false; | 45 | if (ret < 0) |
46 | } | 46 | pr_info("cannot load conntrack support for proto=%u\n", |
47 | return true; | 47 | par->family); |
48 | return ret; | ||
48 | } | 49 | } |
49 | 50 | ||
50 | static void state_mt_destroy(const struct xt_mtdtor_param *par) | 51 | static void state_mt_destroy(const struct xt_mtdtor_param *par) |
51 | { | 52 | { |
52 | nf_ct_l3proto_module_put(par->match->family); | 53 | nf_ct_l3proto_module_put(par->family); |
53 | } | 54 | } |
54 | 55 | ||
55 | static struct xt_match state_mt_reg[] __read_mostly = { | 56 | static struct xt_match state_mt_reg __read_mostly = { |
56 | { | 57 | .name = "state", |
57 | .name = "state", | 58 | .family = NFPROTO_UNSPEC, |
58 | .family = NFPROTO_IPV4, | 59 | .checkentry = state_mt_check, |
59 | .checkentry = state_mt_check, | 60 | .match = state_mt, |
60 | .match = state_mt, | 61 | .destroy = state_mt_destroy, |
61 | .destroy = state_mt_destroy, | 62 | .matchsize = sizeof(struct xt_state_info), |
62 | .matchsize = sizeof(struct xt_state_info), | 63 | .me = THIS_MODULE, |
63 | .me = THIS_MODULE, | ||
64 | }, | ||
65 | { | ||
66 | .name = "state", | ||
67 | .family = NFPROTO_IPV6, | ||
68 | .checkentry = state_mt_check, | ||
69 | .match = state_mt, | ||
70 | .destroy = state_mt_destroy, | ||
71 | .matchsize = sizeof(struct xt_state_info), | ||
72 | .me = THIS_MODULE, | ||
73 | }, | ||
74 | }; | 64 | }; |
75 | 65 | ||
76 | static int __init state_mt_init(void) | 66 | static int __init state_mt_init(void) |
77 | { | 67 | { |
78 | return xt_register_matches(state_mt_reg, ARRAY_SIZE(state_mt_reg)); | 68 | return xt_register_match(&state_mt_reg); |
79 | } | 69 | } |
80 | 70 | ||
81 | static void __exit state_mt_exit(void) | 71 | static void __exit state_mt_exit(void) |
82 | { | 72 | { |
83 | xt_unregister_matches(state_mt_reg, ARRAY_SIZE(state_mt_reg)); | 73 | xt_unregister_match(&state_mt_reg); |
84 | } | 74 | } |
85 | 75 | ||
86 | module_init(state_mt_init); | 76 | module_init(state_mt_init); |
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c index 937ce0633e99..96e62b8fd6b1 100644 --- a/net/netfilter/xt_statistic.c +++ b/net/netfilter/xt_statistic.c | |||
@@ -30,7 +30,7 @@ MODULE_ALIAS("ip6t_statistic"); | |||
30 | static DEFINE_SPINLOCK(nth_lock); | 30 | static DEFINE_SPINLOCK(nth_lock); |
31 | 31 | ||
32 | static bool | 32 | static bool |
33 | statistic_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 33 | statistic_mt(const struct sk_buff *skb, struct xt_action_param *par) |
34 | { | 34 | { |
35 | const struct xt_statistic_info *info = par->matchinfo; | 35 | const struct xt_statistic_info *info = par->matchinfo; |
36 | bool ret = info->flags & XT_STATISTIC_INVERT; | 36 | bool ret = info->flags & XT_STATISTIC_INVERT; |
@@ -53,22 +53,20 @@ statistic_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
53 | return ret; | 53 | return ret; |
54 | } | 54 | } |
55 | 55 | ||
56 | static bool statistic_mt_check(const struct xt_mtchk_param *par) | 56 | static int statistic_mt_check(const struct xt_mtchk_param *par) |
57 | { | 57 | { |
58 | struct xt_statistic_info *info = par->matchinfo; | 58 | struct xt_statistic_info *info = par->matchinfo; |
59 | 59 | ||
60 | if (info->mode > XT_STATISTIC_MODE_MAX || | 60 | if (info->mode > XT_STATISTIC_MODE_MAX || |
61 | info->flags & ~XT_STATISTIC_MASK) | 61 | info->flags & ~XT_STATISTIC_MASK) |
62 | return false; | 62 | return -EINVAL; |
63 | 63 | ||
64 | info->master = kzalloc(sizeof(*info->master), GFP_KERNEL); | 64 | info->master = kzalloc(sizeof(*info->master), GFP_KERNEL); |
65 | if (info->master == NULL) { | 65 | if (info->master == NULL) |
66 | printk(KERN_ERR KBUILD_MODNAME ": Out of memory\n"); | 66 | return -ENOMEM; |
67 | return false; | ||
68 | } | ||
69 | info->master->count = info->u.nth.count; | 67 | info->master->count = info->u.nth.count; |
70 | 68 | ||
71 | return true; | 69 | return 0; |
72 | } | 70 | } |
73 | 71 | ||
74 | static void statistic_mt_destroy(const struct xt_mtdtor_param *par) | 72 | static void statistic_mt_destroy(const struct xt_mtdtor_param *par) |
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c index 96801ffd8af8..d3c48b14ab94 100644 --- a/net/netfilter/xt_string.c +++ b/net/netfilter/xt_string.c | |||
@@ -23,16 +23,14 @@ MODULE_ALIAS("ipt_string"); | |||
23 | MODULE_ALIAS("ip6t_string"); | 23 | MODULE_ALIAS("ip6t_string"); |
24 | 24 | ||
25 | static bool | 25 | static bool |
26 | string_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 26 | string_mt(const struct sk_buff *skb, struct xt_action_param *par) |
27 | { | 27 | { |
28 | const struct xt_string_info *conf = par->matchinfo; | 28 | const struct xt_string_info *conf = par->matchinfo; |
29 | struct ts_state state; | 29 | struct ts_state state; |
30 | int invert; | 30 | bool invert; |
31 | 31 | ||
32 | memset(&state, 0, sizeof(struct ts_state)); | 32 | memset(&state, 0, sizeof(struct ts_state)); |
33 | 33 | invert = conf->u.v1.flags & XT_STRING_FLAG_INVERT; | |
34 | invert = (par->match->revision == 0 ? conf->u.v0.invert : | ||
35 | conf->u.v1.flags & XT_STRING_FLAG_INVERT); | ||
36 | 34 | ||
37 | return (skb_find_text((struct sk_buff *)skb, conf->from_offset, | 35 | return (skb_find_text((struct sk_buff *)skb, conf->from_offset, |
38 | conf->to_offset, conf->config, &state) | 36 | conf->to_offset, conf->config, &state) |
@@ -41,7 +39,7 @@ string_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
41 | 39 | ||
42 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *)(m)) | 40 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *)(m)) |
43 | 41 | ||
44 | static bool string_mt_check(const struct xt_mtchk_param *par) | 42 | static int string_mt_check(const struct xt_mtchk_param *par) |
45 | { | 43 | { |
46 | struct xt_string_info *conf = par->matchinfo; | 44 | struct xt_string_info *conf = par->matchinfo; |
47 | struct ts_config *ts_conf; | 45 | struct ts_config *ts_conf; |
@@ -49,26 +47,23 @@ static bool string_mt_check(const struct xt_mtchk_param *par) | |||
49 | 47 | ||
50 | /* Damn, can't handle this case properly with iptables... */ | 48 | /* Damn, can't handle this case properly with iptables... */ |
51 | if (conf->from_offset > conf->to_offset) | 49 | if (conf->from_offset > conf->to_offset) |
52 | return false; | 50 | return -EINVAL; |
53 | if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0') | 51 | if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0') |
54 | return false; | 52 | return -EINVAL; |
55 | if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE) | 53 | if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE) |
56 | return false; | 54 | return -EINVAL; |
57 | if (par->match->revision == 1) { | 55 | if (conf->u.v1.flags & |
58 | if (conf->u.v1.flags & | 56 | ~(XT_STRING_FLAG_IGNORECASE | XT_STRING_FLAG_INVERT)) |
59 | ~(XT_STRING_FLAG_IGNORECASE | XT_STRING_FLAG_INVERT)) | 57 | return -EINVAL; |
60 | return false; | 58 | if (conf->u.v1.flags & XT_STRING_FLAG_IGNORECASE) |
61 | if (conf->u.v1.flags & XT_STRING_FLAG_IGNORECASE) | 59 | flags |= TS_IGNORECASE; |
62 | flags |= TS_IGNORECASE; | ||
63 | } | ||
64 | ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen, | 60 | ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen, |
65 | GFP_KERNEL, flags); | 61 | GFP_KERNEL, flags); |
66 | if (IS_ERR(ts_conf)) | 62 | if (IS_ERR(ts_conf)) |
67 | return false; | 63 | return PTR_ERR(ts_conf); |
68 | 64 | ||
69 | conf->config = ts_conf; | 65 | conf->config = ts_conf; |
70 | 66 | return 0; | |
71 | return true; | ||
72 | } | 67 | } |
73 | 68 | ||
74 | static void string_mt_destroy(const struct xt_mtdtor_param *par) | 69 | static void string_mt_destroy(const struct xt_mtdtor_param *par) |
@@ -76,38 +71,25 @@ static void string_mt_destroy(const struct xt_mtdtor_param *par) | |||
76 | textsearch_destroy(STRING_TEXT_PRIV(par->matchinfo)->config); | 71 | textsearch_destroy(STRING_TEXT_PRIV(par->matchinfo)->config); |
77 | } | 72 | } |
78 | 73 | ||
79 | static struct xt_match xt_string_mt_reg[] __read_mostly = { | 74 | static struct xt_match xt_string_mt_reg __read_mostly = { |
80 | { | 75 | .name = "string", |
81 | .name = "string", | 76 | .revision = 1, |
82 | .revision = 0, | 77 | .family = NFPROTO_UNSPEC, |
83 | .family = NFPROTO_UNSPEC, | 78 | .checkentry = string_mt_check, |
84 | .checkentry = string_mt_check, | 79 | .match = string_mt, |
85 | .match = string_mt, | 80 | .destroy = string_mt_destroy, |
86 | .destroy = string_mt_destroy, | 81 | .matchsize = sizeof(struct xt_string_info), |
87 | .matchsize = sizeof(struct xt_string_info), | 82 | .me = THIS_MODULE, |
88 | .me = THIS_MODULE | ||
89 | }, | ||
90 | { | ||
91 | .name = "string", | ||
92 | .revision = 1, | ||
93 | .family = NFPROTO_UNSPEC, | ||
94 | .checkentry = string_mt_check, | ||
95 | .match = string_mt, | ||
96 | .destroy = string_mt_destroy, | ||
97 | .matchsize = sizeof(struct xt_string_info), | ||
98 | .me = THIS_MODULE | ||
99 | }, | ||
100 | }; | 83 | }; |
101 | 84 | ||
102 | static int __init string_mt_init(void) | 85 | static int __init string_mt_init(void) |
103 | { | 86 | { |
104 | return xt_register_matches(xt_string_mt_reg, | 87 | return xt_register_match(&xt_string_mt_reg); |
105 | ARRAY_SIZE(xt_string_mt_reg)); | ||
106 | } | 88 | } |
107 | 89 | ||
108 | static void __exit string_mt_exit(void) | 90 | static void __exit string_mt_exit(void) |
109 | { | 91 | { |
110 | xt_unregister_matches(xt_string_mt_reg, ARRAY_SIZE(xt_string_mt_reg)); | 92 | xt_unregister_match(&xt_string_mt_reg); |
111 | } | 93 | } |
112 | 94 | ||
113 | module_init(string_mt_init); | 95 | module_init(string_mt_init); |
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c index 4809b34b10f8..c53d4d18eadf 100644 --- a/net/netfilter/xt_tcpmss.c +++ b/net/netfilter/xt_tcpmss.c | |||
@@ -25,7 +25,7 @@ MODULE_ALIAS("ipt_tcpmss"); | |||
25 | MODULE_ALIAS("ip6t_tcpmss"); | 25 | MODULE_ALIAS("ip6t_tcpmss"); |
26 | 26 | ||
27 | static bool | 27 | static bool |
28 | tcpmss_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 28 | tcpmss_mt(const struct sk_buff *skb, struct xt_action_param *par) |
29 | { | 29 | { |
30 | const struct xt_tcpmss_match_info *info = par->matchinfo; | 30 | const struct xt_tcpmss_match_info *info = par->matchinfo; |
31 | const struct tcphdr *th; | 31 | const struct tcphdr *th; |
@@ -73,7 +73,7 @@ out: | |||
73 | return info->invert; | 73 | return info->invert; |
74 | 74 | ||
75 | dropit: | 75 | dropit: |
76 | *par->hotdrop = true; | 76 | par->hotdrop = true; |
77 | return false; | 77 | return false; |
78 | } | 78 | } |
79 | 79 | ||
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c index 1ebdc4934eed..c14d4645daa3 100644 --- a/net/netfilter/xt_tcpudp.c +++ b/net/netfilter/xt_tcpudp.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
1 | #include <linux/types.h> | 2 | #include <linux/types.h> |
2 | #include <linux/module.h> | 3 | #include <linux/module.h> |
3 | #include <net/ip.h> | 4 | #include <net/ip.h> |
@@ -19,13 +20,6 @@ MODULE_ALIAS("ipt_tcp"); | |||
19 | MODULE_ALIAS("ip6t_udp"); | 20 | MODULE_ALIAS("ip6t_udp"); |
20 | MODULE_ALIAS("ip6t_tcp"); | 21 | MODULE_ALIAS("ip6t_tcp"); |
21 | 22 | ||
22 | #ifdef DEBUG_IP_FIREWALL_USER | ||
23 | #define duprintf(format, args...) printk(format , ## args) | ||
24 | #else | ||
25 | #define duprintf(format, args...) | ||
26 | #endif | ||
27 | |||
28 | |||
29 | /* Returns 1 if the port is matched by the range, 0 otherwise */ | 23 | /* Returns 1 if the port is matched by the range, 0 otherwise */ |
30 | static inline bool | 24 | static inline bool |
31 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, bool invert) | 25 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, bool invert) |
@@ -46,7 +40,7 @@ tcp_find_option(u_int8_t option, | |||
46 | u_int8_t _opt[60 - sizeof(struct tcphdr)]; | 40 | u_int8_t _opt[60 - sizeof(struct tcphdr)]; |
47 | unsigned int i; | 41 | unsigned int i; |
48 | 42 | ||
49 | duprintf("tcp_match: finding option\n"); | 43 | pr_debug("finding option\n"); |
50 | 44 | ||
51 | if (!optlen) | 45 | if (!optlen) |
52 | return invert; | 46 | return invert; |
@@ -68,7 +62,7 @@ tcp_find_option(u_int8_t option, | |||
68 | return invert; | 62 | return invert; |
69 | } | 63 | } |
70 | 64 | ||
71 | static bool tcp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 65 | static bool tcp_mt(const struct sk_buff *skb, struct xt_action_param *par) |
72 | { | 66 | { |
73 | const struct tcphdr *th; | 67 | const struct tcphdr *th; |
74 | struct tcphdr _tcph; | 68 | struct tcphdr _tcph; |
@@ -82,8 +76,8 @@ static bool tcp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
82 | flag overwrite to pass the direction checks. | 76 | flag overwrite to pass the direction checks. |
83 | */ | 77 | */ |
84 | if (par->fragoff == 1) { | 78 | if (par->fragoff == 1) { |
85 | duprintf("Dropping evil TCP offset=1 frag.\n"); | 79 | pr_debug("Dropping evil TCP offset=1 frag.\n"); |
86 | *par->hotdrop = true; | 80 | par->hotdrop = true; |
87 | } | 81 | } |
88 | /* Must not be a fragment. */ | 82 | /* Must not be a fragment. */ |
89 | return false; | 83 | return false; |
@@ -95,8 +89,8 @@ static bool tcp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
95 | if (th == NULL) { | 89 | if (th == NULL) { |
96 | /* We've been asked to examine this packet, and we | 90 | /* We've been asked to examine this packet, and we |
97 | can't. Hence, no choice but to drop. */ | 91 | can't. Hence, no choice but to drop. */ |
98 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | 92 | pr_debug("Dropping evil TCP offset=0 tinygram.\n"); |
99 | *par->hotdrop = true; | 93 | par->hotdrop = true; |
100 | return false; | 94 | return false; |
101 | } | 95 | } |
102 | 96 | ||
@@ -114,27 +108,27 @@ static bool tcp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
114 | return false; | 108 | return false; |
115 | if (tcpinfo->option) { | 109 | if (tcpinfo->option) { |
116 | if (th->doff * 4 < sizeof(_tcph)) { | 110 | if (th->doff * 4 < sizeof(_tcph)) { |
117 | *par->hotdrop = true; | 111 | par->hotdrop = true; |
118 | return false; | 112 | return false; |
119 | } | 113 | } |
120 | if (!tcp_find_option(tcpinfo->option, skb, par->thoff, | 114 | if (!tcp_find_option(tcpinfo->option, skb, par->thoff, |
121 | th->doff*4 - sizeof(_tcph), | 115 | th->doff*4 - sizeof(_tcph), |
122 | tcpinfo->invflags & XT_TCP_INV_OPTION, | 116 | tcpinfo->invflags & XT_TCP_INV_OPTION, |
123 | par->hotdrop)) | 117 | &par->hotdrop)) |
124 | return false; | 118 | return false; |
125 | } | 119 | } |
126 | return true; | 120 | return true; |
127 | } | 121 | } |
128 | 122 | ||
129 | static bool tcp_mt_check(const struct xt_mtchk_param *par) | 123 | static int tcp_mt_check(const struct xt_mtchk_param *par) |
130 | { | 124 | { |
131 | const struct xt_tcp *tcpinfo = par->matchinfo; | 125 | const struct xt_tcp *tcpinfo = par->matchinfo; |
132 | 126 | ||
133 | /* Must specify no unknown invflags */ | 127 | /* Must specify no unknown invflags */ |
134 | return !(tcpinfo->invflags & ~XT_TCP_INV_MASK); | 128 | return (tcpinfo->invflags & ~XT_TCP_INV_MASK) ? -EINVAL : 0; |
135 | } | 129 | } |
136 | 130 | ||
137 | static bool udp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 131 | static bool udp_mt(const struct sk_buff *skb, struct xt_action_param *par) |
138 | { | 132 | { |
139 | const struct udphdr *uh; | 133 | const struct udphdr *uh; |
140 | struct udphdr _udph; | 134 | struct udphdr _udph; |
@@ -148,8 +142,8 @@ static bool udp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
148 | if (uh == NULL) { | 142 | if (uh == NULL) { |
149 | /* We've been asked to examine this packet, and we | 143 | /* We've been asked to examine this packet, and we |
150 | can't. Hence, no choice but to drop. */ | 144 | can't. Hence, no choice but to drop. */ |
151 | duprintf("Dropping evil UDP tinygram.\n"); | 145 | pr_debug("Dropping evil UDP tinygram.\n"); |
152 | *par->hotdrop = true; | 146 | par->hotdrop = true; |
153 | return false; | 147 | return false; |
154 | } | 148 | } |
155 | 149 | ||
@@ -161,12 +155,12 @@ static bool udp_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
161 | !!(udpinfo->invflags & XT_UDP_INV_DSTPT)); | 155 | !!(udpinfo->invflags & XT_UDP_INV_DSTPT)); |
162 | } | 156 | } |
163 | 157 | ||
164 | static bool udp_mt_check(const struct xt_mtchk_param *par) | 158 | static int udp_mt_check(const struct xt_mtchk_param *par) |
165 | { | 159 | { |
166 | const struct xt_udp *udpinfo = par->matchinfo; | 160 | const struct xt_udp *udpinfo = par->matchinfo; |
167 | 161 | ||
168 | /* Must specify no unknown invflags */ | 162 | /* Must specify no unknown invflags */ |
169 | return !(udpinfo->invflags & ~XT_UDP_INV_MASK); | 163 | return (udpinfo->invflags & ~XT_UDP_INV_MASK) ? -EINVAL : 0; |
170 | } | 164 | } |
171 | 165 | ||
172 | static struct xt_match tcpudp_mt_reg[] __read_mostly = { | 166 | static struct xt_match tcpudp_mt_reg[] __read_mostly = { |
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c index 93acaa59d108..c48975ff8ea2 100644 --- a/net/netfilter/xt_time.c +++ b/net/netfilter/xt_time.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * xt_time | 2 | * xt_time |
3 | * Copyright © CC Computer Consultants GmbH, 2007 | 3 | * Copyright © CC Computer Consultants GmbH, 2007 |
4 | * Contact: <jengelh@computergmbh.de> | ||
5 | * | 4 | * |
6 | * based on ipt_time by Fabrice MARIE <fabrice@netfilter.org> | 5 | * based on ipt_time by Fabrice MARIE <fabrice@netfilter.org> |
7 | * This is a module which is used for time matching | 6 | * This is a module which is used for time matching |
@@ -149,11 +148,10 @@ static void localtime_3(struct xtm *r, time_t time) | |||
149 | } | 148 | } |
150 | 149 | ||
151 | r->month = i + 1; | 150 | r->month = i + 1; |
152 | return; | ||
153 | } | 151 | } |
154 | 152 | ||
155 | static bool | 153 | static bool |
156 | time_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 154 | time_mt(const struct sk_buff *skb, struct xt_action_param *par) |
157 | { | 155 | { |
158 | const struct xt_time_info *info = par->matchinfo; | 156 | const struct xt_time_info *info = par->matchinfo; |
159 | unsigned int packet_time; | 157 | unsigned int packet_time; |
@@ -218,18 +216,18 @@ time_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
218 | return true; | 216 | return true; |
219 | } | 217 | } |
220 | 218 | ||
221 | static bool time_mt_check(const struct xt_mtchk_param *par) | 219 | static int time_mt_check(const struct xt_mtchk_param *par) |
222 | { | 220 | { |
223 | const struct xt_time_info *info = par->matchinfo; | 221 | const struct xt_time_info *info = par->matchinfo; |
224 | 222 | ||
225 | if (info->daytime_start > XT_TIME_MAX_DAYTIME || | 223 | if (info->daytime_start > XT_TIME_MAX_DAYTIME || |
226 | info->daytime_stop > XT_TIME_MAX_DAYTIME) { | 224 | info->daytime_stop > XT_TIME_MAX_DAYTIME) { |
227 | printk(KERN_WARNING "xt_time: invalid argument - start or " | 225 | pr_info("invalid argument - start or " |
228 | "stop time greater than 23:59:59\n"); | 226 | "stop time greater than 23:59:59\n"); |
229 | return false; | 227 | return -EDOM; |
230 | } | 228 | } |
231 | 229 | ||
232 | return true; | 230 | return 0; |
233 | } | 231 | } |
234 | 232 | ||
235 | static struct xt_match xt_time_mt_reg __read_mostly = { | 233 | static struct xt_match xt_time_mt_reg __read_mostly = { |
@@ -264,7 +262,7 @@ static void __exit time_mt_exit(void) | |||
264 | 262 | ||
265 | module_init(time_mt_init); | 263 | module_init(time_mt_init); |
266 | module_exit(time_mt_exit); | 264 | module_exit(time_mt_exit); |
267 | MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>"); | 265 | MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); |
268 | MODULE_DESCRIPTION("Xtables: time-based matching"); | 266 | MODULE_DESCRIPTION("Xtables: time-based matching"); |
269 | MODULE_LICENSE("GPL"); | 267 | MODULE_LICENSE("GPL"); |
270 | MODULE_ALIAS("ipt_time"); | 268 | MODULE_ALIAS("ipt_time"); |
diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c index 24a527624500..a95b50342dbb 100644 --- a/net/netfilter/xt_u32.c +++ b/net/netfilter/xt_u32.c | |||
@@ -3,7 +3,6 @@ | |||
3 | * | 3 | * |
4 | * Original author: Don Cohen <don@isis.cs3-inc.com> | 4 | * Original author: Don Cohen <don@isis.cs3-inc.com> |
5 | * (C) CC Computer Consultants GmbH, 2007 | 5 | * (C) CC Computer Consultants GmbH, 2007 |
6 | * Contact: <jengelh@computergmbh.de> | ||
7 | */ | 6 | */ |
8 | 7 | ||
9 | #include <linux/module.h> | 8 | #include <linux/module.h> |
@@ -87,7 +86,7 @@ static bool u32_match_it(const struct xt_u32 *data, | |||
87 | return true; | 86 | return true; |
88 | } | 87 | } |
89 | 88 | ||
90 | static bool u32_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 89 | static bool u32_mt(const struct sk_buff *skb, struct xt_action_param *par) |
91 | { | 90 | { |
92 | const struct xt_u32 *data = par->matchinfo; | 91 | const struct xt_u32 *data = par->matchinfo; |
93 | bool ret; | 92 | bool ret; |
@@ -117,7 +116,7 @@ static void __exit u32_mt_exit(void) | |||
117 | 116 | ||
118 | module_init(u32_mt_init); | 117 | module_init(u32_mt_init); |
119 | module_exit(u32_mt_exit); | 118 | module_exit(u32_mt_exit); |
120 | MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>"); | 119 | MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); |
121 | MODULE_DESCRIPTION("Xtables: arbitrary byte matching"); | 120 | MODULE_DESCRIPTION("Xtables: arbitrary byte matching"); |
122 | MODULE_LICENSE("GPL"); | 121 | MODULE_LICENSE("GPL"); |
123 | MODULE_ALIAS("ipt_u32"); | 122 | MODULE_ALIAS("ipt_u32"); |
diff --git a/net/netlabel/netlabel_addrlist.h b/net/netlabel/netlabel_addrlist.h index 07ae7fd82be1..1c1c093cf279 100644 --- a/net/netlabel/netlabel_addrlist.h +++ b/net/netlabel/netlabel_addrlist.h | |||
@@ -130,7 +130,6 @@ static inline void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, | |||
130 | int src, const char *dev, | 130 | int src, const char *dev, |
131 | __be32 addr, __be32 mask) | 131 | __be32 addr, __be32 mask) |
132 | { | 132 | { |
133 | return; | ||
134 | } | 133 | } |
135 | #endif | 134 | #endif |
136 | 135 | ||
@@ -203,7 +202,6 @@ static inline void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf, | |||
203 | const struct in6_addr *addr, | 202 | const struct in6_addr *addr, |
204 | const struct in6_addr *mask) | 203 | const struct in6_addr *mask) |
205 | { | 204 | { |
206 | return; | ||
207 | } | 205 | } |
208 | #endif | 206 | #endif |
209 | #endif /* IPV6 */ | 207 | #endif /* IPV6 */ |
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index a3d64aabe2f7..e2b0a680dd56 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c | |||
@@ -670,7 +670,6 @@ static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface) | |||
670 | 670 | ||
671 | unlhsh_condremove_failure: | 671 | unlhsh_condremove_failure: |
672 | spin_unlock(&netlbl_unlhsh_lock); | 672 | spin_unlock(&netlbl_unlhsh_lock); |
673 | return; | ||
674 | } | 673 | } |
675 | 674 | ||
676 | /** | 675 | /** |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 795424396aff..6464a1972a69 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -545,7 +545,7 @@ static int netlink_autobind(struct socket *sock) | |||
545 | struct hlist_head *head; | 545 | struct hlist_head *head; |
546 | struct sock *osk; | 546 | struct sock *osk; |
547 | struct hlist_node *node; | 547 | struct hlist_node *node; |
548 | s32 pid = current->tgid; | 548 | s32 pid = task_tgid_vnr(current); |
549 | int err; | 549 | int err; |
550 | static s32 rover = -4097; | 550 | static s32 rover = -4097; |
551 | 551 | ||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 06438fa2b1e5..aa4308afcc7f 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -21,15 +21,17 @@ | |||
21 | 21 | ||
22 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ | 22 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ |
23 | 23 | ||
24 | static inline void genl_lock(void) | 24 | void genl_lock(void) |
25 | { | 25 | { |
26 | mutex_lock(&genl_mutex); | 26 | mutex_lock(&genl_mutex); |
27 | } | 27 | } |
28 | EXPORT_SYMBOL(genl_lock); | ||
28 | 29 | ||
29 | static inline void genl_unlock(void) | 30 | void genl_unlock(void) |
30 | { | 31 | { |
31 | mutex_unlock(&genl_mutex); | 32 | mutex_unlock(&genl_mutex); |
32 | } | 33 | } |
34 | EXPORT_SYMBOL(genl_unlock); | ||
33 | 35 | ||
34 | #define GENL_FAM_TAB_SIZE 16 | 36 | #define GENL_FAM_TAB_SIZE 16 |
35 | #define GENL_FAM_TAB_MASK (GENL_FAM_TAB_SIZE - 1) | 37 | #define GENL_FAM_TAB_MASK (GENL_FAM_TAB_SIZE - 1) |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index fa07f044b599..06cb02796a0e 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -739,7 +739,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, | |||
739 | DEFINE_WAIT(wait); | 739 | DEFINE_WAIT(wait); |
740 | 740 | ||
741 | for (;;) { | 741 | for (;;) { |
742 | prepare_to_wait(sk->sk_sleep, &wait, | 742 | prepare_to_wait(sk_sleep(sk), &wait, |
743 | TASK_INTERRUPTIBLE); | 743 | TASK_INTERRUPTIBLE); |
744 | if (sk->sk_state != TCP_SYN_SENT) | 744 | if (sk->sk_state != TCP_SYN_SENT) |
745 | break; | 745 | break; |
@@ -752,7 +752,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, | |||
752 | err = -ERESTARTSYS; | 752 | err = -ERESTARTSYS; |
753 | break; | 753 | break; |
754 | } | 754 | } |
755 | finish_wait(sk->sk_sleep, &wait); | 755 | finish_wait(sk_sleep(sk), &wait); |
756 | if (err) | 756 | if (err) |
757 | goto out_release; | 757 | goto out_release; |
758 | } | 758 | } |
@@ -798,7 +798,7 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags) | |||
798 | * hooked into the SABM we saved | 798 | * hooked into the SABM we saved |
799 | */ | 799 | */ |
800 | for (;;) { | 800 | for (;;) { |
801 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 801 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
802 | skb = skb_dequeue(&sk->sk_receive_queue); | 802 | skb = skb_dequeue(&sk->sk_receive_queue); |
803 | if (skb) | 803 | if (skb) |
804 | break; | 804 | break; |
@@ -816,7 +816,7 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags) | |||
816 | err = -ERESTARTSYS; | 816 | err = -ERESTARTSYS; |
817 | break; | 817 | break; |
818 | } | 818 | } |
819 | finish_wait(sk->sk_sleep, &wait); | 819 | finish_wait(sk_sleep(sk), &wait); |
820 | if (err) | 820 | if (err) |
821 | goto out_release; | 821 | goto out_release; |
822 | 822 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 243946d4809d..2078a277e06b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -82,6 +82,7 @@ | |||
82 | #include <linux/mutex.h> | 82 | #include <linux/mutex.h> |
83 | #include <linux/if_vlan.h> | 83 | #include <linux/if_vlan.h> |
84 | #include <linux/virtio_net.h> | 84 | #include <linux/virtio_net.h> |
85 | #include <linux/errqueue.h> | ||
85 | 86 | ||
86 | #ifdef CONFIG_INET | 87 | #ifdef CONFIG_INET |
87 | #include <net/inet_common.h> | 88 | #include <net/inet_common.h> |
@@ -315,6 +316,8 @@ static inline struct packet_sock *pkt_sk(struct sock *sk) | |||
315 | 316 | ||
316 | static void packet_sock_destruct(struct sock *sk) | 317 | static void packet_sock_destruct(struct sock *sk) |
317 | { | 318 | { |
319 | skb_queue_purge(&sk->sk_error_queue); | ||
320 | |||
318 | WARN_ON(atomic_read(&sk->sk_rmem_alloc)); | 321 | WARN_ON(atomic_read(&sk->sk_rmem_alloc)); |
319 | WARN_ON(atomic_read(&sk->sk_wmem_alloc)); | 322 | WARN_ON(atomic_read(&sk->sk_wmem_alloc)); |
320 | 323 | ||
@@ -483,6 +486,9 @@ retry: | |||
483 | skb->dev = dev; | 486 | skb->dev = dev; |
484 | skb->priority = sk->sk_priority; | 487 | skb->priority = sk->sk_priority; |
485 | skb->mark = sk->sk_mark; | 488 | skb->mark = sk->sk_mark; |
489 | err = sock_tx_timestamp(msg, sk, skb_tx(skb)); | ||
490 | if (err < 0) | ||
491 | goto out_unlock; | ||
486 | 492 | ||
487 | dev_queue_xmit(skb); | 493 | dev_queue_xmit(skb); |
488 | rcu_read_unlock(); | 494 | rcu_read_unlock(); |
@@ -1188,6 +1194,9 @@ static int packet_snd(struct socket *sock, | |||
1188 | err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len); | 1194 | err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len); |
1189 | if (err) | 1195 | if (err) |
1190 | goto out_free; | 1196 | goto out_free; |
1197 | err = sock_tx_timestamp(msg, sk, skb_tx(skb)); | ||
1198 | if (err < 0) | ||
1199 | goto out_free; | ||
1191 | 1200 | ||
1192 | skb->protocol = proto; | 1201 | skb->protocol = proto; |
1193 | skb->dev = dev; | 1202 | skb->dev = dev; |
@@ -1487,6 +1496,51 @@ out: | |||
1487 | return err; | 1496 | return err; |
1488 | } | 1497 | } |
1489 | 1498 | ||
1499 | static int packet_recv_error(struct sock *sk, struct msghdr *msg, int len) | ||
1500 | { | ||
1501 | struct sock_exterr_skb *serr; | ||
1502 | struct sk_buff *skb, *skb2; | ||
1503 | int copied, err; | ||
1504 | |||
1505 | err = -EAGAIN; | ||
1506 | skb = skb_dequeue(&sk->sk_error_queue); | ||
1507 | if (skb == NULL) | ||
1508 | goto out; | ||
1509 | |||
1510 | copied = skb->len; | ||
1511 | if (copied > len) { | ||
1512 | msg->msg_flags |= MSG_TRUNC; | ||
1513 | copied = len; | ||
1514 | } | ||
1515 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | ||
1516 | if (err) | ||
1517 | goto out_free_skb; | ||
1518 | |||
1519 | sock_recv_timestamp(msg, sk, skb); | ||
1520 | |||
1521 | serr = SKB_EXT_ERR(skb); | ||
1522 | put_cmsg(msg, SOL_PACKET, PACKET_TX_TIMESTAMP, | ||
1523 | sizeof(serr->ee), &serr->ee); | ||
1524 | |||
1525 | msg->msg_flags |= MSG_ERRQUEUE; | ||
1526 | err = copied; | ||
1527 | |||
1528 | /* Reset and regenerate socket error */ | ||
1529 | spin_lock_bh(&sk->sk_error_queue.lock); | ||
1530 | sk->sk_err = 0; | ||
1531 | if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) { | ||
1532 | sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno; | ||
1533 | spin_unlock_bh(&sk->sk_error_queue.lock); | ||
1534 | sk->sk_error_report(sk); | ||
1535 | } else | ||
1536 | spin_unlock_bh(&sk->sk_error_queue.lock); | ||
1537 | |||
1538 | out_free_skb: | ||
1539 | kfree_skb(skb); | ||
1540 | out: | ||
1541 | return err; | ||
1542 | } | ||
1543 | |||
1490 | /* | 1544 | /* |
1491 | * Pull a packet from our receive queue and hand it to the user. | 1545 | * Pull a packet from our receive queue and hand it to the user. |
1492 | * If necessary we block. | 1546 | * If necessary we block. |
@@ -1502,7 +1556,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1502 | int vnet_hdr_len = 0; | 1556 | int vnet_hdr_len = 0; |
1503 | 1557 | ||
1504 | err = -EINVAL; | 1558 | err = -EINVAL; |
1505 | if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) | 1559 | if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT|MSG_ERRQUEUE)) |
1506 | goto out; | 1560 | goto out; |
1507 | 1561 | ||
1508 | #if 0 | 1562 | #if 0 |
@@ -1511,6 +1565,11 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1511 | return -ENODEV; | 1565 | return -ENODEV; |
1512 | #endif | 1566 | #endif |
1513 | 1567 | ||
1568 | if (flags & MSG_ERRQUEUE) { | ||
1569 | err = packet_recv_error(sk, msg, len); | ||
1570 | goto out; | ||
1571 | } | ||
1572 | |||
1514 | /* | 1573 | /* |
1515 | * Call the generic datagram receiver. This handles all sorts | 1574 | * Call the generic datagram receiver. This handles all sorts |
1516 | * of horrible races and re-entrancy so we can forget about it | 1575 | * of horrible races and re-entrancy so we can forget about it |
@@ -1692,9 +1751,9 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, | |||
1692 | if (i->alen != dev->addr_len) | 1751 | if (i->alen != dev->addr_len) |
1693 | return -EINVAL; | 1752 | return -EINVAL; |
1694 | if (what > 0) | 1753 | if (what > 0) |
1695 | return dev_mc_add(dev, i->addr, i->alen, 0); | 1754 | return dev_mc_add(dev, i->addr); |
1696 | else | 1755 | else |
1697 | return dev_mc_delete(dev, i->addr, i->alen, 0); | 1756 | return dev_mc_del(dev, i->addr); |
1698 | break; | 1757 | break; |
1699 | case PACKET_MR_PROMISC: | 1758 | case PACKET_MR_PROMISC: |
1700 | return dev_set_promiscuity(dev, what); | 1759 | return dev_set_promiscuity(dev, what); |
@@ -1706,9 +1765,9 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, | |||
1706 | if (i->alen != dev->addr_len) | 1765 | if (i->alen != dev->addr_len) |
1707 | return -EINVAL; | 1766 | return -EINVAL; |
1708 | if (what > 0) | 1767 | if (what > 0) |
1709 | return dev_unicast_add(dev, i->addr); | 1768 | return dev_uc_add(dev, i->addr); |
1710 | else | 1769 | else |
1711 | return dev_unicast_delete(dev, i->addr); | 1770 | return dev_uc_del(dev, i->addr); |
1712 | break; | 1771 | break; |
1713 | default: | 1772 | default: |
1714 | break; | 1773 | break; |
diff --git a/net/phonet/pep.c b/net/phonet/pep.c index e2a95762abd3..af4d38bc3b22 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c | |||
@@ -664,12 +664,12 @@ static int pep_wait_connreq(struct sock *sk, int noblock) | |||
664 | if (signal_pending(tsk)) | 664 | if (signal_pending(tsk)) |
665 | return sock_intr_errno(timeo); | 665 | return sock_intr_errno(timeo); |
666 | 666 | ||
667 | prepare_to_wait_exclusive(&sk->sk_socket->wait, &wait, | 667 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
668 | TASK_INTERRUPTIBLE); | 668 | TASK_INTERRUPTIBLE); |
669 | release_sock(sk); | 669 | release_sock(sk); |
670 | timeo = schedule_timeout(timeo); | 670 | timeo = schedule_timeout(timeo); |
671 | lock_sock(sk); | 671 | lock_sock(sk); |
672 | finish_wait(&sk->sk_socket->wait, &wait); | 672 | finish_wait(sk_sleep(sk), &wait); |
673 | } | 673 | } |
674 | 674 | ||
675 | return 0; | 675 | return 0; |
@@ -910,10 +910,10 @@ disabled: | |||
910 | goto out; | 910 | goto out; |
911 | } | 911 | } |
912 | 912 | ||
913 | prepare_to_wait(&sk->sk_socket->wait, &wait, | 913 | prepare_to_wait(sk_sleep(sk), &wait, |
914 | TASK_INTERRUPTIBLE); | 914 | TASK_INTERRUPTIBLE); |
915 | done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits)); | 915 | done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits)); |
916 | finish_wait(&sk->sk_socket->wait, &wait); | 916 | finish_wait(sk_sleep(sk), &wait); |
917 | 917 | ||
918 | if (sk->sk_state != TCP_ESTABLISHED) | 918 | if (sk->sk_state != TCP_ESTABLISHED) |
919 | goto disabled; | 919 | goto disabled; |
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 9b4ced6e0968..c33da6576942 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c | |||
@@ -46,9 +46,16 @@ struct phonet_net { | |||
46 | 46 | ||
47 | int phonet_net_id __read_mostly; | 47 | int phonet_net_id __read_mostly; |
48 | 48 | ||
49 | static struct phonet_net *phonet_pernet(struct net *net) | ||
50 | { | ||
51 | BUG_ON(!net); | ||
52 | |||
53 | return net_generic(net, phonet_net_id); | ||
54 | } | ||
55 | |||
49 | struct phonet_device_list *phonet_device_list(struct net *net) | 56 | struct phonet_device_list *phonet_device_list(struct net *net) |
50 | { | 57 | { |
51 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 58 | struct phonet_net *pnn = phonet_pernet(net); |
52 | return &pnn->pndevs; | 59 | return &pnn->pndevs; |
53 | } | 60 | } |
54 | 61 | ||
@@ -261,7 +268,7 @@ static int phonet_device_autoconf(struct net_device *dev) | |||
261 | 268 | ||
262 | static void phonet_route_autodel(struct net_device *dev) | 269 | static void phonet_route_autodel(struct net_device *dev) |
263 | { | 270 | { |
264 | struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id); | 271 | struct phonet_net *pnn = phonet_pernet(dev_net(dev)); |
265 | unsigned i; | 272 | unsigned i; |
266 | DECLARE_BITMAP(deleted, 64); | 273 | DECLARE_BITMAP(deleted, 64); |
267 | 274 | ||
@@ -313,7 +320,7 @@ static struct notifier_block phonet_device_notifier = { | |||
313 | /* Per-namespace Phonet devices handling */ | 320 | /* Per-namespace Phonet devices handling */ |
314 | static int __net_init phonet_init_net(struct net *net) | 321 | static int __net_init phonet_init_net(struct net *net) |
315 | { | 322 | { |
316 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 323 | struct phonet_net *pnn = phonet_pernet(net); |
317 | 324 | ||
318 | if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops)) | 325 | if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops)) |
319 | return -ENOMEM; | 326 | return -ENOMEM; |
@@ -326,7 +333,7 @@ static int __net_init phonet_init_net(struct net *net) | |||
326 | 333 | ||
327 | static void __net_exit phonet_exit_net(struct net *net) | 334 | static void __net_exit phonet_exit_net(struct net *net) |
328 | { | 335 | { |
329 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 336 | struct phonet_net *pnn = phonet_pernet(net); |
330 | struct net_device *dev; | 337 | struct net_device *dev; |
331 | unsigned i; | 338 | unsigned i; |
332 | 339 | ||
@@ -376,7 +383,7 @@ void phonet_device_exit(void) | |||
376 | 383 | ||
377 | int phonet_route_add(struct net_device *dev, u8 daddr) | 384 | int phonet_route_add(struct net_device *dev, u8 daddr) |
378 | { | 385 | { |
379 | struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id); | 386 | struct phonet_net *pnn = phonet_pernet(dev_net(dev)); |
380 | struct phonet_routes *routes = &pnn->routes; | 387 | struct phonet_routes *routes = &pnn->routes; |
381 | int err = -EEXIST; | 388 | int err = -EEXIST; |
382 | 389 | ||
@@ -393,7 +400,7 @@ int phonet_route_add(struct net_device *dev, u8 daddr) | |||
393 | 400 | ||
394 | int phonet_route_del(struct net_device *dev, u8 daddr) | 401 | int phonet_route_del(struct net_device *dev, u8 daddr) |
395 | { | 402 | { |
396 | struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id); | 403 | struct phonet_net *pnn = phonet_pernet(dev_net(dev)); |
397 | struct phonet_routes *routes = &pnn->routes; | 404 | struct phonet_routes *routes = &pnn->routes; |
398 | 405 | ||
399 | daddr = daddr >> 2; | 406 | daddr = daddr >> 2; |
@@ -413,7 +420,7 @@ int phonet_route_del(struct net_device *dev, u8 daddr) | |||
413 | 420 | ||
414 | struct net_device *phonet_route_get(struct net *net, u8 daddr) | 421 | struct net_device *phonet_route_get(struct net *net, u8 daddr) |
415 | { | 422 | { |
416 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 423 | struct phonet_net *pnn = phonet_pernet(net); |
417 | struct phonet_routes *routes = &pnn->routes; | 424 | struct phonet_routes *routes = &pnn->routes; |
418 | struct net_device *dev; | 425 | struct net_device *dev; |
419 | 426 | ||
@@ -428,7 +435,7 @@ struct net_device *phonet_route_get(struct net *net, u8 daddr) | |||
428 | 435 | ||
429 | struct net_device *phonet_route_output(struct net *net, u8 daddr) | 436 | struct net_device *phonet_route_output(struct net *net, u8 daddr) |
430 | { | 437 | { |
431 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 438 | struct phonet_net *pnn = phonet_pernet(net); |
432 | struct phonet_routes *routes = &pnn->routes; | 439 | struct phonet_routes *routes = &pnn->routes; |
433 | struct net_device *dev; | 440 | struct net_device *dev; |
434 | 441 | ||
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index c785bfd0744f..6e9848bf0370 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
@@ -265,7 +265,7 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock, | |||
265 | struct pep_sock *pn = pep_sk(sk); | 265 | struct pep_sock *pn = pep_sk(sk); |
266 | unsigned int mask = 0; | 266 | unsigned int mask = 0; |
267 | 267 | ||
268 | poll_wait(file, &sock->wait, wait); | 268 | poll_wait(file, sk_sleep(sk), wait); |
269 | 269 | ||
270 | switch (sk->sk_state) { | 270 | switch (sk->sk_state) { |
271 | case TCP_LISTEN: | 271 | case TCP_LISTEN: |
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index f81862baf4d0..aebfecbdb841 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c | |||
@@ -158,9 +158,10 @@ static unsigned int rds_poll(struct file *file, struct socket *sock, | |||
158 | unsigned int mask = 0; | 158 | unsigned int mask = 0; |
159 | unsigned long flags; | 159 | unsigned long flags; |
160 | 160 | ||
161 | poll_wait(file, sk->sk_sleep, wait); | 161 | poll_wait(file, sk_sleep(sk), wait); |
162 | 162 | ||
163 | poll_wait(file, &rds_poll_waitq, wait); | 163 | if (rs->rs_seen_congestion) |
164 | poll_wait(file, &rds_poll_waitq, wait); | ||
164 | 165 | ||
165 | read_lock_irqsave(&rs->rs_recv_lock, flags); | 166 | read_lock_irqsave(&rs->rs_recv_lock, flags); |
166 | if (!rs->rs_cong_monitor) { | 167 | if (!rs->rs_cong_monitor) { |
@@ -182,6 +183,10 @@ static unsigned int rds_poll(struct file *file, struct socket *sock, | |||
182 | mask |= (POLLOUT | POLLWRNORM); | 183 | mask |= (POLLOUT | POLLWRNORM); |
183 | read_unlock_irqrestore(&rs->rs_recv_lock, flags); | 184 | read_unlock_irqrestore(&rs->rs_recv_lock, flags); |
184 | 185 | ||
186 | /* clear state any time we wake a seen-congested socket */ | ||
187 | if (mask) | ||
188 | rs->rs_seen_congestion = 0; | ||
189 | |||
185 | return mask; | 190 | return mask; |
186 | } | 191 | } |
187 | 192 | ||
@@ -447,7 +452,6 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, | |||
447 | struct rds_info_lengths *lens) | 452 | struct rds_info_lengths *lens) |
448 | { | 453 | { |
449 | struct rds_sock *rs; | 454 | struct rds_sock *rs; |
450 | struct sock *sk; | ||
451 | struct rds_incoming *inc; | 455 | struct rds_incoming *inc; |
452 | unsigned long flags; | 456 | unsigned long flags; |
453 | unsigned int total = 0; | 457 | unsigned int total = 0; |
@@ -457,7 +461,6 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, | |||
457 | spin_lock_irqsave(&rds_sock_lock, flags); | 461 | spin_lock_irqsave(&rds_sock_lock, flags); |
458 | 462 | ||
459 | list_for_each_entry(rs, &rds_sock_list, rs_item) { | 463 | list_for_each_entry(rs, &rds_sock_list, rs_item) { |
460 | sk = rds_rs_to_sk(rs); | ||
461 | read_lock(&rs->rs_recv_lock); | 464 | read_lock(&rs->rs_recv_lock); |
462 | 465 | ||
463 | /* XXX too lazy to maintain counts.. */ | 466 | /* XXX too lazy to maintain counts.. */ |
diff --git a/net/rds/cong.c b/net/rds/cong.c index f1da27ceb064..0871a29f0780 100644 --- a/net/rds/cong.c +++ b/net/rds/cong.c | |||
@@ -219,8 +219,6 @@ void rds_cong_queue_updates(struct rds_cong_map *map) | |||
219 | spin_lock_irqsave(&rds_cong_lock, flags); | 219 | spin_lock_irqsave(&rds_cong_lock, flags); |
220 | 220 | ||
221 | list_for_each_entry(conn, &map->m_conn_list, c_map_item) { | 221 | list_for_each_entry(conn, &map->m_conn_list, c_map_item) { |
222 | if (conn->c_loopback) | ||
223 | continue; | ||
224 | if (!test_and_set_bit(0, &conn->c_map_queued)) { | 222 | if (!test_and_set_bit(0, &conn->c_map_queued)) { |
225 | rds_stats_inc(s_cong_update_queued); | 223 | rds_stats_inc(s_cong_update_queued); |
226 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); | 224 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); |
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 88d0856cb797..10ed0d55f759 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
@@ -204,9 +204,10 @@ static void rds_ib_qp_event_handler(struct ib_event *event, void *data) | |||
204 | rdma_notify(ic->i_cm_id, IB_EVENT_COMM_EST); | 204 | rdma_notify(ic->i_cm_id, IB_EVENT_COMM_EST); |
205 | break; | 205 | break; |
206 | default: | 206 | default: |
207 | rds_ib_conn_error(conn, "RDS/IB: Fatal QP Event %u " | 207 | rdsdebug("Fatal QP Event %u " |
208 | "- connection %pI4->%pI4, reconnecting\n", | 208 | "- connection %pI4->%pI4, reconnecting\n", |
209 | event->event, &conn->c_laddr, &conn->c_faddr); | 209 | event->event, &conn->c_laddr, &conn->c_faddr); |
210 | rds_conn_drop(conn); | ||
210 | break; | 211 | break; |
211 | } | 212 | } |
212 | } | 213 | } |
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c index 059989fdb7d7..a54cd63f9e35 100644 --- a/net/rds/ib_rdma.c +++ b/net/rds/ib_rdma.c | |||
@@ -235,8 +235,8 @@ void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *pool) | |||
235 | { | 235 | { |
236 | flush_workqueue(rds_wq); | 236 | flush_workqueue(rds_wq); |
237 | rds_ib_flush_mr_pool(pool, 1); | 237 | rds_ib_flush_mr_pool(pool, 1); |
238 | BUG_ON(atomic_read(&pool->item_count)); | 238 | WARN_ON(atomic_read(&pool->item_count)); |
239 | BUG_ON(atomic_read(&pool->free_pinned)); | 239 | WARN_ON(atomic_read(&pool->free_pinned)); |
240 | kfree(pool); | 240 | kfree(pool); |
241 | } | 241 | } |
242 | 242 | ||
@@ -441,6 +441,7 @@ static void __rds_ib_teardown_mr(struct rds_ib_mr *ibmr) | |||
441 | 441 | ||
442 | /* FIXME we need a way to tell a r/w MR | 442 | /* FIXME we need a way to tell a r/w MR |
443 | * from a r/o MR */ | 443 | * from a r/o MR */ |
444 | BUG_ON(in_interrupt()); | ||
444 | set_page_dirty(page); | 445 | set_page_dirty(page); |
445 | put_page(page); | 446 | put_page(page); |
446 | } | 447 | } |
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index c7dd11b835f0..c74e9904a6b2 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c | |||
@@ -469,8 +469,8 @@ static void rds_ib_send_ack(struct rds_ib_connection *ic, unsigned int adv_credi | |||
469 | set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags); | 469 | set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags); |
470 | 470 | ||
471 | rds_ib_stats_inc(s_ib_ack_send_failure); | 471 | rds_ib_stats_inc(s_ib_ack_send_failure); |
472 | /* Need to finesse this later. */ | 472 | |
473 | BUG(); | 473 | rds_ib_conn_error(ic->conn, "sending ack failed\n"); |
474 | } else | 474 | } else |
475 | rds_ib_stats_inc(s_ib_ack_sent); | 475 | rds_ib_stats_inc(s_ib_ack_sent); |
476 | } | 476 | } |
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index a10fab6886d1..17fa80803ab0 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c | |||
@@ -243,8 +243,12 @@ void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context) | |||
243 | struct rds_message *rm; | 243 | struct rds_message *rm; |
244 | 244 | ||
245 | rm = rds_send_get_message(conn, send->s_op); | 245 | rm = rds_send_get_message(conn, send->s_op); |
246 | if (rm) | 246 | if (rm) { |
247 | if (rm->m_rdma_op) | ||
248 | rds_ib_send_unmap_rdma(ic, rm->m_rdma_op); | ||
247 | rds_ib_send_rdma_complete(rm, wc.status); | 249 | rds_ib_send_rdma_complete(rm, wc.status); |
250 | rds_message_put(rm); | ||
251 | } | ||
248 | } | 252 | } |
249 | 253 | ||
250 | oldest = (oldest + 1) % ic->i_send_ring.w_nr; | 254 | oldest = (oldest + 1) % ic->i_send_ring.w_nr; |
@@ -482,6 +486,13 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, | |||
482 | BUG_ON(off % RDS_FRAG_SIZE); | 486 | BUG_ON(off % RDS_FRAG_SIZE); |
483 | BUG_ON(hdr_off != 0 && hdr_off != sizeof(struct rds_header)); | 487 | BUG_ON(hdr_off != 0 && hdr_off != sizeof(struct rds_header)); |
484 | 488 | ||
489 | /* Do not send cong updates to IB loopback */ | ||
490 | if (conn->c_loopback | ||
491 | && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { | ||
492 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); | ||
493 | return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; | ||
494 | } | ||
495 | |||
485 | /* FIXME we may overallocate here */ | 496 | /* FIXME we may overallocate here */ |
486 | if (be32_to_cpu(rm->m_inc.i_hdr.h_len) == 0) | 497 | if (be32_to_cpu(rm->m_inc.i_hdr.h_len) == 0) |
487 | i = 1; | 498 | i = 1; |
@@ -574,8 +585,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, | |||
574 | rds_ib_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); | 585 | rds_ib_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); |
575 | adv_credits += posted; | 586 | adv_credits += posted; |
576 | BUG_ON(adv_credits > 255); | 587 | BUG_ON(adv_credits > 255); |
577 | } else if (ic->i_rm != rm) | 588 | } |
578 | BUG(); | ||
579 | 589 | ||
580 | send = &ic->i_sends[pos]; | 590 | send = &ic->i_sends[pos]; |
581 | first = send; | 591 | first = send; |
@@ -714,8 +724,8 @@ add_header: | |||
714 | ic->i_rm = prev->s_rm; | 724 | ic->i_rm = prev->s_rm; |
715 | prev->s_rm = NULL; | 725 | prev->s_rm = NULL; |
716 | } | 726 | } |
717 | /* Finesse this later */ | 727 | |
718 | BUG(); | 728 | rds_ib_conn_error(ic->conn, "ib_post_send failed\n"); |
719 | goto out; | 729 | goto out; |
720 | } | 730 | } |
721 | 731 | ||
diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c index 3e9460f935d8..a9d951b4fbae 100644 --- a/net/rds/iw_cm.c +++ b/net/rds/iw_cm.c | |||
@@ -157,9 +157,11 @@ static void rds_iw_qp_event_handler(struct ib_event *event, void *data) | |||
157 | case IB_EVENT_QP_REQ_ERR: | 157 | case IB_EVENT_QP_REQ_ERR: |
158 | case IB_EVENT_QP_FATAL: | 158 | case IB_EVENT_QP_FATAL: |
159 | default: | 159 | default: |
160 | rds_iw_conn_error(conn, "RDS/IW: Fatal QP Event %u - connection %pI4->%pI4...reconnecting\n", | 160 | rdsdebug("Fatal QP Event %u " |
161 | "- connection %pI4->%pI4, reconnecting\n", | ||
161 | event->event, &conn->c_laddr, | 162 | event->event, &conn->c_laddr, |
162 | &conn->c_faddr); | 163 | &conn->c_faddr); |
164 | rds_conn_drop(conn); | ||
163 | break; | 165 | break; |
164 | } | 166 | } |
165 | } | 167 | } |
diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c index da43ee840ca3..3d479067d54d 100644 --- a/net/rds/iw_recv.c +++ b/net/rds/iw_recv.c | |||
@@ -469,8 +469,8 @@ static void rds_iw_send_ack(struct rds_iw_connection *ic, unsigned int adv_credi | |||
469 | set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags); | 469 | set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags); |
470 | 470 | ||
471 | rds_iw_stats_inc(s_iw_ack_send_failure); | 471 | rds_iw_stats_inc(s_iw_ack_send_failure); |
472 | /* Need to finesse this later. */ | 472 | |
473 | BUG(); | 473 | rds_iw_conn_error(ic->conn, "sending ack failed\n"); |
474 | } else | 474 | } else |
475 | rds_iw_stats_inc(s_iw_ack_sent); | 475 | rds_iw_stats_inc(s_iw_ack_sent); |
476 | } | 476 | } |
diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c index 1379e9d66a78..52182ff7519e 100644 --- a/net/rds/iw_send.c +++ b/net/rds/iw_send.c | |||
@@ -616,8 +616,7 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm, | |||
616 | rds_iw_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); | 616 | rds_iw_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); |
617 | adv_credits += posted; | 617 | adv_credits += posted; |
618 | BUG_ON(adv_credits > 255); | 618 | BUG_ON(adv_credits > 255); |
619 | } else if (ic->i_rm != rm) | 619 | } |
620 | BUG(); | ||
621 | 620 | ||
622 | send = &ic->i_sends[pos]; | 621 | send = &ic->i_sends[pos]; |
623 | first = send; | 622 | first = send; |
diff --git a/net/rds/loop.c b/net/rds/loop.c index 0d7a159158b8..dd9879379457 100644 --- a/net/rds/loop.c +++ b/net/rds/loop.c | |||
@@ -81,16 +81,9 @@ static int rds_loop_xmit_cong_map(struct rds_connection *conn, | |||
81 | struct rds_cong_map *map, | 81 | struct rds_cong_map *map, |
82 | unsigned long offset) | 82 | unsigned long offset) |
83 | { | 83 | { |
84 | unsigned long i; | ||
85 | |||
86 | BUG_ON(offset); | 84 | BUG_ON(offset); |
87 | BUG_ON(map != conn->c_lcong); | 85 | BUG_ON(map != conn->c_lcong); |
88 | 86 | ||
89 | for (i = 0; i < RDS_CONG_MAP_PAGES; i++) { | ||
90 | memcpy((void *)conn->c_fcong->m_page_addrs[i], | ||
91 | (void *)map->m_page_addrs[i], PAGE_SIZE); | ||
92 | } | ||
93 | |||
94 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); | 87 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); |
95 | 88 | ||
96 | return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; | 89 | return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; |
diff --git a/net/rds/rdma.c b/net/rds/rdma.c index 5ce9437cad67..75fd13bb631b 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c | |||
@@ -439,8 +439,10 @@ void rds_rdma_free_op(struct rds_rdma_op *ro) | |||
439 | /* Mark page dirty if it was possibly modified, which | 439 | /* Mark page dirty if it was possibly modified, which |
440 | * is the case for a RDMA_READ which copies from remote | 440 | * is the case for a RDMA_READ which copies from remote |
441 | * to local memory */ | 441 | * to local memory */ |
442 | if (!ro->r_write) | 442 | if (!ro->r_write) { |
443 | BUG_ON(in_interrupt()); | ||
443 | set_page_dirty(page); | 444 | set_page_dirty(page); |
445 | } | ||
444 | put_page(page); | 446 | put_page(page); |
445 | } | 447 | } |
446 | 448 | ||
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index 7b155081b4dc..e599ba2f950d 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c | |||
@@ -101,7 +101,7 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id, | |||
101 | break; | 101 | break; |
102 | 102 | ||
103 | case RDMA_CM_EVENT_DISCONNECTED: | 103 | case RDMA_CM_EVENT_DISCONNECTED: |
104 | printk(KERN_WARNING "RDS/RDMA: DISCONNECT event - dropping connection " | 104 | rdsdebug("DISCONNECT event - dropping connection " |
105 | "%pI4->%pI4\n", &conn->c_laddr, | 105 | "%pI4->%pI4\n", &conn->c_laddr, |
106 | &conn->c_faddr); | 106 | &conn->c_faddr); |
107 | rds_conn_drop(conn); | 107 | rds_conn_drop(conn); |
@@ -109,8 +109,7 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id, | |||
109 | 109 | ||
110 | default: | 110 | default: |
111 | /* things like device disconnect? */ | 111 | /* things like device disconnect? */ |
112 | printk(KERN_ERR "unknown event %u\n", event->event); | 112 | printk(KERN_ERR "RDS: unknown event %u!\n", event->event); |
113 | BUG(); | ||
114 | break; | 113 | break; |
115 | } | 114 | } |
116 | 115 | ||
diff --git a/net/rds/rds.h b/net/rds/rds.h index 85d6f897ecc7..c224b5bb3ba9 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h | |||
@@ -388,6 +388,8 @@ struct rds_sock { | |||
388 | 388 | ||
389 | /* flag indicating we were congested or not */ | 389 | /* flag indicating we were congested or not */ |
390 | int rs_congested; | 390 | int rs_congested; |
391 | /* seen congestion (ENOBUFS) when sending? */ | ||
392 | int rs_seen_congestion; | ||
391 | 393 | ||
392 | /* rs_lock protects all these adjacent members before the newline */ | 394 | /* rs_lock protects all these adjacent members before the newline */ |
393 | spinlock_t rs_lock; | 395 | spinlock_t rs_lock; |
@@ -490,7 +492,7 @@ void rds_sock_put(struct rds_sock *rs); | |||
490 | void rds_wake_sk_sleep(struct rds_sock *rs); | 492 | void rds_wake_sk_sleep(struct rds_sock *rs); |
491 | static inline void __rds_wake_sk_sleep(struct sock *sk) | 493 | static inline void __rds_wake_sk_sleep(struct sock *sk) |
492 | { | 494 | { |
493 | wait_queue_head_t *waitq = sk->sk_sleep; | 495 | wait_queue_head_t *waitq = sk_sleep(sk); |
494 | 496 | ||
495 | if (!sock_flag(sk, SOCK_DEAD) && waitq) | 497 | if (!sock_flag(sk, SOCK_DEAD) && waitq) |
496 | wake_up(waitq); | 498 | wake_up(waitq); |
diff --git a/net/rds/recv.c b/net/rds/recv.c index e2a2b9344f7b..795a00b7f2cb 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c | |||
@@ -432,7 +432,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
432 | break; | 432 | break; |
433 | } | 433 | } |
434 | 434 | ||
435 | timeo = wait_event_interruptible_timeout(*sk->sk_sleep, | 435 | timeo = wait_event_interruptible_timeout(*sk_sleep(sk), |
436 | (!list_empty(&rs->rs_notify_queue) || | 436 | (!list_empty(&rs->rs_notify_queue) || |
437 | rs->rs_cong_notify || | 437 | rs->rs_cong_notify || |
438 | rds_next_incoming(rs, &inc)), timeo); | 438 | rds_next_incoming(rs, &inc)), timeo); |
diff --git a/net/rds/send.c b/net/rds/send.c index f04b929ded92..9c1c6bcaa6c9 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
@@ -508,12 +508,13 @@ EXPORT_SYMBOL_GPL(rds_send_get_message); | |||
508 | */ | 508 | */ |
509 | void rds_send_remove_from_sock(struct list_head *messages, int status) | 509 | void rds_send_remove_from_sock(struct list_head *messages, int status) |
510 | { | 510 | { |
511 | unsigned long flags = 0; /* silence gcc :P */ | 511 | unsigned long flags; |
512 | struct rds_sock *rs = NULL; | 512 | struct rds_sock *rs = NULL; |
513 | struct rds_message *rm; | 513 | struct rds_message *rm; |
514 | 514 | ||
515 | local_irq_save(flags); | ||
516 | while (!list_empty(messages)) { | 515 | while (!list_empty(messages)) { |
516 | int was_on_sock = 0; | ||
517 | |||
517 | rm = list_entry(messages->next, struct rds_message, | 518 | rm = list_entry(messages->next, struct rds_message, |
518 | m_conn_item); | 519 | m_conn_item); |
519 | list_del_init(&rm->m_conn_item); | 520 | list_del_init(&rm->m_conn_item); |
@@ -528,20 +529,19 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) | |||
528 | * while we're messing with it. It does not prevent the | 529 | * while we're messing with it. It does not prevent the |
529 | * message from being removed from the socket, though. | 530 | * message from being removed from the socket, though. |
530 | */ | 531 | */ |
531 | spin_lock(&rm->m_rs_lock); | 532 | spin_lock_irqsave(&rm->m_rs_lock, flags); |
532 | if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) | 533 | if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) |
533 | goto unlock_and_drop; | 534 | goto unlock_and_drop; |
534 | 535 | ||
535 | if (rs != rm->m_rs) { | 536 | if (rs != rm->m_rs) { |
536 | if (rs) { | 537 | if (rs) { |
537 | spin_unlock(&rs->rs_lock); | ||
538 | rds_wake_sk_sleep(rs); | 538 | rds_wake_sk_sleep(rs); |
539 | sock_put(rds_rs_to_sk(rs)); | 539 | sock_put(rds_rs_to_sk(rs)); |
540 | } | 540 | } |
541 | rs = rm->m_rs; | 541 | rs = rm->m_rs; |
542 | spin_lock(&rs->rs_lock); | ||
543 | sock_hold(rds_rs_to_sk(rs)); | 542 | sock_hold(rds_rs_to_sk(rs)); |
544 | } | 543 | } |
544 | spin_lock(&rs->rs_lock); | ||
545 | 545 | ||
546 | if (test_and_clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) { | 546 | if (test_and_clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) { |
547 | struct rds_rdma_op *ro = rm->m_rdma_op; | 547 | struct rds_rdma_op *ro = rm->m_rdma_op; |
@@ -558,21 +558,22 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) | |||
558 | notifier->n_status = status; | 558 | notifier->n_status = status; |
559 | rm->m_rdma_op->r_notifier = NULL; | 559 | rm->m_rdma_op->r_notifier = NULL; |
560 | } | 560 | } |
561 | rds_message_put(rm); | 561 | was_on_sock = 1; |
562 | rm->m_rs = NULL; | 562 | rm->m_rs = NULL; |
563 | } | 563 | } |
564 | spin_unlock(&rs->rs_lock); | ||
564 | 565 | ||
565 | unlock_and_drop: | 566 | unlock_and_drop: |
566 | spin_unlock(&rm->m_rs_lock); | 567 | spin_unlock_irqrestore(&rm->m_rs_lock, flags); |
567 | rds_message_put(rm); | 568 | rds_message_put(rm); |
569 | if (was_on_sock) | ||
570 | rds_message_put(rm); | ||
568 | } | 571 | } |
569 | 572 | ||
570 | if (rs) { | 573 | if (rs) { |
571 | spin_unlock(&rs->rs_lock); | ||
572 | rds_wake_sk_sleep(rs); | 574 | rds_wake_sk_sleep(rs); |
573 | sock_put(rds_rs_to_sk(rs)); | 575 | sock_put(rds_rs_to_sk(rs)); |
574 | } | 576 | } |
575 | local_irq_restore(flags); | ||
576 | } | 577 | } |
577 | 578 | ||
578 | /* | 579 | /* |
@@ -634,9 +635,6 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
634 | list_move(&rm->m_sock_item, &list); | 635 | list_move(&rm->m_sock_item, &list); |
635 | rds_send_sndbuf_remove(rs, rm); | 636 | rds_send_sndbuf_remove(rs, rm); |
636 | clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags); | 637 | clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags); |
637 | |||
638 | /* If this is a RDMA operation, notify the app. */ | ||
639 | __rds_rdma_send_complete(rs, rm, RDS_RDMA_CANCELED); | ||
640 | } | 638 | } |
641 | 639 | ||
642 | /* order flag updates with the rs lock */ | 640 | /* order flag updates with the rs lock */ |
@@ -645,9 +643,6 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
645 | 643 | ||
646 | spin_unlock_irqrestore(&rs->rs_lock, flags); | 644 | spin_unlock_irqrestore(&rs->rs_lock, flags); |
647 | 645 | ||
648 | if (wake) | ||
649 | rds_wake_sk_sleep(rs); | ||
650 | |||
651 | conn = NULL; | 646 | conn = NULL; |
652 | 647 | ||
653 | /* now remove the messages from the conn list as needed */ | 648 | /* now remove the messages from the conn list as needed */ |
@@ -655,6 +650,10 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
655 | /* We do this here rather than in the loop above, so that | 650 | /* We do this here rather than in the loop above, so that |
656 | * we don't have to nest m_rs_lock under rs->rs_lock */ | 651 | * we don't have to nest m_rs_lock under rs->rs_lock */ |
657 | spin_lock_irqsave(&rm->m_rs_lock, flags2); | 652 | spin_lock_irqsave(&rm->m_rs_lock, flags2); |
653 | /* If this is a RDMA operation, notify the app. */ | ||
654 | spin_lock(&rs->rs_lock); | ||
655 | __rds_rdma_send_complete(rs, rm, RDS_RDMA_CANCELED); | ||
656 | spin_unlock(&rs->rs_lock); | ||
658 | rm->m_rs = NULL; | 657 | rm->m_rs = NULL; |
659 | spin_unlock_irqrestore(&rm->m_rs_lock, flags2); | 658 | spin_unlock_irqrestore(&rm->m_rs_lock, flags2); |
660 | 659 | ||
@@ -683,6 +682,9 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
683 | if (conn) | 682 | if (conn) |
684 | spin_unlock_irqrestore(&conn->c_lock, flags); | 683 | spin_unlock_irqrestore(&conn->c_lock, flags); |
685 | 684 | ||
685 | if (wake) | ||
686 | rds_wake_sk_sleep(rs); | ||
687 | |||
686 | while (!list_empty(&list)) { | 688 | while (!list_empty(&list)) { |
687 | rm = list_entry(list.next, struct rds_message, m_sock_item); | 689 | rm = list_entry(list.next, struct rds_message, m_sock_item); |
688 | list_del_init(&rm->m_sock_item); | 690 | list_del_init(&rm->m_sock_item); |
@@ -816,7 +818,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
816 | int ret = 0; | 818 | int ret = 0; |
817 | int queued = 0, allocated_mr = 0; | 819 | int queued = 0, allocated_mr = 0; |
818 | int nonblock = msg->msg_flags & MSG_DONTWAIT; | 820 | int nonblock = msg->msg_flags & MSG_DONTWAIT; |
819 | long timeo = sock_rcvtimeo(sk, nonblock); | 821 | long timeo = sock_sndtimeo(sk, nonblock); |
820 | 822 | ||
821 | /* Mirror Linux UDP mirror of BSD error message compatibility */ | 823 | /* Mirror Linux UDP mirror of BSD error message compatibility */ |
822 | /* XXX: Perhaps MSG_MORE someday */ | 824 | /* XXX: Perhaps MSG_MORE someday */ |
@@ -895,8 +897,10 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
895 | queue_delayed_work(rds_wq, &conn->c_conn_w, 0); | 897 | queue_delayed_work(rds_wq, &conn->c_conn_w, 0); |
896 | 898 | ||
897 | ret = rds_cong_wait(conn->c_fcong, dport, nonblock, rs); | 899 | ret = rds_cong_wait(conn->c_fcong, dport, nonblock, rs); |
898 | if (ret) | 900 | if (ret) { |
901 | rs->rs_seen_congestion = 1; | ||
899 | goto out; | 902 | goto out; |
903 | } | ||
900 | 904 | ||
901 | while (!rds_send_queue_rm(rs, conn, rm, rs->rs_bound_port, | 905 | while (!rds_send_queue_rm(rs, conn, rm, rs->rs_bound_port, |
902 | dport, &queued)) { | 906 | dport, &queued)) { |
@@ -911,7 +915,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
911 | goto out; | 915 | goto out; |
912 | } | 916 | } |
913 | 917 | ||
914 | timeo = wait_event_interruptible_timeout(*sk->sk_sleep, | 918 | timeo = wait_event_interruptible_timeout(*sk_sleep(sk), |
915 | rds_send_queue_rm(rs, conn, rm, | 919 | rds_send_queue_rm(rs, conn, rm, |
916 | rs->rs_bound_port, | 920 | rs->rs_bound_port, |
917 | dport, | 921 | dport, |
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c index 056256285987..c397524c039c 100644 --- a/net/rds/tcp_connect.c +++ b/net/rds/tcp_connect.c | |||
@@ -141,7 +141,7 @@ void rds_tcp_conn_shutdown(struct rds_connection *conn) | |||
141 | 141 | ||
142 | release_sock(sock->sk); | 142 | release_sock(sock->sk); |
143 | sock_release(sock); | 143 | sock_release(sock); |
144 | }; | 144 | } |
145 | 145 | ||
146 | if (tc->t_tinc) { | 146 | if (tc->t_tinc) { |
147 | rds_inc_put(&tc->t_tinc->ti_inc); | 147 | rds_inc_put(&tc->t_tinc->ti_inc); |
diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c index e08ec912d8b0..1aba6878fa5d 100644 --- a/net/rds/tcp_recv.c +++ b/net/rds/tcp_recv.c | |||
@@ -98,6 +98,7 @@ int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov, | |||
98 | goto out; | 98 | goto out; |
99 | } | 99 | } |
100 | 100 | ||
101 | rds_stats_add(s_copy_to_user, to_copy); | ||
101 | size -= to_copy; | 102 | size -= to_copy; |
102 | ret += to_copy; | 103 | ret += to_copy; |
103 | skb_off += to_copy; | 104 | skb_off += to_copy; |
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c index 34fdcc059e54..a28b895ff0d1 100644 --- a/net/rds/tcp_send.c +++ b/net/rds/tcp_send.c | |||
@@ -240,7 +240,9 @@ void rds_tcp_write_space(struct sock *sk) | |||
240 | tc->t_last_seen_una = rds_tcp_snd_una(tc); | 240 | tc->t_last_seen_una = rds_tcp_snd_una(tc); |
241 | rds_send_drop_acked(conn, rds_tcp_snd_una(tc), rds_tcp_is_acked); | 241 | rds_send_drop_acked(conn, rds_tcp_snd_una(tc), rds_tcp_is_acked); |
242 | 242 | ||
243 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); | 243 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) |
244 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); | ||
245 | |||
244 | out: | 246 | out: |
245 | read_unlock(&sk->sk_callback_lock); | 247 | read_unlock(&sk->sk_callback_lock); |
246 | 248 | ||
diff --git a/net/rds/threads.c b/net/rds/threads.c index 00fa10e59af8..786c20eaaf5e 100644 --- a/net/rds/threads.c +++ b/net/rds/threads.c | |||
@@ -259,7 +259,7 @@ void rds_threads_exit(void) | |||
259 | 259 | ||
260 | int __init rds_threads_init(void) | 260 | int __init rds_threads_init(void) |
261 | { | 261 | { |
262 | rds_wq = create_singlethread_workqueue("krdsd"); | 262 | rds_wq = create_workqueue("krdsd"); |
263 | if (rds_wq == NULL) | 263 | if (rds_wq == NULL) |
264 | return -ENOMEM; | 264 | return -ENOMEM; |
265 | 265 | ||
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index a9fa86f65983..51875a0c5d48 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -629,6 +629,49 @@ static ssize_t rfkill_persistent_show(struct device *dev, | |||
629 | return sprintf(buf, "%d\n", rfkill->persistent); | 629 | return sprintf(buf, "%d\n", rfkill->persistent); |
630 | } | 630 | } |
631 | 631 | ||
632 | static ssize_t rfkill_hard_show(struct device *dev, | ||
633 | struct device_attribute *attr, | ||
634 | char *buf) | ||
635 | { | ||
636 | struct rfkill *rfkill = to_rfkill(dev); | ||
637 | |||
638 | return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 ); | ||
639 | } | ||
640 | |||
641 | static ssize_t rfkill_soft_show(struct device *dev, | ||
642 | struct device_attribute *attr, | ||
643 | char *buf) | ||
644 | { | ||
645 | struct rfkill *rfkill = to_rfkill(dev); | ||
646 | |||
647 | return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 ); | ||
648 | } | ||
649 | |||
650 | static ssize_t rfkill_soft_store(struct device *dev, | ||
651 | struct device_attribute *attr, | ||
652 | const char *buf, size_t count) | ||
653 | { | ||
654 | struct rfkill *rfkill = to_rfkill(dev); | ||
655 | unsigned long state; | ||
656 | int err; | ||
657 | |||
658 | if (!capable(CAP_NET_ADMIN)) | ||
659 | return -EPERM; | ||
660 | |||
661 | err = strict_strtoul(buf, 0, &state); | ||
662 | if (err) | ||
663 | return err; | ||
664 | |||
665 | if (state > 1 ) | ||
666 | return -EINVAL; | ||
667 | |||
668 | mutex_lock(&rfkill_global_mutex); | ||
669 | rfkill_set_block(rfkill, state); | ||
670 | mutex_unlock(&rfkill_global_mutex); | ||
671 | |||
672 | return err ?: count; | ||
673 | } | ||
674 | |||
632 | static u8 user_state_from_blocked(unsigned long state) | 675 | static u8 user_state_from_blocked(unsigned long state) |
633 | { | 676 | { |
634 | if (state & RFKILL_BLOCK_HW) | 677 | if (state & RFKILL_BLOCK_HW) |
@@ -644,14 +687,8 @@ static ssize_t rfkill_state_show(struct device *dev, | |||
644 | char *buf) | 687 | char *buf) |
645 | { | 688 | { |
646 | struct rfkill *rfkill = to_rfkill(dev); | 689 | struct rfkill *rfkill = to_rfkill(dev); |
647 | unsigned long flags; | ||
648 | u32 state; | ||
649 | |||
650 | spin_lock_irqsave(&rfkill->lock, flags); | ||
651 | state = rfkill->state; | ||
652 | spin_unlock_irqrestore(&rfkill->lock, flags); | ||
653 | 690 | ||
654 | return sprintf(buf, "%d\n", user_state_from_blocked(state)); | 691 | return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state)); |
655 | } | 692 | } |
656 | 693 | ||
657 | static ssize_t rfkill_state_store(struct device *dev, | 694 | static ssize_t rfkill_state_store(struct device *dev, |
@@ -701,6 +738,8 @@ static struct device_attribute rfkill_dev_attrs[] = { | |||
701 | __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), | 738 | __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), |
702 | __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), | 739 | __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), |
703 | __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), | 740 | __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), |
741 | __ATTR(soft, S_IRUGO|S_IWUSR, rfkill_soft_show, rfkill_soft_store), | ||
742 | __ATTR(hard, S_IRUGO, rfkill_hard_show, NULL), | ||
704 | __ATTR_NULL | 743 | __ATTR_NULL |
705 | }; | 744 | }; |
706 | 745 | ||
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 4fb711a035f4..8e45e76a95f5 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -845,7 +845,7 @@ rose_try_next_neigh: | |||
845 | DEFINE_WAIT(wait); | 845 | DEFINE_WAIT(wait); |
846 | 846 | ||
847 | for (;;) { | 847 | for (;;) { |
848 | prepare_to_wait(sk->sk_sleep, &wait, | 848 | prepare_to_wait(sk_sleep(sk), &wait, |
849 | TASK_INTERRUPTIBLE); | 849 | TASK_INTERRUPTIBLE); |
850 | if (sk->sk_state != TCP_SYN_SENT) | 850 | if (sk->sk_state != TCP_SYN_SENT) |
851 | break; | 851 | break; |
@@ -858,7 +858,7 @@ rose_try_next_neigh: | |||
858 | err = -ERESTARTSYS; | 858 | err = -ERESTARTSYS; |
859 | break; | 859 | break; |
860 | } | 860 | } |
861 | finish_wait(sk->sk_sleep, &wait); | 861 | finish_wait(sk_sleep(sk), &wait); |
862 | 862 | ||
863 | if (err) | 863 | if (err) |
864 | goto out_release; | 864 | goto out_release; |
@@ -911,7 +911,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) | |||
911 | * hooked into the SABM we saved | 911 | * hooked into the SABM we saved |
912 | */ | 912 | */ |
913 | for (;;) { | 913 | for (;;) { |
914 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 914 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
915 | 915 | ||
916 | skb = skb_dequeue(&sk->sk_receive_queue); | 916 | skb = skb_dequeue(&sk->sk_receive_queue); |
917 | if (skb) | 917 | if (skb) |
@@ -930,7 +930,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) | |||
930 | err = -ERESTARTSYS; | 930 | err = -ERESTARTSYS; |
931 | break; | 931 | break; |
932 | } | 932 | } |
933 | finish_wait(sk->sk_sleep, &wait); | 933 | finish_wait(sk_sleep(sk), &wait); |
934 | if (err) | 934 | if (err) |
935 | goto out_release; | 935 | goto out_release; |
936 | 936 | ||
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index c060095b27ce..0b9bb2085ce4 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -62,13 +62,15 @@ static inline int rxrpc_writable(struct sock *sk) | |||
62 | static void rxrpc_write_space(struct sock *sk) | 62 | static void rxrpc_write_space(struct sock *sk) |
63 | { | 63 | { |
64 | _enter("%p", sk); | 64 | _enter("%p", sk); |
65 | read_lock(&sk->sk_callback_lock); | 65 | rcu_read_lock(); |
66 | if (rxrpc_writable(sk)) { | 66 | if (rxrpc_writable(sk)) { |
67 | if (sk_has_sleeper(sk)) | 67 | struct socket_wq *wq = rcu_dereference(sk->sk_wq); |
68 | wake_up_interruptible(sk->sk_sleep); | 68 | |
69 | if (wq_has_sleeper(wq)) | ||
70 | wake_up_interruptible(&wq->wait); | ||
69 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 71 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
70 | } | 72 | } |
71 | read_unlock(&sk->sk_callback_lock); | 73 | rcu_read_unlock(); |
72 | } | 74 | } |
73 | 75 | ||
74 | /* | 76 | /* |
@@ -589,7 +591,7 @@ static unsigned int rxrpc_poll(struct file *file, struct socket *sock, | |||
589 | unsigned int mask; | 591 | unsigned int mask; |
590 | struct sock *sk = sock->sk; | 592 | struct sock *sk = sock->sk; |
591 | 593 | ||
592 | sock_poll_wait(file, sk->sk_sleep, wait); | 594 | sock_poll_wait(file, sk_sleep(sk), wait); |
593 | mask = 0; | 595 | mask = 0; |
594 | 596 | ||
595 | /* the socket is readable if there are any messages waiting on the Rx | 597 | /* the socket is readable if there are any messages waiting on the Rx |
diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c index 60c2b94e6b54..0c65013e3bfe 100644 --- a/net/rxrpc/ar-recvmsg.c +++ b/net/rxrpc/ar-recvmsg.c | |||
@@ -91,7 +91,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
91 | 91 | ||
92 | /* wait for a message to turn up */ | 92 | /* wait for a message to turn up */ |
93 | release_sock(&rx->sk); | 93 | release_sock(&rx->sk); |
94 | prepare_to_wait_exclusive(rx->sk.sk_sleep, &wait, | 94 | prepare_to_wait_exclusive(sk_sleep(&rx->sk), &wait, |
95 | TASK_INTERRUPTIBLE); | 95 | TASK_INTERRUPTIBLE); |
96 | ret = sock_error(&rx->sk); | 96 | ret = sock_error(&rx->sk); |
97 | if (ret) | 97 | if (ret) |
@@ -102,7 +102,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
102 | goto wait_interrupted; | 102 | goto wait_interrupted; |
103 | timeo = schedule_timeout(timeo); | 103 | timeo = schedule_timeout(timeo); |
104 | } | 104 | } |
105 | finish_wait(rx->sk.sk_sleep, &wait); | 105 | finish_wait(sk_sleep(&rx->sk), &wait); |
106 | lock_sock(&rx->sk); | 106 | lock_sock(&rx->sk); |
107 | continue; | 107 | continue; |
108 | } | 108 | } |
@@ -356,7 +356,7 @@ csum_copy_error: | |||
356 | wait_interrupted: | 356 | wait_interrupted: |
357 | ret = sock_intr_errno(timeo); | 357 | ret = sock_intr_errno(timeo); |
358 | wait_error: | 358 | wait_error: |
359 | finish_wait(rx->sk.sk_sleep, &wait); | 359 | finish_wait(sk_sleep(&rx->sk), &wait); |
360 | if (continue_call) | 360 | if (continue_call) |
361 | rxrpc_put_call(continue_call); | 361 | rxrpc_put_call(continue_call); |
362 | if (copied) | 362 | if (copied) |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index d8e0171d9a4b..972378f47f3c 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -153,7 +153,7 @@ int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, | |||
153 | } else if (type == RTM_GETACTION) { | 153 | } else if (type == RTM_GETACTION) { |
154 | return tcf_dump_walker(skb, cb, a, hinfo); | 154 | return tcf_dump_walker(skb, cb, a, hinfo); |
155 | } else { | 155 | } else { |
156 | printk("tcf_generic_walker: unknown action %d\n", type); | 156 | WARN(1, "tcf_generic_walker: unknown action %d\n", type); |
157 | return -EINVAL; | 157 | return -EINVAL; |
158 | } | 158 | } |
159 | } | 159 | } |
@@ -403,8 +403,9 @@ void tcf_action_destroy(struct tc_action *act, int bind) | |||
403 | module_put(a->ops->owner); | 403 | module_put(a->ops->owner); |
404 | act = act->next; | 404 | act = act->next; |
405 | kfree(a); | 405 | kfree(a); |
406 | } else { /*FIXME: Remove later - catch insertion bugs*/ | 406 | } else { |
407 | printk("tcf_action_destroy: BUG? destroying NULL ops\n"); | 407 | /*FIXME: Remove later - catch insertion bugs*/ |
408 | WARN(1, "tcf_action_destroy: BUG? destroying NULL ops\n"); | ||
408 | act = act->next; | 409 | act = act->next; |
409 | kfree(a); | 410 | kfree(a); |
410 | } | 411 | } |
@@ -668,7 +669,8 @@ nlmsg_failure: | |||
668 | } | 669 | } |
669 | 670 | ||
670 | static int | 671 | static int |
671 | act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event) | 672 | act_get_notify(struct net *net, u32 pid, struct nlmsghdr *n, |
673 | struct tc_action *a, int event) | ||
672 | { | 674 | { |
673 | struct sk_buff *skb; | 675 | struct sk_buff *skb; |
674 | 676 | ||
@@ -680,7 +682,7 @@ act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event) | |||
680 | return -EINVAL; | 682 | return -EINVAL; |
681 | } | 683 | } |
682 | 684 | ||
683 | return rtnl_unicast(skb, &init_net, pid); | 685 | return rtnl_unicast(skb, net, pid); |
684 | } | 686 | } |
685 | 687 | ||
686 | static struct tc_action * | 688 | static struct tc_action * |
@@ -743,14 +745,15 @@ static struct tc_action *create_a(int i) | |||
743 | 745 | ||
744 | act = kzalloc(sizeof(*act), GFP_KERNEL); | 746 | act = kzalloc(sizeof(*act), GFP_KERNEL); |
745 | if (act == NULL) { | 747 | if (act == NULL) { |
746 | printk("create_a: failed to alloc!\n"); | 748 | pr_debug("create_a: failed to alloc!\n"); |
747 | return NULL; | 749 | return NULL; |
748 | } | 750 | } |
749 | act->order = i; | 751 | act->order = i; |
750 | return act; | 752 | return act; |
751 | } | 753 | } |
752 | 754 | ||
753 | static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid) | 755 | static int tca_action_flush(struct net *net, struct nlattr *nla, |
756 | struct nlmsghdr *n, u32 pid) | ||
754 | { | 757 | { |
755 | struct sk_buff *skb; | 758 | struct sk_buff *skb; |
756 | unsigned char *b; | 759 | unsigned char *b; |
@@ -764,13 +767,13 @@ static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid) | |||
764 | int err = -ENOMEM; | 767 | int err = -ENOMEM; |
765 | 768 | ||
766 | if (a == NULL) { | 769 | if (a == NULL) { |
767 | printk("tca_action_flush: couldnt create tc_action\n"); | 770 | pr_debug("tca_action_flush: couldnt create tc_action\n"); |
768 | return err; | 771 | return err; |
769 | } | 772 | } |
770 | 773 | ||
771 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 774 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
772 | if (!skb) { | 775 | if (!skb) { |
773 | printk("tca_action_flush: failed skb alloc\n"); | 776 | pr_debug("tca_action_flush: failed skb alloc\n"); |
774 | kfree(a); | 777 | kfree(a); |
775 | return err; | 778 | return err; |
776 | } | 779 | } |
@@ -809,7 +812,7 @@ static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid) | |||
809 | nlh->nlmsg_flags |= NLM_F_ROOT; | 812 | nlh->nlmsg_flags |= NLM_F_ROOT; |
810 | module_put(a->ops->owner); | 813 | module_put(a->ops->owner); |
811 | kfree(a); | 814 | kfree(a); |
812 | err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 815 | err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); |
813 | if (err > 0) | 816 | if (err > 0) |
814 | return 0; | 817 | return 0; |
815 | 818 | ||
@@ -826,7 +829,8 @@ noflush_out: | |||
826 | } | 829 | } |
827 | 830 | ||
828 | static int | 831 | static int |
829 | tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event) | 832 | tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, |
833 | u32 pid, int event) | ||
830 | { | 834 | { |
831 | int i, ret; | 835 | int i, ret; |
832 | struct nlattr *tb[TCA_ACT_MAX_PRIO+1]; | 836 | struct nlattr *tb[TCA_ACT_MAX_PRIO+1]; |
@@ -838,7 +842,7 @@ tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event) | |||
838 | 842 | ||
839 | if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) { | 843 | if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) { |
840 | if (tb[1] != NULL) | 844 | if (tb[1] != NULL) |
841 | return tca_action_flush(tb[1], n, pid); | 845 | return tca_action_flush(net, tb[1], n, pid); |
842 | else | 846 | else |
843 | return -EINVAL; | 847 | return -EINVAL; |
844 | } | 848 | } |
@@ -859,7 +863,7 @@ tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event) | |||
859 | } | 863 | } |
860 | 864 | ||
861 | if (event == RTM_GETACTION) | 865 | if (event == RTM_GETACTION) |
862 | ret = act_get_notify(pid, n, head, event); | 866 | ret = act_get_notify(net, pid, n, head, event); |
863 | else { /* delete */ | 867 | else { /* delete */ |
864 | struct sk_buff *skb; | 868 | struct sk_buff *skb; |
865 | 869 | ||
@@ -878,7 +882,7 @@ tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event) | |||
878 | 882 | ||
879 | /* now do the delete */ | 883 | /* now do the delete */ |
880 | tcf_action_destroy(head, 0); | 884 | tcf_action_destroy(head, 0); |
881 | ret = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, | 885 | ret = rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
882 | n->nlmsg_flags&NLM_F_ECHO); | 886 | n->nlmsg_flags&NLM_F_ECHO); |
883 | if (ret > 0) | 887 | if (ret > 0) |
884 | return 0; | 888 | return 0; |
@@ -889,8 +893,8 @@ err: | |||
889 | return ret; | 893 | return ret; |
890 | } | 894 | } |
891 | 895 | ||
892 | static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, | 896 | static int tcf_add_notify(struct net *net, struct tc_action *a, |
893 | u16 flags) | 897 | u32 pid, u32 seq, int event, u16 flags) |
894 | { | 898 | { |
895 | struct tcamsg *t; | 899 | struct tcamsg *t; |
896 | struct nlmsghdr *nlh; | 900 | struct nlmsghdr *nlh; |
@@ -923,7 +927,7 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, | |||
923 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; | 927 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
924 | NETLINK_CB(skb).dst_group = RTNLGRP_TC; | 928 | NETLINK_CB(skb).dst_group = RTNLGRP_TC; |
925 | 929 | ||
926 | err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, flags&NLM_F_ECHO); | 930 | err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, flags&NLM_F_ECHO); |
927 | if (err > 0) | 931 | if (err > 0) |
928 | err = 0; | 932 | err = 0; |
929 | return err; | 933 | return err; |
@@ -936,7 +940,8 @@ nlmsg_failure: | |||
936 | 940 | ||
937 | 941 | ||
938 | static int | 942 | static int |
939 | tcf_action_add(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int ovr) | 943 | tcf_action_add(struct net *net, struct nlattr *nla, struct nlmsghdr *n, |
944 | u32 pid, int ovr) | ||
940 | { | 945 | { |
941 | int ret = 0; | 946 | int ret = 0; |
942 | struct tc_action *act; | 947 | struct tc_action *act; |
@@ -954,7 +959,7 @@ tcf_action_add(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int ovr) | |||
954 | /* dump then free all the actions after update; inserted policy | 959 | /* dump then free all the actions after update; inserted policy |
955 | * stays intact | 960 | * stays intact |
956 | * */ | 961 | * */ |
957 | ret = tcf_add_notify(act, pid, seq, RTM_NEWACTION, n->nlmsg_flags); | 962 | ret = tcf_add_notify(net, act, pid, seq, RTM_NEWACTION, n->nlmsg_flags); |
958 | for (a = act; a; a = act) { | 963 | for (a = act; a; a = act) { |
959 | act = a->next; | 964 | act = a->next; |
960 | kfree(a); | 965 | kfree(a); |
@@ -970,15 +975,12 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
970 | u32 pid = skb ? NETLINK_CB(skb).pid : 0; | 975 | u32 pid = skb ? NETLINK_CB(skb).pid : 0; |
971 | int ret = 0, ovr = 0; | 976 | int ret = 0, ovr = 0; |
972 | 977 | ||
973 | if (!net_eq(net, &init_net)) | ||
974 | return -EINVAL; | ||
975 | |||
976 | ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL); | 978 | ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL); |
977 | if (ret < 0) | 979 | if (ret < 0) |
978 | return ret; | 980 | return ret; |
979 | 981 | ||
980 | if (tca[TCA_ACT_TAB] == NULL) { | 982 | if (tca[TCA_ACT_TAB] == NULL) { |
981 | printk("tc_ctl_action: received NO action attribs\n"); | 983 | pr_notice("tc_ctl_action: received NO action attribs\n"); |
982 | return -EINVAL; | 984 | return -EINVAL; |
983 | } | 985 | } |
984 | 986 | ||
@@ -995,15 +997,17 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
995 | if (n->nlmsg_flags&NLM_F_REPLACE) | 997 | if (n->nlmsg_flags&NLM_F_REPLACE) |
996 | ovr = 1; | 998 | ovr = 1; |
997 | replay: | 999 | replay: |
998 | ret = tcf_action_add(tca[TCA_ACT_TAB], n, pid, ovr); | 1000 | ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, pid, ovr); |
999 | if (ret == -EAGAIN) | 1001 | if (ret == -EAGAIN) |
1000 | goto replay; | 1002 | goto replay; |
1001 | break; | 1003 | break; |
1002 | case RTM_DELACTION: | 1004 | case RTM_DELACTION: |
1003 | ret = tca_action_gd(tca[TCA_ACT_TAB], n, pid, RTM_DELACTION); | 1005 | ret = tca_action_gd(net, tca[TCA_ACT_TAB], n, |
1006 | pid, RTM_DELACTION); | ||
1004 | break; | 1007 | break; |
1005 | case RTM_GETACTION: | 1008 | case RTM_GETACTION: |
1006 | ret = tca_action_gd(tca[TCA_ACT_TAB], n, pid, RTM_GETACTION); | 1009 | ret = tca_action_gd(net, tca[TCA_ACT_TAB], n, |
1010 | pid, RTM_GETACTION); | ||
1007 | break; | 1011 | break; |
1008 | default: | 1012 | default: |
1009 | BUG(); | 1013 | BUG(); |
@@ -1043,7 +1047,6 @@ find_dump_kind(const struct nlmsghdr *n) | |||
1043 | static int | 1047 | static int |
1044 | tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | 1048 | tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) |
1045 | { | 1049 | { |
1046 | struct net *net = sock_net(skb->sk); | ||
1047 | struct nlmsghdr *nlh; | 1050 | struct nlmsghdr *nlh; |
1048 | unsigned char *b = skb_tail_pointer(skb); | 1051 | unsigned char *b = skb_tail_pointer(skb); |
1049 | struct nlattr *nest; | 1052 | struct nlattr *nest; |
@@ -1053,11 +1056,8 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1053 | struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh); | 1056 | struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh); |
1054 | struct nlattr *kind = find_dump_kind(cb->nlh); | 1057 | struct nlattr *kind = find_dump_kind(cb->nlh); |
1055 | 1058 | ||
1056 | if (!net_eq(net, &init_net)) | ||
1057 | return 0; | ||
1058 | |||
1059 | if (kind == NULL) { | 1059 | if (kind == NULL) { |
1060 | printk("tc_dump_action: action bad kind\n"); | 1060 | pr_info("tc_dump_action: action bad kind\n"); |
1061 | return 0; | 1061 | return 0; |
1062 | } | 1062 | } |
1063 | 1063 | ||
@@ -1070,7 +1070,8 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1070 | a.ops = a_o; | 1070 | a.ops = a_o; |
1071 | 1071 | ||
1072 | if (a_o->walk == NULL) { | 1072 | if (a_o->walk == NULL) { |
1073 | printk("tc_dump_action: %s !capable of dumping table\n", a_o->kind); | 1073 | WARN(1, "tc_dump_action: %s !capable of dumping table\n", |
1074 | a_o->kind); | ||
1074 | goto nla_put_failure; | 1075 | goto nla_put_failure; |
1075 | } | 1076 | } |
1076 | 1077 | ||
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index e7f796aec657..8406c6654990 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
@@ -202,9 +202,9 @@ MODULE_LICENSE("GPL"); | |||
202 | static int __init gact_init_module(void) | 202 | static int __init gact_init_module(void) |
203 | { | 203 | { |
204 | #ifdef CONFIG_GACT_PROB | 204 | #ifdef CONFIG_GACT_PROB |
205 | printk("GACT probability on\n"); | 205 | printk(KERN_INFO "GACT probability on\n"); |
206 | #else | 206 | #else |
207 | printk("GACT probability NOT on\n"); | 207 | printk(KERN_INFO "GACT probability NOT on\n"); |
208 | #endif | 208 | #endif |
209 | return tcf_register_action(&act_gact_ops); | 209 | return tcf_register_action(&act_gact_ops); |
210 | } | 210 | } |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index da27a170b6b7..c7e59e6ec349 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -47,8 +47,8 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int | |||
47 | 47 | ||
48 | target = xt_request_find_target(AF_INET, t->u.user.name, | 48 | target = xt_request_find_target(AF_INET, t->u.user.name, |
49 | t->u.user.revision); | 49 | t->u.user.revision); |
50 | if (!target) | 50 | if (IS_ERR(target)) |
51 | return -ENOENT; | 51 | return PTR_ERR(target); |
52 | 52 | ||
53 | t->u.kernel.target = target; | 53 | t->u.kernel.target = target; |
54 | par.table = table; | 54 | par.table = table; |
@@ -199,7 +199,7 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, | |||
199 | { | 199 | { |
200 | int ret = 0, result = 0; | 200 | int ret = 0, result = 0; |
201 | struct tcf_ipt *ipt = a->priv; | 201 | struct tcf_ipt *ipt = a->priv; |
202 | struct xt_target_param par; | 202 | struct xt_action_param par; |
203 | 203 | ||
204 | if (skb_cloned(skb)) { | 204 | if (skb_cloned(skb)) { |
205 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 205 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
@@ -235,7 +235,8 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, | |||
235 | break; | 235 | break; |
236 | default: | 236 | default: |
237 | if (net_ratelimit()) | 237 | if (net_ratelimit()) |
238 | printk("Bogus netfilter code %d assume ACCEPT\n", ret); | 238 | pr_notice("tc filter: Bogus netfilter code" |
239 | " %d assume ACCEPT\n", ret); | ||
239 | result = TC_POLICE_OK; | 240 | result = TC_POLICE_OK; |
240 | break; | 241 | break; |
241 | } | 242 | } |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index c046682054eb..c0b6863e3b87 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -164,8 +164,8 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a, | |||
164 | dev = m->tcfm_dev; | 164 | dev = m->tcfm_dev; |
165 | if (!(dev->flags & IFF_UP)) { | 165 | if (!(dev->flags & IFF_UP)) { |
166 | if (net_ratelimit()) | 166 | if (net_ratelimit()) |
167 | printk("mirred to Houston: device %s is gone!\n", | 167 | pr_notice("tc mirred to Houston: device %s is gone!\n", |
168 | dev->name); | 168 | dev->name); |
169 | goto out; | 169 | goto out; |
170 | } | 170 | } |
171 | 171 | ||
@@ -252,7 +252,7 @@ MODULE_LICENSE("GPL"); | |||
252 | 252 | ||
253 | static int __init mirred_init_module(void) | 253 | static int __init mirred_init_module(void) |
254 | { | 254 | { |
255 | printk("Mirror/redirect action on\n"); | 255 | pr_info("Mirror/redirect action on\n"); |
256 | return tcf_register_action(&act_mirred_ops); | 256 | return tcf_register_action(&act_mirred_ops); |
257 | } | 257 | } |
258 | 258 | ||
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index b7dcfedc802e..fdbd0b7bd840 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
@@ -158,11 +158,13 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, | |||
158 | } | 158 | } |
159 | 159 | ||
160 | if (offset % 4) { | 160 | if (offset % 4) { |
161 | printk("offset must be on 32 bit boundaries\n"); | 161 | pr_info("tc filter pedit" |
162 | " offset must be on 32 bit boundaries\n"); | ||
162 | goto bad; | 163 | goto bad; |
163 | } | 164 | } |
164 | if (offset > 0 && offset > skb->len) { | 165 | if (offset > 0 && offset > skb->len) { |
165 | printk("offset %d cant exceed pkt length %d\n", | 166 | pr_info("tc filter pedit" |
167 | " offset %d cant exceed pkt length %d\n", | ||
166 | offset, skb->len); | 168 | offset, skb->len); |
167 | goto bad; | 169 | goto bad; |
168 | } | 170 | } |
@@ -176,9 +178,8 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, | |||
176 | if (munged) | 178 | if (munged) |
177 | skb->tc_verd = SET_TC_MUNGED(skb->tc_verd); | 179 | skb->tc_verd = SET_TC_MUNGED(skb->tc_verd); |
178 | goto done; | 180 | goto done; |
179 | } else { | 181 | } else |
180 | printk("pedit BUG: index %d\n", p->tcf_index); | 182 | WARN(1, "pedit BUG: index %d\n", p->tcf_index); |
181 | } | ||
182 | 183 | ||
183 | bad: | 184 | bad: |
184 | p->tcf_qstats.overlimits++; | 185 | p->tcf_qstats.overlimits++; |
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 622ca809c15c..1b4bc691d7d1 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
@@ -49,7 +49,7 @@ static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result | |||
49 | * Example if this was the 3rd packet and the string was "hello" | 49 | * Example if this was the 3rd packet and the string was "hello" |
50 | * then it would look like "hello_3" (without quotes) | 50 | * then it would look like "hello_3" (without quotes) |
51 | **/ | 51 | **/ |
52 | printk("simple: %s_%d\n", | 52 | pr_info("simple: %s_%d\n", |
53 | (char *)d->tcfd_defdata, d->tcf_bstats.packets); | 53 | (char *)d->tcfd_defdata, d->tcf_bstats.packets); |
54 | spin_unlock(&d->tcf_lock); | 54 | spin_unlock(&d->tcf_lock); |
55 | return d->tcf_action; | 55 | return d->tcf_action; |
@@ -205,7 +205,7 @@ static int __init simp_init_module(void) | |||
205 | { | 205 | { |
206 | int ret = tcf_register_action(&act_simp_ops); | 206 | int ret = tcf_register_action(&act_simp_ops); |
207 | if (!ret) | 207 | if (!ret) |
208 | printk("Simple TC action Loaded\n"); | 208 | pr_info("Simple TC action Loaded\n"); |
209 | return ret; | 209 | return ret; |
210 | } | 210 | } |
211 | 211 | ||
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index f082b27ff46d..5fd0c28ef79a 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -99,8 +99,9 @@ out: | |||
99 | } | 99 | } |
100 | EXPORT_SYMBOL(unregister_tcf_proto_ops); | 100 | EXPORT_SYMBOL(unregister_tcf_proto_ops); |
101 | 101 | ||
102 | static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 102 | static int tfilter_notify(struct net *net, struct sk_buff *oskb, |
103 | struct tcf_proto *tp, unsigned long fh, int event); | 103 | struct nlmsghdr *n, struct tcf_proto *tp, |
104 | unsigned long fh, int event); | ||
104 | 105 | ||
105 | 106 | ||
106 | /* Select new prio value from the range, managed by kernel. */ | 107 | /* Select new prio value from the range, managed by kernel. */ |
@@ -138,9 +139,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
138 | int err; | 139 | int err; |
139 | int tp_created = 0; | 140 | int tp_created = 0; |
140 | 141 | ||
141 | if (!net_eq(net, &init_net)) | ||
142 | return -EINVAL; | ||
143 | |||
144 | replay: | 142 | replay: |
145 | t = NLMSG_DATA(n); | 143 | t = NLMSG_DATA(n); |
146 | protocol = TC_H_MIN(t->tcm_info); | 144 | protocol = TC_H_MIN(t->tcm_info); |
@@ -159,7 +157,7 @@ replay: | |||
159 | /* Find head of filter chain. */ | 157 | /* Find head of filter chain. */ |
160 | 158 | ||
161 | /* Find link */ | 159 | /* Find link */ |
162 | dev = __dev_get_by_index(&init_net, t->tcm_ifindex); | 160 | dev = __dev_get_by_index(net, t->tcm_ifindex); |
163 | if (dev == NULL) | 161 | if (dev == NULL) |
164 | return -ENODEV; | 162 | return -ENODEV; |
165 | 163 | ||
@@ -283,7 +281,7 @@ replay: | |||
283 | *back = tp->next; | 281 | *back = tp->next; |
284 | spin_unlock_bh(root_lock); | 282 | spin_unlock_bh(root_lock); |
285 | 283 | ||
286 | tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER); | 284 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); |
287 | tcf_destroy(tp); | 285 | tcf_destroy(tp); |
288 | err = 0; | 286 | err = 0; |
289 | goto errout; | 287 | goto errout; |
@@ -306,10 +304,10 @@ replay: | |||
306 | case RTM_DELTFILTER: | 304 | case RTM_DELTFILTER: |
307 | err = tp->ops->delete(tp, fh); | 305 | err = tp->ops->delete(tp, fh); |
308 | if (err == 0) | 306 | if (err == 0) |
309 | tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER); | 307 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); |
310 | goto errout; | 308 | goto errout; |
311 | case RTM_GETTFILTER: | 309 | case RTM_GETTFILTER: |
312 | err = tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER); | 310 | err = tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER); |
313 | goto errout; | 311 | goto errout; |
314 | default: | 312 | default: |
315 | err = -EINVAL; | 313 | err = -EINVAL; |
@@ -325,7 +323,7 @@ replay: | |||
325 | *back = tp; | 323 | *back = tp; |
326 | spin_unlock_bh(root_lock); | 324 | spin_unlock_bh(root_lock); |
327 | } | 325 | } |
328 | tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER); | 326 | tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER); |
329 | } else { | 327 | } else { |
330 | if (tp_created) | 328 | if (tp_created) |
331 | tcf_destroy(tp); | 329 | tcf_destroy(tp); |
@@ -371,8 +369,9 @@ nla_put_failure: | |||
371 | return -1; | 369 | return -1; |
372 | } | 370 | } |
373 | 371 | ||
374 | static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 372 | static int tfilter_notify(struct net *net, struct sk_buff *oskb, |
375 | struct tcf_proto *tp, unsigned long fh, int event) | 373 | struct nlmsghdr *n, struct tcf_proto *tp, |
374 | unsigned long fh, int event) | ||
376 | { | 375 | { |
377 | struct sk_buff *skb; | 376 | struct sk_buff *skb; |
378 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; | 377 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; |
@@ -386,7 +385,7 @@ static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n, | |||
386 | return -EINVAL; | 385 | return -EINVAL; |
387 | } | 386 | } |
388 | 387 | ||
389 | return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, | 388 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
390 | n->nlmsg_flags & NLM_F_ECHO); | 389 | n->nlmsg_flags & NLM_F_ECHO); |
391 | } | 390 | } |
392 | 391 | ||
@@ -419,12 +418,9 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) | |||
419 | const struct Qdisc_class_ops *cops; | 418 | const struct Qdisc_class_ops *cops; |
420 | struct tcf_dump_args arg; | 419 | struct tcf_dump_args arg; |
421 | 420 | ||
422 | if (!net_eq(net, &init_net)) | ||
423 | return 0; | ||
424 | |||
425 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) | 421 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) |
426 | return skb->len; | 422 | return skb->len; |
427 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | 423 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
428 | return skb->len; | 424 | return skb->len; |
429 | 425 | ||
430 | if (!tcm->tcm_parent) | 426 | if (!tcm->tcm_parent) |
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 6ed61b10e002..f73542d2cdd0 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c | |||
@@ -602,7 +602,6 @@ static unsigned long flow_get(struct tcf_proto *tp, u32 handle) | |||
602 | 602 | ||
603 | static void flow_put(struct tcf_proto *tp, unsigned long f) | 603 | static void flow_put(struct tcf_proto *tp, unsigned long f) |
604 | { | 604 | { |
605 | return; | ||
606 | } | 605 | } |
607 | 606 | ||
608 | static int flow_dump(struct tcf_proto *tp, unsigned long fh, | 607 | static int flow_dump(struct tcf_proto *tp, unsigned long fh, |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 17c5dfc67320..96275422c619 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -211,7 +211,7 @@ check_terminal: | |||
211 | 211 | ||
212 | deadloop: | 212 | deadloop: |
213 | if (net_ratelimit()) | 213 | if (net_ratelimit()) |
214 | printk("cls_u32: dead loop\n"); | 214 | printk(KERN_WARNING "cls_u32: dead loop\n"); |
215 | return -1; | 215 | return -1; |
216 | } | 216 | } |
217 | 217 | ||
@@ -768,15 +768,15 @@ static struct tcf_proto_ops cls_u32_ops __read_mostly = { | |||
768 | 768 | ||
769 | static int __init init_u32(void) | 769 | static int __init init_u32(void) |
770 | { | 770 | { |
771 | printk("u32 classifier\n"); | 771 | pr_info("u32 classifier\n"); |
772 | #ifdef CONFIG_CLS_U32_PERF | 772 | #ifdef CONFIG_CLS_U32_PERF |
773 | printk(" Performance counters on\n"); | 773 | pr_info(" Performance counters on\n"); |
774 | #endif | 774 | #endif |
775 | #ifdef CONFIG_NET_CLS_IND | 775 | #ifdef CONFIG_NET_CLS_IND |
776 | printk(" input device check on \n"); | 776 | pr_info(" input device check on\n"); |
777 | #endif | 777 | #endif |
778 | #ifdef CONFIG_NET_CLS_ACT | 778 | #ifdef CONFIG_NET_CLS_ACT |
779 | printk(" Actions configured \n"); | 779 | pr_info(" Actions configured\n"); |
780 | #endif | 780 | #endif |
781 | return register_tcf_proto_ops(&cls_u32_ops); | 781 | return register_tcf_proto_ops(&cls_u32_ops); |
782 | } | 782 | } |
diff --git a/net/sched/ematch.c b/net/sched/ematch.c index e782bdeedc58..5e37da961f80 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c | |||
@@ -527,7 +527,8 @@ pop_stack: | |||
527 | 527 | ||
528 | stack_overflow: | 528 | stack_overflow: |
529 | if (net_ratelimit()) | 529 | if (net_ratelimit()) |
530 | printk("Local stack overflow, increase NET_EMATCH_STACK\n"); | 530 | printk(KERN_WARNING "tc ematch: local stack overflow," |
531 | " increase NET_EMATCH_STACK\n"); | ||
531 | return -1; | 532 | return -1; |
532 | } | 533 | } |
533 | EXPORT_SYMBOL(__tcf_em_tree_match); | 534 | EXPORT_SYMBOL(__tcf_em_tree_match); |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 145268ca57cf..fe35c1f338c2 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -35,10 +35,12 @@ | |||
35 | #include <net/netlink.h> | 35 | #include <net/netlink.h> |
36 | #include <net/pkt_sched.h> | 36 | #include <net/pkt_sched.h> |
37 | 37 | ||
38 | static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid, | 38 | static int qdisc_notify(struct net *net, struct sk_buff *oskb, |
39 | struct nlmsghdr *n, u32 clid, | ||
39 | struct Qdisc *old, struct Qdisc *new); | 40 | struct Qdisc *old, struct Qdisc *new); |
40 | static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 41 | static int tclass_notify(struct net *net, struct sk_buff *oskb, |
41 | struct Qdisc *q, unsigned long cl, int event); | 42 | struct nlmsghdr *n, struct Qdisc *q, |
43 | unsigned long cl, int event); | ||
42 | 44 | ||
43 | /* | 45 | /* |
44 | 46 | ||
@@ -639,11 +641,12 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) | |||
639 | } | 641 | } |
640 | EXPORT_SYMBOL(qdisc_tree_decrease_qlen); | 642 | EXPORT_SYMBOL(qdisc_tree_decrease_qlen); |
641 | 643 | ||
642 | static void notify_and_destroy(struct sk_buff *skb, struct nlmsghdr *n, u32 clid, | 644 | static void notify_and_destroy(struct net *net, struct sk_buff *skb, |
645 | struct nlmsghdr *n, u32 clid, | ||
643 | struct Qdisc *old, struct Qdisc *new) | 646 | struct Qdisc *old, struct Qdisc *new) |
644 | { | 647 | { |
645 | if (new || old) | 648 | if (new || old) |
646 | qdisc_notify(skb, n, clid, old, new); | 649 | qdisc_notify(net, skb, n, clid, old, new); |
647 | 650 | ||
648 | if (old) | 651 | if (old) |
649 | qdisc_destroy(old); | 652 | qdisc_destroy(old); |
@@ -663,6 +666,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
663 | struct Qdisc *new, struct Qdisc *old) | 666 | struct Qdisc *new, struct Qdisc *old) |
664 | { | 667 | { |
665 | struct Qdisc *q = old; | 668 | struct Qdisc *q = old; |
669 | struct net *net = dev_net(dev); | ||
666 | int err = 0; | 670 | int err = 0; |
667 | 671 | ||
668 | if (parent == NULL) { | 672 | if (parent == NULL) { |
@@ -699,12 +703,13 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
699 | } | 703 | } |
700 | 704 | ||
701 | if (!ingress) { | 705 | if (!ingress) { |
702 | notify_and_destroy(skb, n, classid, dev->qdisc, new); | 706 | notify_and_destroy(net, skb, n, classid, |
707 | dev->qdisc, new); | ||
703 | if (new && !new->ops->attach) | 708 | if (new && !new->ops->attach) |
704 | atomic_inc(&new->refcnt); | 709 | atomic_inc(&new->refcnt); |
705 | dev->qdisc = new ? : &noop_qdisc; | 710 | dev->qdisc = new ? : &noop_qdisc; |
706 | } else { | 711 | } else { |
707 | notify_and_destroy(skb, n, classid, old, new); | 712 | notify_and_destroy(net, skb, n, classid, old, new); |
708 | } | 713 | } |
709 | 714 | ||
710 | if (dev->flags & IFF_UP) | 715 | if (dev->flags & IFF_UP) |
@@ -722,7 +727,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
722 | err = -ENOENT; | 727 | err = -ENOENT; |
723 | } | 728 | } |
724 | if (!err) | 729 | if (!err) |
725 | notify_and_destroy(skb, n, classid, old, new); | 730 | notify_and_destroy(net, skb, n, classid, old, new); |
726 | } | 731 | } |
727 | return err; | 732 | return err; |
728 | } | 733 | } |
@@ -948,10 +953,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
948 | struct Qdisc *p = NULL; | 953 | struct Qdisc *p = NULL; |
949 | int err; | 954 | int err; |
950 | 955 | ||
951 | if (!net_eq(net, &init_net)) | 956 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
952 | return -EINVAL; | ||
953 | |||
954 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | ||
955 | return -ENODEV; | 957 | return -ENODEV; |
956 | 958 | ||
957 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 959 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -991,7 +993,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
991 | if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0) | 993 | if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0) |
992 | return err; | 994 | return err; |
993 | } else { | 995 | } else { |
994 | qdisc_notify(skb, n, clid, NULL, q); | 996 | qdisc_notify(net, skb, n, clid, NULL, q); |
995 | } | 997 | } |
996 | return 0; | 998 | return 0; |
997 | } | 999 | } |
@@ -1010,16 +1012,13 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1010 | struct Qdisc *q, *p; | 1012 | struct Qdisc *q, *p; |
1011 | int err; | 1013 | int err; |
1012 | 1014 | ||
1013 | if (!net_eq(net, &init_net)) | ||
1014 | return -EINVAL; | ||
1015 | |||
1016 | replay: | 1015 | replay: |
1017 | /* Reinit, just in case something touches this. */ | 1016 | /* Reinit, just in case something touches this. */ |
1018 | tcm = NLMSG_DATA(n); | 1017 | tcm = NLMSG_DATA(n); |
1019 | clid = tcm->tcm_parent; | 1018 | clid = tcm->tcm_parent; |
1020 | q = p = NULL; | 1019 | q = p = NULL; |
1021 | 1020 | ||
1022 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | 1021 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
1023 | return -ENODEV; | 1022 | return -ENODEV; |
1024 | 1023 | ||
1025 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1024 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1106,7 +1105,7 @@ replay: | |||
1106 | return -EINVAL; | 1105 | return -EINVAL; |
1107 | err = qdisc_change(q, tca); | 1106 | err = qdisc_change(q, tca); |
1108 | if (err == 0) | 1107 | if (err == 0) |
1109 | qdisc_notify(skb, n, clid, NULL, q); | 1108 | qdisc_notify(net, skb, n, clid, NULL, q); |
1110 | return err; | 1109 | return err; |
1111 | 1110 | ||
1112 | create_n_graft: | 1111 | create_n_graft: |
@@ -1196,8 +1195,9 @@ nla_put_failure: | |||
1196 | return -1; | 1195 | return -1; |
1197 | } | 1196 | } |
1198 | 1197 | ||
1199 | static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 1198 | static int qdisc_notify(struct net *net, struct sk_buff *oskb, |
1200 | u32 clid, struct Qdisc *old, struct Qdisc *new) | 1199 | struct nlmsghdr *n, u32 clid, |
1200 | struct Qdisc *old, struct Qdisc *new) | ||
1201 | { | 1201 | { |
1202 | struct sk_buff *skb; | 1202 | struct sk_buff *skb; |
1203 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; | 1203 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; |
@@ -1216,7 +1216,7 @@ static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, | |||
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | if (skb->len) | 1218 | if (skb->len) |
1219 | return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1219 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); |
1220 | 1220 | ||
1221 | err_out: | 1221 | err_out: |
1222 | kfree_skb(skb); | 1222 | kfree_skb(skb); |
@@ -1275,15 +1275,12 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) | |||
1275 | int s_idx, s_q_idx; | 1275 | int s_idx, s_q_idx; |
1276 | struct net_device *dev; | 1276 | struct net_device *dev; |
1277 | 1277 | ||
1278 | if (!net_eq(net, &init_net)) | ||
1279 | return 0; | ||
1280 | |||
1281 | s_idx = cb->args[0]; | 1278 | s_idx = cb->args[0]; |
1282 | s_q_idx = q_idx = cb->args[1]; | 1279 | s_q_idx = q_idx = cb->args[1]; |
1283 | 1280 | ||
1284 | rcu_read_lock(); | 1281 | rcu_read_lock(); |
1285 | idx = 0; | 1282 | idx = 0; |
1286 | for_each_netdev_rcu(&init_net, dev) { | 1283 | for_each_netdev_rcu(net, dev) { |
1287 | struct netdev_queue *dev_queue; | 1284 | struct netdev_queue *dev_queue; |
1288 | 1285 | ||
1289 | if (idx < s_idx) | 1286 | if (idx < s_idx) |
@@ -1335,10 +1332,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1335 | u32 qid = TC_H_MAJ(clid); | 1332 | u32 qid = TC_H_MAJ(clid); |
1336 | int err; | 1333 | int err; |
1337 | 1334 | ||
1338 | if (!net_eq(net, &init_net)) | 1335 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
1339 | return -EINVAL; | ||
1340 | |||
1341 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | ||
1342 | return -ENODEV; | 1336 | return -ENODEV; |
1343 | 1337 | ||
1344 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1338 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1419,10 +1413,10 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1419 | if (cops->delete) | 1413 | if (cops->delete) |
1420 | err = cops->delete(q, cl); | 1414 | err = cops->delete(q, cl); |
1421 | if (err == 0) | 1415 | if (err == 0) |
1422 | tclass_notify(skb, n, q, cl, RTM_DELTCLASS); | 1416 | tclass_notify(net, skb, n, q, cl, RTM_DELTCLASS); |
1423 | goto out; | 1417 | goto out; |
1424 | case RTM_GETTCLASS: | 1418 | case RTM_GETTCLASS: |
1425 | err = tclass_notify(skb, n, q, cl, RTM_NEWTCLASS); | 1419 | err = tclass_notify(net, skb, n, q, cl, RTM_NEWTCLASS); |
1426 | goto out; | 1420 | goto out; |
1427 | default: | 1421 | default: |
1428 | err = -EINVAL; | 1422 | err = -EINVAL; |
@@ -1435,7 +1429,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1435 | if (cops->change) | 1429 | if (cops->change) |
1436 | err = cops->change(q, clid, pid, tca, &new_cl); | 1430 | err = cops->change(q, clid, pid, tca, &new_cl); |
1437 | if (err == 0) | 1431 | if (err == 0) |
1438 | tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS); | 1432 | tclass_notify(net, skb, n, q, new_cl, RTM_NEWTCLASS); |
1439 | 1433 | ||
1440 | out: | 1434 | out: |
1441 | if (cl) | 1435 | if (cl) |
@@ -1487,8 +1481,9 @@ nla_put_failure: | |||
1487 | return -1; | 1481 | return -1; |
1488 | } | 1482 | } |
1489 | 1483 | ||
1490 | static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 1484 | static int tclass_notify(struct net *net, struct sk_buff *oskb, |
1491 | struct Qdisc *q, unsigned long cl, int event) | 1485 | struct nlmsghdr *n, struct Qdisc *q, |
1486 | unsigned long cl, int event) | ||
1492 | { | 1487 | { |
1493 | struct sk_buff *skb; | 1488 | struct sk_buff *skb; |
1494 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; | 1489 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; |
@@ -1502,7 +1497,7 @@ static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | |||
1502 | return -EINVAL; | 1497 | return -EINVAL; |
1503 | } | 1498 | } |
1504 | 1499 | ||
1505 | return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1500 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); |
1506 | } | 1501 | } |
1507 | 1502 | ||
1508 | struct qdisc_dump_args | 1503 | struct qdisc_dump_args |
@@ -1577,12 +1572,9 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1577 | struct net_device *dev; | 1572 | struct net_device *dev; |
1578 | int t, s_t; | 1573 | int t, s_t; |
1579 | 1574 | ||
1580 | if (!net_eq(net, &init_net)) | ||
1581 | return 0; | ||
1582 | |||
1583 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) | 1575 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) |
1584 | return 0; | 1576 | return 0; |
1585 | if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | 1577 | if ((dev = dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
1586 | return 0; | 1578 | return 0; |
1587 | 1579 | ||
1588 | s_t = cb->args[0]; | 1580 | s_t = cb->args[0]; |
@@ -1645,9 +1637,12 @@ reclassify: | |||
1645 | tp = otp; | 1637 | tp = otp; |
1646 | 1638 | ||
1647 | if (verd++ >= MAX_REC_LOOP) { | 1639 | if (verd++ >= MAX_REC_LOOP) { |
1648 | printk("rule prio %u protocol %02x reclassify loop, " | 1640 | if (net_ratelimit()) |
1649 | "packet dropped\n", | 1641 | printk(KERN_NOTICE |
1650 | tp->prio&0xffff, ntohs(tp->protocol)); | 1642 | "%s: packet reclassify loop" |
1643 | " rule prio %u protocol %02x\n", | ||
1644 | tp->q->ops->id, | ||
1645 | tp->prio & 0xffff, ntohs(tp->protocol)); | ||
1651 | return TC_ACT_SHOT; | 1646 | return TC_ACT_SHOT; |
1652 | } | 1647 | } |
1653 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); | 1648 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); |
@@ -1692,7 +1687,7 @@ static int psched_show(struct seq_file *seq, void *v) | |||
1692 | 1687 | ||
1693 | static int psched_open(struct inode *inode, struct file *file) | 1688 | static int psched_open(struct inode *inode, struct file *file) |
1694 | { | 1689 | { |
1695 | return single_open(file, psched_show, PDE(inode)->data); | 1690 | return single_open(file, psched_show, NULL); |
1696 | } | 1691 | } |
1697 | 1692 | ||
1698 | static const struct file_operations psched_fops = { | 1693 | static const struct file_operations psched_fops = { |
@@ -1702,15 +1697,53 @@ static const struct file_operations psched_fops = { | |||
1702 | .llseek = seq_lseek, | 1697 | .llseek = seq_lseek, |
1703 | .release = single_release, | 1698 | .release = single_release, |
1704 | }; | 1699 | }; |
1700 | |||
1701 | static int __net_init psched_net_init(struct net *net) | ||
1702 | { | ||
1703 | struct proc_dir_entry *e; | ||
1704 | |||
1705 | e = proc_net_fops_create(net, "psched", 0, &psched_fops); | ||
1706 | if (e == NULL) | ||
1707 | return -ENOMEM; | ||
1708 | |||
1709 | return 0; | ||
1710 | } | ||
1711 | |||
1712 | static void __net_exit psched_net_exit(struct net *net) | ||
1713 | { | ||
1714 | proc_net_remove(net, "psched"); | ||
1715 | } | ||
1716 | #else | ||
1717 | static int __net_init psched_net_init(struct net *net) | ||
1718 | { | ||
1719 | return 0; | ||
1720 | } | ||
1721 | |||
1722 | static void __net_exit psched_net_exit(struct net *net) | ||
1723 | { | ||
1724 | } | ||
1705 | #endif | 1725 | #endif |
1706 | 1726 | ||
1727 | static struct pernet_operations psched_net_ops = { | ||
1728 | .init = psched_net_init, | ||
1729 | .exit = psched_net_exit, | ||
1730 | }; | ||
1731 | |||
1707 | static int __init pktsched_init(void) | 1732 | static int __init pktsched_init(void) |
1708 | { | 1733 | { |
1734 | int err; | ||
1735 | |||
1736 | err = register_pernet_subsys(&psched_net_ops); | ||
1737 | if (err) { | ||
1738 | printk(KERN_ERR "pktsched_init: " | ||
1739 | "cannot initialize per netns operations\n"); | ||
1740 | return err; | ||
1741 | } | ||
1742 | |||
1709 | register_qdisc(&pfifo_qdisc_ops); | 1743 | register_qdisc(&pfifo_qdisc_ops); |
1710 | register_qdisc(&bfifo_qdisc_ops); | 1744 | register_qdisc(&bfifo_qdisc_ops); |
1711 | register_qdisc(&pfifo_head_drop_qdisc_ops); | 1745 | register_qdisc(&pfifo_head_drop_qdisc_ops); |
1712 | register_qdisc(&mq_qdisc_ops); | 1746 | register_qdisc(&mq_qdisc_ops); |
1713 | proc_net_fops_create(&init_net, "psched", 0, &psched_fops); | ||
1714 | 1747 | ||
1715 | rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL); | 1748 | rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL); |
1716 | rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL); | 1749 | rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL); |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index ff4dd53eeff0..a63029ef3edd 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <net/pkt_sched.h> | 28 | #include <net/pkt_sched.h> |
29 | #include <net/dst.h> | ||
29 | 30 | ||
30 | /* Main transmission queue. */ | 31 | /* Main transmission queue. */ |
31 | 32 | ||
@@ -40,6 +41,7 @@ | |||
40 | 41 | ||
41 | static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) | 42 | static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) |
42 | { | 43 | { |
44 | skb_dst_force(skb); | ||
43 | q->gso_skb = skb; | 45 | q->gso_skb = skb; |
44 | q->qstats.requeues++; | 46 | q->qstats.requeues++; |
45 | q->q.qlen++; /* it's still part of the queue */ | 47 | q->q.qlen++; /* it's still part of the queue */ |
@@ -94,7 +96,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, | |||
94 | * Another cpu is holding lock, requeue & delay xmits for | 96 | * Another cpu is holding lock, requeue & delay xmits for |
95 | * some time. | 97 | * some time. |
96 | */ | 98 | */ |
97 | __get_cpu_var(netdev_rx_stat).cpu_collision++; | 99 | __get_cpu_var(softnet_data).cpu_collision++; |
98 | ret = dev_requeue_skb(skb, q); | 100 | ret = dev_requeue_skb(skb, q); |
99 | } | 101 | } |
100 | 102 | ||
@@ -179,7 +181,7 @@ static inline int qdisc_restart(struct Qdisc *q) | |||
179 | skb = dequeue_skb(q); | 181 | skb = dequeue_skb(q); |
180 | if (unlikely(!skb)) | 182 | if (unlikely(!skb)) |
181 | return 0; | 183 | return 0; |
182 | 184 | WARN_ON_ONCE(skb_dst_is_noref(skb)); | |
183 | root_lock = qdisc_lock(q); | 185 | root_lock = qdisc_lock(q); |
184 | dev = qdisc_dev(q); | 186 | dev = qdisc_dev(q); |
185 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); | 187 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); |
@@ -529,7 +531,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, | |||
529 | unsigned int size; | 531 | unsigned int size; |
530 | int err = -ENOBUFS; | 532 | int err = -ENOBUFS; |
531 | 533 | ||
532 | /* ensure that the Qdisc and the private data are 32-byte aligned */ | 534 | /* ensure that the Qdisc and the private data are 64-byte aligned */ |
533 | size = QDISC_ALIGN(sizeof(*sch)); | 535 | size = QDISC_ALIGN(sizeof(*sch)); |
534 | size += ops->priv_size + (QDISC_ALIGNTO - 1); | 536 | size += ops->priv_size + (QDISC_ALIGNTO - 1); |
535 | 537 | ||
@@ -591,6 +593,13 @@ void qdisc_reset(struct Qdisc *qdisc) | |||
591 | } | 593 | } |
592 | EXPORT_SYMBOL(qdisc_reset); | 594 | EXPORT_SYMBOL(qdisc_reset); |
593 | 595 | ||
596 | static void qdisc_rcu_free(struct rcu_head *head) | ||
597 | { | ||
598 | struct Qdisc *qdisc = container_of(head, struct Qdisc, rcu_head); | ||
599 | |||
600 | kfree((char *) qdisc - qdisc->padded); | ||
601 | } | ||
602 | |||
594 | void qdisc_destroy(struct Qdisc *qdisc) | 603 | void qdisc_destroy(struct Qdisc *qdisc) |
595 | { | 604 | { |
596 | const struct Qdisc_ops *ops = qdisc->ops; | 605 | const struct Qdisc_ops *ops = qdisc->ops; |
@@ -614,7 +623,11 @@ void qdisc_destroy(struct Qdisc *qdisc) | |||
614 | dev_put(qdisc_dev(qdisc)); | 623 | dev_put(qdisc_dev(qdisc)); |
615 | 624 | ||
616 | kfree_skb(qdisc->gso_skb); | 625 | kfree_skb(qdisc->gso_skb); |
617 | kfree((char *) qdisc - qdisc->padded); | 626 | /* |
627 | * gen_estimator est_timer() might access qdisc->q.lock, | ||
628 | * wait a RCU grace period before freeing qdisc. | ||
629 | */ | ||
630 | call_rcu(&qdisc->rcu_head, qdisc_rcu_free); | ||
618 | } | 631 | } |
619 | EXPORT_SYMBOL(qdisc_destroy); | 632 | EXPORT_SYMBOL(qdisc_destroy); |
620 | 633 | ||
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index b38b39c60752..abd904be4287 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -617,7 +617,6 @@ rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, u64 y) | |||
617 | rtsc->y = y; | 617 | rtsc->y = y; |
618 | rtsc->dx = dx; | 618 | rtsc->dx = dx; |
619 | rtsc->dy = dy; | 619 | rtsc->dy = dy; |
620 | return; | ||
621 | } | 620 | } |
622 | 621 | ||
623 | static void | 622 | static void |
@@ -1155,7 +1154,7 @@ static struct hfsc_class * | |||
1155 | hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | 1154 | hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) |
1156 | { | 1155 | { |
1157 | struct hfsc_sched *q = qdisc_priv(sch); | 1156 | struct hfsc_sched *q = qdisc_priv(sch); |
1158 | struct hfsc_class *cl; | 1157 | struct hfsc_class *head, *cl; |
1159 | struct tcf_result res; | 1158 | struct tcf_result res; |
1160 | struct tcf_proto *tcf; | 1159 | struct tcf_proto *tcf; |
1161 | int result; | 1160 | int result; |
@@ -1166,6 +1165,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
1166 | return cl; | 1165 | return cl; |
1167 | 1166 | ||
1168 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | 1167 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; |
1168 | head = &q->root; | ||
1169 | tcf = q->root.filter_list; | 1169 | tcf = q->root.filter_list; |
1170 | while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) { | 1170 | while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) { |
1171 | #ifdef CONFIG_NET_CLS_ACT | 1171 | #ifdef CONFIG_NET_CLS_ACT |
@@ -1180,6 +1180,8 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
1180 | if ((cl = (struct hfsc_class *)res.class) == NULL) { | 1180 | if ((cl = (struct hfsc_class *)res.class) == NULL) { |
1181 | if ((cl = hfsc_find_class(res.classid, sch)) == NULL) | 1181 | if ((cl = hfsc_find_class(res.classid, sch)) == NULL) |
1182 | break; /* filter selected invalid classid */ | 1182 | break; /* filter selected invalid classid */ |
1183 | if (cl->level >= head->level) | ||
1184 | break; /* filter may only point downwards */ | ||
1183 | } | 1185 | } |
1184 | 1186 | ||
1185 | if (cl->level == 0) | 1187 | if (cl->level == 0) |
@@ -1187,6 +1189,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
1187 | 1189 | ||
1188 | /* apply inner filter chain */ | 1190 | /* apply inner filter chain */ |
1189 | tcf = cl->filter_list; | 1191 | tcf = cl->filter_list; |
1192 | head = cl; | ||
1190 | } | 1193 | } |
1191 | 1194 | ||
1192 | /* classification failed, try default class */ | 1195 | /* classification failed, try default class */ |
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index a9e646bdb605..f10e34a68445 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c | |||
@@ -44,7 +44,6 @@ static void ingress_put(struct Qdisc *sch, unsigned long cl) | |||
44 | 44 | ||
45 | static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker) | 45 | static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker) |
46 | { | 46 | { |
47 | return; | ||
48 | } | 47 | } |
49 | 48 | ||
50 | static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch, unsigned long cl) | 49 | static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch, unsigned long cl) |
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c index b2aba3f5e6fa..fe91e50f9d98 100644 --- a/net/sched/sch_mq.c +++ b/net/sched/sch_mq.c | |||
@@ -174,7 +174,6 @@ static unsigned long mq_get(struct Qdisc *sch, u32 classid) | |||
174 | 174 | ||
175 | static void mq_put(struct Qdisc *sch, unsigned long cl) | 175 | static void mq_put(struct Qdisc *sch, unsigned long cl) |
176 | { | 176 | { |
177 | return; | ||
178 | } | 177 | } |
179 | 178 | ||
180 | static int mq_dump_class(struct Qdisc *sch, unsigned long cl, | 179 | static int mq_dump_class(struct Qdisc *sch, unsigned long cl, |
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index c50876cd8704..6ae251279fc2 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c | |||
@@ -340,7 +340,6 @@ static unsigned long multiq_bind(struct Qdisc *sch, unsigned long parent, | |||
340 | 340 | ||
341 | static void multiq_put(struct Qdisc *q, unsigned long cl) | 341 | static void multiq_put(struct Qdisc *q, unsigned long cl) |
342 | { | 342 | { |
343 | return; | ||
344 | } | 343 | } |
345 | 344 | ||
346 | static int multiq_dump_class(struct Qdisc *sch, unsigned long cl, | 345 | static int multiq_dump_class(struct Qdisc *sch, unsigned long cl, |
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 81672e0c1b25..0748fb1e3a49 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c | |||
@@ -303,7 +303,6 @@ static unsigned long prio_bind(struct Qdisc *sch, unsigned long parent, u32 clas | |||
303 | 303 | ||
304 | static void prio_put(struct Qdisc *q, unsigned long cl) | 304 | static void prio_put(struct Qdisc *q, unsigned long cl) |
305 | { | 305 | { |
306 | return; | ||
307 | } | 306 | } |
308 | 307 | ||
309 | static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, | 308 | static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, |
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 072cdf442f8e..8d42bb3ba540 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c | |||
@@ -303,7 +303,6 @@ static unsigned long red_get(struct Qdisc *sch, u32 classid) | |||
303 | 303 | ||
304 | static void red_put(struct Qdisc *sch, unsigned long arg) | 304 | static void red_put(struct Qdisc *sch, unsigned long arg) |
305 | { | 305 | { |
306 | return; | ||
307 | } | 306 | } |
308 | 307 | ||
309 | static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker) | 308 | static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker) |
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index c5a9ac566007..c65762823f5e 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -123,8 +123,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
123 | case htons(ETH_P_IP): | 123 | case htons(ETH_P_IP): |
124 | { | 124 | { |
125 | const struct iphdr *iph = ip_hdr(skb); | 125 | const struct iphdr *iph = ip_hdr(skb); |
126 | h = iph->daddr; | 126 | h = (__force u32)iph->daddr; |
127 | h2 = iph->saddr ^ iph->protocol; | 127 | h2 = (__force u32)iph->saddr ^ iph->protocol; |
128 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && | 128 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && |
129 | (iph->protocol == IPPROTO_TCP || | 129 | (iph->protocol == IPPROTO_TCP || |
130 | iph->protocol == IPPROTO_UDP || | 130 | iph->protocol == IPPROTO_UDP || |
@@ -138,8 +138,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
138 | case htons(ETH_P_IPV6): | 138 | case htons(ETH_P_IPV6): |
139 | { | 139 | { |
140 | struct ipv6hdr *iph = ipv6_hdr(skb); | 140 | struct ipv6hdr *iph = ipv6_hdr(skb); |
141 | h = iph->daddr.s6_addr32[3]; | 141 | h = (__force u32)iph->daddr.s6_addr32[3]; |
142 | h2 = iph->saddr.s6_addr32[3] ^ iph->nexthdr; | 142 | h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr; |
143 | if (iph->nexthdr == IPPROTO_TCP || | 143 | if (iph->nexthdr == IPPROTO_TCP || |
144 | iph->nexthdr == IPPROTO_UDP || | 144 | iph->nexthdr == IPPROTO_UDP || |
145 | iph->nexthdr == IPPROTO_UDPLITE || | 145 | iph->nexthdr == IPPROTO_UDPLITE || |
@@ -150,7 +150,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
150 | break; | 150 | break; |
151 | } | 151 | } |
152 | default: | 152 | default: |
153 | h = (unsigned long)skb_dst(skb) ^ skb->protocol; | 153 | h = (unsigned long)skb_dst(skb) ^ (__force u32)skb->protocol; |
154 | h2 = (unsigned long)skb->sk; | 154 | h2 = (unsigned long)skb->sk; |
155 | } | 155 | } |
156 | 156 | ||
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 8fb8107ab188..0991c640cd3e 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -273,7 +273,11 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt) | |||
273 | if (max_size < 0) | 273 | if (max_size < 0) |
274 | goto done; | 274 | goto done; |
275 | 275 | ||
276 | if (qopt->limit > 0) { | 276 | if (q->qdisc != &noop_qdisc) { |
277 | err = fifo_set_limit(q->qdisc, qopt->limit); | ||
278 | if (err) | ||
279 | goto done; | ||
280 | } else if (qopt->limit > 0) { | ||
277 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); | 281 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); |
278 | if (IS_ERR(child)) { | 282 | if (IS_ERR(child)) { |
279 | err = PTR_ERR(child); | 283 | err = PTR_ERR(child); |
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index 58b3e882a187..126b014eb79b 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig | |||
@@ -37,6 +37,18 @@ menuconfig IP_SCTP | |||
37 | 37 | ||
38 | if IP_SCTP | 38 | if IP_SCTP |
39 | 39 | ||
40 | config NET_SCTPPROBE | ||
41 | tristate "SCTP: Association probing" | ||
42 | depends on PROC_FS && KPROBES | ||
43 | ---help--- | ||
44 | This module allows for capturing the changes to SCTP association | ||
45 | state in response to incoming packets. It is used for debugging | ||
46 | SCTP congestion control algorithms. If you don't understand | ||
47 | what was just said, you don't need it: say N. | ||
48 | |||
49 | To compile this code as a module, choose M here: the | ||
50 | module will be called sctp_probe. | ||
51 | |||
40 | config SCTP_DBG_MSG | 52 | config SCTP_DBG_MSG |
41 | bool "SCTP: Debug messages" | 53 | bool "SCTP: Debug messages" |
42 | help | 54 | help |
diff --git a/net/sctp/Makefile b/net/sctp/Makefile index 6b794734380a..5c30b7a873df 100644 --- a/net/sctp/Makefile +++ b/net/sctp/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_IP_SCTP) += sctp.o | 5 | obj-$(CONFIG_IP_SCTP) += sctp.o |
6 | obj-$(CONFIG_NET_SCTPPROBE) += sctp_probe.o | ||
6 | 7 | ||
7 | sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ | 8 | sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ |
8 | protocol.o endpointola.o associola.o \ | 9 | protocol.o endpointola.o associola.o \ |
@@ -11,6 +12,8 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ | |||
11 | tsnmap.o bind_addr.o socket.o primitive.o \ | 12 | tsnmap.o bind_addr.o socket.o primitive.o \ |
12 | output.o input.o debug.o ssnmap.o auth.o | 13 | output.o input.o debug.o ssnmap.o auth.o |
13 | 14 | ||
15 | sctp_probe-y := probe.o | ||
16 | |||
14 | sctp-$(CONFIG_SCTP_DBG_OBJCNT) += objcnt.o | 17 | sctp-$(CONFIG_SCTP_DBG_OBJCNT) += objcnt.o |
15 | sctp-$(CONFIG_PROC_FS) += proc.o | 18 | sctp-$(CONFIG_PROC_FS) += proc.o |
16 | sctp-$(CONFIG_SYSCTL) += sysctl.o | 19 | sctp-$(CONFIG_SYSCTL) += sysctl.o |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 99c93ee98ad9..e41feff19e43 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -87,9 +87,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
87 | /* Retrieve the SCTP per socket area. */ | 87 | /* Retrieve the SCTP per socket area. */ |
88 | sp = sctp_sk((struct sock *)sk); | 88 | sp = sctp_sk((struct sock *)sk); |
89 | 89 | ||
90 | /* Init all variables to a known value. */ | ||
91 | memset(asoc, 0, sizeof(struct sctp_association)); | ||
92 | |||
93 | /* Discarding const is appropriate here. */ | 90 | /* Discarding const is appropriate here. */ |
94 | asoc->ep = (struct sctp_endpoint *)ep; | 91 | asoc->ep = (struct sctp_endpoint *)ep; |
95 | sctp_endpoint_hold(asoc->ep); | 92 | sctp_endpoint_hold(asoc->ep); |
@@ -762,7 +759,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
762 | asoc->peer.retran_path = peer; | 759 | asoc->peer.retran_path = peer; |
763 | } | 760 | } |
764 | 761 | ||
765 | if (asoc->peer.active_path == asoc->peer.retran_path) { | 762 | if (asoc->peer.active_path == asoc->peer.retran_path && |
763 | peer->state != SCTP_UNCONFIRMED) { | ||
766 | asoc->peer.retran_path = peer; | 764 | asoc->peer.retran_path = peer; |
767 | } | 765 | } |
768 | 766 | ||
@@ -818,8 +816,6 @@ void sctp_assoc_del_nonprimary_peers(struct sctp_association *asoc, | |||
818 | if (t != primary) | 816 | if (t != primary) |
819 | sctp_assoc_rm_peer(asoc, t); | 817 | sctp_assoc_rm_peer(asoc, t); |
820 | } | 818 | } |
821 | |||
822 | return; | ||
823 | } | 819 | } |
824 | 820 | ||
825 | /* Engage in transport control operations. | 821 | /* Engage in transport control operations. |
@@ -1320,12 +1316,13 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1320 | /* Keep track of the next transport in case | 1316 | /* Keep track of the next transport in case |
1321 | * we don't find any active transport. | 1317 | * we don't find any active transport. |
1322 | */ | 1318 | */ |
1323 | if (!next) | 1319 | if (t->state != SCTP_UNCONFIRMED && !next) |
1324 | next = t; | 1320 | next = t; |
1325 | } | 1321 | } |
1326 | } | 1322 | } |
1327 | 1323 | ||
1328 | asoc->peer.retran_path = t; | 1324 | if (t) |
1325 | asoc->peer.retran_path = t; | ||
1329 | 1326 | ||
1330 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | 1327 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" |
1331 | " %p addr: ", | 1328 | " %p addr: ", |
@@ -1485,7 +1482,7 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len) | |||
1485 | if (asoc->rwnd >= len) { | 1482 | if (asoc->rwnd >= len) { |
1486 | asoc->rwnd -= len; | 1483 | asoc->rwnd -= len; |
1487 | if (over) { | 1484 | if (over) { |
1488 | asoc->rwnd_press = asoc->rwnd; | 1485 | asoc->rwnd_press += asoc->rwnd; |
1489 | asoc->rwnd = 0; | 1486 | asoc->rwnd = 0; |
1490 | } | 1487 | } |
1491 | } else { | 1488 | } else { |
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 3eab6db59a37..476caaf100ed 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
@@ -58,9 +58,9 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg) | |||
58 | msg->send_failed = 0; | 58 | msg->send_failed = 0; |
59 | msg->send_error = 0; | 59 | msg->send_error = 0; |
60 | msg->can_abandon = 0; | 60 | msg->can_abandon = 0; |
61 | msg->can_delay = 1; | ||
61 | msg->expires_at = 0; | 62 | msg->expires_at = 0; |
62 | INIT_LIST_HEAD(&msg->chunks); | 63 | INIT_LIST_HEAD(&msg->chunks); |
63 | msg->msg_size = 0; | ||
64 | } | 64 | } |
65 | 65 | ||
66 | /* Allocate and initialize datamsg. */ | 66 | /* Allocate and initialize datamsg. */ |
@@ -157,7 +157,6 @@ static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chu | |||
157 | { | 157 | { |
158 | sctp_datamsg_hold(msg); | 158 | sctp_datamsg_hold(msg); |
159 | chunk->msg = msg; | 159 | chunk->msg = msg; |
160 | msg->msg_size += chunk->skb->len; | ||
161 | } | 160 | } |
162 | 161 | ||
163 | 162 | ||
@@ -247,6 +246,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
247 | if (msg_len >= first_len) { | 246 | if (msg_len >= first_len) { |
248 | msg_len -= first_len; | 247 | msg_len -= first_len; |
249 | whole = 1; | 248 | whole = 1; |
249 | msg->can_delay = 0; | ||
250 | } | 250 | } |
251 | 251 | ||
252 | /* How many full sized? How many bytes leftover? */ | 252 | /* How many full sized? How many bytes leftover? */ |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 7ec09ba03a1c..e10acc01c75f 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -70,8 +70,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
70 | struct sctp_shared_key *null_key; | 70 | struct sctp_shared_key *null_key; |
71 | int err; | 71 | int err; |
72 | 72 | ||
73 | memset(ep, 0, sizeof(struct sctp_endpoint)); | ||
74 | |||
75 | ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); | 73 | ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); |
76 | if (!ep->digest) | 74 | if (!ep->digest) |
77 | return NULL; | 75 | return NULL; |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 9fb5d37c37ad..732689140fb8 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -232,7 +232,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) | |||
232 | if (!(transport->param_flags & SPP_PMTUD_ENABLE)) | 232 | if (!(transport->param_flags & SPP_PMTUD_ENABLE)) |
233 | skb->local_df = 1; | 233 | skb->local_df = 1; |
234 | 234 | ||
235 | return ip6_xmit(sk, skb, &fl, np->opt, 0); | 235 | return ip6_xmit(sk, skb, &fl, np->opt); |
236 | } | 236 | } |
237 | 237 | ||
238 | /* Returns the dst cache entry for the given source and destination ip | 238 | /* Returns the dst cache entry for the given source and destination ip |
@@ -277,20 +277,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, | |||
277 | static inline int sctp_v6_addr_match_len(union sctp_addr *s1, | 277 | static inline int sctp_v6_addr_match_len(union sctp_addr *s1, |
278 | union sctp_addr *s2) | 278 | union sctp_addr *s2) |
279 | { | 279 | { |
280 | struct in6_addr *a1 = &s1->v6.sin6_addr; | 280 | return ipv6_addr_diff(&s1->v6.sin6_addr, &s2->v6.sin6_addr); |
281 | struct in6_addr *a2 = &s2->v6.sin6_addr; | ||
282 | int i, j; | ||
283 | |||
284 | for (i = 0; i < 4 ; i++) { | ||
285 | __be32 a1xora2; | ||
286 | |||
287 | a1xora2 = a1->s6_addr32[i] ^ a2->s6_addr32[i]; | ||
288 | |||
289 | if ((j = fls(ntohl(a1xora2)))) | ||
290 | return (i * 32 + 32 - j); | ||
291 | } | ||
292 | |||
293 | return (i*32); | ||
294 | } | 281 | } |
295 | 282 | ||
296 | /* Fills in the source address(saddr) based on the destination address(daddr) | 283 | /* Fills in the source address(saddr) based on the destination address(daddr) |
@@ -372,13 +359,13 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, | |||
372 | } | 359 | } |
373 | 360 | ||
374 | read_lock_bh(&in6_dev->lock); | 361 | read_lock_bh(&in6_dev->lock); |
375 | for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) { | 362 | list_for_each_entry(ifp, &in6_dev->addr_list, if_list) { |
376 | /* Add the address to the local list. */ | 363 | /* Add the address to the local list. */ |
377 | addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); | 364 | addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); |
378 | if (addr) { | 365 | if (addr) { |
379 | addr->a.v6.sin6_family = AF_INET6; | 366 | addr->a.v6.sin6_family = AF_INET6; |
380 | addr->a.v6.sin6_port = 0; | 367 | addr->a.v6.sin6_port = 0; |
381 | addr->a.v6.sin6_addr = ifp->addr; | 368 | ipv6_addr_copy(&addr->a.v6.sin6_addr, &ifp->addr); |
382 | addr->a.v6.sin6_scope_id = dev->ifindex; | 369 | addr->a.v6.sin6_scope_id = dev->ifindex; |
383 | addr->valid = 1; | 370 | addr->valid = 1; |
384 | INIT_LIST_HEAD(&addr->list); | 371 | INIT_LIST_HEAD(&addr->list); |
@@ -419,7 +406,7 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) | |||
419 | { | 406 | { |
420 | addr->v6.sin6_family = AF_INET6; | 407 | addr->v6.sin6_family = AF_INET6; |
421 | addr->v6.sin6_port = 0; | 408 | addr->v6.sin6_port = 0; |
422 | addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr; | 409 | ipv6_addr_copy(&addr->v6.sin6_addr, &inet6_sk(sk)->rcv_saddr); |
423 | } | 410 | } |
424 | 411 | ||
425 | /* Initialize sk->sk_rcv_saddr from sctp_addr. */ | 412 | /* Initialize sk->sk_rcv_saddr from sctp_addr. */ |
@@ -432,7 +419,7 @@ static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk) | |||
432 | inet6_sk(sk)->rcv_saddr.s6_addr32[3] = | 419 | inet6_sk(sk)->rcv_saddr.s6_addr32[3] = |
433 | addr->v4.sin_addr.s_addr; | 420 | addr->v4.sin_addr.s_addr; |
434 | } else { | 421 | } else { |
435 | inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr; | 422 | ipv6_addr_copy(&inet6_sk(sk)->rcv_saddr, &addr->v6.sin6_addr); |
436 | } | 423 | } |
437 | } | 424 | } |
438 | 425 | ||
@@ -445,7 +432,7 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) | |||
445 | inet6_sk(sk)->daddr.s6_addr32[2] = htonl(0x0000ffff); | 432 | inet6_sk(sk)->daddr.s6_addr32[2] = htonl(0x0000ffff); |
446 | inet6_sk(sk)->daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr; | 433 | inet6_sk(sk)->daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr; |
447 | } else { | 434 | } else { |
448 | inet6_sk(sk)->daddr = addr->v6.sin6_addr; | 435 | ipv6_addr_copy(&inet6_sk(sk)->daddr, &addr->v6.sin6_addr); |
449 | } | 436 | } |
450 | } | 437 | } |
451 | 438 | ||
diff --git a/net/sctp/output.c b/net/sctp/output.c index fad261d41ec2..a646681f5acd 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -429,24 +429,17 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
429 | list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { | 429 | list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { |
430 | list_del_init(&chunk->list); | 430 | list_del_init(&chunk->list); |
431 | if (sctp_chunk_is_data(chunk)) { | 431 | if (sctp_chunk_is_data(chunk)) { |
432 | /* 6.3.1 C4) When data is in flight and when allowed | ||
433 | * by rule C5, a new RTT measurement MUST be made each | ||
434 | * round trip. Furthermore, new RTT measurements | ||
435 | * SHOULD be made no more than once per round-trip | ||
436 | * for a given destination transport address. | ||
437 | */ | ||
432 | 438 | ||
433 | if (!chunk->resent) { | 439 | if (!tp->rto_pending) { |
434 | 440 | chunk->rtt_in_progress = 1; | |
435 | /* 6.3.1 C4) When data is in flight and when allowed | 441 | tp->rto_pending = 1; |
436 | * by rule C5, a new RTT measurement MUST be made each | ||
437 | * round trip. Furthermore, new RTT measurements | ||
438 | * SHOULD be made no more than once per round-trip | ||
439 | * for a given destination transport address. | ||
440 | */ | ||
441 | |||
442 | if (!tp->rto_pending) { | ||
443 | chunk->rtt_in_progress = 1; | ||
444 | tp->rto_pending = 1; | ||
445 | } | ||
446 | } | 442 | } |
447 | |||
448 | chunk->resent = 1; | ||
449 | |||
450 | has_data = 1; | 443 | has_data = 1; |
451 | } | 444 | } |
452 | 445 | ||
@@ -681,7 +674,7 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, | |||
681 | * Don't delay large message writes that may have been | 674 | * Don't delay large message writes that may have been |
682 | * fragmeneted into small peices. | 675 | * fragmeneted into small peices. |
683 | */ | 676 | */ |
684 | if ((len < max) && (chunk->msg->msg_size < max)) { | 677 | if ((len < max) && chunk->msg->can_delay) { |
685 | retval = SCTP_XMIT_NAGLE_DELAY; | 678 | retval = SCTP_XMIT_NAGLE_DELAY; |
686 | goto finish; | 679 | goto finish; |
687 | } | 680 | } |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index abfc0b8dee74..c04b2eb59186 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -62,7 +62,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
62 | struct list_head *transmitted_queue, | 62 | struct list_head *transmitted_queue, |
63 | struct sctp_transport *transport, | 63 | struct sctp_transport *transport, |
64 | struct sctp_sackhdr *sack, | 64 | struct sctp_sackhdr *sack, |
65 | __u32 highest_new_tsn); | 65 | __u32 *highest_new_tsn); |
66 | 66 | ||
67 | static void sctp_mark_missing(struct sctp_outq *q, | 67 | static void sctp_mark_missing(struct sctp_outq *q, |
68 | struct list_head *transmitted_queue, | 68 | struct list_head *transmitted_queue, |
@@ -80,7 +80,6 @@ static inline void sctp_outq_head_data(struct sctp_outq *q, | |||
80 | { | 80 | { |
81 | list_add(&ch->list, &q->out_chunk_list); | 81 | list_add(&ch->list, &q->out_chunk_list); |
82 | q->out_qlen += ch->skb->len; | 82 | q->out_qlen += ch->skb->len; |
83 | return; | ||
84 | } | 83 | } |
85 | 84 | ||
86 | /* Take data from the front of the queue. */ | 85 | /* Take data from the front of the queue. */ |
@@ -103,7 +102,6 @@ static inline void sctp_outq_tail_data(struct sctp_outq *q, | |||
103 | { | 102 | { |
104 | list_add_tail(&ch->list, &q->out_chunk_list); | 103 | list_add_tail(&ch->list, &q->out_chunk_list); |
105 | q->out_qlen += ch->skb->len; | 104 | q->out_qlen += ch->skb->len; |
106 | return; | ||
107 | } | 105 | } |
108 | 106 | ||
109 | /* | 107 | /* |
@@ -308,7 +306,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
308 | /* If it is data, queue it up, otherwise, send it | 306 | /* If it is data, queue it up, otherwise, send it |
309 | * immediately. | 307 | * immediately. |
310 | */ | 308 | */ |
311 | if (SCTP_CID_DATA == chunk->chunk_hdr->type) { | 309 | if (sctp_chunk_is_data(chunk)) { |
312 | /* Is it OK to queue data chunks? */ | 310 | /* Is it OK to queue data chunks? */ |
313 | /* From 9. Termination of Association | 311 | /* From 9. Termination of Association |
314 | * | 312 | * |
@@ -598,11 +596,23 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
598 | if (fast_rtx && !chunk->fast_retransmit) | 596 | if (fast_rtx && !chunk->fast_retransmit) |
599 | continue; | 597 | continue; |
600 | 598 | ||
599 | redo: | ||
601 | /* Attempt to append this chunk to the packet. */ | 600 | /* Attempt to append this chunk to the packet. */ |
602 | status = sctp_packet_append_chunk(pkt, chunk); | 601 | status = sctp_packet_append_chunk(pkt, chunk); |
603 | 602 | ||
604 | switch (status) { | 603 | switch (status) { |
605 | case SCTP_XMIT_PMTU_FULL: | 604 | case SCTP_XMIT_PMTU_FULL: |
605 | if (!pkt->has_data && !pkt->has_cookie_echo) { | ||
606 | /* If this packet did not contain DATA then | ||
607 | * retransmission did not happen, so do it | ||
608 | * again. We'll ignore the error here since | ||
609 | * control chunks are already freed so there | ||
610 | * is nothing we can do. | ||
611 | */ | ||
612 | sctp_packet_transmit(pkt); | ||
613 | goto redo; | ||
614 | } | ||
615 | |||
606 | /* Send this packet. */ | 616 | /* Send this packet. */ |
607 | error = sctp_packet_transmit(pkt); | 617 | error = sctp_packet_transmit(pkt); |
608 | 618 | ||
@@ -647,14 +657,6 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
647 | if (chunk->fast_retransmit == SCTP_NEED_FRTX) | 657 | if (chunk->fast_retransmit == SCTP_NEED_FRTX) |
648 | chunk->fast_retransmit = SCTP_DONT_FRTX; | 658 | chunk->fast_retransmit = SCTP_DONT_FRTX; |
649 | 659 | ||
650 | /* Force start T3-rtx timer when fast retransmitting | ||
651 | * the earliest outstanding TSN | ||
652 | */ | ||
653 | if (!timer && fast_rtx && | ||
654 | ntohl(chunk->subh.data_hdr->tsn) == | ||
655 | asoc->ctsn_ack_point + 1) | ||
656 | timer = 2; | ||
657 | |||
658 | q->empty = 0; | 660 | q->empty = 0; |
659 | break; | 661 | break; |
660 | } | 662 | } |
@@ -854,6 +856,12 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
854 | if (status != SCTP_XMIT_OK) { | 856 | if (status != SCTP_XMIT_OK) { |
855 | /* put the chunk back */ | 857 | /* put the chunk back */ |
856 | list_add(&chunk->list, &q->control_chunk_list); | 858 | list_add(&chunk->list, &q->control_chunk_list); |
859 | } else if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) { | ||
860 | /* PR-SCTP C5) If a FORWARD TSN is sent, the | ||
861 | * sender MUST assure that at least one T3-rtx | ||
862 | * timer is running. | ||
863 | */ | ||
864 | sctp_transport_reset_timers(transport); | ||
857 | } | 865 | } |
858 | break; | 866 | break; |
859 | 867 | ||
@@ -906,8 +914,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
906 | rtx_timeout, &start_timer); | 914 | rtx_timeout, &start_timer); |
907 | 915 | ||
908 | if (start_timer) | 916 | if (start_timer) |
909 | sctp_transport_reset_timers(transport, | 917 | sctp_transport_reset_timers(transport); |
910 | start_timer-1); | ||
911 | 918 | ||
912 | /* This can happen on COOKIE-ECHO resend. Only | 919 | /* This can happen on COOKIE-ECHO resend. Only |
913 | * one chunk can get bundled with a COOKIE-ECHO. | 920 | * one chunk can get bundled with a COOKIE-ECHO. |
@@ -1040,7 +1047,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
1040 | list_add_tail(&chunk->transmitted_list, | 1047 | list_add_tail(&chunk->transmitted_list, |
1041 | &transport->transmitted); | 1048 | &transport->transmitted); |
1042 | 1049 | ||
1043 | sctp_transport_reset_timers(transport, 0); | 1050 | sctp_transport_reset_timers(transport); |
1044 | 1051 | ||
1045 | q->empty = 0; | 1052 | q->empty = 0; |
1046 | 1053 | ||
@@ -1100,32 +1107,6 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc, | |||
1100 | assoc->unack_data = unack_data; | 1107 | assoc->unack_data = unack_data; |
1101 | } | 1108 | } |
1102 | 1109 | ||
1103 | /* Return the highest new tsn that is acknowledged by the given SACK chunk. */ | ||
1104 | static __u32 sctp_highest_new_tsn(struct sctp_sackhdr *sack, | ||
1105 | struct sctp_association *asoc) | ||
1106 | { | ||
1107 | struct sctp_transport *transport; | ||
1108 | struct sctp_chunk *chunk; | ||
1109 | __u32 highest_new_tsn, tsn; | ||
1110 | struct list_head *transport_list = &asoc->peer.transport_addr_list; | ||
1111 | |||
1112 | highest_new_tsn = ntohl(sack->cum_tsn_ack); | ||
1113 | |||
1114 | list_for_each_entry(transport, transport_list, transports) { | ||
1115 | list_for_each_entry(chunk, &transport->transmitted, | ||
1116 | transmitted_list) { | ||
1117 | tsn = ntohl(chunk->subh.data_hdr->tsn); | ||
1118 | |||
1119 | if (!chunk->tsn_gap_acked && | ||
1120 | TSN_lt(highest_new_tsn, tsn) && | ||
1121 | sctp_acked(sack, tsn)) | ||
1122 | highest_new_tsn = tsn; | ||
1123 | } | ||
1124 | } | ||
1125 | |||
1126 | return highest_new_tsn; | ||
1127 | } | ||
1128 | |||
1129 | /* This is where we REALLY process a SACK. | 1110 | /* This is where we REALLY process a SACK. |
1130 | * | 1111 | * |
1131 | * Process the SACK against the outqueue. Mostly, this just frees | 1112 | * Process the SACK against the outqueue. Mostly, this just frees |
@@ -1145,6 +1126,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1145 | struct sctp_transport *primary = asoc->peer.primary_path; | 1126 | struct sctp_transport *primary = asoc->peer.primary_path; |
1146 | int count_of_newacks = 0; | 1127 | int count_of_newacks = 0; |
1147 | int gap_ack_blocks; | 1128 | int gap_ack_blocks; |
1129 | u8 accum_moved = 0; | ||
1148 | 1130 | ||
1149 | /* Grab the association's destination address list. */ | 1131 | /* Grab the association's destination address list. */ |
1150 | transport_list = &asoc->peer.transport_addr_list; | 1132 | transport_list = &asoc->peer.transport_addr_list; |
@@ -1193,18 +1175,15 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1193 | if (gap_ack_blocks) | 1175 | if (gap_ack_blocks) |
1194 | highest_tsn += ntohs(frags[gap_ack_blocks - 1].gab.end); | 1176 | highest_tsn += ntohs(frags[gap_ack_blocks - 1].gab.end); |
1195 | 1177 | ||
1196 | if (TSN_lt(asoc->highest_sacked, highest_tsn)) { | 1178 | if (TSN_lt(asoc->highest_sacked, highest_tsn)) |
1197 | highest_new_tsn = highest_tsn; | ||
1198 | asoc->highest_sacked = highest_tsn; | 1179 | asoc->highest_sacked = highest_tsn; |
1199 | } else { | ||
1200 | highest_new_tsn = sctp_highest_new_tsn(sack, asoc); | ||
1201 | } | ||
1202 | 1180 | ||
1181 | highest_new_tsn = sack_ctsn; | ||
1203 | 1182 | ||
1204 | /* Run through the retransmit queue. Credit bytes received | 1183 | /* Run through the retransmit queue. Credit bytes received |
1205 | * and free those chunks that we can. | 1184 | * and free those chunks that we can. |
1206 | */ | 1185 | */ |
1207 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn); | 1186 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, &highest_new_tsn); |
1208 | 1187 | ||
1209 | /* Run through the transmitted queue. | 1188 | /* Run through the transmitted queue. |
1210 | * Credit bytes received and free those chunks which we can. | 1189 | * Credit bytes received and free those chunks which we can. |
@@ -1213,7 +1192,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1213 | */ | 1192 | */ |
1214 | list_for_each_entry(transport, transport_list, transports) { | 1193 | list_for_each_entry(transport, transport_list, transports) { |
1215 | sctp_check_transmitted(q, &transport->transmitted, | 1194 | sctp_check_transmitted(q, &transport->transmitted, |
1216 | transport, sack, highest_new_tsn); | 1195 | transport, sack, &highest_new_tsn); |
1217 | /* | 1196 | /* |
1218 | * SFR-CACC algorithm: | 1197 | * SFR-CACC algorithm: |
1219 | * C) Let count_of_newacks be the number of | 1198 | * C) Let count_of_newacks be the number of |
@@ -1223,16 +1202,22 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1223 | count_of_newacks ++; | 1202 | count_of_newacks ++; |
1224 | } | 1203 | } |
1225 | 1204 | ||
1205 | /* Move the Cumulative TSN Ack Point if appropriate. */ | ||
1206 | if (TSN_lt(asoc->ctsn_ack_point, sack_ctsn)) { | ||
1207 | asoc->ctsn_ack_point = sack_ctsn; | ||
1208 | accum_moved = 1; | ||
1209 | } | ||
1210 | |||
1226 | if (gap_ack_blocks) { | 1211 | if (gap_ack_blocks) { |
1212 | |||
1213 | if (asoc->fast_recovery && accum_moved) | ||
1214 | highest_new_tsn = highest_tsn; | ||
1215 | |||
1227 | list_for_each_entry(transport, transport_list, transports) | 1216 | list_for_each_entry(transport, transport_list, transports) |
1228 | sctp_mark_missing(q, &transport->transmitted, transport, | 1217 | sctp_mark_missing(q, &transport->transmitted, transport, |
1229 | highest_new_tsn, count_of_newacks); | 1218 | highest_new_tsn, count_of_newacks); |
1230 | } | 1219 | } |
1231 | 1220 | ||
1232 | /* Move the Cumulative TSN Ack Point if appropriate. */ | ||
1233 | if (TSN_lt(asoc->ctsn_ack_point, sack_ctsn)) | ||
1234 | asoc->ctsn_ack_point = sack_ctsn; | ||
1235 | |||
1236 | /* Update unack_data field in the assoc. */ | 1221 | /* Update unack_data field in the assoc. */ |
1237 | sctp_sack_update_unack_data(asoc, sack); | 1222 | sctp_sack_update_unack_data(asoc, sack); |
1238 | 1223 | ||
@@ -1315,7 +1300,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1315 | struct list_head *transmitted_queue, | 1300 | struct list_head *transmitted_queue, |
1316 | struct sctp_transport *transport, | 1301 | struct sctp_transport *transport, |
1317 | struct sctp_sackhdr *sack, | 1302 | struct sctp_sackhdr *sack, |
1318 | __u32 highest_new_tsn_in_sack) | 1303 | __u32 *highest_new_tsn_in_sack) |
1319 | { | 1304 | { |
1320 | struct list_head *lchunk; | 1305 | struct list_head *lchunk; |
1321 | struct sctp_chunk *tchunk; | 1306 | struct sctp_chunk *tchunk; |
@@ -1387,7 +1372,6 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1387 | * instance). | 1372 | * instance). |
1388 | */ | 1373 | */ |
1389 | if (!tchunk->tsn_gap_acked && | 1374 | if (!tchunk->tsn_gap_acked && |
1390 | !tchunk->resent && | ||
1391 | tchunk->rtt_in_progress) { | 1375 | tchunk->rtt_in_progress) { |
1392 | tchunk->rtt_in_progress = 0; | 1376 | tchunk->rtt_in_progress = 0; |
1393 | rtt = jiffies - tchunk->sent_at; | 1377 | rtt = jiffies - tchunk->sent_at; |
@@ -1404,6 +1388,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1404 | */ | 1388 | */ |
1405 | if (!tchunk->tsn_gap_acked) { | 1389 | if (!tchunk->tsn_gap_acked) { |
1406 | tchunk->tsn_gap_acked = 1; | 1390 | tchunk->tsn_gap_acked = 1; |
1391 | *highest_new_tsn_in_sack = tsn; | ||
1407 | bytes_acked += sctp_data_size(tchunk); | 1392 | bytes_acked += sctp_data_size(tchunk); |
1408 | if (!tchunk->transport) | 1393 | if (!tchunk->transport) |
1409 | migrate_bytes += sctp_data_size(tchunk); | 1394 | migrate_bytes += sctp_data_size(tchunk); |
@@ -1677,7 +1662,8 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
1677 | struct sctp_chunk *chunk; | 1662 | struct sctp_chunk *chunk; |
1678 | __u32 tsn; | 1663 | __u32 tsn; |
1679 | char do_fast_retransmit = 0; | 1664 | char do_fast_retransmit = 0; |
1680 | struct sctp_transport *primary = q->asoc->peer.primary_path; | 1665 | struct sctp_association *asoc = q->asoc; |
1666 | struct sctp_transport *primary = asoc->peer.primary_path; | ||
1681 | 1667 | ||
1682 | list_for_each_entry(chunk, transmitted_queue, transmitted_list) { | 1668 | list_for_each_entry(chunk, transmitted_queue, transmitted_list) { |
1683 | 1669 | ||
diff --git a/net/sctp/probe.c b/net/sctp/probe.c new file mode 100644 index 000000000000..db3a42b8b349 --- /dev/null +++ b/net/sctp/probe.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /* | ||
2 | * sctp_probe - Observe the SCTP flow with kprobes. | ||
3 | * | ||
4 | * The idea for this came from Werner Almesberger's umlsim | ||
5 | * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org> | ||
6 | * | ||
7 | * Modified for SCTP from Stephen Hemminger's code | ||
8 | * Copyright (C) 2010, Wei Yongjun <yjwei@cn.fujitsu.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/kprobes.h> | ||
27 | #include <linux/socket.h> | ||
28 | #include <linux/sctp.h> | ||
29 | #include <linux/proc_fs.h> | ||
30 | #include <linux/vmalloc.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/kfifo.h> | ||
33 | #include <linux/time.h> | ||
34 | #include <net/net_namespace.h> | ||
35 | |||
36 | #include <net/sctp/sctp.h> | ||
37 | #include <net/sctp/sm.h> | ||
38 | |||
39 | MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>"); | ||
40 | MODULE_DESCRIPTION("SCTP snooper"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | static int port __read_mostly = 0; | ||
44 | MODULE_PARM_DESC(port, "Port to match (0=all)"); | ||
45 | module_param(port, int, 0); | ||
46 | |||
47 | static int bufsize __read_mostly = 64 * 1024; | ||
48 | MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)"); | ||
49 | module_param(bufsize, int, 0); | ||
50 | |||
51 | static int full __read_mostly = 1; | ||
52 | MODULE_PARM_DESC(full, "Full log (1=every ack packet received, 0=only cwnd changes)"); | ||
53 | module_param(full, int, 0); | ||
54 | |||
55 | static const char procname[] = "sctpprobe"; | ||
56 | |||
57 | static struct { | ||
58 | struct kfifo fifo; | ||
59 | spinlock_t lock; | ||
60 | wait_queue_head_t wait; | ||
61 | struct timespec tstart; | ||
62 | } sctpw; | ||
63 | |||
64 | static void printl(const char *fmt, ...) | ||
65 | { | ||
66 | va_list args; | ||
67 | int len; | ||
68 | char tbuf[256]; | ||
69 | |||
70 | va_start(args, fmt); | ||
71 | len = vscnprintf(tbuf, sizeof(tbuf), fmt, args); | ||
72 | va_end(args); | ||
73 | |||
74 | kfifo_in_locked(&sctpw.fifo, tbuf, len, &sctpw.lock); | ||
75 | wake_up(&sctpw.wait); | ||
76 | } | ||
77 | |||
78 | static int sctpprobe_open(struct inode *inode, struct file *file) | ||
79 | { | ||
80 | kfifo_reset(&sctpw.fifo); | ||
81 | getnstimeofday(&sctpw.tstart); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static ssize_t sctpprobe_read(struct file *file, char __user *buf, | ||
87 | size_t len, loff_t *ppos) | ||
88 | { | ||
89 | int error = 0, cnt = 0; | ||
90 | unsigned char *tbuf; | ||
91 | |||
92 | if (!buf) | ||
93 | return -EINVAL; | ||
94 | |||
95 | if (len == 0) | ||
96 | return 0; | ||
97 | |||
98 | tbuf = vmalloc(len); | ||
99 | if (!tbuf) | ||
100 | return -ENOMEM; | ||
101 | |||
102 | error = wait_event_interruptible(sctpw.wait, | ||
103 | kfifo_len(&sctpw.fifo) != 0); | ||
104 | if (error) | ||
105 | goto out_free; | ||
106 | |||
107 | cnt = kfifo_out_locked(&sctpw.fifo, tbuf, len, &sctpw.lock); | ||
108 | error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0; | ||
109 | |||
110 | out_free: | ||
111 | vfree(tbuf); | ||
112 | |||
113 | return error ? error : cnt; | ||
114 | } | ||
115 | |||
116 | static const struct file_operations sctpprobe_fops = { | ||
117 | .owner = THIS_MODULE, | ||
118 | .open = sctpprobe_open, | ||
119 | .read = sctpprobe_read, | ||
120 | }; | ||
121 | |||
122 | sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep, | ||
123 | const struct sctp_association *asoc, | ||
124 | const sctp_subtype_t type, | ||
125 | void *arg, | ||
126 | sctp_cmd_seq_t *commands) | ||
127 | { | ||
128 | struct sctp_transport *sp; | ||
129 | static __u32 lcwnd = 0; | ||
130 | struct timespec now; | ||
131 | |||
132 | sp = asoc->peer.primary_path; | ||
133 | |||
134 | if ((full || sp->cwnd != lcwnd) && | ||
135 | (!port || asoc->peer.port == port || | ||
136 | ep->base.bind_addr.port == port)) { | ||
137 | lcwnd = sp->cwnd; | ||
138 | |||
139 | getnstimeofday(&now); | ||
140 | now = timespec_sub(now, sctpw.tstart); | ||
141 | |||
142 | printl("%lu.%06lu ", (unsigned long) now.tv_sec, | ||
143 | (unsigned long) now.tv_nsec / NSEC_PER_USEC); | ||
144 | |||
145 | printl("%p %5d %5d %5d %8d %5d ", asoc, | ||
146 | ep->base.bind_addr.port, asoc->peer.port, | ||
147 | asoc->pathmtu, asoc->peer.rwnd, asoc->unack_data); | ||
148 | |||
149 | list_for_each_entry(sp, &asoc->peer.transport_addr_list, | ||
150 | transports) { | ||
151 | if (sp == asoc->peer.primary_path) | ||
152 | printl("*"); | ||
153 | |||
154 | if (sp->ipaddr.sa.sa_family == AF_INET) | ||
155 | printl("%pI4 ", &sp->ipaddr.v4.sin_addr); | ||
156 | else | ||
157 | printl("%pI6 ", &sp->ipaddr.v6.sin6_addr); | ||
158 | |||
159 | printl("%2u %8u %8u %8u %8u %8u ", | ||
160 | sp->state, sp->cwnd, sp->ssthresh, | ||
161 | sp->flight_size, sp->partial_bytes_acked, | ||
162 | sp->pathmtu); | ||
163 | } | ||
164 | printl("\n"); | ||
165 | } | ||
166 | |||
167 | jprobe_return(); | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static struct jprobe sctp_recv_probe = { | ||
172 | .kp = { | ||
173 | .symbol_name = "sctp_sf_eat_sack_6_2", | ||
174 | }, | ||
175 | .entry = jsctp_sf_eat_sack, | ||
176 | }; | ||
177 | |||
178 | static __init int sctpprobe_init(void) | ||
179 | { | ||
180 | int ret = -ENOMEM; | ||
181 | |||
182 | init_waitqueue_head(&sctpw.wait); | ||
183 | spin_lock_init(&sctpw.lock); | ||
184 | if (kfifo_alloc(&sctpw.fifo, bufsize, GFP_KERNEL)) | ||
185 | return ret; | ||
186 | |||
187 | if (!proc_net_fops_create(&init_net, procname, S_IRUSR, | ||
188 | &sctpprobe_fops)) | ||
189 | goto free_kfifo; | ||
190 | |||
191 | ret = register_jprobe(&sctp_recv_probe); | ||
192 | if (ret) | ||
193 | goto remove_proc; | ||
194 | |||
195 | pr_info("SCTP probe registered (port=%d)\n", port); | ||
196 | |||
197 | return 0; | ||
198 | |||
199 | remove_proc: | ||
200 | proc_net_remove(&init_net, procname); | ||
201 | free_kfifo: | ||
202 | kfifo_free(&sctpw.fifo); | ||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | static __exit void sctpprobe_exit(void) | ||
207 | { | ||
208 | kfifo_free(&sctpw.fifo); | ||
209 | proc_net_remove(&init_net, procname); | ||
210 | unregister_jprobe(&sctp_recv_probe); | ||
211 | } | ||
212 | |||
213 | module_init(sctpprobe_init); | ||
214 | module_exit(sctpprobe_exit); | ||
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 784bcc9a979d..61aacfbbaa92 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -181,7 +181,6 @@ static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos) | |||
181 | 181 | ||
182 | static void sctp_eps_seq_stop(struct seq_file *seq, void *v) | 182 | static void sctp_eps_seq_stop(struct seq_file *seq, void *v) |
183 | { | 183 | { |
184 | return; | ||
185 | } | 184 | } |
186 | 185 | ||
187 | 186 | ||
@@ -286,7 +285,6 @@ static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) | |||
286 | 285 | ||
287 | static void sctp_assocs_seq_stop(struct seq_file *seq, void *v) | 286 | static void sctp_assocs_seq_stop(struct seq_file *seq, void *v) |
288 | { | 287 | { |
289 | return; | ||
290 | } | 288 | } |
291 | 289 | ||
292 | 290 | ||
@@ -409,7 +407,6 @@ static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
409 | 407 | ||
410 | static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v) | 408 | static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v) |
411 | { | 409 | { |
412 | return; | ||
413 | } | 410 | } |
414 | 411 | ||
415 | static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) | 412 | static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index a56f98e82f92..182749867c72 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -474,13 +474,17 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
474 | 474 | ||
475 | memset(&fl, 0x0, sizeof(struct flowi)); | 475 | memset(&fl, 0x0, sizeof(struct flowi)); |
476 | fl.fl4_dst = daddr->v4.sin_addr.s_addr; | 476 | fl.fl4_dst = daddr->v4.sin_addr.s_addr; |
477 | fl.fl_ip_dport = daddr->v4.sin_port; | ||
477 | fl.proto = IPPROTO_SCTP; | 478 | fl.proto = IPPROTO_SCTP; |
478 | if (asoc) { | 479 | if (asoc) { |
479 | fl.fl4_tos = RT_CONN_FLAGS(asoc->base.sk); | 480 | fl.fl4_tos = RT_CONN_FLAGS(asoc->base.sk); |
480 | fl.oif = asoc->base.sk->sk_bound_dev_if; | 481 | fl.oif = asoc->base.sk->sk_bound_dev_if; |
482 | fl.fl_ip_sport = htons(asoc->base.bind_addr.port); | ||
481 | } | 483 | } |
482 | if (saddr) | 484 | if (saddr) { |
483 | fl.fl4_src = saddr->v4.sin_addr.s_addr; | 485 | fl.fl4_src = saddr->v4.sin_addr.s_addr; |
486 | fl.fl_ip_sport = saddr->v4.sin_port; | ||
487 | } | ||
484 | 488 | ||
485 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", | 489 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", |
486 | __func__, &fl.fl4_dst, &fl.fl4_src); | 490 | __func__, &fl.fl4_dst, &fl.fl4_src); |
@@ -528,6 +532,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
528 | if ((laddr->state == SCTP_ADDR_SRC) && | 532 | if ((laddr->state == SCTP_ADDR_SRC) && |
529 | (AF_INET == laddr->a.sa.sa_family)) { | 533 | (AF_INET == laddr->a.sa.sa_family)) { |
530 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; | 534 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; |
535 | fl.fl_ip_sport = laddr->a.v4.sin_port; | ||
531 | if (!ip_route_output_key(&init_net, &rt, &fl)) { | 536 | if (!ip_route_output_key(&init_net, &rt, &fl)) { |
532 | dst = &rt->u.dst; | 537 | dst = &rt->u.dst; |
533 | goto out_unlock; | 538 | goto out_unlock; |
@@ -854,7 +859,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, | |||
854 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; | 859 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; |
855 | 860 | ||
856 | SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); | 861 | SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); |
857 | return ip_queue_xmit(skb, 0); | 862 | return ip_queue_xmit(skb); |
858 | } | 863 | } |
859 | 864 | ||
860 | static struct sctp_af sctp_af_inet; | 865 | static struct sctp_af sctp_af_inet; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 30c1767186b8..bd2a50b482ac 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -141,7 +141,7 @@ int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code, | |||
141 | len = sizeof(sctp_errhdr_t) + paylen; | 141 | len = sizeof(sctp_errhdr_t) + paylen; |
142 | err.length = htons(len); | 142 | err.length = htons(len); |
143 | 143 | ||
144 | if (skb_tailroom(chunk->skb) > len) | 144 | if (skb_tailroom(chunk->skb) < len) |
145 | return -ENOSPC; | 145 | return -ENOSPC; |
146 | chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk, | 146 | chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk, |
147 | sizeof(sctp_errhdr_t), | 147 | sizeof(sctp_errhdr_t), |
@@ -445,10 +445,17 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
445 | if (!retval) | 445 | if (!retval) |
446 | goto nomem_chunk; | 446 | goto nomem_chunk; |
447 | 447 | ||
448 | /* Per the advice in RFC 2960 6.4, send this reply to | 448 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints |
449 | * the source of the INIT packet. | 449 | * |
450 | * An endpoint SHOULD transmit reply chunks (e.g., SACK, | ||
451 | * HEARTBEAT ACK, * etc.) to the same destination transport | ||
452 | * address from which it received the DATA or control chunk | ||
453 | * to which it is replying. | ||
454 | * | ||
455 | * [INIT ACK back to where the INIT came from.] | ||
450 | */ | 456 | */ |
451 | retval->transport = chunk->transport; | 457 | retval->transport = chunk->transport; |
458 | |||
452 | retval->subh.init_hdr = | 459 | retval->subh.init_hdr = |
453 | sctp_addto_chunk(retval, sizeof(initack), &initack); | 460 | sctp_addto_chunk(retval, sizeof(initack), &initack); |
454 | retval->param_hdr.v = sctp_addto_chunk(retval, addrs_len, addrs.v); | 461 | retval->param_hdr.v = sctp_addto_chunk(retval, addrs_len, addrs.v); |
@@ -487,18 +494,6 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
487 | /* We need to remove the const qualifier at this point. */ | 494 | /* We need to remove the const qualifier at this point. */ |
488 | retval->asoc = (struct sctp_association *) asoc; | 495 | retval->asoc = (struct sctp_association *) asoc; |
489 | 496 | ||
490 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints | ||
491 | * | ||
492 | * An endpoint SHOULD transmit reply chunks (e.g., SACK, | ||
493 | * HEARTBEAT ACK, * etc.) to the same destination transport | ||
494 | * address from which it received the DATA or control chunk | ||
495 | * to which it is replying. | ||
496 | * | ||
497 | * [INIT ACK back to where the INIT came from.] | ||
498 | */ | ||
499 | if (chunk) | ||
500 | retval->transport = chunk->transport; | ||
501 | |||
502 | nomem_chunk: | 497 | nomem_chunk: |
503 | kfree(cookie); | 498 | kfree(cookie); |
504 | nomem_cookie: | 499 | nomem_cookie: |
@@ -1254,7 +1249,6 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, | |||
1254 | INIT_LIST_HEAD(&retval->list); | 1249 | INIT_LIST_HEAD(&retval->list); |
1255 | retval->skb = skb; | 1250 | retval->skb = skb; |
1256 | retval->asoc = (struct sctp_association *)asoc; | 1251 | retval->asoc = (struct sctp_association *)asoc; |
1257 | retval->resent = 0; | ||
1258 | retval->has_tsn = 0; | 1252 | retval->has_tsn = 0; |
1259 | retval->has_ssn = 0; | 1253 | retval->has_ssn = 0; |
1260 | retval->rtt_in_progress = 0; | 1254 | retval->rtt_in_progress = 0; |
@@ -1421,7 +1415,7 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data) | |||
1421 | void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk, | 1415 | void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk, |
1422 | int len, const void *data) | 1416 | int len, const void *data) |
1423 | { | 1417 | { |
1424 | if (skb_tailroom(chunk->skb) > len) | 1418 | if (skb_tailroom(chunk->skb) >= len) |
1425 | return sctp_addto_chunk(chunk, len, data); | 1419 | return sctp_addto_chunk(chunk, len, data); |
1426 | else | 1420 | else |
1427 | return NULL; | 1421 | return NULL; |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index eb1f42f45fdd..f5e5e27cac5e 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -732,11 +732,15 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, | |||
732 | { | 732 | { |
733 | struct sctp_transport *t; | 733 | struct sctp_transport *t; |
734 | 734 | ||
735 | t = sctp_assoc_choose_alter_transport(asoc, | 735 | if (chunk->transport) |
736 | t = chunk->transport; | ||
737 | else { | ||
738 | t = sctp_assoc_choose_alter_transport(asoc, | ||
736 | asoc->shutdown_last_sent_to); | 739 | asoc->shutdown_last_sent_to); |
740 | chunk->transport = t; | ||
741 | } | ||
737 | asoc->shutdown_last_sent_to = t; | 742 | asoc->shutdown_last_sent_to = t; |
738 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; | 743 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; |
739 | chunk->transport = t; | ||
740 | } | 744 | } |
741 | 745 | ||
742 | /* Helper function to change the state of an association. */ | 746 | /* Helper function to change the state of an association. */ |
@@ -888,8 +892,6 @@ static void sctp_cmd_process_fwdtsn(struct sctp_ulpq *ulpq, | |||
888 | sctp_walk_fwdtsn(skip, chunk) { | 892 | sctp_walk_fwdtsn(skip, chunk) { |
889 | sctp_ulpq_skip(ulpq, ntohs(skip->stream), ntohs(skip->ssn)); | 893 | sctp_ulpq_skip(ulpq, ntohs(skip->stream), ntohs(skip->ssn)); |
890 | } | 894 | } |
891 | |||
892 | return; | ||
893 | } | 895 | } |
894 | 896 | ||
895 | /* Helper function to remove the association non-primary peer | 897 | /* Helper function to remove the association non-primary peer |
@@ -908,8 +910,6 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc) | |||
908 | sctp_assoc_del_peer(asoc, &t->ipaddr); | 910 | sctp_assoc_del_peer(asoc, &t->ipaddr); |
909 | } | 911 | } |
910 | } | 912 | } |
911 | |||
912 | return; | ||
913 | } | 913 | } |
914 | 914 | ||
915 | /* Helper function to set sk_err on a 1-1 style socket. */ | 915 | /* Helper function to set sk_err on a 1-1 style socket. */ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 44a1ab03a3f0..ca44917872d2 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -3720,9 +3720,6 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3720 | 3720 | ||
3721 | SCTP_DBG_OBJCNT_INC(sock); | 3721 | SCTP_DBG_OBJCNT_INC(sock); |
3722 | 3722 | ||
3723 | /* Set socket backlog limit. */ | ||
3724 | sk->sk_backlog.limit = sysctl_sctp_rmem[1]; | ||
3725 | |||
3726 | local_bh_disable(); | 3723 | local_bh_disable(); |
3727 | percpu_counter_inc(&sctp_sockets_allocated); | 3724 | percpu_counter_inc(&sctp_sockets_allocated); |
3728 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 3725 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
@@ -4387,7 +4384,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, | |||
4387 | transports) { | 4384 | transports) { |
4388 | memcpy(&temp, &from->ipaddr, sizeof(temp)); | 4385 | memcpy(&temp, &from->ipaddr, sizeof(temp)); |
4389 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); | 4386 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); |
4390 | addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; | 4387 | addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; |
4391 | if (space_left < addrlen) | 4388 | if (space_left < addrlen) |
4392 | return -ENOMEM; | 4389 | return -ENOMEM; |
4393 | if (copy_to_user(to, &temp, addrlen)) | 4390 | if (copy_to_user(to, &temp, addrlen)) |
@@ -5436,6 +5433,8 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5436 | rover++; | 5433 | rover++; |
5437 | if ((rover < low) || (rover > high)) | 5434 | if ((rover < low) || (rover > high)) |
5438 | rover = low; | 5435 | rover = low; |
5436 | if (inet_is_reserved_local_port(rover)) | ||
5437 | continue; | ||
5439 | index = sctp_phashfn(rover); | 5438 | index = sctp_phashfn(rover); |
5440 | head = &sctp_port_hashtable[index]; | 5439 | head = &sctp_port_hashtable[index]; |
5441 | sctp_spin_lock(&head->lock); | 5440 | sctp_spin_lock(&head->lock); |
@@ -5482,7 +5481,6 @@ pp_found: | |||
5482 | */ | 5481 | */ |
5483 | int reuse = sk->sk_reuse; | 5482 | int reuse = sk->sk_reuse; |
5484 | struct sock *sk2; | 5483 | struct sock *sk2; |
5485 | struct hlist_node *node; | ||
5486 | 5484 | ||
5487 | SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); | 5485 | SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); |
5488 | if (pp->fastreuse && sk->sk_reuse && | 5486 | if (pp->fastreuse && sk->sk_reuse && |
@@ -5703,7 +5701,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
5703 | struct sctp_sock *sp = sctp_sk(sk); | 5701 | struct sctp_sock *sp = sctp_sk(sk); |
5704 | unsigned int mask; | 5702 | unsigned int mask; |
5705 | 5703 | ||
5706 | poll_wait(file, sk->sk_sleep, wait); | 5704 | poll_wait(file, sk_sleep(sk), wait); |
5707 | 5705 | ||
5708 | /* A TCP-style listening socket becomes readable when the accept queue | 5706 | /* A TCP-style listening socket becomes readable when the accept queue |
5709 | * is not empty. | 5707 | * is not empty. |
@@ -5944,7 +5942,7 @@ static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p) | |||
5944 | int error; | 5942 | int error; |
5945 | DEFINE_WAIT(wait); | 5943 | DEFINE_WAIT(wait); |
5946 | 5944 | ||
5947 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 5945 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
5948 | 5946 | ||
5949 | /* Socket errors? */ | 5947 | /* Socket errors? */ |
5950 | error = sock_error(sk); | 5948 | error = sock_error(sk); |
@@ -5981,14 +5979,14 @@ static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p) | |||
5981 | sctp_lock_sock(sk); | 5979 | sctp_lock_sock(sk); |
5982 | 5980 | ||
5983 | ready: | 5981 | ready: |
5984 | finish_wait(sk->sk_sleep, &wait); | 5982 | finish_wait(sk_sleep(sk), &wait); |
5985 | return 0; | 5983 | return 0; |
5986 | 5984 | ||
5987 | interrupted: | 5985 | interrupted: |
5988 | error = sock_intr_errno(*timeo_p); | 5986 | error = sock_intr_errno(*timeo_p); |
5989 | 5987 | ||
5990 | out: | 5988 | out: |
5991 | finish_wait(sk->sk_sleep, &wait); | 5989 | finish_wait(sk_sleep(sk), &wait); |
5992 | *err = error; | 5990 | *err = error; |
5993 | return error; | 5991 | return error; |
5994 | } | 5992 | } |
@@ -6062,14 +6060,14 @@ static void __sctp_write_space(struct sctp_association *asoc) | |||
6062 | wake_up_interruptible(&asoc->wait); | 6060 | wake_up_interruptible(&asoc->wait); |
6063 | 6061 | ||
6064 | if (sctp_writeable(sk)) { | 6062 | if (sctp_writeable(sk)) { |
6065 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 6063 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
6066 | wake_up_interruptible(sk->sk_sleep); | 6064 | wake_up_interruptible(sk_sleep(sk)); |
6067 | 6065 | ||
6068 | /* Note that we try to include the Async I/O support | 6066 | /* Note that we try to include the Async I/O support |
6069 | * here by modeling from the current TCP/UDP code. | 6067 | * here by modeling from the current TCP/UDP code. |
6070 | * We have not tested with it yet. | 6068 | * We have not tested with it yet. |
6071 | */ | 6069 | */ |
6072 | if (sock->fasync_list && | 6070 | if (sock->wq->fasync_list && |
6073 | !(sk->sk_shutdown & SEND_SHUTDOWN)) | 6071 | !(sk->sk_shutdown & SEND_SHUTDOWN)) |
6074 | sock_wake_async(sock, | 6072 | sock_wake_async(sock, |
6075 | SOCK_WAKE_SPACE, POLL_OUT); | 6073 | SOCK_WAKE_SPACE, POLL_OUT); |
@@ -6191,12 +6189,15 @@ do_nonblock: | |||
6191 | 6189 | ||
6192 | void sctp_data_ready(struct sock *sk, int len) | 6190 | void sctp_data_ready(struct sock *sk, int len) |
6193 | { | 6191 | { |
6194 | read_lock_bh(&sk->sk_callback_lock); | 6192 | struct socket_wq *wq; |
6195 | if (sk_has_sleeper(sk)) | 6193 | |
6196 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | | 6194 | rcu_read_lock(); |
6195 | wq = rcu_dereference(sk->sk_wq); | ||
6196 | if (wq_has_sleeper(wq)) | ||
6197 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | | ||
6197 | POLLRDNORM | POLLRDBAND); | 6198 | POLLRDNORM | POLLRDBAND); |
6198 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 6199 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
6199 | read_unlock_bh(&sk->sk_callback_lock); | 6200 | rcu_read_unlock(); |
6200 | } | 6201 | } |
6201 | 6202 | ||
6202 | /* If socket sndbuf has changed, wake up all per association waiters. */ | 6203 | /* If socket sndbuf has changed, wake up all per association waiters. */ |
@@ -6307,7 +6308,7 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo) | |||
6307 | 6308 | ||
6308 | 6309 | ||
6309 | for (;;) { | 6310 | for (;;) { |
6310 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, | 6311 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
6311 | TASK_INTERRUPTIBLE); | 6312 | TASK_INTERRUPTIBLE); |
6312 | 6313 | ||
6313 | if (list_empty(&ep->asocs)) { | 6314 | if (list_empty(&ep->asocs)) { |
@@ -6333,7 +6334,7 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo) | |||
6333 | break; | 6334 | break; |
6334 | } | 6335 | } |
6335 | 6336 | ||
6336 | finish_wait(sk->sk_sleep, &wait); | 6337 | finish_wait(sk_sleep(sk), &wait); |
6337 | 6338 | ||
6338 | return err; | 6339 | return err; |
6339 | } | 6340 | } |
@@ -6343,7 +6344,7 @@ static void sctp_wait_for_close(struct sock *sk, long timeout) | |||
6343 | DEFINE_WAIT(wait); | 6344 | DEFINE_WAIT(wait); |
6344 | 6345 | ||
6345 | do { | 6346 | do { |
6346 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 6347 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
6347 | if (list_empty(&sctp_sk(sk)->ep->asocs)) | 6348 | if (list_empty(&sctp_sk(sk)->ep->asocs)) |
6348 | break; | 6349 | break; |
6349 | sctp_release_sock(sk); | 6350 | sctp_release_sock(sk); |
@@ -6351,7 +6352,7 @@ static void sctp_wait_for_close(struct sock *sk, long timeout) | |||
6351 | sctp_lock_sock(sk); | 6352 | sctp_lock_sock(sk); |
6352 | } while (!signal_pending(current) && timeout); | 6353 | } while (!signal_pending(current) && timeout); |
6353 | 6354 | ||
6354 | finish_wait(sk->sk_sleep, &wait); | 6355 | finish_wait(sk_sleep(sk), &wait); |
6355 | } | 6356 | } |
6356 | 6357 | ||
6357 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) | 6358 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 165d54e07fcd..132046cb82fc 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -64,9 +64,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
64 | /* Copy in the address. */ | 64 | /* Copy in the address. */ |
65 | peer->ipaddr = *addr; | 65 | peer->ipaddr = *addr; |
66 | peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); | 66 | peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); |
67 | peer->asoc = NULL; | ||
68 | |||
69 | peer->dst = NULL; | ||
70 | memset(&peer->saddr, 0, sizeof(union sctp_addr)); | 67 | memset(&peer->saddr, 0, sizeof(union sctp_addr)); |
71 | 68 | ||
72 | /* From 6.3.1 RTO Calculation: | 69 | /* From 6.3.1 RTO Calculation: |
@@ -76,34 +73,21 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
76 | * parameter 'RTO.Initial'. | 73 | * parameter 'RTO.Initial'. |
77 | */ | 74 | */ |
78 | peer->rto = msecs_to_jiffies(sctp_rto_initial); | 75 | peer->rto = msecs_to_jiffies(sctp_rto_initial); |
79 | peer->rtt = 0; | ||
80 | peer->rttvar = 0; | ||
81 | peer->srtt = 0; | ||
82 | peer->rto_pending = 0; | ||
83 | peer->hb_sent = 0; | ||
84 | peer->fast_recovery = 0; | ||
85 | 76 | ||
86 | peer->last_time_heard = jiffies; | 77 | peer->last_time_heard = jiffies; |
87 | peer->last_time_ecne_reduced = jiffies; | 78 | peer->last_time_ecne_reduced = jiffies; |
88 | 79 | ||
89 | peer->init_sent_count = 0; | ||
90 | |||
91 | peer->param_flags = SPP_HB_DISABLE | | 80 | peer->param_flags = SPP_HB_DISABLE | |
92 | SPP_PMTUD_ENABLE | | 81 | SPP_PMTUD_ENABLE | |
93 | SPP_SACKDELAY_ENABLE; | 82 | SPP_SACKDELAY_ENABLE; |
94 | peer->hbinterval = 0; | ||
95 | 83 | ||
96 | /* Initialize the default path max_retrans. */ | 84 | /* Initialize the default path max_retrans. */ |
97 | peer->pathmaxrxt = sctp_max_retrans_path; | 85 | peer->pathmaxrxt = sctp_max_retrans_path; |
98 | peer->error_count = 0; | ||
99 | 86 | ||
100 | INIT_LIST_HEAD(&peer->transmitted); | 87 | INIT_LIST_HEAD(&peer->transmitted); |
101 | INIT_LIST_HEAD(&peer->send_ready); | 88 | INIT_LIST_HEAD(&peer->send_ready); |
102 | INIT_LIST_HEAD(&peer->transports); | 89 | INIT_LIST_HEAD(&peer->transports); |
103 | 90 | ||
104 | peer->T3_rtx_timer.expires = 0; | ||
105 | peer->hb_timer.expires = 0; | ||
106 | |||
107 | setup_timer(&peer->T3_rtx_timer, sctp_generate_t3_rtx_event, | 91 | setup_timer(&peer->T3_rtx_timer, sctp_generate_t3_rtx_event, |
108 | (unsigned long)peer); | 92 | (unsigned long)peer); |
109 | setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event, | 93 | setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event, |
@@ -115,15 +99,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
115 | get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce)); | 99 | get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce)); |
116 | 100 | ||
117 | atomic_set(&peer->refcnt, 1); | 101 | atomic_set(&peer->refcnt, 1); |
118 | peer->dead = 0; | ||
119 | |||
120 | peer->malloced = 0; | ||
121 | |||
122 | /* Initialize the state information for SFR-CACC */ | ||
123 | peer->cacc.changeover_active = 0; | ||
124 | peer->cacc.cycling_changeover = 0; | ||
125 | peer->cacc.next_tsn_at_change = 0; | ||
126 | peer->cacc.cacc_saw_newack = 0; | ||
127 | 102 | ||
128 | return peer; | 103 | return peer; |
129 | } | 104 | } |
@@ -201,7 +176,7 @@ static void sctp_transport_destroy(struct sctp_transport *transport) | |||
201 | /* Start T3_rtx timer if it is not already running and update the heartbeat | 176 | /* Start T3_rtx timer if it is not already running and update the heartbeat |
202 | * timer. This routine is called every time a DATA chunk is sent. | 177 | * timer. This routine is called every time a DATA chunk is sent. |
203 | */ | 178 | */ |
204 | void sctp_transport_reset_timers(struct sctp_transport *transport, int force) | 179 | void sctp_transport_reset_timers(struct sctp_transport *transport) |
205 | { | 180 | { |
206 | /* RFC 2960 6.3.2 Retransmission Timer Rules | 181 | /* RFC 2960 6.3.2 Retransmission Timer Rules |
207 | * | 182 | * |
@@ -211,7 +186,7 @@ void sctp_transport_reset_timers(struct sctp_transport *transport, int force) | |||
211 | * address. | 186 | * address. |
212 | */ | 187 | */ |
213 | 188 | ||
214 | if (force || !timer_pending(&transport->T3_rtx_timer)) | 189 | if (!timer_pending(&transport->T3_rtx_timer)) |
215 | if (!mod_timer(&transport->T3_rtx_timer, | 190 | if (!mod_timer(&transport->T3_rtx_timer, |
216 | jiffies + transport->rto)) | 191 | jiffies + transport->rto)) |
217 | sctp_transport_hold(transport); | 192 | sctp_transport_hold(transport); |
@@ -409,15 +384,16 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) | |||
409 | void sctp_transport_raise_cwnd(struct sctp_transport *transport, | 384 | void sctp_transport_raise_cwnd(struct sctp_transport *transport, |
410 | __u32 sack_ctsn, __u32 bytes_acked) | 385 | __u32 sack_ctsn, __u32 bytes_acked) |
411 | { | 386 | { |
387 | struct sctp_association *asoc = transport->asoc; | ||
412 | __u32 cwnd, ssthresh, flight_size, pba, pmtu; | 388 | __u32 cwnd, ssthresh, flight_size, pba, pmtu; |
413 | 389 | ||
414 | cwnd = transport->cwnd; | 390 | cwnd = transport->cwnd; |
415 | flight_size = transport->flight_size; | 391 | flight_size = transport->flight_size; |
416 | 392 | ||
417 | /* See if we need to exit Fast Recovery first */ | 393 | /* See if we need to exit Fast Recovery first */ |
418 | if (transport->fast_recovery && | 394 | if (asoc->fast_recovery && |
419 | TSN_lte(transport->fast_recovery_exit, sack_ctsn)) | 395 | TSN_lte(asoc->fast_recovery_exit, sack_ctsn)) |
420 | transport->fast_recovery = 0; | 396 | asoc->fast_recovery = 0; |
421 | 397 | ||
422 | /* The appropriate cwnd increase algorithm is performed if, and only | 398 | /* The appropriate cwnd increase algorithm is performed if, and only |
423 | * if the cumulative TSN whould advanced and the congestion window is | 399 | * if the cumulative TSN whould advanced and the congestion window is |
@@ -446,7 +422,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport, | |||
446 | * 2) the destination's path MTU. This upper bound protects | 422 | * 2) the destination's path MTU. This upper bound protects |
447 | * against the ACK-Splitting attack outlined in [SAVAGE99]. | 423 | * against the ACK-Splitting attack outlined in [SAVAGE99]. |
448 | */ | 424 | */ |
449 | if (transport->fast_recovery) | 425 | if (asoc->fast_recovery) |
450 | return; | 426 | return; |
451 | 427 | ||
452 | if (bytes_acked > pmtu) | 428 | if (bytes_acked > pmtu) |
@@ -497,6 +473,8 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport, | |||
497 | void sctp_transport_lower_cwnd(struct sctp_transport *transport, | 473 | void sctp_transport_lower_cwnd(struct sctp_transport *transport, |
498 | sctp_lower_cwnd_t reason) | 474 | sctp_lower_cwnd_t reason) |
499 | { | 475 | { |
476 | struct sctp_association *asoc = transport->asoc; | ||
477 | |||
500 | switch (reason) { | 478 | switch (reason) { |
501 | case SCTP_LOWER_CWND_T3_RTX: | 479 | case SCTP_LOWER_CWND_T3_RTX: |
502 | /* RFC 2960 Section 7.2.3, sctpimpguide | 480 | /* RFC 2960 Section 7.2.3, sctpimpguide |
@@ -507,11 +485,11 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
507 | * partial_bytes_acked = 0 | 485 | * partial_bytes_acked = 0 |
508 | */ | 486 | */ |
509 | transport->ssthresh = max(transport->cwnd/2, | 487 | transport->ssthresh = max(transport->cwnd/2, |
510 | 4*transport->asoc->pathmtu); | 488 | 4*asoc->pathmtu); |
511 | transport->cwnd = transport->asoc->pathmtu; | 489 | transport->cwnd = asoc->pathmtu; |
512 | 490 | ||
513 | /* T3-rtx also clears fast recovery on the transport */ | 491 | /* T3-rtx also clears fast recovery */ |
514 | transport->fast_recovery = 0; | 492 | asoc->fast_recovery = 0; |
515 | break; | 493 | break; |
516 | 494 | ||
517 | case SCTP_LOWER_CWND_FAST_RTX: | 495 | case SCTP_LOWER_CWND_FAST_RTX: |
@@ -527,15 +505,15 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
527 | * cwnd = ssthresh | 505 | * cwnd = ssthresh |
528 | * partial_bytes_acked = 0 | 506 | * partial_bytes_acked = 0 |
529 | */ | 507 | */ |
530 | if (transport->fast_recovery) | 508 | if (asoc->fast_recovery) |
531 | return; | 509 | return; |
532 | 510 | ||
533 | /* Mark Fast recovery */ | 511 | /* Mark Fast recovery */ |
534 | transport->fast_recovery = 1; | 512 | asoc->fast_recovery = 1; |
535 | transport->fast_recovery_exit = transport->asoc->next_tsn - 1; | 513 | asoc->fast_recovery_exit = asoc->next_tsn - 1; |
536 | 514 | ||
537 | transport->ssthresh = max(transport->cwnd/2, | 515 | transport->ssthresh = max(transport->cwnd/2, |
538 | 4*transport->asoc->pathmtu); | 516 | 4*asoc->pathmtu); |
539 | transport->cwnd = transport->ssthresh; | 517 | transport->cwnd = transport->ssthresh; |
540 | break; | 518 | break; |
541 | 519 | ||
@@ -555,7 +533,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
555 | if (time_after(jiffies, transport->last_time_ecne_reduced + | 533 | if (time_after(jiffies, transport->last_time_ecne_reduced + |
556 | transport->rtt)) { | 534 | transport->rtt)) { |
557 | transport->ssthresh = max(transport->cwnd/2, | 535 | transport->ssthresh = max(transport->cwnd/2, |
558 | 4*transport->asoc->pathmtu); | 536 | 4*asoc->pathmtu); |
559 | transport->cwnd = transport->ssthresh; | 537 | transport->cwnd = transport->ssthresh; |
560 | transport->last_time_ecne_reduced = jiffies; | 538 | transport->last_time_ecne_reduced = jiffies; |
561 | } | 539 | } |
@@ -571,7 +549,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
571 | * interval. | 549 | * interval. |
572 | */ | 550 | */ |
573 | transport->cwnd = max(transport->cwnd/2, | 551 | transport->cwnd = max(transport->cwnd/2, |
574 | 4*transport->asoc->pathmtu); | 552 | 4*asoc->pathmtu); |
575 | break; | 553 | break; |
576 | } | 554 | } |
577 | 555 | ||
@@ -656,7 +634,6 @@ void sctp_transport_reset(struct sctp_transport *t) | |||
656 | t->error_count = 0; | 634 | t->error_count = 0; |
657 | t->rto_pending = 0; | 635 | t->rto_pending = 0; |
658 | t->hb_sent = 0; | 636 | t->hb_sent = 0; |
659 | t->fast_recovery = 0; | ||
660 | 637 | ||
661 | /* Initialize the state information for SFR-CACC */ | 638 | /* Initialize the state information for SFR-CACC */ |
662 | t->cacc.changeover_active = 0; | 639 | t->cacc.changeover_active = 0; |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 3a448536f0b6..c7f7e49609cb 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -955,7 +955,6 @@ void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn) | |||
955 | * ordering and deliver them if needed. | 955 | * ordering and deliver them if needed. |
956 | */ | 956 | */ |
957 | sctp_ulpq_reap_ordered(ulpq, sid); | 957 | sctp_ulpq_reap_ordered(ulpq, sid); |
958 | return; | ||
959 | } | 958 | } |
960 | 959 | ||
961 | static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq, | 960 | static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq, |
@@ -1064,7 +1063,6 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, | |||
1064 | } | 1063 | } |
1065 | 1064 | ||
1066 | sk_mem_reclaim(asoc->base.sk); | 1065 | sk_mem_reclaim(asoc->base.sk); |
1067 | return; | ||
1068 | } | 1066 | } |
1069 | 1067 | ||
1070 | 1068 | ||
diff --git a/net/socket.c b/net/socket.c index 5e8d0af3c0e7..f9f7d0872cac 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -252,9 +252,14 @@ static struct inode *sock_alloc_inode(struct super_block *sb) | |||
252 | ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); | 252 | ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); |
253 | if (!ei) | 253 | if (!ei) |
254 | return NULL; | 254 | return NULL; |
255 | init_waitqueue_head(&ei->socket.wait); | 255 | ei->socket.wq = kmalloc(sizeof(struct socket_wq), GFP_KERNEL); |
256 | if (!ei->socket.wq) { | ||
257 | kmem_cache_free(sock_inode_cachep, ei); | ||
258 | return NULL; | ||
259 | } | ||
260 | init_waitqueue_head(&ei->socket.wq->wait); | ||
261 | ei->socket.wq->fasync_list = NULL; | ||
256 | 262 | ||
257 | ei->socket.fasync_list = NULL; | ||
258 | ei->socket.state = SS_UNCONNECTED; | 263 | ei->socket.state = SS_UNCONNECTED; |
259 | ei->socket.flags = 0; | 264 | ei->socket.flags = 0; |
260 | ei->socket.ops = NULL; | 265 | ei->socket.ops = NULL; |
@@ -264,10 +269,21 @@ static struct inode *sock_alloc_inode(struct super_block *sb) | |||
264 | return &ei->vfs_inode; | 269 | return &ei->vfs_inode; |
265 | } | 270 | } |
266 | 271 | ||
272 | |||
273 | static void wq_free_rcu(struct rcu_head *head) | ||
274 | { | ||
275 | struct socket_wq *wq = container_of(head, struct socket_wq, rcu); | ||
276 | |||
277 | kfree(wq); | ||
278 | } | ||
279 | |||
267 | static void sock_destroy_inode(struct inode *inode) | 280 | static void sock_destroy_inode(struct inode *inode) |
268 | { | 281 | { |
269 | kmem_cache_free(sock_inode_cachep, | 282 | struct socket_alloc *ei; |
270 | container_of(inode, struct socket_alloc, vfs_inode)); | 283 | |
284 | ei = container_of(inode, struct socket_alloc, vfs_inode); | ||
285 | call_rcu(&ei->socket.wq->rcu, wq_free_rcu); | ||
286 | kmem_cache_free(sock_inode_cachep, ei); | ||
271 | } | 287 | } |
272 | 288 | ||
273 | static void init_once(void *foo) | 289 | static void init_once(void *foo) |
@@ -513,7 +529,7 @@ void sock_release(struct socket *sock) | |||
513 | module_put(owner); | 529 | module_put(owner); |
514 | } | 530 | } |
515 | 531 | ||
516 | if (sock->fasync_list) | 532 | if (sock->wq->fasync_list) |
517 | printk(KERN_ERR "sock_release: fasync list not empty!\n"); | 533 | printk(KERN_ERR "sock_release: fasync list not empty!\n"); |
518 | 534 | ||
519 | percpu_sub(sockets_in_use, 1); | 535 | percpu_sub(sockets_in_use, 1); |
@@ -620,10 +636,9 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
620 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, | 636 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, |
621 | sizeof(tv), &tv); | 637 | sizeof(tv), &tv); |
622 | } else { | 638 | } else { |
623 | struct timespec ts; | 639 | skb_get_timestampns(skb, &ts[0]); |
624 | skb_get_timestampns(skb, &ts); | ||
625 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, | 640 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, |
626 | sizeof(ts), &ts); | 641 | sizeof(ts[0]), &ts[0]); |
627 | } | 642 | } |
628 | } | 643 | } |
629 | 644 | ||
@@ -656,13 +671,13 @@ inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, struct sk_buff | |||
656 | sizeof(__u32), &skb->dropcount); | 671 | sizeof(__u32), &skb->dropcount); |
657 | } | 672 | } |
658 | 673 | ||
659 | void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, | 674 | void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, |
660 | struct sk_buff *skb) | 675 | struct sk_buff *skb) |
661 | { | 676 | { |
662 | sock_recv_timestamp(msg, sk, skb); | 677 | sock_recv_timestamp(msg, sk, skb); |
663 | sock_recv_drops(msg, sk, skb); | 678 | sock_recv_drops(msg, sk, skb); |
664 | } | 679 | } |
665 | EXPORT_SYMBOL_GPL(sock_recv_ts_and_drops); | 680 | EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); |
666 | 681 | ||
667 | static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, | 682 | static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, |
668 | struct msghdr *msg, size_t size, int flags) | 683 | struct msghdr *msg, size_t size, int flags) |
@@ -1068,87 +1083,44 @@ static int sock_close(struct inode *inode, struct file *filp) | |||
1068 | * 1. fasync_list is modified only under process context socket lock | 1083 | * 1. fasync_list is modified only under process context socket lock |
1069 | * i.e. under semaphore. | 1084 | * i.e. under semaphore. |
1070 | * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) | 1085 | * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) |
1071 | * or under socket lock. | 1086 | * or under socket lock |
1072 | * 3. fasync_list can be used from softirq context, so that | ||
1073 | * modification under socket lock have to be enhanced with | ||
1074 | * write_lock_bh(&sk->sk_callback_lock). | ||
1075 | * --ANK (990710) | ||
1076 | */ | 1087 | */ |
1077 | 1088 | ||
1078 | static int sock_fasync(int fd, struct file *filp, int on) | 1089 | static int sock_fasync(int fd, struct file *filp, int on) |
1079 | { | 1090 | { |
1080 | struct fasync_struct *fa, *fna = NULL, **prev; | 1091 | struct socket *sock = filp->private_data; |
1081 | struct socket *sock; | 1092 | struct sock *sk = sock->sk; |
1082 | struct sock *sk; | ||
1083 | |||
1084 | if (on) { | ||
1085 | fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); | ||
1086 | if (fna == NULL) | ||
1087 | return -ENOMEM; | ||
1088 | } | ||
1089 | |||
1090 | sock = filp->private_data; | ||
1091 | 1093 | ||
1092 | sk = sock->sk; | 1094 | if (sk == NULL) |
1093 | if (sk == NULL) { | ||
1094 | kfree(fna); | ||
1095 | return -EINVAL; | 1095 | return -EINVAL; |
1096 | } | ||
1097 | 1096 | ||
1098 | lock_sock(sk); | 1097 | lock_sock(sk); |
1099 | 1098 | ||
1100 | spin_lock(&filp->f_lock); | 1099 | fasync_helper(fd, filp, on, &sock->wq->fasync_list); |
1101 | if (on) | ||
1102 | filp->f_flags |= FASYNC; | ||
1103 | else | ||
1104 | filp->f_flags &= ~FASYNC; | ||
1105 | spin_unlock(&filp->f_lock); | ||
1106 | 1100 | ||
1107 | prev = &(sock->fasync_list); | 1101 | if (!sock->wq->fasync_list) |
1108 | 1102 | sock_reset_flag(sk, SOCK_FASYNC); | |
1109 | for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) | 1103 | else |
1110 | if (fa->fa_file == filp) | ||
1111 | break; | ||
1112 | |||
1113 | if (on) { | ||
1114 | if (fa != NULL) { | ||
1115 | write_lock_bh(&sk->sk_callback_lock); | ||
1116 | fa->fa_fd = fd; | ||
1117 | write_unlock_bh(&sk->sk_callback_lock); | ||
1118 | |||
1119 | kfree(fna); | ||
1120 | goto out; | ||
1121 | } | ||
1122 | fna->fa_file = filp; | ||
1123 | fna->fa_fd = fd; | ||
1124 | fna->magic = FASYNC_MAGIC; | ||
1125 | fna->fa_next = sock->fasync_list; | ||
1126 | write_lock_bh(&sk->sk_callback_lock); | ||
1127 | sock->fasync_list = fna; | ||
1128 | sock_set_flag(sk, SOCK_FASYNC); | 1104 | sock_set_flag(sk, SOCK_FASYNC); |
1129 | write_unlock_bh(&sk->sk_callback_lock); | ||
1130 | } else { | ||
1131 | if (fa != NULL) { | ||
1132 | write_lock_bh(&sk->sk_callback_lock); | ||
1133 | *prev = fa->fa_next; | ||
1134 | if (!sock->fasync_list) | ||
1135 | sock_reset_flag(sk, SOCK_FASYNC); | ||
1136 | write_unlock_bh(&sk->sk_callback_lock); | ||
1137 | kfree(fa); | ||
1138 | } | ||
1139 | } | ||
1140 | 1105 | ||
1141 | out: | 1106 | release_sock(sk); |
1142 | release_sock(sock->sk); | ||
1143 | return 0; | 1107 | return 0; |
1144 | } | 1108 | } |
1145 | 1109 | ||
1146 | /* This function may be called only under socket lock or callback_lock */ | 1110 | /* This function may be called only under socket lock or callback_lock or rcu_lock */ |
1147 | 1111 | ||
1148 | int sock_wake_async(struct socket *sock, int how, int band) | 1112 | int sock_wake_async(struct socket *sock, int how, int band) |
1149 | { | 1113 | { |
1150 | if (!sock || !sock->fasync_list) | 1114 | struct socket_wq *wq; |
1115 | |||
1116 | if (!sock) | ||
1151 | return -1; | 1117 | return -1; |
1118 | rcu_read_lock(); | ||
1119 | wq = rcu_dereference(sock->wq); | ||
1120 | if (!wq || !wq->fasync_list) { | ||
1121 | rcu_read_unlock(); | ||
1122 | return -1; | ||
1123 | } | ||
1152 | switch (how) { | 1124 | switch (how) { |
1153 | case SOCK_WAKE_WAITD: | 1125 | case SOCK_WAKE_WAITD: |
1154 | if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) | 1126 | if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) |
@@ -1160,11 +1132,12 @@ int sock_wake_async(struct socket *sock, int how, int band) | |||
1160 | /* fall through */ | 1132 | /* fall through */ |
1161 | case SOCK_WAKE_IO: | 1133 | case SOCK_WAKE_IO: |
1162 | call_kill: | 1134 | call_kill: |
1163 | __kill_fasync(sock->fasync_list, SIGIO, band); | 1135 | kill_fasync(&wq->fasync_list, SIGIO, band); |
1164 | break; | 1136 | break; |
1165 | case SOCK_WAKE_URG: | 1137 | case SOCK_WAKE_URG: |
1166 | __kill_fasync(sock->fasync_list, SIGURG, band); | 1138 | kill_fasync(&wq->fasync_list, SIGURG, band); |
1167 | } | 1139 | } |
1140 | rcu_read_unlock(); | ||
1168 | return 0; | 1141 | return 0; |
1169 | } | 1142 | } |
1170 | 1143 | ||
@@ -2642,7 +2615,7 @@ static int bond_ioctl(struct net *net, unsigned int cmd, | |||
2642 | return dev_ioctl(net, cmd, uifr); | 2615 | return dev_ioctl(net, cmd, uifr); |
2643 | default: | 2616 | default: |
2644 | return -EINVAL; | 2617 | return -EINVAL; |
2645 | }; | 2618 | } |
2646 | } | 2619 | } |
2647 | 2620 | ||
2648 | static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, | 2621 | static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c index 3308157436d2..a99825d7caa0 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_token.c +++ b/net/sunrpc/auth_gss/gss_spkm3_token.c | |||
@@ -223,7 +223,7 @@ spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **ck | |||
223 | 223 | ||
224 | /* only support SPKM_MIC_TOK */ | 224 | /* only support SPKM_MIC_TOK */ |
225 | if((ptr[6] != 0x01) || (ptr[7] != 0x01)) { | 225 | if((ptr[6] != 0x01) || (ptr[7] != 0x01)) { |
226 | dprintk("RPC: ERROR unsupported SPKM3 token \n"); | 226 | dprintk("RPC: ERROR unsupported SPKM3 token\n"); |
227 | goto out; | 227 | goto out; |
228 | } | 228 | } |
229 | 229 | ||
diff --git a/net/sunrpc/bc_svc.c b/net/sunrpc/bc_svc.c index f0c05d3311c1..7dcfe0cc3500 100644 --- a/net/sunrpc/bc_svc.c +++ b/net/sunrpc/bc_svc.c | |||
@@ -60,7 +60,7 @@ int bc_send(struct rpc_rqst *req) | |||
60 | rpc_put_task(task); | 60 | rpc_put_task(task); |
61 | } | 61 | } |
62 | return ret; | 62 | return ret; |
63 | dprintk("RPC: bc_send ret= %d \n", ret); | 63 | dprintk("RPC: bc_send ret= %d\n", ret); |
64 | } | 64 | } |
65 | 65 | ||
66 | #endif /* CONFIG_NFS_V4_1 */ | 66 | #endif /* CONFIG_NFS_V4_1 */ |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 8c7b5433022a..756fc324db9e 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -1507,7 +1507,6 @@ call_refreshresult(struct rpc_task *task) | |||
1507 | task->tk_action = call_refresh; | 1507 | task->tk_action = call_refresh; |
1508 | if (status != -ETIMEDOUT) | 1508 | if (status != -ETIMEDOUT) |
1509 | rpc_delay(task, 3*HZ); | 1509 | rpc_delay(task, 3*HZ); |
1510 | return; | ||
1511 | } | 1510 | } |
1512 | 1511 | ||
1513 | static __be32 * | 1512 | static __be32 * |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index a33892733643..7e534dd09077 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -150,7 +150,6 @@ static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) | |||
150 | } | 150 | } |
151 | break; | 151 | break; |
152 | } | 152 | } |
153 | return; | ||
154 | } | 153 | } |
155 | 154 | ||
156 | /* | 155 | /* |
@@ -419,8 +418,8 @@ static void svc_udp_data_ready(struct sock *sk, int count) | |||
419 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 418 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
420 | svc_xprt_enqueue(&svsk->sk_xprt); | 419 | svc_xprt_enqueue(&svsk->sk_xprt); |
421 | } | 420 | } |
422 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 421 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
423 | wake_up_interruptible(sk->sk_sleep); | 422 | wake_up_interruptible(sk_sleep(sk)); |
424 | } | 423 | } |
425 | 424 | ||
426 | /* | 425 | /* |
@@ -436,10 +435,10 @@ static void svc_write_space(struct sock *sk) | |||
436 | svc_xprt_enqueue(&svsk->sk_xprt); | 435 | svc_xprt_enqueue(&svsk->sk_xprt); |
437 | } | 436 | } |
438 | 437 | ||
439 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) { | 438 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) { |
440 | dprintk("RPC svc_write_space: someone sleeping on %p\n", | 439 | dprintk("RPC svc_write_space: someone sleeping on %p\n", |
441 | svsk); | 440 | svsk); |
442 | wake_up_interruptible(sk->sk_sleep); | 441 | wake_up_interruptible(sk_sleep(sk)); |
443 | } | 442 | } |
444 | } | 443 | } |
445 | 444 | ||
@@ -751,8 +750,8 @@ static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused) | |||
751 | printk("svc: socket %p: no user data\n", sk); | 750 | printk("svc: socket %p: no user data\n", sk); |
752 | } | 751 | } |
753 | 752 | ||
754 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 753 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
755 | wake_up_interruptible_all(sk->sk_sleep); | 754 | wake_up_interruptible_all(sk_sleep(sk)); |
756 | } | 755 | } |
757 | 756 | ||
758 | /* | 757 | /* |
@@ -771,8 +770,8 @@ static void svc_tcp_state_change(struct sock *sk) | |||
771 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 770 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
772 | svc_xprt_enqueue(&svsk->sk_xprt); | 771 | svc_xprt_enqueue(&svsk->sk_xprt); |
773 | } | 772 | } |
774 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 773 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
775 | wake_up_interruptible_all(sk->sk_sleep); | 774 | wake_up_interruptible_all(sk_sleep(sk)); |
776 | } | 775 | } |
777 | 776 | ||
778 | static void svc_tcp_data_ready(struct sock *sk, int count) | 777 | static void svc_tcp_data_ready(struct sock *sk, int count) |
@@ -785,8 +784,8 @@ static void svc_tcp_data_ready(struct sock *sk, int count) | |||
785 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 784 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
786 | svc_xprt_enqueue(&svsk->sk_xprt); | 785 | svc_xprt_enqueue(&svsk->sk_xprt); |
787 | } | 786 | } |
788 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 787 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
789 | wake_up_interruptible(sk->sk_sleep); | 788 | wake_up_interruptible(sk_sleep(sk)); |
790 | } | 789 | } |
791 | 790 | ||
792 | /* | 791 | /* |
@@ -1481,8 +1480,8 @@ static void svc_sock_detach(struct svc_xprt *xprt) | |||
1481 | sk->sk_data_ready = svsk->sk_odata; | 1480 | sk->sk_data_ready = svsk->sk_odata; |
1482 | sk->sk_write_space = svsk->sk_owspace; | 1481 | sk->sk_write_space = svsk->sk_owspace; |
1483 | 1482 | ||
1484 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1483 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
1485 | wake_up_interruptible(sk->sk_sleep); | 1484 | wake_up_interruptible(sk_sleep(sk)); |
1486 | } | 1485 | } |
1487 | 1486 | ||
1488 | /* | 1487 | /* |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 65fe2e4e7cbf..3fc325399ee4 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -984,7 +984,7 @@ void xprt_reserve(struct rpc_task *task) | |||
984 | 984 | ||
985 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) | 985 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) |
986 | { | 986 | { |
987 | return xprt->xid++; | 987 | return (__force __be32)xprt->xid++; |
988 | } | 988 | } |
989 | 989 | ||
990 | static inline void xprt_init_xid(struct rpc_xprt *xprt) | 990 | static inline void xprt_init_xid(struct rpc_xprt *xprt) |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 02fc7f04dd17..b7cd8cccbe72 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1035,8 +1035,6 @@ static inline void xs_tcp_read_common(struct rpc_xprt *xprt, | |||
1035 | if (transport->tcp_flags & TCP_RCV_LAST_FRAG) | 1035 | if (transport->tcp_flags & TCP_RCV_LAST_FRAG) |
1036 | transport->tcp_flags &= ~TCP_RCV_COPY_DATA; | 1036 | transport->tcp_flags &= ~TCP_RCV_COPY_DATA; |
1037 | } | 1037 | } |
1038 | |||
1039 | return; | ||
1040 | } | 1038 | } |
1041 | 1039 | ||
1042 | /* | 1040 | /* |
@@ -2182,7 +2180,6 @@ static int bc_send_request(struct rpc_task *task) | |||
2182 | 2180 | ||
2183 | static void bc_close(struct rpc_xprt *xprt) | 2181 | static void bc_close(struct rpc_xprt *xprt) |
2184 | { | 2182 | { |
2185 | return; | ||
2186 | } | 2183 | } |
2187 | 2184 | ||
2188 | /* | 2185 | /* |
@@ -2192,7 +2189,6 @@ static void bc_close(struct rpc_xprt *xprt) | |||
2192 | 2189 | ||
2193 | static void bc_destroy(struct rpc_xprt *xprt) | 2190 | static void bc_destroy(struct rpc_xprt *xprt) |
2194 | { | 2191 | { |
2195 | return; | ||
2196 | } | 2192 | } |
2197 | 2193 | ||
2198 | static struct rpc_xprt_ops xs_udp_ops = { | 2194 | static struct rpc_xprt_ops xs_udp_ops = { |
diff --git a/net/sysctl_net.c b/net/sysctl_net.c index 53196009160a..ca84212cfbfe 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c | |||
@@ -82,7 +82,6 @@ static int __net_init sysctl_net_init(struct net *net) | |||
82 | static void __net_exit sysctl_net_exit(struct net *net) | 82 | static void __net_exit sysctl_net_exit(struct net *net) |
83 | { | 83 | { |
84 | WARN_ON(!list_empty(&net->sysctls.list)); | 84 | WARN_ON(!list_empty(&net->sysctls.list)); |
85 | return; | ||
86 | } | 85 | } |
87 | 86 | ||
88 | static struct pernet_operations sysctl_pernet_ops = { | 87 | static struct pernet_operations sysctl_pernet_ops = { |
diff --git a/net/tipc/addr.c b/net/tipc/addr.c index e5207a11edf6..c048543ffbeb 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c | |||
@@ -92,3 +92,35 @@ int tipc_addr_node_valid(u32 addr) | |||
92 | return (tipc_addr_domain_valid(addr) && tipc_node(addr)); | 92 | return (tipc_addr_domain_valid(addr) && tipc_node(addr)); |
93 | } | 93 | } |
94 | 94 | ||
95 | int tipc_in_scope(u32 domain, u32 addr) | ||
96 | { | ||
97 | if (!domain || (domain == addr)) | ||
98 | return 1; | ||
99 | if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */ | ||
100 | return 1; | ||
101 | if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */ | ||
102 | return 1; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * tipc_addr_scope - convert message lookup domain to a 2-bit scope value | ||
108 | */ | ||
109 | |||
110 | int tipc_addr_scope(u32 domain) | ||
111 | { | ||
112 | if (likely(!domain)) | ||
113 | return TIPC_ZONE_SCOPE; | ||
114 | if (tipc_node(domain)) | ||
115 | return TIPC_NODE_SCOPE; | ||
116 | if (tipc_cluster(domain)) | ||
117 | return TIPC_CLUSTER_SCOPE; | ||
118 | return TIPC_ZONE_SCOPE; | ||
119 | } | ||
120 | |||
121 | char *tipc_addr_string_fill(char *string, u32 addr) | ||
122 | { | ||
123 | snprintf(string, 16, "<%u.%u.%u>", | ||
124 | tipc_zone(addr), tipc_cluster(addr), tipc_node(addr)); | ||
125 | return string; | ||
126 | } | ||
diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 3ba67e6ce03e..c1cc5724d8cc 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h | |||
@@ -67,32 +67,6 @@ static inline int may_route(u32 addr) | |||
67 | return(addr ^ tipc_own_addr) >> 11; | 67 | return(addr ^ tipc_own_addr) >> 11; |
68 | } | 68 | } |
69 | 69 | ||
70 | static inline int in_scope(u32 domain, u32 addr) | ||
71 | { | ||
72 | if (!domain || (domain == addr)) | ||
73 | return 1; | ||
74 | if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */ | ||
75 | return 1; | ||
76 | if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */ | ||
77 | return 1; | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * addr_scope - convert message lookup domain to equivalent 2-bit scope value | ||
83 | */ | ||
84 | |||
85 | static inline int addr_scope(u32 domain) | ||
86 | { | ||
87 | if (likely(!domain)) | ||
88 | return TIPC_ZONE_SCOPE; | ||
89 | if (tipc_node(domain)) | ||
90 | return TIPC_NODE_SCOPE; | ||
91 | if (tipc_cluster(domain)) | ||
92 | return TIPC_CLUSTER_SCOPE; | ||
93 | return TIPC_ZONE_SCOPE; | ||
94 | } | ||
95 | |||
96 | /** | 70 | /** |
97 | * addr_domain - convert 2-bit scope value to equivalent message lookup domain | 71 | * addr_domain - convert 2-bit scope value to equivalent message lookup domain |
98 | * | 72 | * |
@@ -110,14 +84,9 @@ static inline int addr_domain(int sc) | |||
110 | return tipc_addr(tipc_zone(tipc_own_addr), 0, 0); | 84 | return tipc_addr(tipc_zone(tipc_own_addr), 0, 0); |
111 | } | 85 | } |
112 | 86 | ||
113 | static inline char *addr_string_fill(char *string, u32 addr) | ||
114 | { | ||
115 | snprintf(string, 16, "<%u.%u.%u>", | ||
116 | tipc_zone(addr), tipc_cluster(addr), tipc_node(addr)); | ||
117 | return string; | ||
118 | } | ||
119 | |||
120 | int tipc_addr_domain_valid(u32); | 87 | int tipc_addr_domain_valid(u32); |
121 | int tipc_addr_node_valid(u32 addr); | 88 | int tipc_addr_node_valid(u32 addr); |
122 | 89 | int tipc_in_scope(u32 domain, u32 addr); | |
90 | int tipc_addr_scope(u32 domain); | ||
91 | char *tipc_addr_string_fill(char *string, u32 addr); | ||
123 | #endif | 92 | #endif |
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index a3bfd4064912..a008c6689305 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -119,7 +119,7 @@ static struct bclink *bclink = NULL; | |||
119 | static struct link *bcl = NULL; | 119 | static struct link *bcl = NULL; |
120 | static DEFINE_SPINLOCK(bc_lock); | 120 | static DEFINE_SPINLOCK(bc_lock); |
121 | 121 | ||
122 | const char tipc_bclink_name[] = "multicast-link"; | 122 | const char tipc_bclink_name[] = "broadcast-link"; |
123 | 123 | ||
124 | 124 | ||
125 | static u32 buf_seqno(struct sk_buff *buf) | 125 | static u32 buf_seqno(struct sk_buff *buf) |
@@ -275,7 +275,7 @@ static void bclink_send_nack(struct tipc_node *n_ptr) | |||
275 | buf = buf_acquire(INT_H_SIZE); | 275 | buf = buf_acquire(INT_H_SIZE); |
276 | if (buf) { | 276 | if (buf) { |
277 | msg = buf_msg(buf); | 277 | msg = buf_msg(buf); |
278 | msg_init(msg, BCAST_PROTOCOL, STATE_MSG, | 278 | tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, |
279 | INT_H_SIZE, n_ptr->addr); | 279 | INT_H_SIZE, n_ptr->addr); |
280 | msg_set_mc_netid(msg, tipc_net_id); | 280 | msg_set_mc_netid(msg, tipc_net_id); |
281 | msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); | 281 | msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); |
@@ -558,10 +558,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, | |||
558 | struct tipc_bearer *unused1, | 558 | struct tipc_bearer *unused1, |
559 | struct tipc_media_addr *unused2) | 559 | struct tipc_media_addr *unused2) |
560 | { | 560 | { |
561 | static int send_count = 0; | ||
562 | |||
563 | int bp_index; | 561 | int bp_index; |
564 | int swap_time; | ||
565 | 562 | ||
566 | /* Prepare buffer for broadcasting (if first time trying to send it) */ | 563 | /* Prepare buffer for broadcasting (if first time trying to send it) */ |
567 | 564 | ||
@@ -575,11 +572,6 @@ static int tipc_bcbearer_send(struct sk_buff *buf, | |||
575 | msg_set_mc_netid(msg, tipc_net_id); | 572 | msg_set_mc_netid(msg, tipc_net_id); |
576 | } | 573 | } |
577 | 574 | ||
578 | /* Determine if bearer pairs should be swapped following this attempt */ | ||
579 | |||
580 | if ((swap_time = (++send_count >= 10))) | ||
581 | send_count = 0; | ||
582 | |||
583 | /* Send buffer over bearers until all targets reached */ | 575 | /* Send buffer over bearers until all targets reached */ |
584 | 576 | ||
585 | bcbearer->remains = tipc_cltr_bcast_nodes; | 577 | bcbearer->remains = tipc_cltr_bcast_nodes; |
@@ -595,21 +587,22 @@ static int tipc_bcbearer_send(struct sk_buff *buf, | |||
595 | if (bcbearer->remains_new.count == bcbearer->remains.count) | 587 | if (bcbearer->remains_new.count == bcbearer->remains.count) |
596 | continue; /* bearer pair doesn't add anything */ | 588 | continue; /* bearer pair doesn't add anything */ |
597 | 589 | ||
598 | if (!p->publ.blocked && | 590 | if (p->publ.blocked || |
599 | !p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { | 591 | p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { |
600 | if (swap_time && s && !s->publ.blocked) | 592 | /* unable to send on primary bearer */ |
601 | goto swap; | 593 | if (!s || s->publ.blocked || |
602 | else | 594 | s->media->send_msg(buf, &s->publ, |
603 | goto update; | 595 | &s->media->bcast_addr)) { |
596 | /* unable to send on either bearer */ | ||
597 | continue; | ||
598 | } | ||
599 | } | ||
600 | |||
601 | if (s) { | ||
602 | bcbearer->bpairs[bp_index].primary = s; | ||
603 | bcbearer->bpairs[bp_index].secondary = p; | ||
604 | } | 604 | } |
605 | 605 | ||
606 | if (!s || s->publ.blocked || | ||
607 | s->media->send_msg(buf, &s->publ, &s->media->bcast_addr)) | ||
608 | continue; /* unable to send using bearer pair */ | ||
609 | swap: | ||
610 | bcbearer->bpairs[bp_index].primary = s; | ||
611 | bcbearer->bpairs[bp_index].secondary = p; | ||
612 | update: | ||
613 | if (bcbearer->remains_new.count == 0) | 606 | if (bcbearer->remains_new.count == 0) |
614 | return 0; | 607 | return 0; |
615 | 608 | ||
@@ -829,3 +822,113 @@ void tipc_bclink_stop(void) | |||
829 | spin_unlock_bh(&bc_lock); | 822 | spin_unlock_bh(&bc_lock); |
830 | } | 823 | } |
831 | 824 | ||
825 | |||
826 | /** | ||
827 | * tipc_nmap_add - add a node to a node map | ||
828 | */ | ||
829 | |||
830 | void tipc_nmap_add(struct tipc_node_map *nm_ptr, u32 node) | ||
831 | { | ||
832 | int n = tipc_node(node); | ||
833 | int w = n / WSIZE; | ||
834 | u32 mask = (1 << (n % WSIZE)); | ||
835 | |||
836 | if ((nm_ptr->map[w] & mask) == 0) { | ||
837 | nm_ptr->count++; | ||
838 | nm_ptr->map[w] |= mask; | ||
839 | } | ||
840 | } | ||
841 | |||
842 | /** | ||
843 | * tipc_nmap_remove - remove a node from a node map | ||
844 | */ | ||
845 | |||
846 | void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node) | ||
847 | { | ||
848 | int n = tipc_node(node); | ||
849 | int w = n / WSIZE; | ||
850 | u32 mask = (1 << (n % WSIZE)); | ||
851 | |||
852 | if ((nm_ptr->map[w] & mask) != 0) { | ||
853 | nm_ptr->map[w] &= ~mask; | ||
854 | nm_ptr->count--; | ||
855 | } | ||
856 | } | ||
857 | |||
858 | /** | ||
859 | * tipc_nmap_diff - find differences between node maps | ||
860 | * @nm_a: input node map A | ||
861 | * @nm_b: input node map B | ||
862 | * @nm_diff: output node map A-B (i.e. nodes of A that are not in B) | ||
863 | */ | ||
864 | |||
865 | void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b, | ||
866 | struct tipc_node_map *nm_diff) | ||
867 | { | ||
868 | int stop = ARRAY_SIZE(nm_a->map); | ||
869 | int w; | ||
870 | int b; | ||
871 | u32 map; | ||
872 | |||
873 | memset(nm_diff, 0, sizeof(*nm_diff)); | ||
874 | for (w = 0; w < stop; w++) { | ||
875 | map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]); | ||
876 | nm_diff->map[w] = map; | ||
877 | if (map != 0) { | ||
878 | for (b = 0 ; b < WSIZE; b++) { | ||
879 | if (map & (1 << b)) | ||
880 | nm_diff->count++; | ||
881 | } | ||
882 | } | ||
883 | } | ||
884 | } | ||
885 | |||
886 | /** | ||
887 | * tipc_port_list_add - add a port to a port list, ensuring no duplicates | ||
888 | */ | ||
889 | |||
890 | void tipc_port_list_add(struct port_list *pl_ptr, u32 port) | ||
891 | { | ||
892 | struct port_list *item = pl_ptr; | ||
893 | int i; | ||
894 | int item_sz = PLSIZE; | ||
895 | int cnt = pl_ptr->count; | ||
896 | |||
897 | for (; ; cnt -= item_sz, item = item->next) { | ||
898 | if (cnt < PLSIZE) | ||
899 | item_sz = cnt; | ||
900 | for (i = 0; i < item_sz; i++) | ||
901 | if (item->ports[i] == port) | ||
902 | return; | ||
903 | if (i < PLSIZE) { | ||
904 | item->ports[i] = port; | ||
905 | pl_ptr->count++; | ||
906 | return; | ||
907 | } | ||
908 | if (!item->next) { | ||
909 | item->next = kmalloc(sizeof(*item), GFP_ATOMIC); | ||
910 | if (!item->next) { | ||
911 | warn("Incomplete multicast delivery, no memory\n"); | ||
912 | return; | ||
913 | } | ||
914 | item->next->next = NULL; | ||
915 | } | ||
916 | } | ||
917 | } | ||
918 | |||
919 | /** | ||
920 | * tipc_port_list_free - free dynamically created entries in port_list chain | ||
921 | * | ||
922 | */ | ||
923 | |||
924 | void tipc_port_list_free(struct port_list *pl_ptr) | ||
925 | { | ||
926 | struct port_list *item; | ||
927 | struct port_list *next; | ||
928 | |||
929 | for (item = pl_ptr->next; item; item = next) { | ||
930 | next = item->next; | ||
931 | kfree(item); | ||
932 | } | ||
933 | } | ||
934 | |||
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 4c1771e95c99..e8c2b81658c7 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
@@ -72,41 +72,11 @@ struct tipc_node; | |||
72 | 72 | ||
73 | extern const char tipc_bclink_name[]; | 73 | extern const char tipc_bclink_name[]; |
74 | 74 | ||
75 | void tipc_nmap_add(struct tipc_node_map *nm_ptr, u32 node); | ||
76 | void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node); | ||
75 | 77 | ||
76 | /** | 78 | /** |
77 | * nmap_add - add a node to a node map | 79 | * tipc_nmap_equal - test for equality of node maps |
78 | */ | ||
79 | |||
80 | static inline void tipc_nmap_add(struct tipc_node_map *nm_ptr, u32 node) | ||
81 | { | ||
82 | int n = tipc_node(node); | ||
83 | int w = n / WSIZE; | ||
84 | u32 mask = (1 << (n % WSIZE)); | ||
85 | |||
86 | if ((nm_ptr->map[w] & mask) == 0) { | ||
87 | nm_ptr->count++; | ||
88 | nm_ptr->map[w] |= mask; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * nmap_remove - remove a node from a node map | ||
94 | */ | ||
95 | |||
96 | static inline void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node) | ||
97 | { | ||
98 | int n = tipc_node(node); | ||
99 | int w = n / WSIZE; | ||
100 | u32 mask = (1 << (n % WSIZE)); | ||
101 | |||
102 | if ((nm_ptr->map[w] & mask) != 0) { | ||
103 | nm_ptr->map[w] &= ~mask; | ||
104 | nm_ptr->count--; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * nmap_equal - test for equality of node maps | ||
110 | */ | 80 | */ |
111 | 81 | ||
112 | static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b) | 82 | static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b) |
@@ -114,84 +84,11 @@ static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_m | |||
114 | return !memcmp(nm_a, nm_b, sizeof(*nm_a)); | 84 | return !memcmp(nm_a, nm_b, sizeof(*nm_a)); |
115 | } | 85 | } |
116 | 86 | ||
117 | /** | 87 | void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b, |
118 | * nmap_diff - find differences between node maps | 88 | struct tipc_node_map *nm_diff); |
119 | * @nm_a: input node map A | ||
120 | * @nm_b: input node map B | ||
121 | * @nm_diff: output node map A-B (i.e. nodes of A that are not in B) | ||
122 | */ | ||
123 | |||
124 | static inline void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b, | ||
125 | struct tipc_node_map *nm_diff) | ||
126 | { | ||
127 | int stop = ARRAY_SIZE(nm_a->map); | ||
128 | int w; | ||
129 | int b; | ||
130 | u32 map; | ||
131 | |||
132 | memset(nm_diff, 0, sizeof(*nm_diff)); | ||
133 | for (w = 0; w < stop; w++) { | ||
134 | map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]); | ||
135 | nm_diff->map[w] = map; | ||
136 | if (map != 0) { | ||
137 | for (b = 0 ; b < WSIZE; b++) { | ||
138 | if (map & (1 << b)) | ||
139 | nm_diff->count++; | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * port_list_add - add a port to a port list, ensuring no duplicates | ||
147 | */ | ||
148 | |||
149 | static inline void tipc_port_list_add(struct port_list *pl_ptr, u32 port) | ||
150 | { | ||
151 | struct port_list *item = pl_ptr; | ||
152 | int i; | ||
153 | int item_sz = PLSIZE; | ||
154 | int cnt = pl_ptr->count; | ||
155 | |||
156 | for (; ; cnt -= item_sz, item = item->next) { | ||
157 | if (cnt < PLSIZE) | ||
158 | item_sz = cnt; | ||
159 | for (i = 0; i < item_sz; i++) | ||
160 | if (item->ports[i] == port) | ||
161 | return; | ||
162 | if (i < PLSIZE) { | ||
163 | item->ports[i] = port; | ||
164 | pl_ptr->count++; | ||
165 | return; | ||
166 | } | ||
167 | if (!item->next) { | ||
168 | item->next = kmalloc(sizeof(*item), GFP_ATOMIC); | ||
169 | if (!item->next) { | ||
170 | warn("Incomplete multicast delivery, no memory\n"); | ||
171 | return; | ||
172 | } | ||
173 | item->next->next = NULL; | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * port_list_free - free dynamically created entries in port_list chain | ||
180 | * | ||
181 | * Note: First item is on stack, so it doesn't need to be released | ||
182 | */ | ||
183 | |||
184 | static inline void tipc_port_list_free(struct port_list *pl_ptr) | ||
185 | { | ||
186 | struct port_list *item; | ||
187 | struct port_list *next; | ||
188 | |||
189 | for (item = pl_ptr->next; item; item = next) { | ||
190 | next = item->next; | ||
191 | kfree(item); | ||
192 | } | ||
193 | } | ||
194 | 89 | ||
90 | void tipc_port_list_add(struct port_list *pl_ptr, u32 port); | ||
91 | void tipc_port_list_free(struct port_list *pl_ptr); | ||
195 | 92 | ||
196 | int tipc_bclink_init(void); | 93 | int tipc_bclink_init(void); |
197 | void tipc_bclink_stop(void); | 94 | void tipc_bclink_stop(void); |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 78091375ca12..52ae17b2583e 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -467,6 +467,18 @@ int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr) | |||
467 | return res; | 467 | return res; |
468 | } | 468 | } |
469 | 469 | ||
470 | /** | ||
471 | * tipc_bearer_congested - determines if bearer is currently congested | ||
472 | */ | ||
473 | |||
474 | int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr) | ||
475 | { | ||
476 | if (unlikely(b_ptr->publ.blocked)) | ||
477 | return 1; | ||
478 | if (likely(list_empty(&b_ptr->cong_links))) | ||
479 | return 0; | ||
480 | return !tipc_bearer_resolve_congestion(b_ptr, l_ptr); | ||
481 | } | ||
470 | 482 | ||
471 | /** | 483 | /** |
472 | * tipc_enable_bearer - enable bearer with the given name | 484 | * tipc_enable_bearer - enable bearer with the given name |
@@ -493,7 +505,7 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) | |||
493 | return -EINVAL; | 505 | return -EINVAL; |
494 | } | 506 | } |
495 | if (!tipc_addr_domain_valid(bcast_scope) || | 507 | if (!tipc_addr_domain_valid(bcast_scope) || |
496 | !in_scope(bcast_scope, tipc_own_addr)) { | 508 | !tipc_in_scope(bcast_scope, tipc_own_addr)) { |
497 | warn("Bearer <%s> rejected, illegal broadcast scope\n", name); | 509 | warn("Bearer <%s> rejected, illegal broadcast scope\n", name); |
498 | return -EINVAL; | 510 | return -EINVAL; |
499 | } | 511 | } |
@@ -571,7 +583,7 @@ restart: | |||
571 | spin_lock_init(&b_ptr->publ.lock); | 583 | spin_lock_init(&b_ptr->publ.lock); |
572 | write_unlock_bh(&tipc_net_lock); | 584 | write_unlock_bh(&tipc_net_lock); |
573 | info("Enabled bearer <%s>, discovery domain %s, priority %u\n", | 585 | info("Enabled bearer <%s>, discovery domain %s, priority %u\n", |
574 | name, addr_string_fill(addr_string, bcast_scope), priority); | 586 | name, tipc_addr_string_fill(addr_string, bcast_scope), priority); |
575 | return 0; | 587 | return 0; |
576 | failed: | 588 | failed: |
577 | write_unlock_bh(&tipc_net_lock); | 589 | write_unlock_bh(&tipc_net_lock); |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 000228e93f9e..a850b389663e 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
@@ -125,6 +125,7 @@ void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest); | |||
125 | void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr); | 125 | void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr); |
126 | struct bearer *tipc_bearer_find_interface(const char *if_name); | 126 | struct bearer *tipc_bearer_find_interface(const char *if_name); |
127 | int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr); | 127 | int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr); |
128 | int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr); | ||
128 | int tipc_bearer_init(void); | 129 | int tipc_bearer_init(void); |
129 | void tipc_bearer_stop(void); | 130 | void tipc_bearer_stop(void); |
130 | void tipc_bearer_lock_push(struct bearer *b_ptr); | 131 | void tipc_bearer_lock_push(struct bearer *b_ptr); |
@@ -154,17 +155,4 @@ static inline int tipc_bearer_send(struct bearer *b_ptr, struct sk_buff *buf, | |||
154 | return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest); | 155 | return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest); |
155 | } | 156 | } |
156 | 157 | ||
157 | /** | 158 | #endif /* _TIPC_BEARER_H */ |
158 | * tipc_bearer_congested - determines if bearer is currently congested | ||
159 | */ | ||
160 | |||
161 | static inline int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr) | ||
162 | { | ||
163 | if (unlikely(b_ptr->publ.blocked)) | ||
164 | return 1; | ||
165 | if (likely(list_empty(&b_ptr->cong_links))) | ||
166 | return 0; | ||
167 | return !tipc_bearer_resolve_congestion(b_ptr, l_ptr); | ||
168 | } | ||
169 | |||
170 | #endif | ||
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c index a7eac00cd363..e68f705381bc 100644 --- a/net/tipc/cluster.c +++ b/net/tipc/cluster.c | |||
@@ -238,7 +238,7 @@ static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest) | |||
238 | if (buf) { | 238 | if (buf) { |
239 | msg = buf_msg(buf); | 239 | msg = buf_msg(buf); |
240 | memset((char *)msg, 0, size); | 240 | memset((char *)msg, 0, size); |
241 | msg_init(msg, ROUTE_DISTRIBUTOR, 0, INT_H_SIZE, dest); | 241 | tipc_msg_init(msg, ROUTE_DISTRIBUTOR, 0, INT_H_SIZE, dest); |
242 | } | 242 | } |
243 | return buf; | 243 | return buf; |
244 | } | 244 | } |
diff --git a/net/tipc/config.c b/net/tipc/config.c index ca3544d030c7..961d1b097146 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
@@ -56,9 +56,6 @@ struct subscr_data { | |||
56 | struct manager { | 56 | struct manager { |
57 | u32 user_ref; | 57 | u32 user_ref; |
58 | u32 port_ref; | 58 | u32 port_ref; |
59 | u32 subscr_ref; | ||
60 | u32 link_subscriptions; | ||
61 | struct list_head link_subscribers; | ||
62 | }; | 59 | }; |
63 | 60 | ||
64 | static struct manager mng = { 0}; | 61 | static struct manager mng = { 0}; |
@@ -70,12 +67,6 @@ static int req_tlv_space; /* request message TLV area size */ | |||
70 | static int rep_headroom; /* reply message headroom to use */ | 67 | static int rep_headroom; /* reply message headroom to use */ |
71 | 68 | ||
72 | 69 | ||
73 | void tipc_cfg_link_event(u32 addr, char *name, int up) | ||
74 | { | ||
75 | /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ | ||
76 | } | ||
77 | |||
78 | |||
79 | struct sk_buff *tipc_cfg_reply_alloc(int payload_size) | 70 | struct sk_buff *tipc_cfg_reply_alloc(int payload_size) |
80 | { | 71 | { |
81 | struct sk_buff *buf; | 72 | struct sk_buff *buf; |
@@ -130,12 +121,24 @@ struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) | |||
130 | } | 121 | } |
131 | 122 | ||
132 | 123 | ||
133 | |||
134 | |||
135 | #if 0 | 124 | #if 0 |
136 | 125 | ||
137 | /* Now obsolete code for handling commands not yet implemented the new way */ | 126 | /* Now obsolete code for handling commands not yet implemented the new way */ |
138 | 127 | ||
128 | /* | ||
129 | * Some of this code assumed that the manager structure contains two added | ||
130 | * fields: | ||
131 | * u32 link_subscriptions; | ||
132 | * struct list_head link_subscribers; | ||
133 | * which are currently not present. These fields may need to be re-introduced | ||
134 | * if and when support for link subscriptions is added. | ||
135 | */ | ||
136 | |||
137 | void tipc_cfg_link_event(u32 addr, char *name, int up) | ||
138 | { | ||
139 | /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ | ||
140 | } | ||
141 | |||
139 | int tipc_cfg_cmd(const struct tipc_cmd_msg * msg, | 142 | int tipc_cfg_cmd(const struct tipc_cmd_msg * msg, |
140 | char *data, | 143 | char *data, |
141 | u32 sz, | 144 | u32 sz, |
@@ -243,13 +246,48 @@ static void cfg_cmd_event(struct tipc_cmd_msg *msg, | |||
243 | default: | 246 | default: |
244 | rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); | 247 | rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); |
245 | } | 248 | } |
246 | exit: | 249 | exit: |
247 | rmsg.result_len = htonl(msg_sect[1].iov_len); | 250 | rmsg.result_len = htonl(msg_sect[1].iov_len); |
248 | rmsg.retval = htonl(rv); | 251 | rmsg.retval = htonl(rv); |
249 | tipc_cfg_respond(msg_sect, 2u, orig); | 252 | tipc_cfg_respond(msg_sect, 2u, orig); |
250 | } | 253 | } |
251 | #endif | 254 | #endif |
252 | 255 | ||
256 | #define MAX_STATS_INFO 2000 | ||
257 | |||
258 | static struct sk_buff *tipc_show_stats(void) | ||
259 | { | ||
260 | struct sk_buff *buf; | ||
261 | struct tlv_desc *rep_tlv; | ||
262 | struct print_buf pb; | ||
263 | int str_len; | ||
264 | u32 value; | ||
265 | |||
266 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
267 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
268 | |||
269 | value = ntohl(*(u32 *)TLV_DATA(req_tlv_area)); | ||
270 | if (value != 0) | ||
271 | return tipc_cfg_reply_error_string("unsupported argument"); | ||
272 | |||
273 | buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); | ||
274 | if (buf == NULL) | ||
275 | return NULL; | ||
276 | |||
277 | rep_tlv = (struct tlv_desc *)buf->data; | ||
278 | tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO); | ||
279 | |||
280 | tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n"); | ||
281 | |||
282 | /* Use additional tipc_printf()'s to return more info ... */ | ||
283 | |||
284 | str_len = tipc_printbuf_validate(&pb); | ||
285 | skb_put(buf, TLV_SPACE(str_len)); | ||
286 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
287 | |||
288 | return buf; | ||
289 | } | ||
290 | |||
253 | static struct sk_buff *cfg_enable_bearer(void) | 291 | static struct sk_buff *cfg_enable_bearer(void) |
254 | { | 292 | { |
255 | struct tipc_bearer_config *args; | 293 | struct tipc_bearer_config *args; |
@@ -533,6 +571,9 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
533 | case TIPC_CMD_DUMP_LOG: | 571 | case TIPC_CMD_DUMP_LOG: |
534 | rep_tlv_buf = tipc_log_dump(); | 572 | rep_tlv_buf = tipc_log_dump(); |
535 | break; | 573 | break; |
574 | case TIPC_CMD_SHOW_STATS: | ||
575 | rep_tlv_buf = tipc_show_stats(); | ||
576 | break; | ||
536 | case TIPC_CMD_SET_LINK_TOL: | 577 | case TIPC_CMD_SET_LINK_TOL: |
537 | case TIPC_CMD_SET_LINK_PRI: | 578 | case TIPC_CMD_SET_LINK_PRI: |
538 | case TIPC_CMD_SET_LINK_WINDOW: | 579 | case TIPC_CMD_SET_LINK_WINDOW: |
@@ -667,9 +708,6 @@ int tipc_cfg_init(void) | |||
667 | struct tipc_name_seq seq; | 708 | struct tipc_name_seq seq; |
668 | int res; | 709 | int res; |
669 | 710 | ||
670 | memset(&mng, 0, sizeof(mng)); | ||
671 | INIT_LIST_HEAD(&mng.link_subscribers); | ||
672 | |||
673 | res = tipc_attach(&mng.user_ref, NULL, NULL); | 711 | res = tipc_attach(&mng.user_ref, NULL, NULL); |
674 | if (res) | 712 | if (res) |
675 | goto failed; | 713 | goto failed; |
diff --git a/net/tipc/core.c b/net/tipc/core.c index 52c571fedbe0..696468117985 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -49,8 +49,6 @@ | |||
49 | #include "config.h" | 49 | #include "config.h" |
50 | 50 | ||
51 | 51 | ||
52 | #define TIPC_MOD_VER "1.6.4" | ||
53 | |||
54 | #ifndef CONFIG_TIPC_ZONES | 52 | #ifndef CONFIG_TIPC_ZONES |
55 | #define CONFIG_TIPC_ZONES 3 | 53 | #define CONFIG_TIPC_ZONES 3 |
56 | #endif | 54 | #endif |
@@ -104,6 +102,30 @@ int tipc_get_mode(void) | |||
104 | } | 102 | } |
105 | 103 | ||
106 | /** | 104 | /** |
105 | * buf_acquire - creates a TIPC message buffer | ||
106 | * @size: message size (including TIPC header) | ||
107 | * | ||
108 | * Returns a new buffer with data pointers set to the specified size. | ||
109 | * | ||
110 | * NOTE: Headroom is reserved to allow prepending of a data link header. | ||
111 | * There may also be unrequested tailroom present at the buffer's end. | ||
112 | */ | ||
113 | |||
114 | struct sk_buff *buf_acquire(u32 size) | ||
115 | { | ||
116 | struct sk_buff *skb; | ||
117 | unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; | ||
118 | |||
119 | skb = alloc_skb_fclone(buf_size, GFP_ATOMIC); | ||
120 | if (skb) { | ||
121 | skb_reserve(skb, BUF_HEADROOM); | ||
122 | skb_put(skb, size); | ||
123 | skb->next = NULL; | ||
124 | } | ||
125 | return skb; | ||
126 | } | ||
127 | |||
128 | /** | ||
107 | * tipc_core_stop_net - shut down TIPC networking sub-systems | 129 | * tipc_core_stop_net - shut down TIPC networking sub-systems |
108 | */ | 130 | */ |
109 | 131 | ||
diff --git a/net/tipc/core.h b/net/tipc/core.h index c58a1d16563a..188799017abd 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -59,6 +59,9 @@ | |||
59 | #include <linux/slab.h> | 59 | #include <linux/slab.h> |
60 | #include <linux/vmalloc.h> | 60 | #include <linux/vmalloc.h> |
61 | 61 | ||
62 | |||
63 | #define TIPC_MOD_VER "2.0.0" | ||
64 | |||
62 | /* | 65 | /* |
63 | * TIPC sanity test macros | 66 | * TIPC sanity test macros |
64 | */ | 67 | */ |
@@ -325,29 +328,7 @@ static inline struct tipc_msg *buf_msg(struct sk_buff *skb) | |||
325 | return (struct tipc_msg *)skb->data; | 328 | return (struct tipc_msg *)skb->data; |
326 | } | 329 | } |
327 | 330 | ||
328 | /** | 331 | extern struct sk_buff *buf_acquire(u32 size); |
329 | * buf_acquire - creates a TIPC message buffer | ||
330 | * @size: message size (including TIPC header) | ||
331 | * | ||
332 | * Returns a new buffer with data pointers set to the specified size. | ||
333 | * | ||
334 | * NOTE: Headroom is reserved to allow prepending of a data link header. | ||
335 | * There may also be unrequested tailroom present at the buffer's end. | ||
336 | */ | ||
337 | |||
338 | static inline struct sk_buff *buf_acquire(u32 size) | ||
339 | { | ||
340 | struct sk_buff *skb; | ||
341 | unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; | ||
342 | |||
343 | skb = alloc_skb_fclone(buf_size, GFP_ATOMIC); | ||
344 | if (skb) { | ||
345 | skb_reserve(skb, BUF_HEADROOM); | ||
346 | skb_put(skb, size); | ||
347 | skb->next = NULL; | ||
348 | } | ||
349 | return skb; | ||
350 | } | ||
351 | 332 | ||
352 | /** | 333 | /** |
353 | * buf_discard - frees a TIPC message buffer | 334 | * buf_discard - frees a TIPC message buffer |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 74b7d1e28aec..fc1fcf5e6b53 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -120,7 +120,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type, | |||
120 | 120 | ||
121 | if (buf) { | 121 | if (buf) { |
122 | msg = buf_msg(buf); | 122 | msg = buf_msg(buf); |
123 | msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain); | 123 | tipc_msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain); |
124 | msg_set_non_seq(msg, 1); | 124 | msg_set_non_seq(msg, 1); |
125 | msg_set_req_links(msg, req_links); | 125 | msg_set_req_links(msg, req_links); |
126 | msg_set_dest_domain(msg, dest_domain); | 126 | msg_set_dest_domain(msg, dest_domain); |
@@ -144,7 +144,7 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr, | |||
144 | char media_addr_str[64]; | 144 | char media_addr_str[64]; |
145 | struct print_buf pb; | 145 | struct print_buf pb; |
146 | 146 | ||
147 | addr_string_fill(node_addr_str, node_addr); | 147 | tipc_addr_string_fill(node_addr_str, node_addr); |
148 | tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str)); | 148 | tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str)); |
149 | tipc_media_addr_printf(&pb, media_addr); | 149 | tipc_media_addr_printf(&pb, media_addr); |
150 | tipc_printbuf_validate(&pb); | 150 | tipc_printbuf_validate(&pb); |
@@ -183,7 +183,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr) | |||
183 | disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr); | 183 | disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr); |
184 | return; | 184 | return; |
185 | } | 185 | } |
186 | if (!in_scope(dest, tipc_own_addr)) | 186 | if (!tipc_in_scope(dest, tipc_own_addr)) |
187 | return; | 187 | return; |
188 | if (is_slave(tipc_own_addr) && is_slave(orig)) | 188 | if (is_slave(tipc_own_addr) && is_slave(orig)) |
189 | return; | 189 | return; |
@@ -224,7 +224,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr) | |||
224 | memcpy(addr, &media_addr, sizeof(*addr)); | 224 | memcpy(addr, &media_addr, sizeof(*addr)); |
225 | tipc_link_reset(link); | 225 | tipc_link_reset(link); |
226 | } | 226 | } |
227 | link_fully_up = (link->state == WORKING_WORKING); | 227 | link_fully_up = link_working_working(link); |
228 | spin_unlock_bh(&n_ptr->lock); | 228 | spin_unlock_bh(&n_ptr->lock); |
229 | if ((type == DSC_RESP_MSG) || link_fully_up) | 229 | if ((type == DSC_RESP_MSG) || link_fully_up) |
230 | return; | 230 | return; |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 1a7e4665af80..a3616b99529b 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -202,41 +202,6 @@ static unsigned int align(unsigned int i) | |||
202 | return (i + 3) & ~3u; | 202 | return (i + 3) & ~3u; |
203 | } | 203 | } |
204 | 204 | ||
205 | static int link_working_working(struct link *l_ptr) | ||
206 | { | ||
207 | return (l_ptr->state == WORKING_WORKING); | ||
208 | } | ||
209 | |||
210 | static int link_working_unknown(struct link *l_ptr) | ||
211 | { | ||
212 | return (l_ptr->state == WORKING_UNKNOWN); | ||
213 | } | ||
214 | |||
215 | static int link_reset_unknown(struct link *l_ptr) | ||
216 | { | ||
217 | return (l_ptr->state == RESET_UNKNOWN); | ||
218 | } | ||
219 | |||
220 | static int link_reset_reset(struct link *l_ptr) | ||
221 | { | ||
222 | return (l_ptr->state == RESET_RESET); | ||
223 | } | ||
224 | |||
225 | static int link_blocked(struct link *l_ptr) | ||
226 | { | ||
227 | return (l_ptr->exp_msg_count || l_ptr->blocked); | ||
228 | } | ||
229 | |||
230 | static int link_congested(struct link *l_ptr) | ||
231 | { | ||
232 | return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]); | ||
233 | } | ||
234 | |||
235 | static u32 link_max_pkt(struct link *l_ptr) | ||
236 | { | ||
237 | return l_ptr->max_pkt; | ||
238 | } | ||
239 | |||
240 | static void link_init_max_pkt(struct link *l_ptr) | 205 | static void link_init_max_pkt(struct link *l_ptr) |
241 | { | 206 | { |
242 | u32 max_pkt; | 207 | u32 max_pkt; |
@@ -468,7 +433,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, | |||
468 | 433 | ||
469 | l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; | 434 | l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; |
470 | msg = l_ptr->pmsg; | 435 | msg = l_ptr->pmsg; |
471 | msg_init(msg, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, l_ptr->addr); | 436 | tipc_msg_init(msg, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, l_ptr->addr); |
472 | msg_set_size(msg, sizeof(l_ptr->proto_msg)); | 437 | msg_set_size(msg, sizeof(l_ptr->proto_msg)); |
473 | msg_set_session(msg, (tipc_random & 0xffff)); | 438 | msg_set_session(msg, (tipc_random & 0xffff)); |
474 | msg_set_bearer_id(msg, b_ptr->identity); | 439 | msg_set_bearer_id(msg, b_ptr->identity); |
@@ -561,9 +526,8 @@ static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz) | |||
561 | goto exit; | 526 | goto exit; |
562 | if (!list_empty(&p_ptr->wait_list)) | 527 | if (!list_empty(&p_ptr->wait_list)) |
563 | goto exit; | 528 | goto exit; |
564 | p_ptr->congested_link = l_ptr; | ||
565 | p_ptr->publ.congested = 1; | 529 | p_ptr->publ.congested = 1; |
566 | p_ptr->waiting_pkts = 1 + ((sz - 1) / link_max_pkt(l_ptr)); | 530 | p_ptr->waiting_pkts = 1 + ((sz - 1) / l_ptr->max_pkt); |
567 | list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports); | 531 | list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports); |
568 | l_ptr->stats.link_congs++; | 532 | l_ptr->stats.link_congs++; |
569 | exit: | 533 | exit: |
@@ -592,7 +556,6 @@ void tipc_link_wakeup_ports(struct link *l_ptr, int all) | |||
592 | if (win <= 0) | 556 | if (win <= 0) |
593 | break; | 557 | break; |
594 | list_del_init(&p_ptr->wait_list); | 558 | list_del_init(&p_ptr->wait_list); |
595 | p_ptr->congested_link = NULL; | ||
596 | spin_lock_bh(p_ptr->publ.lock); | 559 | spin_lock_bh(p_ptr->publ.lock); |
597 | p_ptr->publ.congested = 0; | 560 | p_ptr->publ.congested = 0; |
598 | p_ptr->wakeup(&p_ptr->publ); | 561 | p_ptr->wakeup(&p_ptr->publ); |
@@ -877,7 +840,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) | |||
877 | case TIMEOUT_EVT: | 840 | case TIMEOUT_EVT: |
878 | dbg_link("TIM "); | 841 | dbg_link("TIM "); |
879 | if (l_ptr->next_in_no != l_ptr->checkpoint) { | 842 | if (l_ptr->next_in_no != l_ptr->checkpoint) { |
880 | dbg_link("-> WW \n"); | 843 | dbg_link("-> WW\n"); |
881 | l_ptr->state = WORKING_WORKING; | 844 | l_ptr->state = WORKING_WORKING; |
882 | l_ptr->fsm_msg_cnt = 0; | 845 | l_ptr->fsm_msg_cnt = 0; |
883 | l_ptr->checkpoint = l_ptr->next_in_no; | 846 | l_ptr->checkpoint = l_ptr->next_in_no; |
@@ -934,7 +897,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) | |||
934 | link_set_timer(l_ptr, cont_intv); | 897 | link_set_timer(l_ptr, cont_intv); |
935 | break; | 898 | break; |
936 | case RESET_MSG: | 899 | case RESET_MSG: |
937 | dbg_link("RES \n"); | 900 | dbg_link("RES\n"); |
938 | dbg_link(" -> RR\n"); | 901 | dbg_link(" -> RR\n"); |
939 | l_ptr->state = RESET_RESET; | 902 | l_ptr->state = RESET_RESET; |
940 | l_ptr->fsm_msg_cnt = 0; | 903 | l_ptr->fsm_msg_cnt = 0; |
@@ -947,7 +910,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) | |||
947 | l_ptr->started = 1; | 910 | l_ptr->started = 1; |
948 | /* fall through */ | 911 | /* fall through */ |
949 | case TIMEOUT_EVT: | 912 | case TIMEOUT_EVT: |
950 | dbg_link("TIM \n"); | 913 | dbg_link("TIM\n"); |
951 | tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); | 914 | tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); |
952 | l_ptr->fsm_msg_cnt++; | 915 | l_ptr->fsm_msg_cnt++; |
953 | link_set_timer(l_ptr, cont_intv); | 916 | link_set_timer(l_ptr, cont_intv); |
@@ -1017,7 +980,7 @@ static int link_bundle_buf(struct link *l_ptr, | |||
1017 | return 0; | 980 | return 0; |
1018 | if (skb_tailroom(bundler) < (pad + size)) | 981 | if (skb_tailroom(bundler) < (pad + size)) |
1019 | return 0; | 982 | return 0; |
1020 | if (link_max_pkt(l_ptr) < (to_pos + size)) | 983 | if (l_ptr->max_pkt < (to_pos + size)) |
1021 | return 0; | 984 | return 0; |
1022 | 985 | ||
1023 | skb_put(bundler, pad + size); | 986 | skb_put(bundler, pad + size); |
@@ -1062,9 +1025,9 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) | |||
1062 | u32 size = msg_size(msg); | 1025 | u32 size = msg_size(msg); |
1063 | u32 dsz = msg_data_sz(msg); | 1026 | u32 dsz = msg_data_sz(msg); |
1064 | u32 queue_size = l_ptr->out_queue_size; | 1027 | u32 queue_size = l_ptr->out_queue_size; |
1065 | u32 imp = msg_tot_importance(msg); | 1028 | u32 imp = tipc_msg_tot_importance(msg); |
1066 | u32 queue_limit = l_ptr->queue_limit[imp]; | 1029 | u32 queue_limit = l_ptr->queue_limit[imp]; |
1067 | u32 max_packet = link_max_pkt(l_ptr); | 1030 | u32 max_packet = l_ptr->max_pkt; |
1068 | 1031 | ||
1069 | msg_set_prevnode(msg, tipc_own_addr); /* If routed message */ | 1032 | msg_set_prevnode(msg, tipc_own_addr); /* If routed message */ |
1070 | 1033 | ||
@@ -1127,7 +1090,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) | |||
1127 | struct tipc_msg bundler_hdr; | 1090 | struct tipc_msg bundler_hdr; |
1128 | 1091 | ||
1129 | if (bundler) { | 1092 | if (bundler) { |
1130 | msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG, | 1093 | tipc_msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG, |
1131 | INT_H_SIZE, l_ptr->addr); | 1094 | INT_H_SIZE, l_ptr->addr); |
1132 | skb_copy_to_linear_data(bundler, &bundler_hdr, | 1095 | skb_copy_to_linear_data(bundler, &bundler_hdr, |
1133 | INT_H_SIZE); | 1096 | INT_H_SIZE); |
@@ -1195,7 +1158,7 @@ static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf, | |||
1195 | int res = msg_data_sz(msg); | 1158 | int res = msg_data_sz(msg); |
1196 | 1159 | ||
1197 | if (likely(!link_congested(l_ptr))) { | 1160 | if (likely(!link_congested(l_ptr))) { |
1198 | if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) { | 1161 | if (likely(msg_size(msg) <= l_ptr->max_pkt)) { |
1199 | if (likely(list_empty(&l_ptr->b_ptr->cong_links))) { | 1162 | if (likely(list_empty(&l_ptr->b_ptr->cong_links))) { |
1200 | link_add_to_outqueue(l_ptr, buf, msg); | 1163 | link_add_to_outqueue(l_ptr, buf, msg); |
1201 | if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, | 1164 | if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, |
@@ -1212,7 +1175,7 @@ static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf, | |||
1212 | } | 1175 | } |
1213 | } | 1176 | } |
1214 | else | 1177 | else |
1215 | *used_max_pkt = link_max_pkt(l_ptr); | 1178 | *used_max_pkt = l_ptr->max_pkt; |
1216 | } | 1179 | } |
1217 | return tipc_link_send_buf(l_ptr, buf); /* All other cases */ | 1180 | return tipc_link_send_buf(l_ptr, buf); /* All other cases */ |
1218 | } | 1181 | } |
@@ -1280,7 +1243,7 @@ again: | |||
1280 | * (Must not hold any locks while building message.) | 1243 | * (Must not hold any locks while building message.) |
1281 | */ | 1244 | */ |
1282 | 1245 | ||
1283 | res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt, | 1246 | res = tipc_msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt, |
1284 | !sender->user_port, &buf); | 1247 | !sender->user_port, &buf); |
1285 | 1248 | ||
1286 | read_lock_bh(&tipc_net_lock); | 1249 | read_lock_bh(&tipc_net_lock); |
@@ -1319,7 +1282,7 @@ exit: | |||
1319 | * then re-try fast path or fragment the message | 1282 | * then re-try fast path or fragment the message |
1320 | */ | 1283 | */ |
1321 | 1284 | ||
1322 | sender->publ.max_pkt = link_max_pkt(l_ptr); | 1285 | sender->publ.max_pkt = l_ptr->max_pkt; |
1323 | tipc_node_unlock(node); | 1286 | tipc_node_unlock(node); |
1324 | read_unlock_bh(&tipc_net_lock); | 1287 | read_unlock_bh(&tipc_net_lock); |
1325 | 1288 | ||
@@ -1391,7 +1354,7 @@ again: | |||
1391 | /* Prepare reusable fragment header: */ | 1354 | /* Prepare reusable fragment header: */ |
1392 | 1355 | ||
1393 | msg_dbg(hdr, ">FRAGMENTING>"); | 1356 | msg_dbg(hdr, ">FRAGMENTING>"); |
1394 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | 1357 | tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, |
1395 | INT_H_SIZE, msg_destnode(hdr)); | 1358 | INT_H_SIZE, msg_destnode(hdr)); |
1396 | msg_set_link_selector(&fragm_hdr, sender->publ.ref); | 1359 | msg_set_link_selector(&fragm_hdr, sender->publ.ref); |
1397 | msg_set_size(&fragm_hdr, max_pkt); | 1360 | msg_set_size(&fragm_hdr, max_pkt); |
@@ -1482,8 +1445,8 @@ error: | |||
1482 | tipc_node_unlock(node); | 1445 | tipc_node_unlock(node); |
1483 | goto reject; | 1446 | goto reject; |
1484 | } | 1447 | } |
1485 | if (link_max_pkt(l_ptr) < max_pkt) { | 1448 | if (l_ptr->max_pkt < max_pkt) { |
1486 | sender->publ.max_pkt = link_max_pkt(l_ptr); | 1449 | sender->publ.max_pkt = l_ptr->max_pkt; |
1487 | tipc_node_unlock(node); | 1450 | tipc_node_unlock(node); |
1488 | for (; buf_chain; buf_chain = buf) { | 1451 | for (; buf_chain; buf_chain = buf) { |
1489 | buf = buf_chain->next; | 1452 | buf = buf_chain->next; |
@@ -1553,7 +1516,7 @@ u32 tipc_link_push_packet(struct link *l_ptr) | |||
1553 | 1516 | ||
1554 | /* Continue retransmission now, if there is anything: */ | 1517 | /* Continue retransmission now, if there is anything: */ |
1555 | 1518 | ||
1556 | if (r_q_size && buf && !skb_cloned(buf)) { | 1519 | if (r_q_size && buf) { |
1557 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); | 1520 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); |
1558 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); | 1521 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); |
1559 | if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | 1522 | if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { |
@@ -1650,7 +1613,7 @@ static void link_reset_all(unsigned long addr) | |||
1650 | tipc_node_lock(n_ptr); | 1613 | tipc_node_lock(n_ptr); |
1651 | 1614 | ||
1652 | warn("Resetting all links to %s\n", | 1615 | warn("Resetting all links to %s\n", |
1653 | addr_string_fill(addr_string, n_ptr->addr)); | 1616 | tipc_addr_string_fill(addr_string, n_ptr->addr)); |
1654 | 1617 | ||
1655 | for (i = 0; i < MAX_BEARERS; i++) { | 1618 | for (i = 0; i < MAX_BEARERS; i++) { |
1656 | if (n_ptr->links[i]) { | 1619 | if (n_ptr->links[i]) { |
@@ -1692,7 +1655,7 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf) | |||
1692 | n_ptr = l_ptr->owner->next; | 1655 | n_ptr = l_ptr->owner->next; |
1693 | tipc_node_lock(n_ptr); | 1656 | tipc_node_lock(n_ptr); |
1694 | 1657 | ||
1695 | addr_string_fill(addr_string, n_ptr->addr); | 1658 | tipc_addr_string_fill(addr_string, n_ptr->addr); |
1696 | tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string); | 1659 | tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string); |
1697 | tipc_printf(TIPC_OUTPUT, "Supported: %d, ", n_ptr->bclink.supported); | 1660 | tipc_printf(TIPC_OUTPUT, "Supported: %d, ", n_ptr->bclink.supported); |
1698 | tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked); | 1661 | tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked); |
@@ -1722,15 +1685,16 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, | |||
1722 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); | 1685 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); |
1723 | 1686 | ||
1724 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { | 1687 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { |
1725 | if (!skb_cloned(buf)) { | 1688 | if (l_ptr->retransm_queue_size == 0) { |
1726 | msg_dbg(msg, ">NO_RETR->BCONG>"); | 1689 | msg_dbg(msg, ">NO_RETR->BCONG>"); |
1727 | dbg_print_link(l_ptr, " "); | 1690 | dbg_print_link(l_ptr, " "); |
1728 | l_ptr->retransm_queue_head = msg_seqno(msg); | 1691 | l_ptr->retransm_queue_head = msg_seqno(msg); |
1729 | l_ptr->retransm_queue_size = retransmits; | 1692 | l_ptr->retransm_queue_size = retransmits; |
1730 | return; | ||
1731 | } else { | 1693 | } else { |
1732 | /* Don't retransmit if driver already has the buffer */ | 1694 | err("Unexpected retransmit on link %s (qsize=%d)\n", |
1695 | l_ptr->name, l_ptr->retransm_queue_size); | ||
1733 | } | 1696 | } |
1697 | return; | ||
1734 | } else { | 1698 | } else { |
1735 | /* Detect repeated retransmit failures on uncongested bearer */ | 1699 | /* Detect repeated retransmit failures on uncongested bearer */ |
1736 | 1700 | ||
@@ -1745,7 +1709,7 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, | |||
1745 | } | 1709 | } |
1746 | } | 1710 | } |
1747 | 1711 | ||
1748 | while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { | 1712 | while (retransmits && (buf != l_ptr->next_out) && buf) { |
1749 | msg = buf_msg(buf); | 1713 | msg = buf_msg(buf); |
1750 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | 1714 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); |
1751 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | 1715 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); |
@@ -2434,7 +2398,7 @@ void tipc_link_changeover(struct link *l_ptr) | |||
2434 | return; | 2398 | return; |
2435 | } | 2399 | } |
2436 | 2400 | ||
2437 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | 2401 | tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, |
2438 | ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr); | 2402 | ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr); |
2439 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | 2403 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); |
2440 | msg_set_msgcnt(&tunnel_hdr, msgcount); | 2404 | msg_set_msgcnt(&tunnel_hdr, msgcount); |
@@ -2489,7 +2453,7 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel) | |||
2489 | struct sk_buff *iter; | 2453 | struct sk_buff *iter; |
2490 | struct tipc_msg tunnel_hdr; | 2454 | struct tipc_msg tunnel_hdr; |
2491 | 2455 | ||
2492 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | 2456 | tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, |
2493 | DUPLICATE_MSG, INT_H_SIZE, l_ptr->addr); | 2457 | DUPLICATE_MSG, INT_H_SIZE, l_ptr->addr); |
2494 | msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size); | 2458 | msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size); |
2495 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | 2459 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); |
@@ -2680,7 +2644,7 @@ int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | |||
2680 | u32 dsz = msg_data_sz(inmsg); | 2644 | u32 dsz = msg_data_sz(inmsg); |
2681 | unchar *crs = buf->data; | 2645 | unchar *crs = buf->data; |
2682 | u32 rest = insize; | 2646 | u32 rest = insize; |
2683 | u32 pack_sz = link_max_pkt(l_ptr); | 2647 | u32 pack_sz = l_ptr->max_pkt; |
2684 | u32 fragm_sz = pack_sz - INT_H_SIZE; | 2648 | u32 fragm_sz = pack_sz - INT_H_SIZE; |
2685 | u32 fragm_no = 1; | 2649 | u32 fragm_no = 1; |
2686 | u32 destaddr; | 2650 | u32 destaddr; |
@@ -2695,7 +2659,7 @@ int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | |||
2695 | 2659 | ||
2696 | /* Prepare reusable fragment header: */ | 2660 | /* Prepare reusable fragment header: */ |
2697 | 2661 | ||
2698 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | 2662 | tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, |
2699 | INT_H_SIZE, destaddr); | 2663 | INT_H_SIZE, destaddr); |
2700 | msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); | 2664 | msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); |
2701 | msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); | 2665 | msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); |
@@ -3126,7 +3090,7 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) | |||
3126 | tipc_printf(&pb, "Link <%s>\n" | 3090 | tipc_printf(&pb, "Link <%s>\n" |
3127 | " %s MTU:%u Priority:%u Tolerance:%u ms" | 3091 | " %s MTU:%u Priority:%u Tolerance:%u ms" |
3128 | " Window:%u packets\n", | 3092 | " Window:%u packets\n", |
3129 | l_ptr->name, status, link_max_pkt(l_ptr), | 3093 | l_ptr->name, status, l_ptr->max_pkt, |
3130 | l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]); | 3094 | l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]); |
3131 | tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", | 3095 | tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", |
3132 | l_ptr->next_in_no - l_ptr->stats.recv_info, | 3096 | l_ptr->next_in_no - l_ptr->stats.recv_info, |
@@ -3271,7 +3235,7 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector) | |||
3271 | tipc_node_lock(n_ptr); | 3235 | tipc_node_lock(n_ptr); |
3272 | l_ptr = n_ptr->active_links[selector & 1]; | 3236 | l_ptr = n_ptr->active_links[selector & 1]; |
3273 | if (l_ptr) | 3237 | if (l_ptr) |
3274 | res = link_max_pkt(l_ptr); | 3238 | res = l_ptr->max_pkt; |
3275 | tipc_node_unlock(n_ptr); | 3239 | tipc_node_unlock(n_ptr); |
3276 | } | 3240 | } |
3277 | read_unlock_bh(&tipc_net_lock); | 3241 | read_unlock_bh(&tipc_net_lock); |
@@ -3294,7 +3258,7 @@ static void link_dump_rec_queue(struct link *l_ptr) | |||
3294 | info("buffer %x invalid\n", crs); | 3258 | info("buffer %x invalid\n", crs); |
3295 | return; | 3259 | return; |
3296 | } | 3260 | } |
3297 | msg_dbg(buf_msg(crs), "In rec queue: \n"); | 3261 | msg_dbg(buf_msg(crs), "In rec queue:\n"); |
3298 | crs = crs->next; | 3262 | crs = crs->next; |
3299 | } | 3263 | } |
3300 | } | 3264 | } |
@@ -3329,9 +3293,7 @@ static void link_print(struct link *l_ptr, struct print_buf *buf, | |||
3329 | if (l_ptr->next_out) | 3293 | if (l_ptr->next_out) |
3330 | tipc_printf(buf, "%u..", | 3294 | tipc_printf(buf, "%u..", |
3331 | msg_seqno(buf_msg(l_ptr->next_out))); | 3295 | msg_seqno(buf_msg(l_ptr->next_out))); |
3332 | tipc_printf(buf, "%u]", | 3296 | tipc_printf(buf, "%u]", msg_seqno(buf_msg(l_ptr->last_out))); |
3333 | msg_seqno(buf_msg | ||
3334 | (l_ptr->last_out)), l_ptr->out_queue_size); | ||
3335 | if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) - | 3297 | if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) - |
3336 | msg_seqno(buf_msg(l_ptr->first_out))) | 3298 | msg_seqno(buf_msg(l_ptr->first_out))) |
3337 | != (l_ptr->out_queue_size - 1)) || | 3299 | != (l_ptr->out_queue_size - 1)) || |
diff --git a/net/tipc/link.h b/net/tipc/link.h index 6a51e38ad25c..2e5385c47d30 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -292,4 +292,39 @@ static inline u32 lesser(u32 left, u32 right) | |||
292 | return less_eq(left, right) ? left : right; | 292 | return less_eq(left, right) ? left : right; |
293 | } | 293 | } |
294 | 294 | ||
295 | |||
296 | /* | ||
297 | * Link status checking routines | ||
298 | */ | ||
299 | |||
300 | static inline int link_working_working(struct link *l_ptr) | ||
301 | { | ||
302 | return (l_ptr->state == WORKING_WORKING); | ||
303 | } | ||
304 | |||
305 | static inline int link_working_unknown(struct link *l_ptr) | ||
306 | { | ||
307 | return (l_ptr->state == WORKING_UNKNOWN); | ||
308 | } | ||
309 | |||
310 | static inline int link_reset_unknown(struct link *l_ptr) | ||
311 | { | ||
312 | return (l_ptr->state == RESET_UNKNOWN); | ||
313 | } | ||
314 | |||
315 | static inline int link_reset_reset(struct link *l_ptr) | ||
316 | { | ||
317 | return (l_ptr->state == RESET_RESET); | ||
318 | } | ||
319 | |||
320 | static inline int link_blocked(struct link *l_ptr) | ||
321 | { | ||
322 | return (l_ptr->exp_msg_count || l_ptr->blocked); | ||
323 | } | ||
324 | |||
325 | static inline int link_congested(struct link *l_ptr) | ||
326 | { | ||
327 | return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]); | ||
328 | } | ||
329 | |||
295 | #endif | 330 | #endif |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 73dcd00d674e..381063817b41 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -40,6 +40,100 @@ | |||
40 | #include "msg.h" | 40 | #include "msg.h" |
41 | #include "bearer.h" | 41 | #include "bearer.h" |
42 | 42 | ||
43 | u32 tipc_msg_tot_importance(struct tipc_msg *m) | ||
44 | { | ||
45 | if (likely(msg_isdata(m))) { | ||
46 | if (likely(msg_orignode(m) == tipc_own_addr)) | ||
47 | return msg_importance(m); | ||
48 | return msg_importance(m) + 4; | ||
49 | } | ||
50 | if ((msg_user(m) == MSG_FRAGMENTER) && | ||
51 | (msg_type(m) == FIRST_FRAGMENT)) | ||
52 | return msg_importance(msg_get_wrapped(m)); | ||
53 | return msg_importance(m); | ||
54 | } | ||
55 | |||
56 | |||
57 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, | ||
58 | u32 hsize, u32 destnode) | ||
59 | { | ||
60 | memset(m, 0, hsize); | ||
61 | msg_set_version(m); | ||
62 | msg_set_user(m, user); | ||
63 | msg_set_hdr_sz(m, hsize); | ||
64 | msg_set_size(m, hsize); | ||
65 | msg_set_prevnode(m, tipc_own_addr); | ||
66 | msg_set_type(m, type); | ||
67 | if (!msg_short(m)) { | ||
68 | msg_set_orignode(m, tipc_own_addr); | ||
69 | msg_set_destnode(m, destnode); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * tipc_msg_calc_data_size - determine total data size for message | ||
75 | */ | ||
76 | |||
77 | int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) | ||
78 | { | ||
79 | int dsz = 0; | ||
80 | int i; | ||
81 | |||
82 | for (i = 0; i < num_sect; i++) | ||
83 | dsz += msg_sect[i].iov_len; | ||
84 | return dsz; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * tipc_msg_build - create message using specified header and data | ||
89 | * | ||
90 | * Note: Caller must not hold any locks in case copy_from_user() is interrupted! | ||
91 | * | ||
92 | * Returns message data size or errno | ||
93 | */ | ||
94 | |||
95 | int tipc_msg_build(struct tipc_msg *hdr, | ||
96 | struct iovec const *msg_sect, u32 num_sect, | ||
97 | int max_size, int usrmem, struct sk_buff** buf) | ||
98 | { | ||
99 | int dsz, sz, hsz, pos, res, cnt; | ||
100 | |||
101 | dsz = tipc_msg_calc_data_size(msg_sect, num_sect); | ||
102 | if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { | ||
103 | *buf = NULL; | ||
104 | return -EINVAL; | ||
105 | } | ||
106 | |||
107 | pos = hsz = msg_hdr_sz(hdr); | ||
108 | sz = hsz + dsz; | ||
109 | msg_set_size(hdr, sz); | ||
110 | if (unlikely(sz > max_size)) { | ||
111 | *buf = NULL; | ||
112 | return dsz; | ||
113 | } | ||
114 | |||
115 | *buf = buf_acquire(sz); | ||
116 | if (!(*buf)) | ||
117 | return -ENOMEM; | ||
118 | skb_copy_to_linear_data(*buf, hdr, hsz); | ||
119 | for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { | ||
120 | if (likely(usrmem)) | ||
121 | res = !copy_from_user((*buf)->data + pos, | ||
122 | msg_sect[cnt].iov_base, | ||
123 | msg_sect[cnt].iov_len); | ||
124 | else | ||
125 | skb_copy_to_linear_data_offset(*buf, pos, | ||
126 | msg_sect[cnt].iov_base, | ||
127 | msg_sect[cnt].iov_len); | ||
128 | pos += msg_sect[cnt].iov_len; | ||
129 | } | ||
130 | if (likely(res)) | ||
131 | return dsz; | ||
132 | |||
133 | buf_discard(*buf); | ||
134 | *buf = NULL; | ||
135 | return -EFAULT; | ||
136 | } | ||
43 | 137 | ||
44 | #ifdef CONFIG_TIPC_DEBUG | 138 | #ifdef CONFIG_TIPC_DEBUG |
45 | 139 | ||
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 7ee6ae238147..995d2da35b01 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
@@ -708,100 +708,13 @@ static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos) | |||
708 | #define DSC_REQ_MSG 0 | 708 | #define DSC_REQ_MSG 0 |
709 | #define DSC_RESP_MSG 1 | 709 | #define DSC_RESP_MSG 1 |
710 | 710 | ||
711 | static inline u32 msg_tot_importance(struct tipc_msg *m) | 711 | u32 tipc_msg_tot_importance(struct tipc_msg *m); |
712 | { | 712 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, |
713 | if (likely(msg_isdata(m))) { | 713 | u32 hsize, u32 destnode); |
714 | if (likely(msg_orignode(m) == tipc_own_addr)) | 714 | int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect); |
715 | return msg_importance(m); | 715 | int tipc_msg_build(struct tipc_msg *hdr, |
716 | return msg_importance(m) + 4; | ||
717 | } | ||
718 | if ((msg_user(m) == MSG_FRAGMENTER) && | ||
719 | (msg_type(m) == FIRST_FRAGMENT)) | ||
720 | return msg_importance(msg_get_wrapped(m)); | ||
721 | return msg_importance(m); | ||
722 | } | ||
723 | |||
724 | |||
725 | static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, | ||
726 | u32 hsize, u32 destnode) | ||
727 | { | ||
728 | memset(m, 0, hsize); | ||
729 | msg_set_version(m); | ||
730 | msg_set_user(m, user); | ||
731 | msg_set_hdr_sz(m, hsize); | ||
732 | msg_set_size(m, hsize); | ||
733 | msg_set_prevnode(m, tipc_own_addr); | ||
734 | msg_set_type(m, type); | ||
735 | if (!msg_short(m)) { | ||
736 | msg_set_orignode(m, tipc_own_addr); | ||
737 | msg_set_destnode(m, destnode); | ||
738 | } | ||
739 | } | ||
740 | |||
741 | /** | ||
742 | * msg_calc_data_size - determine total data size for message | ||
743 | */ | ||
744 | |||
745 | static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) | ||
746 | { | ||
747 | int dsz = 0; | ||
748 | int i; | ||
749 | |||
750 | for (i = 0; i < num_sect; i++) | ||
751 | dsz += msg_sect[i].iov_len; | ||
752 | return dsz; | ||
753 | } | ||
754 | |||
755 | /** | ||
756 | * msg_build - create message using specified header and data | ||
757 | * | ||
758 | * Note: Caller must not hold any locks in case copy_from_user() is interrupted! | ||
759 | * | ||
760 | * Returns message data size or errno | ||
761 | */ | ||
762 | |||
763 | static inline int msg_build(struct tipc_msg *hdr, | ||
764 | struct iovec const *msg_sect, u32 num_sect, | 716 | struct iovec const *msg_sect, u32 num_sect, |
765 | int max_size, int usrmem, struct sk_buff** buf) | 717 | int max_size, int usrmem, struct sk_buff** buf); |
766 | { | ||
767 | int dsz, sz, hsz, pos, res, cnt; | ||
768 | |||
769 | dsz = msg_calc_data_size(msg_sect, num_sect); | ||
770 | if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { | ||
771 | *buf = NULL; | ||
772 | return -EINVAL; | ||
773 | } | ||
774 | |||
775 | pos = hsz = msg_hdr_sz(hdr); | ||
776 | sz = hsz + dsz; | ||
777 | msg_set_size(hdr, sz); | ||
778 | if (unlikely(sz > max_size)) { | ||
779 | *buf = NULL; | ||
780 | return dsz; | ||
781 | } | ||
782 | |||
783 | *buf = buf_acquire(sz); | ||
784 | if (!(*buf)) | ||
785 | return -ENOMEM; | ||
786 | skb_copy_to_linear_data(*buf, hdr, hsz); | ||
787 | for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { | ||
788 | if (likely(usrmem)) | ||
789 | res = !copy_from_user((*buf)->data + pos, | ||
790 | msg_sect[cnt].iov_base, | ||
791 | msg_sect[cnt].iov_len); | ||
792 | else | ||
793 | skb_copy_to_linear_data_offset(*buf, pos, | ||
794 | msg_sect[cnt].iov_base, | ||
795 | msg_sect[cnt].iov_len); | ||
796 | pos += msg_sect[cnt].iov_len; | ||
797 | } | ||
798 | if (likely(res)) | ||
799 | return dsz; | ||
800 | |||
801 | buf_discard(*buf); | ||
802 | *buf = NULL; | ||
803 | return -EFAULT; | ||
804 | } | ||
805 | 718 | ||
806 | static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) | 719 | static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) |
807 | { | 720 | { |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 10a69894e2fd..6ac3c543250b 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -103,7 +103,7 @@ static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) | |||
103 | 103 | ||
104 | if (buf != NULL) { | 104 | if (buf != NULL) { |
105 | msg = buf_msg(buf); | 105 | msg = buf_msg(buf); |
106 | msg_init(msg, NAME_DISTRIBUTOR, type, LONG_H_SIZE, dest); | 106 | tipc_msg_init(msg, NAME_DISTRIBUTOR, type, LONG_H_SIZE, dest); |
107 | msg_set_size(msg, LONG_H_SIZE + size); | 107 | msg_set_size(msg, LONG_H_SIZE + size); |
108 | } | 108 | } |
109 | return buf; | 109 | return buf; |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index acab41a48d67..8ba79620db3f 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -627,7 +627,7 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode) | |||
627 | struct name_seq *seq; | 627 | struct name_seq *seq; |
628 | u32 ref; | 628 | u32 ref; |
629 | 629 | ||
630 | if (!in_scope(*destnode, tipc_own_addr)) | 630 | if (!tipc_in_scope(*destnode, tipc_own_addr)) |
631 | return 0; | 631 | return 0; |
632 | 632 | ||
633 | read_lock_bh(&tipc_nametbl_lock); | 633 | read_lock_bh(&tipc_nametbl_lock); |
diff --git a/net/tipc/net.c b/net/tipc/net.c index f25b1cdb64eb..f61b7694138b 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -116,7 +116,7 @@ | |||
116 | */ | 116 | */ |
117 | 117 | ||
118 | DEFINE_RWLOCK(tipc_net_lock); | 118 | DEFINE_RWLOCK(tipc_net_lock); |
119 | struct _zone *tipc_zones[256] = { NULL, }; | 119 | static struct _zone *tipc_zones[256] = { NULL, }; |
120 | struct network tipc_net = { tipc_zones }; | 120 | struct network tipc_net = { tipc_zones }; |
121 | 121 | ||
122 | struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref) | 122 | struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref) |
@@ -219,7 +219,7 @@ void tipc_net_route_msg(struct sk_buff *buf) | |||
219 | 219 | ||
220 | /* Handle message for this node */ | 220 | /* Handle message for this node */ |
221 | dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); | 221 | dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); |
222 | if (in_scope(dnode, tipc_own_addr)) { | 222 | if (tipc_in_scope(dnode, tipc_own_addr)) { |
223 | if (msg_isdata(msg)) { | 223 | if (msg_isdata(msg)) { |
224 | if (msg_mcast(msg)) | 224 | if (msg_mcast(msg)) |
225 | tipc_port_recv_mcast(buf, NULL); | 225 | tipc_port_recv_mcast(buf, NULL); |
@@ -277,7 +277,7 @@ int tipc_net_start(u32 addr) | |||
277 | 277 | ||
278 | info("Started in network mode\n"); | 278 | info("Started in network mode\n"); |
279 | info("Own node address %s, network identity %u\n", | 279 | info("Own node address %s, network identity %u\n", |
280 | addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); | 280 | tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); |
281 | return 0; | 281 | return 0; |
282 | } | 282 | } |
283 | 283 | ||
@@ -291,6 +291,6 @@ void tipc_net_stop(void) | |||
291 | tipc_bclink_stop(); | 291 | tipc_bclink_stop(); |
292 | net_stop(); | 292 | net_stop(); |
293 | write_unlock_bh(&tipc_net_lock); | 293 | write_unlock_bh(&tipc_net_lock); |
294 | info("Left network mode \n"); | 294 | info("Left network mode\n"); |
295 | } | 295 | } |
296 | 296 | ||
diff --git a/net/tipc/node.c b/net/tipc/node.c index 2c24e7d6d950..b634942caba5 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -268,7 +268,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | |||
268 | 268 | ||
269 | if (n_ptr->link_cnt >= 2) { | 269 | if (n_ptr->link_cnt >= 2) { |
270 | err("Attempt to create third link to %s\n", | 270 | err("Attempt to create third link to %s\n", |
271 | addr_string_fill(addr_string, n_ptr->addr)); | 271 | tipc_addr_string_fill(addr_string, n_ptr->addr)); |
272 | return NULL; | 272 | return NULL; |
273 | } | 273 | } |
274 | 274 | ||
@@ -278,9 +278,9 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | |||
278 | n_ptr->link_cnt++; | 278 | n_ptr->link_cnt++; |
279 | return n_ptr; | 279 | return n_ptr; |
280 | } | 280 | } |
281 | err("Attempt to establish second link on <%s> to %s \n", | 281 | err("Attempt to establish second link on <%s> to %s\n", |
282 | l_ptr->b_ptr->publ.name, | 282 | l_ptr->b_ptr->publ.name, |
283 | addr_string_fill(addr_string, l_ptr->addr)); | 283 | tipc_addr_string_fill(addr_string, l_ptr->addr)); |
284 | } | 284 | } |
285 | return NULL; | 285 | return NULL; |
286 | } | 286 | } |
@@ -439,7 +439,7 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
439 | return; | 439 | return; |
440 | 440 | ||
441 | info("Lost contact with %s\n", | 441 | info("Lost contact with %s\n", |
442 | addr_string_fill(addr_string, n_ptr->addr)); | 442 | tipc_addr_string_fill(addr_string, n_ptr->addr)); |
443 | 443 | ||
444 | /* Abort link changeover */ | 444 | /* Abort link changeover */ |
445 | for (i = 0; i < MAX_BEARERS; i++) { | 445 | for (i = 0; i < MAX_BEARERS; i++) { |
@@ -602,7 +602,7 @@ u32 tipc_available_nodes(const u32 domain) | |||
602 | 602 | ||
603 | read_lock_bh(&tipc_net_lock); | 603 | read_lock_bh(&tipc_net_lock); |
604 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 604 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { |
605 | if (!in_scope(domain, n_ptr->addr)) | 605 | if (!tipc_in_scope(domain, n_ptr->addr)) |
606 | continue; | 606 | continue; |
607 | if (tipc_node_is_up(n_ptr)) | 607 | if (tipc_node_is_up(n_ptr)) |
608 | cnt++; | 608 | cnt++; |
@@ -651,7 +651,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
651 | /* Add TLVs for all nodes in scope */ | 651 | /* Add TLVs for all nodes in scope */ |
652 | 652 | ||
653 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 653 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { |
654 | if (!in_scope(domain, n_ptr->addr)) | 654 | if (!tipc_in_scope(domain, n_ptr->addr)) |
655 | continue; | 655 | continue; |
656 | node_info.addr = htonl(n_ptr->addr); | 656 | node_info.addr = htonl(n_ptr->addr); |
657 | node_info.up = htonl(tipc_node_is_up(n_ptr)); | 657 | node_info.up = htonl(tipc_node_is_up(n_ptr)); |
@@ -711,7 +711,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
711 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 711 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { |
712 | u32 i; | 712 | u32 i; |
713 | 713 | ||
714 | if (!in_scope(domain, n_ptr->addr)) | 714 | if (!tipc_in_scope(domain, n_ptr->addr)) |
715 | continue; | 715 | continue; |
716 | tipc_node_lock(n_ptr); | 716 | tipc_node_lock(n_ptr); |
717 | for (i = 0; i < MAX_BEARERS; i++) { | 717 | for (i = 0; i < MAX_BEARERS; i++) { |
diff --git a/net/tipc/port.c b/net/tipc/port.c index e70d27ea6578..0737680e9266 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -116,7 +116,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, | |||
116 | msg_set_namelower(hdr, seq->lower); | 116 | msg_set_namelower(hdr, seq->lower); |
117 | msg_set_nameupper(hdr, seq->upper); | 117 | msg_set_nameupper(hdr, seq->upper); |
118 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); | 118 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); |
119 | res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | 119 | res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, |
120 | !oport->user_port, &buf); | 120 | !oport->user_port, &buf); |
121 | if (unlikely(!buf)) | 121 | if (unlikely(!buf)) |
122 | return res; | 122 | return res; |
@@ -241,13 +241,12 @@ struct tipc_port *tipc_createport_raw(void *usr_handle, | |||
241 | p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; | 241 | p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; |
242 | p_ptr->publ.ref = ref; | 242 | p_ptr->publ.ref = ref; |
243 | msg = &p_ptr->publ.phdr; | 243 | msg = &p_ptr->publ.phdr; |
244 | msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0); | 244 | tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0); |
245 | msg_set_origport(msg, ref); | 245 | msg_set_origport(msg, ref); |
246 | p_ptr->last_in_seqno = 41; | 246 | p_ptr->last_in_seqno = 41; |
247 | p_ptr->sent = 1; | 247 | p_ptr->sent = 1; |
248 | INIT_LIST_HEAD(&p_ptr->wait_list); | 248 | INIT_LIST_HEAD(&p_ptr->wait_list); |
249 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); | 249 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); |
250 | p_ptr->congested_link = NULL; | ||
251 | p_ptr->dispatcher = dispatcher; | 250 | p_ptr->dispatcher = dispatcher; |
252 | p_ptr->wakeup = wakeup; | 251 | p_ptr->wakeup = wakeup; |
253 | p_ptr->user_port = NULL; | 252 | p_ptr->user_port = NULL; |
@@ -396,7 +395,7 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, | |||
396 | buf = buf_acquire(LONG_H_SIZE); | 395 | buf = buf_acquire(LONG_H_SIZE); |
397 | if (buf) { | 396 | if (buf) { |
398 | msg = buf_msg(buf); | 397 | msg = buf_msg(buf); |
399 | msg_init(msg, usr, type, LONG_H_SIZE, destnode); | 398 | tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode); |
400 | msg_set_errcode(msg, err); | 399 | msg_set_errcode(msg, err); |
401 | msg_set_destport(msg, destport); | 400 | msg_set_destport(msg, destport); |
402 | msg_set_origport(msg, origport); | 401 | msg_set_origport(msg, origport); |
@@ -440,7 +439,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) | |||
440 | return data_sz; | 439 | return data_sz; |
441 | } | 440 | } |
442 | rmsg = buf_msg(rbuf); | 441 | rmsg = buf_msg(rbuf); |
443 | msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg)); | 442 | tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg)); |
444 | msg_set_errcode(rmsg, err); | 443 | msg_set_errcode(rmsg, err); |
445 | msg_set_destport(rmsg, msg_origport(msg)); | 444 | msg_set_destport(rmsg, msg_origport(msg)); |
446 | msg_set_origport(rmsg, msg_destport(msg)); | 445 | msg_set_origport(rmsg, msg_destport(msg)); |
@@ -481,7 +480,7 @@ int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, | |||
481 | struct sk_buff *buf; | 480 | struct sk_buff *buf; |
482 | int res; | 481 | int res; |
483 | 482 | ||
484 | res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | 483 | res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, |
485 | !p_ptr->user_port, &buf); | 484 | !p_ptr->user_port, &buf); |
486 | if (!buf) | 485 | if (!buf) |
487 | return res; | 486 | return res; |
@@ -1344,7 +1343,7 @@ int tipc_port_recv_sections(struct port *sender, unsigned int num_sect, | |||
1344 | struct sk_buff *buf; | 1343 | struct sk_buff *buf; |
1345 | int res; | 1344 | int res; |
1346 | 1345 | ||
1347 | res = msg_build(&sender->publ.phdr, msg_sect, num_sect, | 1346 | res = tipc_msg_build(&sender->publ.phdr, msg_sect, num_sect, |
1348 | MAX_MSG_SIZE, !sender->user_port, &buf); | 1347 | MAX_MSG_SIZE, !sender->user_port, &buf); |
1349 | if (likely(buf)) | 1348 | if (likely(buf)) |
1350 | tipc_port_recv_msg(buf); | 1349 | tipc_port_recv_msg(buf); |
@@ -1384,7 +1383,7 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) | |||
1384 | if (port_unreliable(p_ptr)) { | 1383 | if (port_unreliable(p_ptr)) { |
1385 | p_ptr->publ.congested = 0; | 1384 | p_ptr->publ.congested = 0; |
1386 | /* Just calculate msg length and return */ | 1385 | /* Just calculate msg length and return */ |
1387 | return msg_calc_data_size(msg_sect, num_sect); | 1386 | return tipc_msg_calc_data_size(msg_sect, num_sect); |
1388 | } | 1387 | } |
1389 | return -ELINKCONG; | 1388 | return -ELINKCONG; |
1390 | } | 1389 | } |
@@ -1453,7 +1452,7 @@ int tipc_forward2name(u32 ref, | |||
1453 | struct port *p_ptr; | 1452 | struct port *p_ptr; |
1454 | struct tipc_msg *msg; | 1453 | struct tipc_msg *msg; |
1455 | u32 destnode = domain; | 1454 | u32 destnode = domain; |
1456 | u32 destport = 0; | 1455 | u32 destport; |
1457 | int res; | 1456 | int res; |
1458 | 1457 | ||
1459 | p_ptr = tipc_port_deref(ref); | 1458 | p_ptr = tipc_port_deref(ref); |
@@ -1467,7 +1466,7 @@ int tipc_forward2name(u32 ref, | |||
1467 | msg_set_hdr_sz(msg, LONG_H_SIZE); | 1466 | msg_set_hdr_sz(msg, LONG_H_SIZE); |
1468 | msg_set_nametype(msg, name->type); | 1467 | msg_set_nametype(msg, name->type); |
1469 | msg_set_nameinst(msg, name->instance); | 1468 | msg_set_nameinst(msg, name->instance); |
1470 | msg_set_lookup_scope(msg, addr_scope(domain)); | 1469 | msg_set_lookup_scope(msg, tipc_addr_scope(domain)); |
1471 | if (importance <= TIPC_CRITICAL_IMPORTANCE) | 1470 | if (importance <= TIPC_CRITICAL_IMPORTANCE) |
1472 | msg_set_importance(msg,importance); | 1471 | msg_set_importance(msg,importance); |
1473 | destport = tipc_nametbl_translate(name->type, name->instance, &destnode); | 1472 | destport = tipc_nametbl_translate(name->type, name->instance, &destnode); |
@@ -1484,7 +1483,7 @@ int tipc_forward2name(u32 ref, | |||
1484 | return res; | 1483 | return res; |
1485 | if (port_unreliable(p_ptr)) { | 1484 | if (port_unreliable(p_ptr)) { |
1486 | /* Just calculate msg length and return */ | 1485 | /* Just calculate msg length and return */ |
1487 | return msg_calc_data_size(msg_sect, num_sect); | 1486 | return tipc_msg_calc_data_size(msg_sect, num_sect); |
1488 | } | 1487 | } |
1489 | return -ELINKCONG; | 1488 | return -ELINKCONG; |
1490 | } | 1489 | } |
@@ -1525,7 +1524,7 @@ int tipc_forward_buf2name(u32 ref, | |||
1525 | struct port *p_ptr; | 1524 | struct port *p_ptr; |
1526 | struct tipc_msg *msg; | 1525 | struct tipc_msg *msg; |
1527 | u32 destnode = domain; | 1526 | u32 destnode = domain; |
1528 | u32 destport = 0; | 1527 | u32 destport; |
1529 | int res; | 1528 | int res; |
1530 | 1529 | ||
1531 | p_ptr = (struct port *)tipc_ref_deref(ref); | 1530 | p_ptr = (struct port *)tipc_ref_deref(ref); |
@@ -1540,7 +1539,7 @@ int tipc_forward_buf2name(u32 ref, | |||
1540 | msg_set_origport(msg, orig->ref); | 1539 | msg_set_origport(msg, orig->ref); |
1541 | msg_set_nametype(msg, name->type); | 1540 | msg_set_nametype(msg, name->type); |
1542 | msg_set_nameinst(msg, name->instance); | 1541 | msg_set_nameinst(msg, name->instance); |
1543 | msg_set_lookup_scope(msg, addr_scope(domain)); | 1542 | msg_set_lookup_scope(msg, tipc_addr_scope(domain)); |
1544 | msg_set_hdr_sz(msg, LONG_H_SIZE); | 1543 | msg_set_hdr_sz(msg, LONG_H_SIZE); |
1545 | msg_set_size(msg, LONG_H_SIZE + dsz); | 1544 | msg_set_size(msg, LONG_H_SIZE + dsz); |
1546 | destport = tipc_nametbl_translate(name->type, name->instance, &destnode); | 1545 | destport = tipc_nametbl_translate(name->type, name->instance, &destnode); |
@@ -1620,7 +1619,7 @@ int tipc_forward2port(u32 ref, | |||
1620 | return res; | 1619 | return res; |
1621 | if (port_unreliable(p_ptr)) { | 1620 | if (port_unreliable(p_ptr)) { |
1622 | /* Just calculate msg length and return */ | 1621 | /* Just calculate msg length and return */ |
1623 | return msg_calc_data_size(msg_sect, num_sect); | 1622 | return tipc_msg_calc_data_size(msg_sect, num_sect); |
1624 | } | 1623 | } |
1625 | return -ELINKCONG; | 1624 | return -ELINKCONG; |
1626 | } | 1625 | } |
diff --git a/net/tipc/port.h b/net/tipc/port.h index ff31ee4a1dc3..8d1652aab298 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h | |||
@@ -75,7 +75,6 @@ struct user_port { | |||
75 | * @wakeup: ptr to routine to call when port is no longer congested | 75 | * @wakeup: ptr to routine to call when port is no longer congested |
76 | * @user_port: ptr to user port associated with port (if any) | 76 | * @user_port: ptr to user port associated with port (if any) |
77 | * @wait_list: adjacent ports in list of ports waiting on link congestion | 77 | * @wait_list: adjacent ports in list of ports waiting on link congestion |
78 | * @congested_link: ptr to congested link port is waiting on | ||
79 | * @waiting_pkts: | 78 | * @waiting_pkts: |
80 | * @sent: | 79 | * @sent: |
81 | * @acked: | 80 | * @acked: |
@@ -95,7 +94,6 @@ struct port { | |||
95 | void (*wakeup)(struct tipc_port *); | 94 | void (*wakeup)(struct tipc_port *); |
96 | struct user_port *user_port; | 95 | struct user_port *user_port; |
97 | struct list_head wait_list; | 96 | struct list_head wait_list; |
98 | struct link *congested_link; | ||
99 | u32 waiting_pkts; | 97 | u32 waiting_pkts; |
100 | u32 sent; | 98 | u32 sent; |
101 | u32 acked; | 99 | u32 acked; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index cfb20b80b3a1..66e889ba48fd 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -446,7 +446,7 @@ static unsigned int poll(struct file *file, struct socket *sock, | |||
446 | struct sock *sk = sock->sk; | 446 | struct sock *sk = sock->sk; |
447 | u32 mask; | 447 | u32 mask; |
448 | 448 | ||
449 | poll_wait(file, sk->sk_sleep, wait); | 449 | poll_wait(file, sk_sleep(sk), wait); |
450 | 450 | ||
451 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 451 | if (!skb_queue_empty(&sk->sk_receive_queue) || |
452 | (sock->state == SS_UNCONNECTED) || | 452 | (sock->state == SS_UNCONNECTED) || |
@@ -591,7 +591,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
591 | break; | 591 | break; |
592 | } | 592 | } |
593 | release_sock(sk); | 593 | release_sock(sk); |
594 | res = wait_event_interruptible(*sk->sk_sleep, | 594 | res = wait_event_interruptible(*sk_sleep(sk), |
595 | !tport->congested); | 595 | !tport->congested); |
596 | lock_sock(sk); | 596 | lock_sock(sk); |
597 | if (res) | 597 | if (res) |
@@ -650,7 +650,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
650 | break; | 650 | break; |
651 | } | 651 | } |
652 | release_sock(sk); | 652 | release_sock(sk); |
653 | res = wait_event_interruptible(*sk->sk_sleep, | 653 | res = wait_event_interruptible(*sk_sleep(sk), |
654 | (!tport->congested || !tport->connected)); | 654 | (!tport->congested || !tport->connected)); |
655 | lock_sock(sk); | 655 | lock_sock(sk); |
656 | if (res) | 656 | if (res) |
@@ -931,7 +931,7 @@ restart: | |||
931 | goto exit; | 931 | goto exit; |
932 | } | 932 | } |
933 | release_sock(sk); | 933 | release_sock(sk); |
934 | res = wait_event_interruptible(*sk->sk_sleep, | 934 | res = wait_event_interruptible(*sk_sleep(sk), |
935 | (!skb_queue_empty(&sk->sk_receive_queue) || | 935 | (!skb_queue_empty(&sk->sk_receive_queue) || |
936 | (sock->state == SS_DISCONNECTING))); | 936 | (sock->state == SS_DISCONNECTING))); |
937 | lock_sock(sk); | 937 | lock_sock(sk); |
@@ -1064,7 +1064,7 @@ restart: | |||
1064 | goto exit; | 1064 | goto exit; |
1065 | } | 1065 | } |
1066 | release_sock(sk); | 1066 | release_sock(sk); |
1067 | res = wait_event_interruptible(*sk->sk_sleep, | 1067 | res = wait_event_interruptible(*sk_sleep(sk), |
1068 | (!skb_queue_empty(&sk->sk_receive_queue) || | 1068 | (!skb_queue_empty(&sk->sk_receive_queue) || |
1069 | (sock->state == SS_DISCONNECTING))); | 1069 | (sock->state == SS_DISCONNECTING))); |
1070 | lock_sock(sk); | 1070 | lock_sock(sk); |
@@ -1271,8 +1271,8 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
1271 | tipc_disconnect_port(tipc_sk_port(sk)); | 1271 | tipc_disconnect_port(tipc_sk_port(sk)); |
1272 | } | 1272 | } |
1273 | 1273 | ||
1274 | if (waitqueue_active(sk->sk_sleep)) | 1274 | if (waitqueue_active(sk_sleep(sk))) |
1275 | wake_up_interruptible(sk->sk_sleep); | 1275 | wake_up_interruptible(sk_sleep(sk)); |
1276 | return TIPC_OK; | 1276 | return TIPC_OK; |
1277 | } | 1277 | } |
1278 | 1278 | ||
@@ -1343,8 +1343,8 @@ static void wakeupdispatch(struct tipc_port *tport) | |||
1343 | { | 1343 | { |
1344 | struct sock *sk = (struct sock *)tport->usr_handle; | 1344 | struct sock *sk = (struct sock *)tport->usr_handle; |
1345 | 1345 | ||
1346 | if (waitqueue_active(sk->sk_sleep)) | 1346 | if (waitqueue_active(sk_sleep(sk))) |
1347 | wake_up_interruptible(sk->sk_sleep); | 1347 | wake_up_interruptible(sk_sleep(sk)); |
1348 | } | 1348 | } |
1349 | 1349 | ||
1350 | /** | 1350 | /** |
@@ -1426,7 +1426,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1426 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ | 1426 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ |
1427 | 1427 | ||
1428 | release_sock(sk); | 1428 | release_sock(sk); |
1429 | res = wait_event_interruptible_timeout(*sk->sk_sleep, | 1429 | res = wait_event_interruptible_timeout(*sk_sleep(sk), |
1430 | (!skb_queue_empty(&sk->sk_receive_queue) || | 1430 | (!skb_queue_empty(&sk->sk_receive_queue) || |
1431 | (sock->state != SS_CONNECTING)), | 1431 | (sock->state != SS_CONNECTING)), |
1432 | sk->sk_rcvtimeo); | 1432 | sk->sk_rcvtimeo); |
@@ -1521,7 +1521,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
1521 | goto exit; | 1521 | goto exit; |
1522 | } | 1522 | } |
1523 | release_sock(sk); | 1523 | release_sock(sk); |
1524 | res = wait_event_interruptible(*sk->sk_sleep, | 1524 | res = wait_event_interruptible(*sk_sleep(sk), |
1525 | (!skb_queue_empty(&sk->sk_receive_queue))); | 1525 | (!skb_queue_empty(&sk->sk_receive_queue))); |
1526 | lock_sock(sk); | 1526 | lock_sock(sk); |
1527 | if (res) | 1527 | if (res) |
@@ -1632,8 +1632,8 @@ restart: | |||
1632 | /* Discard any unreceived messages; wake up sleeping tasks */ | 1632 | /* Discard any unreceived messages; wake up sleeping tasks */ |
1633 | 1633 | ||
1634 | discard_rx_queue(sk); | 1634 | discard_rx_queue(sk); |
1635 | if (waitqueue_active(sk->sk_sleep)) | 1635 | if (waitqueue_active(sk_sleep(sk))) |
1636 | wake_up_interruptible(sk->sk_sleep); | 1636 | wake_up_interruptible(sk_sleep(sk)); |
1637 | res = 0; | 1637 | res = 0; |
1638 | break; | 1638 | break; |
1639 | 1639 | ||
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index ff123e56114a..ab6eab4c45e2 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -274,7 +274,7 @@ static void subscr_cancel(struct tipc_subscr *s, | |||
274 | { | 274 | { |
275 | struct subscription *sub; | 275 | struct subscription *sub; |
276 | struct subscription *sub_temp; | 276 | struct subscription *sub_temp; |
277 | __u32 type, lower, upper; | 277 | __u32 type, lower, upper, timeout, filter; |
278 | int found = 0; | 278 | int found = 0; |
279 | 279 | ||
280 | /* Find first matching subscription, exit if not found */ | 280 | /* Find first matching subscription, exit if not found */ |
@@ -282,12 +282,18 @@ static void subscr_cancel(struct tipc_subscr *s, | |||
282 | type = ntohl(s->seq.type); | 282 | type = ntohl(s->seq.type); |
283 | lower = ntohl(s->seq.lower); | 283 | lower = ntohl(s->seq.lower); |
284 | upper = ntohl(s->seq.upper); | 284 | upper = ntohl(s->seq.upper); |
285 | timeout = ntohl(s->timeout); | ||
286 | filter = ntohl(s->filter) & ~TIPC_SUB_CANCEL; | ||
285 | 287 | ||
286 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 288 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, |
287 | subscription_list) { | 289 | subscription_list) { |
288 | if ((type == sub->seq.type) && | 290 | if ((type == sub->seq.type) && |
289 | (lower == sub->seq.lower) && | 291 | (lower == sub->seq.lower) && |
290 | (upper == sub->seq.upper)) { | 292 | (upper == sub->seq.upper) && |
293 | (timeout == sub->timeout) && | ||
294 | (filter == sub->filter) && | ||
295 | !memcmp(s->usr_handle,sub->evt.s.usr_handle, | ||
296 | sizeof(s->usr_handle)) ){ | ||
291 | found = 1; | 297 | found = 1; |
292 | break; | 298 | break; |
293 | } | 299 | } |
@@ -304,7 +310,7 @@ static void subscr_cancel(struct tipc_subscr *s, | |||
304 | k_term_timer(&sub->timer); | 310 | k_term_timer(&sub->timer); |
305 | spin_lock_bh(subscriber->lock); | 311 | spin_lock_bh(subscriber->lock); |
306 | } | 312 | } |
307 | dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n", | 313 | dbg("Cancel: removing sub %u,%u,%u from subscriber %p list\n", |
308 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); | 314 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); |
309 | subscr_del(sub); | 315 | subscr_del(sub); |
310 | } | 316 | } |
@@ -352,8 +358,7 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s, | |||
352 | sub->seq.upper = ntohl(s->seq.upper); | 358 | sub->seq.upper = ntohl(s->seq.upper); |
353 | sub->timeout = ntohl(s->timeout); | 359 | sub->timeout = ntohl(s->timeout); |
354 | sub->filter = ntohl(s->filter); | 360 | sub->filter = ntohl(s->filter); |
355 | if ((!(sub->filter & TIPC_SUB_PORTS) == | 361 | if ((sub->filter && (sub->filter != TIPC_SUB_PORTS)) || |
356 | !(sub->filter & TIPC_SUB_SERVICE)) || | ||
357 | (sub->seq.lower > sub->seq.upper)) { | 362 | (sub->seq.lower > sub->seq.upper)) { |
358 | warn("Subscription rejected, illegal request\n"); | 363 | warn("Subscription rejected, illegal request\n"); |
359 | kfree(sub); | 364 | kfree(sub); |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 3d9122e78f41..fef2cc5e9d2b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -313,13 +313,16 @@ static inline int unix_writable(struct sock *sk) | |||
313 | 313 | ||
314 | static void unix_write_space(struct sock *sk) | 314 | static void unix_write_space(struct sock *sk) |
315 | { | 315 | { |
316 | read_lock(&sk->sk_callback_lock); | 316 | struct socket_wq *wq; |
317 | |||
318 | rcu_read_lock(); | ||
317 | if (unix_writable(sk)) { | 319 | if (unix_writable(sk)) { |
318 | if (sk_has_sleeper(sk)) | 320 | wq = rcu_dereference(sk->sk_wq); |
319 | wake_up_interruptible_sync(sk->sk_sleep); | 321 | if (wq_has_sleeper(wq)) |
322 | wake_up_interruptible_sync(&wq->wait); | ||
320 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 323 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
321 | } | 324 | } |
322 | read_unlock(&sk->sk_callback_lock); | 325 | rcu_read_unlock(); |
323 | } | 326 | } |
324 | 327 | ||
325 | /* When dgram socket disconnects (or changes its peer), we clear its receive | 328 | /* When dgram socket disconnects (or changes its peer), we clear its receive |
@@ -406,9 +409,7 @@ static int unix_release_sock(struct sock *sk, int embrion) | |||
406 | skpair->sk_err = ECONNRESET; | 409 | skpair->sk_err = ECONNRESET; |
407 | unix_state_unlock(skpair); | 410 | unix_state_unlock(skpair); |
408 | skpair->sk_state_change(skpair); | 411 | skpair->sk_state_change(skpair); |
409 | read_lock(&skpair->sk_callback_lock); | ||
410 | sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); | 412 | sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); |
411 | read_unlock(&skpair->sk_callback_lock); | ||
412 | } | 413 | } |
413 | sock_put(skpair); /* It may now die */ | 414 | sock_put(skpair); /* It may now die */ |
414 | unix_peer(sk) = NULL; | 415 | unix_peer(sk) = NULL; |
@@ -1142,7 +1143,7 @@ restart: | |||
1142 | newsk->sk_peercred.pid = task_tgid_vnr(current); | 1143 | newsk->sk_peercred.pid = task_tgid_vnr(current); |
1143 | current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid); | 1144 | current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid); |
1144 | newu = unix_sk(newsk); | 1145 | newu = unix_sk(newsk); |
1145 | newsk->sk_sleep = &newu->peer_wait; | 1146 | newsk->sk_wq = &newu->peer_wq; |
1146 | otheru = unix_sk(other); | 1147 | otheru = unix_sk(other); |
1147 | 1148 | ||
1148 | /* copy address information from listening to new sock*/ | 1149 | /* copy address information from listening to new sock*/ |
@@ -1736,7 +1737,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
1736 | unix_state_lock(sk); | 1737 | unix_state_lock(sk); |
1737 | 1738 | ||
1738 | for (;;) { | 1739 | for (;;) { |
1739 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1740 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1740 | 1741 | ||
1741 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 1742 | if (!skb_queue_empty(&sk->sk_receive_queue) || |
1742 | sk->sk_err || | 1743 | sk->sk_err || |
@@ -1752,7 +1753,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
1752 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1753 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
1753 | } | 1754 | } |
1754 | 1755 | ||
1755 | finish_wait(sk->sk_sleep, &wait); | 1756 | finish_wait(sk_sleep(sk), &wait); |
1756 | unix_state_unlock(sk); | 1757 | unix_state_unlock(sk); |
1757 | return timeo; | 1758 | return timeo; |
1758 | } | 1759 | } |
@@ -1931,12 +1932,10 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
1931 | other->sk_shutdown |= peer_mode; | 1932 | other->sk_shutdown |= peer_mode; |
1932 | unix_state_unlock(other); | 1933 | unix_state_unlock(other); |
1933 | other->sk_state_change(other); | 1934 | other->sk_state_change(other); |
1934 | read_lock(&other->sk_callback_lock); | ||
1935 | if (peer_mode == SHUTDOWN_MASK) | 1935 | if (peer_mode == SHUTDOWN_MASK) |
1936 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); | 1936 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); |
1937 | else if (peer_mode & RCV_SHUTDOWN) | 1937 | else if (peer_mode & RCV_SHUTDOWN) |
1938 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); | 1938 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); |
1939 | read_unlock(&other->sk_callback_lock); | ||
1940 | } | 1939 | } |
1941 | if (other) | 1940 | if (other) |
1942 | sock_put(other); | 1941 | sock_put(other); |
@@ -1991,7 +1990,7 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table | |||
1991 | struct sock *sk = sock->sk; | 1990 | struct sock *sk = sock->sk; |
1992 | unsigned int mask; | 1991 | unsigned int mask; |
1993 | 1992 | ||
1994 | sock_poll_wait(file, sk->sk_sleep, wait); | 1993 | sock_poll_wait(file, sk_sleep(sk), wait); |
1995 | mask = 0; | 1994 | mask = 0; |
1996 | 1995 | ||
1997 | /* exceptional events? */ | 1996 | /* exceptional events? */ |
@@ -2028,7 +2027,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2028 | struct sock *sk = sock->sk, *other; | 2027 | struct sock *sk = sock->sk, *other; |
2029 | unsigned int mask, writable; | 2028 | unsigned int mask, writable; |
2030 | 2029 | ||
2031 | sock_poll_wait(file, sk->sk_sleep, wait); | 2030 | sock_poll_wait(file, sk_sleep(sk), wait); |
2032 | mask = 0; | 2031 | mask = 0; |
2033 | 2032 | ||
2034 | /* exceptional events? */ | 2033 | /* exceptional events? */ |
diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 14c22c3768da..c8df6fda0b1f 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c | |||
@@ -153,15 +153,6 @@ void unix_notinflight(struct file *fp) | |||
153 | } | 153 | } |
154 | } | 154 | } |
155 | 155 | ||
156 | static inline struct sk_buff *sock_queue_head(struct sock *sk) | ||
157 | { | ||
158 | return (struct sk_buff *)&sk->sk_receive_queue; | ||
159 | } | ||
160 | |||
161 | #define receive_queue_for_each_skb(sk, next, skb) \ | ||
162 | for (skb = sock_queue_head(sk)->next, next = skb->next; \ | ||
163 | skb != sock_queue_head(sk); skb = next, next = skb->next) | ||
164 | |||
165 | static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), | 156 | static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), |
166 | struct sk_buff_head *hitlist) | 157 | struct sk_buff_head *hitlist) |
167 | { | 158 | { |
@@ -169,7 +160,7 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), | |||
169 | struct sk_buff *next; | 160 | struct sk_buff *next; |
170 | 161 | ||
171 | spin_lock(&x->sk_receive_queue.lock); | 162 | spin_lock(&x->sk_receive_queue.lock); |
172 | receive_queue_for_each_skb(x, next, skb) { | 163 | skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { |
173 | /* | 164 | /* |
174 | * Do we have file descriptors ? | 165 | * Do we have file descriptors ? |
175 | */ | 166 | */ |
@@ -225,7 +216,7 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *), | |||
225 | * and perform a scan on them as well. | 216 | * and perform a scan on them as well. |
226 | */ | 217 | */ |
227 | spin_lock(&x->sk_receive_queue.lock); | 218 | spin_lock(&x->sk_receive_queue.lock); |
228 | receive_queue_for_each_skb(x, next, skb) { | 219 | skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { |
229 | u = unix_sk(skb->sk); | 220 | u = unix_sk(skb->sk); |
230 | 221 | ||
231 | /* | 222 | /* |
diff --git a/net/wimax/op-reset.c b/net/wimax/op-reset.c index 4dc82a54ba30..68bedf3e5443 100644 --- a/net/wimax/op-reset.c +++ b/net/wimax/op-reset.c | |||
@@ -110,7 +110,6 @@ int wimax_gnl_doit_reset(struct sk_buff *skb, struct genl_info *info) | |||
110 | { | 110 | { |
111 | int result, ifindex; | 111 | int result, ifindex; |
112 | struct wimax_dev *wimax_dev; | 112 | struct wimax_dev *wimax_dev; |
113 | struct device *dev; | ||
114 | 113 | ||
115 | d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); | 114 | d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); |
116 | result = -ENODEV; | 115 | result = -ENODEV; |
@@ -123,7 +122,6 @@ int wimax_gnl_doit_reset(struct sk_buff *skb, struct genl_info *info) | |||
123 | wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); | 122 | wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); |
124 | if (wimax_dev == NULL) | 123 | if (wimax_dev == NULL) |
125 | goto error_no_wimax_dev; | 124 | goto error_no_wimax_dev; |
126 | dev = wimax_dev_to_dev(wimax_dev); | ||
127 | /* Execute the operation and send the result back to user space */ | 125 | /* Execute the operation and send the result back to user space */ |
128 | result = wimax_reset(wimax_dev); | 126 | result = wimax_reset(wimax_dev); |
129 | dev_put(wimax_dev->net_dev); | 127 | dev_put(wimax_dev->net_dev); |
diff --git a/net/wimax/op-state-get.c b/net/wimax/op-state-get.c index 11ad3356eb56..aff8776e2d41 100644 --- a/net/wimax/op-state-get.c +++ b/net/wimax/op-state-get.c | |||
@@ -53,7 +53,6 @@ int wimax_gnl_doit_state_get(struct sk_buff *skb, struct genl_info *info) | |||
53 | { | 53 | { |
54 | int result, ifindex; | 54 | int result, ifindex; |
55 | struct wimax_dev *wimax_dev; | 55 | struct wimax_dev *wimax_dev; |
56 | struct device *dev; | ||
57 | 56 | ||
58 | d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); | 57 | d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); |
59 | result = -ENODEV; | 58 | result = -ENODEV; |
@@ -66,7 +65,6 @@ int wimax_gnl_doit_state_get(struct sk_buff *skb, struct genl_info *info) | |||
66 | wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); | 65 | wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); |
67 | if (wimax_dev == NULL) | 66 | if (wimax_dev == NULL) |
68 | goto error_no_wimax_dev; | 67 | goto error_no_wimax_dev; |
69 | dev = wimax_dev_to_dev(wimax_dev); | ||
70 | /* Execute the operation and send the result back to user space */ | 68 | /* Execute the operation and send the result back to user space */ |
71 | result = wimax_state_get(wimax_dev); | 69 | result = wimax_state_get(wimax_dev); |
72 | dev_put(wimax_dev->net_dev); | 70 | dev_put(wimax_dev->net_dev); |
diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 1ed65dbdab03..ee99e7dfcdba 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c | |||
@@ -315,12 +315,11 @@ void __wimax_state_change(struct wimax_dev *wimax_dev, enum wimax_st new_state) | |||
315 | BUG(); | 315 | BUG(); |
316 | } | 316 | } |
317 | __wimax_state_set(wimax_dev, new_state); | 317 | __wimax_state_set(wimax_dev, new_state); |
318 | if (stch_skb) | 318 | if (!IS_ERR(stch_skb)) |
319 | wimax_gnl_re_state_change_send(wimax_dev, stch_skb, header); | 319 | wimax_gnl_re_state_change_send(wimax_dev, stch_skb, header); |
320 | out: | 320 | out: |
321 | d_fnend(3, dev, "(wimax_dev %p new_state %u [old %u]) = void\n", | 321 | d_fnend(3, dev, "(wimax_dev %p new_state %u [old %u]) = void\n", |
322 | wimax_dev, new_state, old_state); | 322 | wimax_dev, new_state, old_state); |
323 | return; | ||
324 | } | 323 | } |
325 | 324 | ||
326 | 325 | ||
@@ -362,7 +361,6 @@ void wimax_state_change(struct wimax_dev *wimax_dev, enum wimax_st new_state) | |||
362 | if (wimax_dev->state > __WIMAX_ST_NULL) | 361 | if (wimax_dev->state > __WIMAX_ST_NULL) |
363 | __wimax_state_change(wimax_dev, new_state); | 362 | __wimax_state_change(wimax_dev, new_state); |
364 | mutex_unlock(&wimax_dev->mutex); | 363 | mutex_unlock(&wimax_dev->mutex); |
365 | return; | ||
366 | } | 364 | } |
367 | EXPORT_SYMBOL_GPL(wimax_state_change); | 365 | EXPORT_SYMBOL_GPL(wimax_state_change); |
368 | 366 | ||
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index bf1737fc9a7e..d92d088026bf 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -10,38 +10,6 @@ | |||
10 | #include "core.h" | 10 | #include "core.h" |
11 | 11 | ||
12 | struct ieee80211_channel * | 12 | struct ieee80211_channel * |
13 | rdev_fixed_channel(struct cfg80211_registered_device *rdev, | ||
14 | struct wireless_dev *for_wdev) | ||
15 | { | ||
16 | struct wireless_dev *wdev; | ||
17 | struct ieee80211_channel *result = NULL; | ||
18 | |||
19 | WARN_ON(!mutex_is_locked(&rdev->devlist_mtx)); | ||
20 | |||
21 | list_for_each_entry(wdev, &rdev->netdev_list, list) { | ||
22 | if (wdev == for_wdev) | ||
23 | continue; | ||
24 | |||
25 | /* | ||
26 | * Lock manually to tell lockdep about allowed | ||
27 | * nesting here if for_wdev->mtx is held already. | ||
28 | * This is ok as it's all under the rdev devlist | ||
29 | * mutex and as such can only be done once at any | ||
30 | * given time. | ||
31 | */ | ||
32 | mutex_lock_nested(&wdev->mtx, SINGLE_DEPTH_NESTING); | ||
33 | if (wdev->current_bss) | ||
34 | result = wdev->current_bss->pub.channel; | ||
35 | wdev_unlock(wdev); | ||
36 | |||
37 | if (result) | ||
38 | break; | ||
39 | } | ||
40 | |||
41 | return result; | ||
42 | } | ||
43 | |||
44 | struct ieee80211_channel * | ||
45 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | 13 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, |
46 | int freq, enum nl80211_channel_type channel_type) | 14 | int freq, enum nl80211_channel_type channel_type) |
47 | { | 15 | { |
@@ -75,15 +43,22 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | |||
75 | return chan; | 43 | return chan; |
76 | } | 44 | } |
77 | 45 | ||
78 | int rdev_set_freq(struct cfg80211_registered_device *rdev, | 46 | int cfg80211_set_freq(struct cfg80211_registered_device *rdev, |
79 | struct wireless_dev *for_wdev, | 47 | struct wireless_dev *wdev, int freq, |
80 | int freq, enum nl80211_channel_type channel_type) | 48 | enum nl80211_channel_type channel_type) |
81 | { | 49 | { |
82 | struct ieee80211_channel *chan; | 50 | struct ieee80211_channel *chan; |
83 | int result; | 51 | int result; |
84 | 52 | ||
85 | if (rdev_fixed_channel(rdev, for_wdev)) | 53 | if (wdev->iftype == NL80211_IFTYPE_MONITOR) |
86 | return -EBUSY; | 54 | wdev = NULL; |
55 | |||
56 | if (wdev) { | ||
57 | ASSERT_WDEV_LOCK(wdev); | ||
58 | |||
59 | if (!netif_running(wdev->netdev)) | ||
60 | return -ENETDOWN; | ||
61 | } | ||
87 | 62 | ||
88 | if (!rdev->ops->set_channel) | 63 | if (!rdev->ops->set_channel) |
89 | return -EOPNOTSUPP; | 64 | return -EOPNOTSUPP; |
@@ -92,11 +67,14 @@ int rdev_set_freq(struct cfg80211_registered_device *rdev, | |||
92 | if (!chan) | 67 | if (!chan) |
93 | return -EINVAL; | 68 | return -EINVAL; |
94 | 69 | ||
95 | result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type); | 70 | result = rdev->ops->set_channel(&rdev->wiphy, |
71 | wdev ? wdev->netdev : NULL, | ||
72 | chan, channel_type); | ||
96 | if (result) | 73 | if (result) |
97 | return result; | 74 | return result; |
98 | 75 | ||
99 | rdev->channel = chan; | 76 | if (wdev) |
77 | wdev->channel = chan; | ||
100 | 78 | ||
101 | return 0; | 79 | return 0; |
102 | } | 80 | } |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 6ac70c101523..37d0e0ab4432 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -705,7 +705,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
705 | wdev->ps = true; | 705 | wdev->ps = true; |
706 | else | 706 | else |
707 | wdev->ps = false; | 707 | wdev->ps = false; |
708 | wdev->ps_timeout = 100; | 708 | /* allow mac80211 to determine the timeout */ |
709 | wdev->ps_timeout = -1; | ||
709 | if (rdev->ops->set_power_mgmt) | 710 | if (rdev->ops->set_power_mgmt) |
710 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, | 711 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, |
711 | wdev->ps, | 712 | wdev->ps, |
diff --git a/net/wireless/core.h b/net/wireless/core.h index d52da913145a..ae930acf75e9 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -70,9 +70,6 @@ struct cfg80211_registered_device { | |||
70 | struct work_struct conn_work; | 70 | struct work_struct conn_work; |
71 | struct work_struct event_work; | 71 | struct work_struct event_work; |
72 | 72 | ||
73 | /* current channel */ | ||
74 | struct ieee80211_channel *channel; | ||
75 | |||
76 | /* must be last because of the way we do wiphy_priv(), | 73 | /* must be last because of the way we do wiphy_priv(), |
77 | * and it should at least be aligned to NETDEV_ALIGN */ | 74 | * and it should at least be aligned to NETDEV_ALIGN */ |
78 | struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); | 75 | struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); |
@@ -293,13 +290,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
293 | const u8 *bssid, | 290 | const u8 *bssid, |
294 | const u8 *ssid, int ssid_len, | 291 | const u8 *ssid, int ssid_len, |
295 | const u8 *ie, int ie_len, | 292 | const u8 *ie, int ie_len, |
296 | const u8 *key, int key_len, int key_idx); | 293 | const u8 *key, int key_len, int key_idx, |
294 | bool local_state_change); | ||
297 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 295 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
298 | struct net_device *dev, struct ieee80211_channel *chan, | 296 | struct net_device *dev, struct ieee80211_channel *chan, |
299 | enum nl80211_auth_type auth_type, const u8 *bssid, | 297 | enum nl80211_auth_type auth_type, const u8 *bssid, |
300 | const u8 *ssid, int ssid_len, | 298 | const u8 *ssid, int ssid_len, |
301 | const u8 *ie, int ie_len, | 299 | const u8 *ie, int ie_len, |
302 | const u8 *key, int key_len, int key_idx); | 300 | const u8 *key, int key_len, int key_idx, |
301 | bool local_state_change); | ||
303 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 302 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
304 | struct net_device *dev, | 303 | struct net_device *dev, |
305 | struct ieee80211_channel *chan, | 304 | struct ieee80211_channel *chan, |
@@ -315,13 +314,16 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
315 | struct cfg80211_crypto_settings *crypt); | 314 | struct cfg80211_crypto_settings *crypt); |
316 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 315 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
317 | struct net_device *dev, const u8 *bssid, | 316 | struct net_device *dev, const u8 *bssid, |
318 | const u8 *ie, int ie_len, u16 reason); | 317 | const u8 *ie, int ie_len, u16 reason, |
318 | bool local_state_change); | ||
319 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 319 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
320 | struct net_device *dev, const u8 *bssid, | 320 | struct net_device *dev, const u8 *bssid, |
321 | const u8 *ie, int ie_len, u16 reason); | 321 | const u8 *ie, int ie_len, u16 reason, |
322 | bool local_state_change); | ||
322 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 323 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
323 | struct net_device *dev, const u8 *bssid, | 324 | struct net_device *dev, const u8 *bssid, |
324 | const u8 *ie, int ie_len, u16 reason); | 325 | const u8 *ie, int ie_len, u16 reason, |
326 | bool local_state_change); | ||
325 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | 327 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, |
326 | struct net_device *dev); | 328 | struct net_device *dev); |
327 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 329 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
@@ -383,14 +385,11 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
383 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); | 385 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); |
384 | 386 | ||
385 | struct ieee80211_channel * | 387 | struct ieee80211_channel * |
386 | rdev_fixed_channel(struct cfg80211_registered_device *rdev, | ||
387 | struct wireless_dev *for_wdev); | ||
388 | struct ieee80211_channel * | ||
389 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | 388 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, |
390 | int freq, enum nl80211_channel_type channel_type); | 389 | int freq, enum nl80211_channel_type channel_type); |
391 | int rdev_set_freq(struct cfg80211_registered_device *rdev, | 390 | int cfg80211_set_freq(struct cfg80211_registered_device *rdev, |
392 | struct wireless_dev *for_wdev, | 391 | struct wireless_dev *wdev, int freq, |
393 | int freq, enum nl80211_channel_type channel_type); | 392 | enum nl80211_channel_type channel_type); |
394 | 393 | ||
395 | u16 cfg80211_calculate_bitrate(struct rate_info *rate); | 394 | u16 cfg80211_calculate_bitrate(struct rate_info *rate); |
396 | 395 | ||
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 6a5acf750174..adcabba02e20 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -81,15 +81,10 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
81 | struct cfg80211_cached_keys *connkeys) | 81 | struct cfg80211_cached_keys *connkeys) |
82 | { | 82 | { |
83 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 83 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
84 | struct ieee80211_channel *chan; | ||
85 | int err; | 84 | int err; |
86 | 85 | ||
87 | ASSERT_WDEV_LOCK(wdev); | 86 | ASSERT_WDEV_LOCK(wdev); |
88 | 87 | ||
89 | chan = rdev_fixed_channel(rdev, wdev); | ||
90 | if (chan && chan != params->channel) | ||
91 | return -EBUSY; | ||
92 | |||
93 | if (wdev->ssid_len) | 88 | if (wdev->ssid_len) |
94 | return -EALREADY; | 89 | return -EALREADY; |
95 | 90 | ||
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 22139fa46115..48ead6f0426d 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -378,7 +378,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
378 | const u8 *bssid, | 378 | const u8 *bssid, |
379 | const u8 *ssid, int ssid_len, | 379 | const u8 *ssid, int ssid_len, |
380 | const u8 *ie, int ie_len, | 380 | const u8 *ie, int ie_len, |
381 | const u8 *key, int key_len, int key_idx) | 381 | const u8 *key, int key_len, int key_idx, |
382 | bool local_state_change) | ||
382 | { | 383 | { |
383 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 384 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
384 | struct cfg80211_auth_request req; | 385 | struct cfg80211_auth_request req; |
@@ -408,6 +409,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
408 | 409 | ||
409 | memset(&req, 0, sizeof(req)); | 410 | memset(&req, 0, sizeof(req)); |
410 | 411 | ||
412 | req.local_state_change = local_state_change; | ||
411 | req.ie = ie; | 413 | req.ie = ie; |
412 | req.ie_len = ie_len; | 414 | req.ie_len = ie_len; |
413 | req.auth_type = auth_type; | 415 | req.auth_type = auth_type; |
@@ -434,12 +436,18 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
434 | goto out; | 436 | goto out; |
435 | } | 437 | } |
436 | 438 | ||
437 | wdev->authtry_bsses[slot] = bss; | 439 | if (local_state_change) |
440 | wdev->auth_bsses[slot] = bss; | ||
441 | else | ||
442 | wdev->authtry_bsses[slot] = bss; | ||
438 | cfg80211_hold_bss(bss); | 443 | cfg80211_hold_bss(bss); |
439 | 444 | ||
440 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); | 445 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); |
441 | if (err) { | 446 | if (err) { |
442 | wdev->authtry_bsses[slot] = NULL; | 447 | if (local_state_change) |
448 | wdev->auth_bsses[slot] = NULL; | ||
449 | else | ||
450 | wdev->authtry_bsses[slot] = NULL; | ||
443 | cfg80211_unhold_bss(bss); | 451 | cfg80211_unhold_bss(bss); |
444 | } | 452 | } |
445 | 453 | ||
@@ -454,14 +462,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
454 | enum nl80211_auth_type auth_type, const u8 *bssid, | 462 | enum nl80211_auth_type auth_type, const u8 *bssid, |
455 | const u8 *ssid, int ssid_len, | 463 | const u8 *ssid, int ssid_len, |
456 | const u8 *ie, int ie_len, | 464 | const u8 *ie, int ie_len, |
457 | const u8 *key, int key_len, int key_idx) | 465 | const u8 *key, int key_len, int key_idx, |
466 | bool local_state_change) | ||
458 | { | 467 | { |
459 | int err; | 468 | int err; |
460 | 469 | ||
461 | wdev_lock(dev->ieee80211_ptr); | 470 | wdev_lock(dev->ieee80211_ptr); |
462 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 471 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
463 | ssid, ssid_len, ie, ie_len, | 472 | ssid, ssid_len, ie, ie_len, |
464 | key, key_len, key_idx); | 473 | key, key_len, key_idx, local_state_change); |
465 | wdev_unlock(dev->ieee80211_ptr); | 474 | wdev_unlock(dev->ieee80211_ptr); |
466 | 475 | ||
467 | return err; | 476 | return err; |
@@ -555,7 +564,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
555 | 564 | ||
556 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 565 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
557 | struct net_device *dev, const u8 *bssid, | 566 | struct net_device *dev, const u8 *bssid, |
558 | const u8 *ie, int ie_len, u16 reason) | 567 | const u8 *ie, int ie_len, u16 reason, |
568 | bool local_state_change) | ||
559 | { | 569 | { |
560 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 570 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
561 | struct cfg80211_deauth_request req; | 571 | struct cfg80211_deauth_request req; |
@@ -565,6 +575,7 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
565 | 575 | ||
566 | memset(&req, 0, sizeof(req)); | 576 | memset(&req, 0, sizeof(req)); |
567 | req.reason_code = reason; | 577 | req.reason_code = reason; |
578 | req.local_state_change = local_state_change; | ||
568 | req.ie = ie; | 579 | req.ie = ie; |
569 | req.ie_len = ie_len; | 580 | req.ie_len = ie_len; |
570 | if (wdev->current_bss && | 581 | if (wdev->current_bss && |
@@ -591,13 +602,15 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
591 | 602 | ||
592 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 603 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
593 | struct net_device *dev, const u8 *bssid, | 604 | struct net_device *dev, const u8 *bssid, |
594 | const u8 *ie, int ie_len, u16 reason) | 605 | const u8 *ie, int ie_len, u16 reason, |
606 | bool local_state_change) | ||
595 | { | 607 | { |
596 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 608 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
597 | int err; | 609 | int err; |
598 | 610 | ||
599 | wdev_lock(wdev); | 611 | wdev_lock(wdev); |
600 | err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason); | 612 | err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason, |
613 | local_state_change); | ||
601 | wdev_unlock(wdev); | 614 | wdev_unlock(wdev); |
602 | 615 | ||
603 | return err; | 616 | return err; |
@@ -605,7 +618,8 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
605 | 618 | ||
606 | static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 619 | static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
607 | struct net_device *dev, const u8 *bssid, | 620 | struct net_device *dev, const u8 *bssid, |
608 | const u8 *ie, int ie_len, u16 reason) | 621 | const u8 *ie, int ie_len, u16 reason, |
622 | bool local_state_change) | ||
609 | { | 623 | { |
610 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 624 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
611 | struct cfg80211_disassoc_request req; | 625 | struct cfg80211_disassoc_request req; |
@@ -620,6 +634,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
620 | 634 | ||
621 | memset(&req, 0, sizeof(req)); | 635 | memset(&req, 0, sizeof(req)); |
622 | req.reason_code = reason; | 636 | req.reason_code = reason; |
637 | req.local_state_change = local_state_change; | ||
623 | req.ie = ie; | 638 | req.ie = ie; |
624 | req.ie_len = ie_len; | 639 | req.ie_len = ie_len; |
625 | if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) | 640 | if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) |
@@ -632,13 +647,15 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
632 | 647 | ||
633 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 648 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
634 | struct net_device *dev, const u8 *bssid, | 649 | struct net_device *dev, const u8 *bssid, |
635 | const u8 *ie, int ie_len, u16 reason) | 650 | const u8 *ie, int ie_len, u16 reason, |
651 | bool local_state_change) | ||
636 | { | 652 | { |
637 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 653 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
638 | int err; | 654 | int err; |
639 | 655 | ||
640 | wdev_lock(wdev); | 656 | wdev_lock(wdev); |
641 | err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason); | 657 | err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason, |
658 | local_state_change); | ||
642 | wdev_unlock(wdev); | 659 | wdev_unlock(wdev); |
643 | 660 | ||
644 | return err; | 661 | return err; |
@@ -895,3 +912,16 @@ void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | |||
895 | nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); | 912 | nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); |
896 | } | 913 | } |
897 | EXPORT_SYMBOL(cfg80211_action_tx_status); | 914 | EXPORT_SYMBOL(cfg80211_action_tx_status); |
915 | |||
916 | void cfg80211_cqm_rssi_notify(struct net_device *dev, | ||
917 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
918 | gfp_t gfp) | ||
919 | { | ||
920 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
921 | struct wiphy *wiphy = wdev->wiphy; | ||
922 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
923 | |||
924 | /* Indicate roaming trigger event to user space */ | ||
925 | nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp); | ||
926 | } | ||
927 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 030cf153bea2..aaa1aad566cd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -150,6 +150,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
150 | .len = IEEE80211_MAX_DATA_LEN }, | 150 | .len = IEEE80211_MAX_DATA_LEN }, |
151 | [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, | 151 | [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, |
152 | [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, | 152 | [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, |
153 | [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, | ||
154 | [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, | ||
155 | [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 }, | ||
153 | }; | 156 | }; |
154 | 157 | ||
155 | /* policy for the attributes */ | 158 | /* policy for the attributes */ |
@@ -586,6 +589,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
586 | i++; | 589 | i++; |
587 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 590 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
588 | } | 591 | } |
592 | CMD(set_channel, SET_CHANNEL); | ||
589 | 593 | ||
590 | #undef CMD | 594 | #undef CMD |
591 | 595 | ||
@@ -686,10 +690,90 @@ static int parse_txq_params(struct nlattr *tb[], | |||
686 | return 0; | 690 | return 0; |
687 | } | 691 | } |
688 | 692 | ||
693 | static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) | ||
694 | { | ||
695 | /* | ||
696 | * You can only set the channel explicitly for AP, mesh | ||
697 | * and WDS type interfaces; all others have their channel | ||
698 | * managed via their respective "establish a connection" | ||
699 | * command (connect, join, ...) | ||
700 | * | ||
701 | * Monitors are special as they are normally slaved to | ||
702 | * whatever else is going on, so they behave as though | ||
703 | * you tried setting the wiphy channel itself. | ||
704 | */ | ||
705 | return !wdev || | ||
706 | wdev->iftype == NL80211_IFTYPE_AP || | ||
707 | wdev->iftype == NL80211_IFTYPE_WDS || | ||
708 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || | ||
709 | wdev->iftype == NL80211_IFTYPE_MONITOR; | ||
710 | } | ||
711 | |||
712 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | ||
713 | struct wireless_dev *wdev, | ||
714 | struct genl_info *info) | ||
715 | { | ||
716 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
717 | u32 freq; | ||
718 | int result; | ||
719 | |||
720 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
721 | return -EINVAL; | ||
722 | |||
723 | if (!nl80211_can_set_dev_channel(wdev)) | ||
724 | return -EOPNOTSUPP; | ||
725 | |||
726 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | ||
727 | channel_type = nla_get_u32(info->attrs[ | ||
728 | NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | ||
729 | if (channel_type != NL80211_CHAN_NO_HT && | ||
730 | channel_type != NL80211_CHAN_HT20 && | ||
731 | channel_type != NL80211_CHAN_HT40PLUS && | ||
732 | channel_type != NL80211_CHAN_HT40MINUS) | ||
733 | return -EINVAL; | ||
734 | } | ||
735 | |||
736 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
737 | |||
738 | mutex_lock(&rdev->devlist_mtx); | ||
739 | if (wdev) { | ||
740 | wdev_lock(wdev); | ||
741 | result = cfg80211_set_freq(rdev, wdev, freq, channel_type); | ||
742 | wdev_unlock(wdev); | ||
743 | } else { | ||
744 | result = cfg80211_set_freq(rdev, NULL, freq, channel_type); | ||
745 | } | ||
746 | mutex_unlock(&rdev->devlist_mtx); | ||
747 | |||
748 | return result; | ||
749 | } | ||
750 | |||
751 | static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info) | ||
752 | { | ||
753 | struct cfg80211_registered_device *rdev; | ||
754 | struct net_device *netdev; | ||
755 | int result; | ||
756 | |||
757 | rtnl_lock(); | ||
758 | |||
759 | result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev); | ||
760 | if (result) | ||
761 | goto unlock; | ||
762 | |||
763 | result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info); | ||
764 | |||
765 | unlock: | ||
766 | rtnl_unlock(); | ||
767 | |||
768 | return result; | ||
769 | } | ||
770 | |||
689 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | 771 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) |
690 | { | 772 | { |
691 | struct cfg80211_registered_device *rdev; | 773 | struct cfg80211_registered_device *rdev; |
692 | int result = 0, rem_txq_params = 0; | 774 | struct net_device *netdev = NULL; |
775 | struct wireless_dev *wdev; | ||
776 | int result, rem_txq_params = 0; | ||
693 | struct nlattr *nl_txq_params; | 777 | struct nlattr *nl_txq_params; |
694 | u32 changed; | 778 | u32 changed; |
695 | u8 retry_short = 0, retry_long = 0; | 779 | u8 retry_short = 0, retry_long = 0; |
@@ -698,16 +782,50 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
698 | 782 | ||
699 | rtnl_lock(); | 783 | rtnl_lock(); |
700 | 784 | ||
785 | /* | ||
786 | * Try to find the wiphy and netdev. Normally this | ||
787 | * function shouldn't need the netdev, but this is | ||
788 | * done for backward compatibility -- previously | ||
789 | * setting the channel was done per wiphy, but now | ||
790 | * it is per netdev. Previous userland like hostapd | ||
791 | * also passed a netdev to set_wiphy, so that it is | ||
792 | * possible to let that go to the right netdev! | ||
793 | */ | ||
701 | mutex_lock(&cfg80211_mutex); | 794 | mutex_lock(&cfg80211_mutex); |
702 | 795 | ||
703 | rdev = __cfg80211_rdev_from_info(info); | 796 | if (info->attrs[NL80211_ATTR_IFINDEX]) { |
704 | if (IS_ERR(rdev)) { | 797 | int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); |
705 | mutex_unlock(&cfg80211_mutex); | 798 | |
706 | result = PTR_ERR(rdev); | 799 | netdev = dev_get_by_index(genl_info_net(info), ifindex); |
707 | goto unlock; | 800 | if (netdev && netdev->ieee80211_ptr) { |
801 | rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); | ||
802 | mutex_lock(&rdev->mtx); | ||
803 | } else | ||
804 | netdev = NULL; | ||
708 | } | 805 | } |
709 | 806 | ||
710 | mutex_lock(&rdev->mtx); | 807 | if (!netdev) { |
808 | rdev = __cfg80211_rdev_from_info(info); | ||
809 | if (IS_ERR(rdev)) { | ||
810 | mutex_unlock(&cfg80211_mutex); | ||
811 | result = PTR_ERR(rdev); | ||
812 | goto unlock; | ||
813 | } | ||
814 | wdev = NULL; | ||
815 | netdev = NULL; | ||
816 | result = 0; | ||
817 | |||
818 | mutex_lock(&rdev->mtx); | ||
819 | } else if (netif_running(netdev) && | ||
820 | nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) | ||
821 | wdev = netdev->ieee80211_ptr; | ||
822 | else | ||
823 | wdev = NULL; | ||
824 | |||
825 | /* | ||
826 | * end workaround code, by now the rdev is available | ||
827 | * and locked, and wdev may or may not be NULL. | ||
828 | */ | ||
711 | 829 | ||
712 | if (info->attrs[NL80211_ATTR_WIPHY_NAME]) | 830 | if (info->attrs[NL80211_ATTR_WIPHY_NAME]) |
713 | result = cfg80211_dev_rename( | 831 | result = cfg80211_dev_rename( |
@@ -746,26 +864,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
746 | } | 864 | } |
747 | 865 | ||
748 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 866 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
749 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 867 | result = __nl80211_set_channel(rdev, wdev, info); |
750 | u32 freq; | ||
751 | |||
752 | result = -EINVAL; | ||
753 | |||
754 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | ||
755 | channel_type = nla_get_u32(info->attrs[ | ||
756 | NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | ||
757 | if (channel_type != NL80211_CHAN_NO_HT && | ||
758 | channel_type != NL80211_CHAN_HT20 && | ||
759 | channel_type != NL80211_CHAN_HT40PLUS && | ||
760 | channel_type != NL80211_CHAN_HT40MINUS) | ||
761 | goto bad_res; | ||
762 | } | ||
763 | |||
764 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
765 | |||
766 | mutex_lock(&rdev->devlist_mtx); | ||
767 | result = rdev_set_freq(rdev, NULL, freq, channel_type); | ||
768 | mutex_unlock(&rdev->devlist_mtx); | ||
769 | if (result) | 868 | if (result) |
770 | goto bad_res; | 869 | goto bad_res; |
771 | } | 870 | } |
@@ -862,6 +961,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
862 | 961 | ||
863 | bad_res: | 962 | bad_res: |
864 | mutex_unlock(&rdev->mtx); | 963 | mutex_unlock(&rdev->mtx); |
964 | if (netdev) | ||
965 | dev_put(netdev); | ||
865 | unlock: | 966 | unlock: |
866 | rtnl_unlock(); | 967 | rtnl_unlock(); |
867 | return result; | 968 | return result; |
@@ -2096,7 +2197,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
2096 | goto out_rtnl; | 2197 | goto out_rtnl; |
2097 | 2198 | ||
2098 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2199 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2099 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 2200 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2201 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | ||
2100 | err = -EINVAL; | 2202 | err = -EINVAL; |
2101 | goto out; | 2203 | goto out; |
2102 | } | 2204 | } |
@@ -2439,6 +2541,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
2439 | params.use_cts_prot = -1; | 2541 | params.use_cts_prot = -1; |
2440 | params.use_short_preamble = -1; | 2542 | params.use_short_preamble = -1; |
2441 | params.use_short_slot_time = -1; | 2543 | params.use_short_slot_time = -1; |
2544 | params.ap_isolate = -1; | ||
2442 | 2545 | ||
2443 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) | 2546 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) |
2444 | params.use_cts_prot = | 2547 | params.use_cts_prot = |
@@ -2455,6 +2558,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
2455 | params.basic_rates_len = | 2558 | params.basic_rates_len = |
2456 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 2559 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
2457 | } | 2560 | } |
2561 | if (info->attrs[NL80211_ATTR_AP_ISOLATE]) | ||
2562 | params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); | ||
2458 | 2563 | ||
2459 | rtnl_lock(); | 2564 | rtnl_lock(); |
2460 | 2565 | ||
@@ -3392,6 +3497,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3392 | int err, ssid_len, ie_len = 0; | 3497 | int err, ssid_len, ie_len = 0; |
3393 | enum nl80211_auth_type auth_type; | 3498 | enum nl80211_auth_type auth_type; |
3394 | struct key_parse key; | 3499 | struct key_parse key; |
3500 | bool local_state_change; | ||
3395 | 3501 | ||
3396 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3502 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3397 | return -EINVAL; | 3503 | return -EINVAL; |
@@ -3470,9 +3576,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3470 | goto out; | 3576 | goto out; |
3471 | } | 3577 | } |
3472 | 3578 | ||
3579 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | ||
3580 | |||
3473 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 3581 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
3474 | ssid, ssid_len, ie, ie_len, | 3582 | ssid, ssid_len, ie, ie_len, |
3475 | key.p.key, key.p.key_len, key.idx); | 3583 | key.p.key, key.p.key_len, key.idx, |
3584 | local_state_change); | ||
3476 | 3585 | ||
3477 | out: | 3586 | out: |
3478 | cfg80211_unlock_rdev(rdev); | 3587 | cfg80211_unlock_rdev(rdev); |
@@ -3551,9 +3660,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3551 | { | 3660 | { |
3552 | struct cfg80211_registered_device *rdev; | 3661 | struct cfg80211_registered_device *rdev; |
3553 | struct net_device *dev; | 3662 | struct net_device *dev; |
3554 | struct wireless_dev *wdev; | ||
3555 | struct cfg80211_crypto_settings crypto; | 3663 | struct cfg80211_crypto_settings crypto; |
3556 | struct ieee80211_channel *chan, *fixedchan; | 3664 | struct ieee80211_channel *chan; |
3557 | const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; | 3665 | const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; |
3558 | int err, ssid_len, ie_len = 0; | 3666 | int err, ssid_len, ie_len = 0; |
3559 | bool use_mfp = false; | 3667 | bool use_mfp = false; |
@@ -3596,16 +3704,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3596 | goto out; | 3704 | goto out; |
3597 | } | 3705 | } |
3598 | 3706 | ||
3599 | mutex_lock(&rdev->devlist_mtx); | ||
3600 | wdev = dev->ieee80211_ptr; | ||
3601 | fixedchan = rdev_fixed_channel(rdev, wdev); | ||
3602 | if (fixedchan && chan != fixedchan) { | ||
3603 | err = -EBUSY; | ||
3604 | mutex_unlock(&rdev->devlist_mtx); | ||
3605 | goto out; | ||
3606 | } | ||
3607 | mutex_unlock(&rdev->devlist_mtx); | ||
3608 | |||
3609 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 3707 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
3610 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 3708 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
3611 | 3709 | ||
@@ -3649,6 +3747,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3649 | const u8 *ie = NULL, *bssid; | 3747 | const u8 *ie = NULL, *bssid; |
3650 | int err, ie_len = 0; | 3748 | int err, ie_len = 0; |
3651 | u16 reason_code; | 3749 | u16 reason_code; |
3750 | bool local_state_change; | ||
3652 | 3751 | ||
3653 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3752 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3654 | return -EINVAL; | 3753 | return -EINVAL; |
@@ -3694,7 +3793,10 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3694 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3793 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3695 | } | 3794 | } |
3696 | 3795 | ||
3697 | err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code); | 3796 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
3797 | |||
3798 | err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, | ||
3799 | local_state_change); | ||
3698 | 3800 | ||
3699 | out: | 3801 | out: |
3700 | cfg80211_unlock_rdev(rdev); | 3802 | cfg80211_unlock_rdev(rdev); |
@@ -3711,6 +3813,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3711 | const u8 *ie = NULL, *bssid; | 3813 | const u8 *ie = NULL, *bssid; |
3712 | int err, ie_len = 0; | 3814 | int err, ie_len = 0; |
3713 | u16 reason_code; | 3815 | u16 reason_code; |
3816 | bool local_state_change; | ||
3714 | 3817 | ||
3715 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3818 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3716 | return -EINVAL; | 3819 | return -EINVAL; |
@@ -3756,7 +3859,10 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3756 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3859 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3757 | } | 3860 | } |
3758 | 3861 | ||
3759 | err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code); | 3862 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
3863 | |||
3864 | err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, | ||
3865 | local_state_change); | ||
3760 | 3866 | ||
3761 | out: | 3867 | out: |
3762 | cfg80211_unlock_rdev(rdev); | 3868 | cfg80211_unlock_rdev(rdev); |
@@ -4779,6 +4885,84 @@ unlock_rtnl: | |||
4779 | return err; | 4885 | return err; |
4780 | } | 4886 | } |
4781 | 4887 | ||
4888 | static struct nla_policy | ||
4889 | nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = { | ||
4890 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, | ||
4891 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, | ||
4892 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, | ||
4893 | }; | ||
4894 | |||
4895 | static int nl80211_set_cqm_rssi(struct genl_info *info, | ||
4896 | s32 threshold, u32 hysteresis) | ||
4897 | { | ||
4898 | struct cfg80211_registered_device *rdev; | ||
4899 | struct wireless_dev *wdev; | ||
4900 | struct net_device *dev; | ||
4901 | int err; | ||
4902 | |||
4903 | if (threshold > 0) | ||
4904 | return -EINVAL; | ||
4905 | |||
4906 | rtnl_lock(); | ||
4907 | |||
4908 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4909 | if (err) | ||
4910 | goto unlock_rdev; | ||
4911 | |||
4912 | wdev = dev->ieee80211_ptr; | ||
4913 | |||
4914 | if (!rdev->ops->set_cqm_rssi_config) { | ||
4915 | err = -EOPNOTSUPP; | ||
4916 | goto unlock_rdev; | ||
4917 | } | ||
4918 | |||
4919 | if (wdev->iftype != NL80211_IFTYPE_STATION) { | ||
4920 | err = -EOPNOTSUPP; | ||
4921 | goto unlock_rdev; | ||
4922 | } | ||
4923 | |||
4924 | err = rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev, | ||
4925 | threshold, hysteresis); | ||
4926 | |||
4927 | unlock_rdev: | ||
4928 | cfg80211_unlock_rdev(rdev); | ||
4929 | dev_put(dev); | ||
4930 | rtnl_unlock(); | ||
4931 | |||
4932 | return err; | ||
4933 | } | ||
4934 | |||
4935 | static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) | ||
4936 | { | ||
4937 | struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1]; | ||
4938 | struct nlattr *cqm; | ||
4939 | int err; | ||
4940 | |||
4941 | cqm = info->attrs[NL80211_ATTR_CQM]; | ||
4942 | if (!cqm) { | ||
4943 | err = -EINVAL; | ||
4944 | goto out; | ||
4945 | } | ||
4946 | |||
4947 | err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm, | ||
4948 | nl80211_attr_cqm_policy); | ||
4949 | if (err) | ||
4950 | goto out; | ||
4951 | |||
4952 | if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] && | ||
4953 | attrs[NL80211_ATTR_CQM_RSSI_HYST]) { | ||
4954 | s32 threshold; | ||
4955 | u32 hysteresis; | ||
4956 | threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); | ||
4957 | hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); | ||
4958 | err = nl80211_set_cqm_rssi(info, threshold, hysteresis); | ||
4959 | } else | ||
4960 | err = -EINVAL; | ||
4961 | |||
4962 | out: | ||
4963 | return err; | ||
4964 | } | ||
4965 | |||
4782 | static struct genl_ops nl80211_ops[] = { | 4966 | static struct genl_ops nl80211_ops[] = { |
4783 | { | 4967 | { |
4784 | .cmd = NL80211_CMD_GET_WIPHY, | 4968 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -5083,6 +5267,18 @@ static struct genl_ops nl80211_ops[] = { | |||
5083 | .policy = nl80211_policy, | 5267 | .policy = nl80211_policy, |
5084 | /* can be retrieved by unprivileged users */ | 5268 | /* can be retrieved by unprivileged users */ |
5085 | }, | 5269 | }, |
5270 | { | ||
5271 | .cmd = NL80211_CMD_SET_CQM, | ||
5272 | .doit = nl80211_set_cqm, | ||
5273 | .policy = nl80211_policy, | ||
5274 | .flags = GENL_ADMIN_PERM, | ||
5275 | }, | ||
5276 | { | ||
5277 | .cmd = NL80211_CMD_SET_CHANNEL, | ||
5278 | .doit = nl80211_set_channel, | ||
5279 | .policy = nl80211_policy, | ||
5280 | .flags = GENL_ADMIN_PERM, | ||
5281 | }, | ||
5086 | }; | 5282 | }; |
5087 | 5283 | ||
5088 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 5284 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -5833,6 +6029,52 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | |||
5833 | nlmsg_free(msg); | 6029 | nlmsg_free(msg); |
5834 | } | 6030 | } |
5835 | 6031 | ||
6032 | void | ||
6033 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | ||
6034 | struct net_device *netdev, | ||
6035 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
6036 | gfp_t gfp) | ||
6037 | { | ||
6038 | struct sk_buff *msg; | ||
6039 | struct nlattr *pinfoattr; | ||
6040 | void *hdr; | ||
6041 | |||
6042 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
6043 | if (!msg) | ||
6044 | return; | ||
6045 | |||
6046 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM); | ||
6047 | if (!hdr) { | ||
6048 | nlmsg_free(msg); | ||
6049 | return; | ||
6050 | } | ||
6051 | |||
6052 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
6053 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
6054 | |||
6055 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); | ||
6056 | if (!pinfoattr) | ||
6057 | goto nla_put_failure; | ||
6058 | |||
6059 | NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, | ||
6060 | rssi_event); | ||
6061 | |||
6062 | nla_nest_end(msg, pinfoattr); | ||
6063 | |||
6064 | if (genlmsg_end(msg, hdr) < 0) { | ||
6065 | nlmsg_free(msg); | ||
6066 | return; | ||
6067 | } | ||
6068 | |||
6069 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
6070 | nl80211_mlme_mcgrp.id, gfp); | ||
6071 | return; | ||
6072 | |||
6073 | nla_put_failure: | ||
6074 | genlmsg_cancel(msg, hdr); | ||
6075 | nlmsg_free(msg); | ||
6076 | } | ||
6077 | |||
5836 | static int nl80211_netlink_notify(struct notifier_block * nb, | 6078 | static int nl80211_netlink_notify(struct notifier_block * nb, |
5837 | unsigned long state, | 6079 | unsigned long state, |
5838 | void *_notify) | 6080 | void *_notify) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 4ca511102c6c..2ad7fbc7d9f1 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -82,4 +82,10 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | |||
82 | const u8 *buf, size_t len, bool ack, | 82 | const u8 *buf, size_t len, bool ack, |
83 | gfp_t gfp); | 83 | gfp_t gfp); |
84 | 84 | ||
85 | void | ||
86 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | ||
87 | struct net_device *netdev, | ||
88 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
89 | gfp_t gfp); | ||
90 | |||
85 | #endif /* __NET_WIRELESS_NL80211_H */ | 91 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 422da20d1e5b..8f0d97dd3109 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -2356,10 +2356,10 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
2356 | rdev->country_ie_alpha2[1]); | 2356 | rdev->country_ie_alpha2[1]); |
2357 | } else | 2357 | } else |
2358 | printk(KERN_INFO "cfg80211: Current regulatory " | 2358 | printk(KERN_INFO "cfg80211: Current regulatory " |
2359 | "domain intersected: \n"); | 2359 | "domain intersected:\n"); |
2360 | } else | 2360 | } else |
2361 | printk(KERN_INFO "cfg80211: Current regulatory " | 2361 | printk(KERN_INFO "cfg80211: Current regulatory " |
2362 | "domain intersected: \n"); | 2362 | "domain intersected:\n"); |
2363 | } else if (is_world_regdom(rd->alpha2)) | 2363 | } else if (is_world_regdom(rd->alpha2)) |
2364 | printk(KERN_INFO "cfg80211: World regulatory " | 2364 | printk(KERN_INFO "cfg80211: World regulatory " |
2365 | "domain updated:\n"); | 2365 | "domain updated:\n"); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f4dfd5f5f2ea..72222f0074db 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -171,7 +171,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
171 | params->ssid, params->ssid_len, | 171 | params->ssid, params->ssid_len, |
172 | NULL, 0, | 172 | NULL, 0, |
173 | params->key, params->key_len, | 173 | params->key, params->key_len, |
174 | params->key_idx); | 174 | params->key_idx, false); |
175 | case CFG80211_CONN_ASSOCIATE_NEXT: | 175 | case CFG80211_CONN_ASSOCIATE_NEXT: |
176 | BUG_ON(!rdev->ops->assoc); | 176 | BUG_ON(!rdev->ops->assoc); |
177 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 177 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |
@@ -186,12 +186,13 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
186 | if (err) | 186 | if (err) |
187 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 187 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
188 | NULL, 0, | 188 | NULL, 0, |
189 | WLAN_REASON_DEAUTH_LEAVING); | 189 | WLAN_REASON_DEAUTH_LEAVING, |
190 | false); | ||
190 | return err; | 191 | return err; |
191 | case CFG80211_CONN_DEAUTH_ASSOC_FAIL: | 192 | case CFG80211_CONN_DEAUTH_ASSOC_FAIL: |
192 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 193 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
193 | NULL, 0, | 194 | NULL, 0, |
194 | WLAN_REASON_DEAUTH_LEAVING); | 195 | WLAN_REASON_DEAUTH_LEAVING, false); |
195 | /* return an error so that we call __cfg80211_connect_result() */ | 196 | /* return an error so that we call __cfg80211_connect_result() */ |
196 | return -EINVAL; | 197 | return -EINVAL; |
197 | default: | 198 | default: |
@@ -517,12 +518,16 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
517 | ev->type = EVENT_CONNECT_RESULT; | 518 | ev->type = EVENT_CONNECT_RESULT; |
518 | if (bssid) | 519 | if (bssid) |
519 | memcpy(ev->cr.bssid, bssid, ETH_ALEN); | 520 | memcpy(ev->cr.bssid, bssid, ETH_ALEN); |
520 | ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev); | 521 | if (req_ie_len) { |
521 | ev->cr.req_ie_len = req_ie_len; | 522 | ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev); |
522 | memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len); | 523 | ev->cr.req_ie_len = req_ie_len; |
523 | ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; | 524 | memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len); |
524 | ev->cr.resp_ie_len = resp_ie_len; | 525 | } |
525 | memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); | 526 | if (resp_ie_len) { |
527 | ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; | ||
528 | ev->cr.resp_ie_len = resp_ie_len; | ||
529 | memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); | ||
530 | } | ||
526 | ev->cr.status = status; | 531 | ev->cr.status = status; |
527 | 532 | ||
528 | spin_lock_irqsave(&wdev->event_lock, flags); | 533 | spin_lock_irqsave(&wdev->event_lock, flags); |
@@ -676,7 +681,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
676 | continue; | 681 | continue; |
677 | bssid = wdev->auth_bsses[i]->pub.bssid; | 682 | bssid = wdev->auth_bsses[i]->pub.bssid; |
678 | ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, | 683 | ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, |
679 | WLAN_REASON_DEAUTH_LEAVING); | 684 | WLAN_REASON_DEAUTH_LEAVING, |
685 | false); | ||
680 | WARN(ret, "deauth failed: %d\n", ret); | 686 | WARN(ret, "deauth failed: %d\n", ret); |
681 | } | 687 | } |
682 | } | 688 | } |
@@ -735,7 +741,6 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
735 | const u8 *prev_bssid) | 741 | const u8 *prev_bssid) |
736 | { | 742 | { |
737 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 743 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
738 | struct ieee80211_channel *chan; | ||
739 | struct cfg80211_bss *bss = NULL; | 744 | struct cfg80211_bss *bss = NULL; |
740 | int err; | 745 | int err; |
741 | 746 | ||
@@ -744,10 +749,6 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
744 | if (wdev->sme_state != CFG80211_SME_IDLE) | 749 | if (wdev->sme_state != CFG80211_SME_IDLE) |
745 | return -EALREADY; | 750 | return -EALREADY; |
746 | 751 | ||
747 | chan = rdev_fixed_channel(rdev, wdev); | ||
748 | if (chan && chan != connect->channel) | ||
749 | return -EBUSY; | ||
750 | |||
751 | if (WARN_ON(wdev->connect_keys)) { | 752 | if (WARN_ON(wdev->connect_keys)) { |
752 | kfree(wdev->connect_keys); | 753 | kfree(wdev->connect_keys); |
753 | wdev->connect_keys = NULL; | 754 | wdev->connect_keys = NULL; |
@@ -935,7 +936,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
935 | /* wdev->conn->params.bssid must be set if > SCANNING */ | 936 | /* wdev->conn->params.bssid must be set if > SCANNING */ |
936 | err = __cfg80211_mlme_deauth(rdev, dev, | 937 | err = __cfg80211_mlme_deauth(rdev, dev, |
937 | wdev->conn->params.bssid, | 938 | wdev->conn->params.bssid, |
938 | NULL, 0, reason); | 939 | NULL, 0, reason, false); |
939 | if (err) | 940 | if (err) |
940 | return err; | 941 | return err; |
941 | } else { | 942 | } else { |
@@ -991,7 +992,8 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx) | |||
991 | 992 | ||
992 | memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); | 993 | memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); |
993 | if (__cfg80211_mlme_deauth(rdev, dev, bssid, | 994 | if (__cfg80211_mlme_deauth(rdev, dev, bssid, |
994 | NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) { | 995 | NULL, 0, WLAN_REASON_DEAUTH_LEAVING, |
996 | false)) { | ||
995 | /* whatever -- assume gone anyway */ | 997 | /* whatever -- assume gone anyway */ |
996 | cfg80211_unhold_bss(wdev->auth_bsses[idx]); | 998 | cfg80211_unhold_bss(wdev->auth_bsses[idx]); |
997 | cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); | 999 | cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index d3574a4eb3ba..3416373a9c0c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -331,11 +331,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
331 | if (iftype == NL80211_IFTYPE_MESH_POINT) { | 331 | if (iftype == NL80211_IFTYPE_MESH_POINT) { |
332 | struct ieee80211s_hdr *meshdr = | 332 | struct ieee80211s_hdr *meshdr = |
333 | (struct ieee80211s_hdr *) (skb->data + hdrlen); | 333 | (struct ieee80211s_hdr *) (skb->data + hdrlen); |
334 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | 334 | /* make sure meshdr->flags is on the linear part */ |
335 | if (!pskb_may_pull(skb, hdrlen + 1)) | ||
336 | return -1; | ||
335 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | 337 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { |
336 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | 338 | skb_copy_bits(skb, hdrlen + |
337 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | 339 | offsetof(struct ieee80211s_hdr, eaddr1), |
340 | dst, ETH_ALEN); | ||
341 | skb_copy_bits(skb, hdrlen + | ||
342 | offsetof(struct ieee80211s_hdr, eaddr2), | ||
343 | src, ETH_ALEN); | ||
338 | } | 344 | } |
345 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
339 | } | 346 | } |
340 | break; | 347 | break; |
341 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): | 348 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): |
@@ -347,9 +354,14 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
347 | if (iftype == NL80211_IFTYPE_MESH_POINT) { | 354 | if (iftype == NL80211_IFTYPE_MESH_POINT) { |
348 | struct ieee80211s_hdr *meshdr = | 355 | struct ieee80211s_hdr *meshdr = |
349 | (struct ieee80211s_hdr *) (skb->data + hdrlen); | 356 | (struct ieee80211s_hdr *) (skb->data + hdrlen); |
350 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | 357 | /* make sure meshdr->flags is on the linear part */ |
358 | if (!pskb_may_pull(skb, hdrlen + 1)) | ||
359 | return -1; | ||
351 | if (meshdr->flags & MESH_FLAGS_AE_A4) | 360 | if (meshdr->flags & MESH_FLAGS_AE_A4) |
352 | memcpy(src, meshdr->eaddr1, ETH_ALEN); | 361 | skb_copy_bits(skb, hdrlen + |
362 | offsetof(struct ieee80211s_hdr, eaddr1), | ||
363 | src, ETH_ALEN); | ||
364 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
353 | } | 365 | } |
354 | break; | 366 | break; |
355 | case cpu_to_le16(0): | 367 | case cpu_to_le16(0): |
@@ -358,7 +370,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
358 | break; | 370 | break; |
359 | } | 371 | } |
360 | 372 | ||
361 | if (unlikely(skb->len - hdrlen < 8)) | 373 | if (!pskb_may_pull(skb, hdrlen + 8)) |
362 | return -1; | 374 | return -1; |
363 | 375 | ||
364 | payload = skb->data + hdrlen; | 376 | payload = skb->data + hdrlen; |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index a60a2773b497..96342993cf93 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -782,16 +782,22 @@ int cfg80211_wext_siwfreq(struct net_device *dev, | |||
782 | return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra); | 782 | return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra); |
783 | case NL80211_IFTYPE_ADHOC: | 783 | case NL80211_IFTYPE_ADHOC: |
784 | return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); | 784 | return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); |
785 | default: | 785 | case NL80211_IFTYPE_MONITOR: |
786 | case NL80211_IFTYPE_WDS: | ||
787 | case NL80211_IFTYPE_MESH_POINT: | ||
786 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); | 788 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); |
787 | if (freq < 0) | 789 | if (freq < 0) |
788 | return freq; | 790 | return freq; |
789 | if (freq == 0) | 791 | if (freq == 0) |
790 | return -EINVAL; | 792 | return -EINVAL; |
793 | wdev_lock(wdev); | ||
791 | mutex_lock(&rdev->devlist_mtx); | 794 | mutex_lock(&rdev->devlist_mtx); |
792 | err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT); | 795 | err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); |
793 | mutex_unlock(&rdev->devlist_mtx); | 796 | mutex_unlock(&rdev->devlist_mtx); |
797 | wdev_unlock(wdev); | ||
794 | return err; | 798 | return err; |
799 | default: | ||
800 | return -EOPNOTSUPP; | ||
795 | } | 801 | } |
796 | } | 802 | } |
797 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq); | 803 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq); |
@@ -801,7 +807,6 @@ int cfg80211_wext_giwfreq(struct net_device *dev, | |||
801 | struct iw_freq *freq, char *extra) | 807 | struct iw_freq *freq, char *extra) |
802 | { | 808 | { |
803 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 809 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
804 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
805 | 810 | ||
806 | switch (wdev->iftype) { | 811 | switch (wdev->iftype) { |
807 | case NL80211_IFTYPE_STATION: | 812 | case NL80211_IFTYPE_STATION: |
@@ -809,9 +814,9 @@ int cfg80211_wext_giwfreq(struct net_device *dev, | |||
809 | case NL80211_IFTYPE_ADHOC: | 814 | case NL80211_IFTYPE_ADHOC: |
810 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | 815 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); |
811 | default: | 816 | default: |
812 | if (!rdev->channel) | 817 | if (!wdev->channel) |
813 | return -EINVAL; | 818 | return -EINVAL; |
814 | freq->m = rdev->channel->center_freq; | 819 | freq->m = wdev->channel->center_freq; |
815 | freq->e = 6; | 820 | freq->e = 6; |
816 | return 0; | 821 | return 0; |
817 | } | 822 | } |
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 4f5a47091fde..0ef17bc42bac 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c | |||
@@ -29,226 +29,226 @@ typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, | |||
29 | * know about. | 29 | * know about. |
30 | */ | 30 | */ |
31 | static const struct iw_ioctl_description standard_ioctl[] = { | 31 | static const struct iw_ioctl_description standard_ioctl[] = { |
32 | [SIOCSIWCOMMIT - SIOCIWFIRST] = { | 32 | [IW_IOCTL_IDX(SIOCSIWCOMMIT)] = { |
33 | .header_type = IW_HEADER_TYPE_NULL, | 33 | .header_type = IW_HEADER_TYPE_NULL, |
34 | }, | 34 | }, |
35 | [SIOCGIWNAME - SIOCIWFIRST] = { | 35 | [IW_IOCTL_IDX(SIOCGIWNAME)] = { |
36 | .header_type = IW_HEADER_TYPE_CHAR, | 36 | .header_type = IW_HEADER_TYPE_CHAR, |
37 | .flags = IW_DESCR_FLAG_DUMP, | 37 | .flags = IW_DESCR_FLAG_DUMP, |
38 | }, | 38 | }, |
39 | [SIOCSIWNWID - SIOCIWFIRST] = { | 39 | [IW_IOCTL_IDX(SIOCSIWNWID)] = { |
40 | .header_type = IW_HEADER_TYPE_PARAM, | 40 | .header_type = IW_HEADER_TYPE_PARAM, |
41 | .flags = IW_DESCR_FLAG_EVENT, | 41 | .flags = IW_DESCR_FLAG_EVENT, |
42 | }, | 42 | }, |
43 | [SIOCGIWNWID - SIOCIWFIRST] = { | 43 | [IW_IOCTL_IDX(SIOCGIWNWID)] = { |
44 | .header_type = IW_HEADER_TYPE_PARAM, | 44 | .header_type = IW_HEADER_TYPE_PARAM, |
45 | .flags = IW_DESCR_FLAG_DUMP, | 45 | .flags = IW_DESCR_FLAG_DUMP, |
46 | }, | 46 | }, |
47 | [SIOCSIWFREQ - SIOCIWFIRST] = { | 47 | [IW_IOCTL_IDX(SIOCSIWFREQ)] = { |
48 | .header_type = IW_HEADER_TYPE_FREQ, | 48 | .header_type = IW_HEADER_TYPE_FREQ, |
49 | .flags = IW_DESCR_FLAG_EVENT, | 49 | .flags = IW_DESCR_FLAG_EVENT, |
50 | }, | 50 | }, |
51 | [SIOCGIWFREQ - SIOCIWFIRST] = { | 51 | [IW_IOCTL_IDX(SIOCGIWFREQ)] = { |
52 | .header_type = IW_HEADER_TYPE_FREQ, | 52 | .header_type = IW_HEADER_TYPE_FREQ, |
53 | .flags = IW_DESCR_FLAG_DUMP, | 53 | .flags = IW_DESCR_FLAG_DUMP, |
54 | }, | 54 | }, |
55 | [SIOCSIWMODE - SIOCIWFIRST] = { | 55 | [IW_IOCTL_IDX(SIOCSIWMODE)] = { |
56 | .header_type = IW_HEADER_TYPE_UINT, | 56 | .header_type = IW_HEADER_TYPE_UINT, |
57 | .flags = IW_DESCR_FLAG_EVENT, | 57 | .flags = IW_DESCR_FLAG_EVENT, |
58 | }, | 58 | }, |
59 | [SIOCGIWMODE - SIOCIWFIRST] = { | 59 | [IW_IOCTL_IDX(SIOCGIWMODE)] = { |
60 | .header_type = IW_HEADER_TYPE_UINT, | 60 | .header_type = IW_HEADER_TYPE_UINT, |
61 | .flags = IW_DESCR_FLAG_DUMP, | 61 | .flags = IW_DESCR_FLAG_DUMP, |
62 | }, | 62 | }, |
63 | [SIOCSIWSENS - SIOCIWFIRST] = { | 63 | [IW_IOCTL_IDX(SIOCSIWSENS)] = { |
64 | .header_type = IW_HEADER_TYPE_PARAM, | 64 | .header_type = IW_HEADER_TYPE_PARAM, |
65 | }, | 65 | }, |
66 | [SIOCGIWSENS - SIOCIWFIRST] = { | 66 | [IW_IOCTL_IDX(SIOCGIWSENS)] = { |
67 | .header_type = IW_HEADER_TYPE_PARAM, | 67 | .header_type = IW_HEADER_TYPE_PARAM, |
68 | }, | 68 | }, |
69 | [SIOCSIWRANGE - SIOCIWFIRST] = { | 69 | [IW_IOCTL_IDX(SIOCSIWRANGE)] = { |
70 | .header_type = IW_HEADER_TYPE_NULL, | 70 | .header_type = IW_HEADER_TYPE_NULL, |
71 | }, | 71 | }, |
72 | [SIOCGIWRANGE - SIOCIWFIRST] = { | 72 | [IW_IOCTL_IDX(SIOCGIWRANGE)] = { |
73 | .header_type = IW_HEADER_TYPE_POINT, | 73 | .header_type = IW_HEADER_TYPE_POINT, |
74 | .token_size = 1, | 74 | .token_size = 1, |
75 | .max_tokens = sizeof(struct iw_range), | 75 | .max_tokens = sizeof(struct iw_range), |
76 | .flags = IW_DESCR_FLAG_DUMP, | 76 | .flags = IW_DESCR_FLAG_DUMP, |
77 | }, | 77 | }, |
78 | [SIOCSIWPRIV - SIOCIWFIRST] = { | 78 | [IW_IOCTL_IDX(SIOCSIWPRIV)] = { |
79 | .header_type = IW_HEADER_TYPE_NULL, | 79 | .header_type = IW_HEADER_TYPE_NULL, |
80 | }, | 80 | }, |
81 | [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ | 81 | [IW_IOCTL_IDX(SIOCGIWPRIV)] = { /* (handled directly by us) */ |
82 | .header_type = IW_HEADER_TYPE_POINT, | 82 | .header_type = IW_HEADER_TYPE_POINT, |
83 | .token_size = sizeof(struct iw_priv_args), | 83 | .token_size = sizeof(struct iw_priv_args), |
84 | .max_tokens = 16, | 84 | .max_tokens = 16, |
85 | .flags = IW_DESCR_FLAG_NOMAX, | 85 | .flags = IW_DESCR_FLAG_NOMAX, |
86 | }, | 86 | }, |
87 | [SIOCSIWSTATS - SIOCIWFIRST] = { | 87 | [IW_IOCTL_IDX(SIOCSIWSTATS)] = { |
88 | .header_type = IW_HEADER_TYPE_NULL, | 88 | .header_type = IW_HEADER_TYPE_NULL, |
89 | }, | 89 | }, |
90 | [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ | 90 | [IW_IOCTL_IDX(SIOCGIWSTATS)] = { /* (handled directly by us) */ |
91 | .header_type = IW_HEADER_TYPE_POINT, | 91 | .header_type = IW_HEADER_TYPE_POINT, |
92 | .token_size = 1, | 92 | .token_size = 1, |
93 | .max_tokens = sizeof(struct iw_statistics), | 93 | .max_tokens = sizeof(struct iw_statistics), |
94 | .flags = IW_DESCR_FLAG_DUMP, | 94 | .flags = IW_DESCR_FLAG_DUMP, |
95 | }, | 95 | }, |
96 | [SIOCSIWSPY - SIOCIWFIRST] = { | 96 | [IW_IOCTL_IDX(SIOCSIWSPY)] = { |
97 | .header_type = IW_HEADER_TYPE_POINT, | 97 | .header_type = IW_HEADER_TYPE_POINT, |
98 | .token_size = sizeof(struct sockaddr), | 98 | .token_size = sizeof(struct sockaddr), |
99 | .max_tokens = IW_MAX_SPY, | 99 | .max_tokens = IW_MAX_SPY, |
100 | }, | 100 | }, |
101 | [SIOCGIWSPY - SIOCIWFIRST] = { | 101 | [IW_IOCTL_IDX(SIOCGIWSPY)] = { |
102 | .header_type = IW_HEADER_TYPE_POINT, | 102 | .header_type = IW_HEADER_TYPE_POINT, |
103 | .token_size = sizeof(struct sockaddr) + | 103 | .token_size = sizeof(struct sockaddr) + |
104 | sizeof(struct iw_quality), | 104 | sizeof(struct iw_quality), |
105 | .max_tokens = IW_MAX_SPY, | 105 | .max_tokens = IW_MAX_SPY, |
106 | }, | 106 | }, |
107 | [SIOCSIWTHRSPY - SIOCIWFIRST] = { | 107 | [IW_IOCTL_IDX(SIOCSIWTHRSPY)] = { |
108 | .header_type = IW_HEADER_TYPE_POINT, | 108 | .header_type = IW_HEADER_TYPE_POINT, |
109 | .token_size = sizeof(struct iw_thrspy), | 109 | .token_size = sizeof(struct iw_thrspy), |
110 | .min_tokens = 1, | 110 | .min_tokens = 1, |
111 | .max_tokens = 1, | 111 | .max_tokens = 1, |
112 | }, | 112 | }, |
113 | [SIOCGIWTHRSPY - SIOCIWFIRST] = { | 113 | [IW_IOCTL_IDX(SIOCGIWTHRSPY)] = { |
114 | .header_type = IW_HEADER_TYPE_POINT, | 114 | .header_type = IW_HEADER_TYPE_POINT, |
115 | .token_size = sizeof(struct iw_thrspy), | 115 | .token_size = sizeof(struct iw_thrspy), |
116 | .min_tokens = 1, | 116 | .min_tokens = 1, |
117 | .max_tokens = 1, | 117 | .max_tokens = 1, |
118 | }, | 118 | }, |
119 | [SIOCSIWAP - SIOCIWFIRST] = { | 119 | [IW_IOCTL_IDX(SIOCSIWAP)] = { |
120 | .header_type = IW_HEADER_TYPE_ADDR, | 120 | .header_type = IW_HEADER_TYPE_ADDR, |
121 | }, | 121 | }, |
122 | [SIOCGIWAP - SIOCIWFIRST] = { | 122 | [IW_IOCTL_IDX(SIOCGIWAP)] = { |
123 | .header_type = IW_HEADER_TYPE_ADDR, | 123 | .header_type = IW_HEADER_TYPE_ADDR, |
124 | .flags = IW_DESCR_FLAG_DUMP, | 124 | .flags = IW_DESCR_FLAG_DUMP, |
125 | }, | 125 | }, |
126 | [SIOCSIWMLME - SIOCIWFIRST] = { | 126 | [IW_IOCTL_IDX(SIOCSIWMLME)] = { |
127 | .header_type = IW_HEADER_TYPE_POINT, | 127 | .header_type = IW_HEADER_TYPE_POINT, |
128 | .token_size = 1, | 128 | .token_size = 1, |
129 | .min_tokens = sizeof(struct iw_mlme), | 129 | .min_tokens = sizeof(struct iw_mlme), |
130 | .max_tokens = sizeof(struct iw_mlme), | 130 | .max_tokens = sizeof(struct iw_mlme), |
131 | }, | 131 | }, |
132 | [SIOCGIWAPLIST - SIOCIWFIRST] = { | 132 | [IW_IOCTL_IDX(SIOCGIWAPLIST)] = { |
133 | .header_type = IW_HEADER_TYPE_POINT, | 133 | .header_type = IW_HEADER_TYPE_POINT, |
134 | .token_size = sizeof(struct sockaddr) + | 134 | .token_size = sizeof(struct sockaddr) + |
135 | sizeof(struct iw_quality), | 135 | sizeof(struct iw_quality), |
136 | .max_tokens = IW_MAX_AP, | 136 | .max_tokens = IW_MAX_AP, |
137 | .flags = IW_DESCR_FLAG_NOMAX, | 137 | .flags = IW_DESCR_FLAG_NOMAX, |
138 | }, | 138 | }, |
139 | [SIOCSIWSCAN - SIOCIWFIRST] = { | 139 | [IW_IOCTL_IDX(SIOCSIWSCAN)] = { |
140 | .header_type = IW_HEADER_TYPE_POINT, | 140 | .header_type = IW_HEADER_TYPE_POINT, |
141 | .token_size = 1, | 141 | .token_size = 1, |
142 | .min_tokens = 0, | 142 | .min_tokens = 0, |
143 | .max_tokens = sizeof(struct iw_scan_req), | 143 | .max_tokens = sizeof(struct iw_scan_req), |
144 | }, | 144 | }, |
145 | [SIOCGIWSCAN - SIOCIWFIRST] = { | 145 | [IW_IOCTL_IDX(SIOCGIWSCAN)] = { |
146 | .header_type = IW_HEADER_TYPE_POINT, | 146 | .header_type = IW_HEADER_TYPE_POINT, |
147 | .token_size = 1, | 147 | .token_size = 1, |
148 | .max_tokens = IW_SCAN_MAX_DATA, | 148 | .max_tokens = IW_SCAN_MAX_DATA, |
149 | .flags = IW_DESCR_FLAG_NOMAX, | 149 | .flags = IW_DESCR_FLAG_NOMAX, |
150 | }, | 150 | }, |
151 | [SIOCSIWESSID - SIOCIWFIRST] = { | 151 | [IW_IOCTL_IDX(SIOCSIWESSID)] = { |
152 | .header_type = IW_HEADER_TYPE_POINT, | 152 | .header_type = IW_HEADER_TYPE_POINT, |
153 | .token_size = 1, | 153 | .token_size = 1, |
154 | .max_tokens = IW_ESSID_MAX_SIZE, | 154 | .max_tokens = IW_ESSID_MAX_SIZE, |
155 | .flags = IW_DESCR_FLAG_EVENT, | 155 | .flags = IW_DESCR_FLAG_EVENT, |
156 | }, | 156 | }, |
157 | [SIOCGIWESSID - SIOCIWFIRST] = { | 157 | [IW_IOCTL_IDX(SIOCGIWESSID)] = { |
158 | .header_type = IW_HEADER_TYPE_POINT, | 158 | .header_type = IW_HEADER_TYPE_POINT, |
159 | .token_size = 1, | 159 | .token_size = 1, |
160 | .max_tokens = IW_ESSID_MAX_SIZE, | 160 | .max_tokens = IW_ESSID_MAX_SIZE, |
161 | .flags = IW_DESCR_FLAG_DUMP, | 161 | .flags = IW_DESCR_FLAG_DUMP, |
162 | }, | 162 | }, |
163 | [SIOCSIWNICKN - SIOCIWFIRST] = { | 163 | [IW_IOCTL_IDX(SIOCSIWNICKN)] = { |
164 | .header_type = IW_HEADER_TYPE_POINT, | 164 | .header_type = IW_HEADER_TYPE_POINT, |
165 | .token_size = 1, | 165 | .token_size = 1, |
166 | .max_tokens = IW_ESSID_MAX_SIZE, | 166 | .max_tokens = IW_ESSID_MAX_SIZE, |
167 | }, | 167 | }, |
168 | [SIOCGIWNICKN - SIOCIWFIRST] = { | 168 | [IW_IOCTL_IDX(SIOCGIWNICKN)] = { |
169 | .header_type = IW_HEADER_TYPE_POINT, | 169 | .header_type = IW_HEADER_TYPE_POINT, |
170 | .token_size = 1, | 170 | .token_size = 1, |
171 | .max_tokens = IW_ESSID_MAX_SIZE, | 171 | .max_tokens = IW_ESSID_MAX_SIZE, |
172 | }, | 172 | }, |
173 | [SIOCSIWRATE - SIOCIWFIRST] = { | 173 | [IW_IOCTL_IDX(SIOCSIWRATE)] = { |
174 | .header_type = IW_HEADER_TYPE_PARAM, | 174 | .header_type = IW_HEADER_TYPE_PARAM, |
175 | }, | 175 | }, |
176 | [SIOCGIWRATE - SIOCIWFIRST] = { | 176 | [IW_IOCTL_IDX(SIOCGIWRATE)] = { |
177 | .header_type = IW_HEADER_TYPE_PARAM, | 177 | .header_type = IW_HEADER_TYPE_PARAM, |
178 | }, | 178 | }, |
179 | [SIOCSIWRTS - SIOCIWFIRST] = { | 179 | [IW_IOCTL_IDX(SIOCSIWRTS)] = { |
180 | .header_type = IW_HEADER_TYPE_PARAM, | 180 | .header_type = IW_HEADER_TYPE_PARAM, |
181 | }, | 181 | }, |
182 | [SIOCGIWRTS - SIOCIWFIRST] = { | 182 | [IW_IOCTL_IDX(SIOCGIWRTS)] = { |
183 | .header_type = IW_HEADER_TYPE_PARAM, | 183 | .header_type = IW_HEADER_TYPE_PARAM, |
184 | }, | 184 | }, |
185 | [SIOCSIWFRAG - SIOCIWFIRST] = { | 185 | [IW_IOCTL_IDX(SIOCSIWFRAG)] = { |
186 | .header_type = IW_HEADER_TYPE_PARAM, | 186 | .header_type = IW_HEADER_TYPE_PARAM, |
187 | }, | 187 | }, |
188 | [SIOCGIWFRAG - SIOCIWFIRST] = { | 188 | [IW_IOCTL_IDX(SIOCGIWFRAG)] = { |
189 | .header_type = IW_HEADER_TYPE_PARAM, | 189 | .header_type = IW_HEADER_TYPE_PARAM, |
190 | }, | 190 | }, |
191 | [SIOCSIWTXPOW - SIOCIWFIRST] = { | 191 | [IW_IOCTL_IDX(SIOCSIWTXPOW)] = { |
192 | .header_type = IW_HEADER_TYPE_PARAM, | 192 | .header_type = IW_HEADER_TYPE_PARAM, |
193 | }, | 193 | }, |
194 | [SIOCGIWTXPOW - SIOCIWFIRST] = { | 194 | [IW_IOCTL_IDX(SIOCGIWTXPOW)] = { |
195 | .header_type = IW_HEADER_TYPE_PARAM, | 195 | .header_type = IW_HEADER_TYPE_PARAM, |
196 | }, | 196 | }, |
197 | [SIOCSIWRETRY - SIOCIWFIRST] = { | 197 | [IW_IOCTL_IDX(SIOCSIWRETRY)] = { |
198 | .header_type = IW_HEADER_TYPE_PARAM, | 198 | .header_type = IW_HEADER_TYPE_PARAM, |
199 | }, | 199 | }, |
200 | [SIOCGIWRETRY - SIOCIWFIRST] = { | 200 | [IW_IOCTL_IDX(SIOCGIWRETRY)] = { |
201 | .header_type = IW_HEADER_TYPE_PARAM, | 201 | .header_type = IW_HEADER_TYPE_PARAM, |
202 | }, | 202 | }, |
203 | [SIOCSIWENCODE - SIOCIWFIRST] = { | 203 | [IW_IOCTL_IDX(SIOCSIWENCODE)] = { |
204 | .header_type = IW_HEADER_TYPE_POINT, | 204 | .header_type = IW_HEADER_TYPE_POINT, |
205 | .token_size = 1, | 205 | .token_size = 1, |
206 | .max_tokens = IW_ENCODING_TOKEN_MAX, | 206 | .max_tokens = IW_ENCODING_TOKEN_MAX, |
207 | .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT, | 207 | .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT, |
208 | }, | 208 | }, |
209 | [SIOCGIWENCODE - SIOCIWFIRST] = { | 209 | [IW_IOCTL_IDX(SIOCGIWENCODE)] = { |
210 | .header_type = IW_HEADER_TYPE_POINT, | 210 | .header_type = IW_HEADER_TYPE_POINT, |
211 | .token_size = 1, | 211 | .token_size = 1, |
212 | .max_tokens = IW_ENCODING_TOKEN_MAX, | 212 | .max_tokens = IW_ENCODING_TOKEN_MAX, |
213 | .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT, | 213 | .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT, |
214 | }, | 214 | }, |
215 | [SIOCSIWPOWER - SIOCIWFIRST] = { | 215 | [IW_IOCTL_IDX(SIOCSIWPOWER)] = { |
216 | .header_type = IW_HEADER_TYPE_PARAM, | 216 | .header_type = IW_HEADER_TYPE_PARAM, |
217 | }, | 217 | }, |
218 | [SIOCGIWPOWER - SIOCIWFIRST] = { | 218 | [IW_IOCTL_IDX(SIOCGIWPOWER)] = { |
219 | .header_type = IW_HEADER_TYPE_PARAM, | 219 | .header_type = IW_HEADER_TYPE_PARAM, |
220 | }, | 220 | }, |
221 | [SIOCSIWGENIE - SIOCIWFIRST] = { | 221 | [IW_IOCTL_IDX(SIOCSIWGENIE)] = { |
222 | .header_type = IW_HEADER_TYPE_POINT, | 222 | .header_type = IW_HEADER_TYPE_POINT, |
223 | .token_size = 1, | 223 | .token_size = 1, |
224 | .max_tokens = IW_GENERIC_IE_MAX, | 224 | .max_tokens = IW_GENERIC_IE_MAX, |
225 | }, | 225 | }, |
226 | [SIOCGIWGENIE - SIOCIWFIRST] = { | 226 | [IW_IOCTL_IDX(SIOCGIWGENIE)] = { |
227 | .header_type = IW_HEADER_TYPE_POINT, | 227 | .header_type = IW_HEADER_TYPE_POINT, |
228 | .token_size = 1, | 228 | .token_size = 1, |
229 | .max_tokens = IW_GENERIC_IE_MAX, | 229 | .max_tokens = IW_GENERIC_IE_MAX, |
230 | }, | 230 | }, |
231 | [SIOCSIWAUTH - SIOCIWFIRST] = { | 231 | [IW_IOCTL_IDX(SIOCSIWAUTH)] = { |
232 | .header_type = IW_HEADER_TYPE_PARAM, | 232 | .header_type = IW_HEADER_TYPE_PARAM, |
233 | }, | 233 | }, |
234 | [SIOCGIWAUTH - SIOCIWFIRST] = { | 234 | [IW_IOCTL_IDX(SIOCGIWAUTH)] = { |
235 | .header_type = IW_HEADER_TYPE_PARAM, | 235 | .header_type = IW_HEADER_TYPE_PARAM, |
236 | }, | 236 | }, |
237 | [SIOCSIWENCODEEXT - SIOCIWFIRST] = { | 237 | [IW_IOCTL_IDX(SIOCSIWENCODEEXT)] = { |
238 | .header_type = IW_HEADER_TYPE_POINT, | 238 | .header_type = IW_HEADER_TYPE_POINT, |
239 | .token_size = 1, | 239 | .token_size = 1, |
240 | .min_tokens = sizeof(struct iw_encode_ext), | 240 | .min_tokens = sizeof(struct iw_encode_ext), |
241 | .max_tokens = sizeof(struct iw_encode_ext) + | 241 | .max_tokens = sizeof(struct iw_encode_ext) + |
242 | IW_ENCODING_TOKEN_MAX, | 242 | IW_ENCODING_TOKEN_MAX, |
243 | }, | 243 | }, |
244 | [SIOCGIWENCODEEXT - SIOCIWFIRST] = { | 244 | [IW_IOCTL_IDX(SIOCGIWENCODEEXT)] = { |
245 | .header_type = IW_HEADER_TYPE_POINT, | 245 | .header_type = IW_HEADER_TYPE_POINT, |
246 | .token_size = 1, | 246 | .token_size = 1, |
247 | .min_tokens = sizeof(struct iw_encode_ext), | 247 | .min_tokens = sizeof(struct iw_encode_ext), |
248 | .max_tokens = sizeof(struct iw_encode_ext) + | 248 | .max_tokens = sizeof(struct iw_encode_ext) + |
249 | IW_ENCODING_TOKEN_MAX, | 249 | IW_ENCODING_TOKEN_MAX, |
250 | }, | 250 | }, |
251 | [SIOCSIWPMKSA - SIOCIWFIRST] = { | 251 | [IW_IOCTL_IDX(SIOCSIWPMKSA)] = { |
252 | .header_type = IW_HEADER_TYPE_POINT, | 252 | .header_type = IW_HEADER_TYPE_POINT, |
253 | .token_size = 1, | 253 | .token_size = 1, |
254 | .min_tokens = sizeof(struct iw_pmksa), | 254 | .min_tokens = sizeof(struct iw_pmksa), |
@@ -262,44 +262,44 @@ static const unsigned standard_ioctl_num = ARRAY_SIZE(standard_ioctl); | |||
262 | * we know about. | 262 | * we know about. |
263 | */ | 263 | */ |
264 | static const struct iw_ioctl_description standard_event[] = { | 264 | static const struct iw_ioctl_description standard_event[] = { |
265 | [IWEVTXDROP - IWEVFIRST] = { | 265 | [IW_EVENT_IDX(IWEVTXDROP)] = { |
266 | .header_type = IW_HEADER_TYPE_ADDR, | 266 | .header_type = IW_HEADER_TYPE_ADDR, |
267 | }, | 267 | }, |
268 | [IWEVQUAL - IWEVFIRST] = { | 268 | [IW_EVENT_IDX(IWEVQUAL)] = { |
269 | .header_type = IW_HEADER_TYPE_QUAL, | 269 | .header_type = IW_HEADER_TYPE_QUAL, |
270 | }, | 270 | }, |
271 | [IWEVCUSTOM - IWEVFIRST] = { | 271 | [IW_EVENT_IDX(IWEVCUSTOM)] = { |
272 | .header_type = IW_HEADER_TYPE_POINT, | 272 | .header_type = IW_HEADER_TYPE_POINT, |
273 | .token_size = 1, | 273 | .token_size = 1, |
274 | .max_tokens = IW_CUSTOM_MAX, | 274 | .max_tokens = IW_CUSTOM_MAX, |
275 | }, | 275 | }, |
276 | [IWEVREGISTERED - IWEVFIRST] = { | 276 | [IW_EVENT_IDX(IWEVREGISTERED)] = { |
277 | .header_type = IW_HEADER_TYPE_ADDR, | 277 | .header_type = IW_HEADER_TYPE_ADDR, |
278 | }, | 278 | }, |
279 | [IWEVEXPIRED - IWEVFIRST] = { | 279 | [IW_EVENT_IDX(IWEVEXPIRED)] = { |
280 | .header_type = IW_HEADER_TYPE_ADDR, | 280 | .header_type = IW_HEADER_TYPE_ADDR, |
281 | }, | 281 | }, |
282 | [IWEVGENIE - IWEVFIRST] = { | 282 | [IW_EVENT_IDX(IWEVGENIE)] = { |
283 | .header_type = IW_HEADER_TYPE_POINT, | 283 | .header_type = IW_HEADER_TYPE_POINT, |
284 | .token_size = 1, | 284 | .token_size = 1, |
285 | .max_tokens = IW_GENERIC_IE_MAX, | 285 | .max_tokens = IW_GENERIC_IE_MAX, |
286 | }, | 286 | }, |
287 | [IWEVMICHAELMICFAILURE - IWEVFIRST] = { | 287 | [IW_EVENT_IDX(IWEVMICHAELMICFAILURE)] = { |
288 | .header_type = IW_HEADER_TYPE_POINT, | 288 | .header_type = IW_HEADER_TYPE_POINT, |
289 | .token_size = 1, | 289 | .token_size = 1, |
290 | .max_tokens = sizeof(struct iw_michaelmicfailure), | 290 | .max_tokens = sizeof(struct iw_michaelmicfailure), |
291 | }, | 291 | }, |
292 | [IWEVASSOCREQIE - IWEVFIRST] = { | 292 | [IW_EVENT_IDX(IWEVASSOCREQIE)] = { |
293 | .header_type = IW_HEADER_TYPE_POINT, | 293 | .header_type = IW_HEADER_TYPE_POINT, |
294 | .token_size = 1, | 294 | .token_size = 1, |
295 | .max_tokens = IW_GENERIC_IE_MAX, | 295 | .max_tokens = IW_GENERIC_IE_MAX, |
296 | }, | 296 | }, |
297 | [IWEVASSOCRESPIE - IWEVFIRST] = { | 297 | [IW_EVENT_IDX(IWEVASSOCRESPIE)] = { |
298 | .header_type = IW_HEADER_TYPE_POINT, | 298 | .header_type = IW_HEADER_TYPE_POINT, |
299 | .token_size = 1, | 299 | .token_size = 1, |
300 | .max_tokens = IW_GENERIC_IE_MAX, | 300 | .max_tokens = IW_GENERIC_IE_MAX, |
301 | }, | 301 | }, |
302 | [IWEVPMKIDCAND - IWEVFIRST] = { | 302 | [IW_EVENT_IDX(IWEVPMKIDCAND)] = { |
303 | .header_type = IW_HEADER_TYPE_POINT, | 303 | .header_type = IW_HEADER_TYPE_POINT, |
304 | .token_size = 1, | 304 | .token_size = 1, |
305 | .max_tokens = sizeof(struct iw_pmkid_cand), | 305 | .max_tokens = sizeof(struct iw_pmkid_cand), |
@@ -450,11 +450,11 @@ void wireless_send_event(struct net_device * dev, | |||
450 | 450 | ||
451 | /* Get the description of the Event */ | 451 | /* Get the description of the Event */ |
452 | if (cmd <= SIOCIWLAST) { | 452 | if (cmd <= SIOCIWLAST) { |
453 | cmd_index = cmd - SIOCIWFIRST; | 453 | cmd_index = IW_IOCTL_IDX(cmd); |
454 | if (cmd_index < standard_ioctl_num) | 454 | if (cmd_index < standard_ioctl_num) |
455 | descr = &(standard_ioctl[cmd_index]); | 455 | descr = &(standard_ioctl[cmd_index]); |
456 | } else { | 456 | } else { |
457 | cmd_index = cmd - IWEVFIRST; | 457 | cmd_index = IW_EVENT_IDX(cmd); |
458 | if (cmd_index < standard_event_num) | 458 | if (cmd_index < standard_event_num) |
459 | descr = &(standard_event[cmd_index]); | 459 | descr = &(standard_event[cmd_index]); |
460 | } | 460 | } |
@@ -663,7 +663,7 @@ static iw_handler get_handler(struct net_device *dev, unsigned int cmd) | |||
663 | return NULL; | 663 | return NULL; |
664 | 664 | ||
665 | /* Try as a standard command */ | 665 | /* Try as a standard command */ |
666 | index = cmd - SIOCIWFIRST; | 666 | index = IW_IOCTL_IDX(cmd); |
667 | if (index < handlers->num_standard) | 667 | if (index < handlers->num_standard) |
668 | return handlers->standard[index]; | 668 | return handlers->standard[index]; |
669 | 669 | ||
@@ -955,9 +955,9 @@ static int ioctl_standard_call(struct net_device * dev, | |||
955 | int ret = -EINVAL; | 955 | int ret = -EINVAL; |
956 | 956 | ||
957 | /* Get the description of the IOCTL */ | 957 | /* Get the description of the IOCTL */ |
958 | if ((cmd - SIOCIWFIRST) >= standard_ioctl_num) | 958 | if (IW_IOCTL_IDX(cmd) >= standard_ioctl_num) |
959 | return -EOPNOTSUPP; | 959 | return -EOPNOTSUPP; |
960 | descr = &(standard_ioctl[cmd - SIOCIWFIRST]); | 960 | descr = &(standard_ioctl[IW_IOCTL_IDX(cmd)]); |
961 | 961 | ||
962 | /* Check if we have a pointer to user space data or not */ | 962 | /* Check if we have a pointer to user space data or not */ |
963 | if (descr->header_type != IW_HEADER_TYPE_POINT) { | 963 | if (descr->header_type != IW_HEADER_TYPE_POINT) { |
@@ -1013,7 +1013,7 @@ static int compat_standard_call(struct net_device *dev, | |||
1013 | struct iw_point iwp; | 1013 | struct iw_point iwp; |
1014 | int err; | 1014 | int err; |
1015 | 1015 | ||
1016 | descr = standard_ioctl + (cmd - SIOCIWFIRST); | 1016 | descr = standard_ioctl + IW_IOCTL_IDX(cmd); |
1017 | 1017 | ||
1018 | if (descr->header_type != IW_HEADER_TYPE_POINT) | 1018 | if (descr->header_type != IW_HEADER_TYPE_POINT) |
1019 | return ioctl_standard_call(dev, iwr, cmd, info, handler); | 1019 | return ioctl_standard_call(dev, iwr, cmd, info, handler); |
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index d5c6140f4cb8..9818198add8a 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -108,7 +108,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
108 | 108 | ||
109 | /* SSID is not set, we just want to switch channel */ | 109 | /* SSID is not set, we just want to switch channel */ |
110 | if (chan && !wdev->wext.connect.ssid_len) { | 110 | if (chan && !wdev->wext.connect.ssid_len) { |
111 | err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); | 111 | err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); |
112 | goto out; | 112 | goto out; |
113 | } | 113 | } |
114 | 114 | ||
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 36e84e13c6aa..5e86d4e97dce 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -453,7 +453,6 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, | |||
453 | struct sock *sk = sock->sk; | 453 | struct sock *sk = sock->sk; |
454 | int rc = -ENOPROTOOPT; | 454 | int rc = -ENOPROTOOPT; |
455 | 455 | ||
456 | lock_kernel(); | ||
457 | if (level != SOL_X25 || optname != X25_QBITINCL) | 456 | if (level != SOL_X25 || optname != X25_QBITINCL) |
458 | goto out; | 457 | goto out; |
459 | 458 | ||
@@ -465,10 +464,12 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, | |||
465 | if (get_user(opt, (int __user *)optval)) | 464 | if (get_user(opt, (int __user *)optval)) |
466 | goto out; | 465 | goto out; |
467 | 466 | ||
468 | x25_sk(sk)->qbitincl = !!opt; | 467 | if (opt) |
468 | set_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags); | ||
469 | else | ||
470 | clear_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags); | ||
469 | rc = 0; | 471 | rc = 0; |
470 | out: | 472 | out: |
471 | unlock_kernel(); | ||
472 | return rc; | 473 | return rc; |
473 | } | 474 | } |
474 | 475 | ||
@@ -478,7 +479,6 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
478 | struct sock *sk = sock->sk; | 479 | struct sock *sk = sock->sk; |
479 | int val, len, rc = -ENOPROTOOPT; | 480 | int val, len, rc = -ENOPROTOOPT; |
480 | 481 | ||
481 | lock_kernel(); | ||
482 | if (level != SOL_X25 || optname != X25_QBITINCL) | 482 | if (level != SOL_X25 || optname != X25_QBITINCL) |
483 | goto out; | 483 | goto out; |
484 | 484 | ||
@@ -496,10 +496,9 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
496 | if (put_user(len, optlen)) | 496 | if (put_user(len, optlen)) |
497 | goto out; | 497 | goto out; |
498 | 498 | ||
499 | val = x25_sk(sk)->qbitincl; | 499 | val = test_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags); |
500 | rc = copy_to_user(optval, &val, len) ? -EFAULT : 0; | 500 | rc = copy_to_user(optval, &val, len) ? -EFAULT : 0; |
501 | out: | 501 | out: |
502 | unlock_kernel(); | ||
503 | return rc; | 502 | return rc; |
504 | } | 503 | } |
505 | 504 | ||
@@ -583,7 +582,7 @@ static int x25_create(struct net *net, struct socket *sock, int protocol, | |||
583 | x25->t2 = sysctl_x25_ack_holdback_timeout; | 582 | x25->t2 = sysctl_x25_ack_holdback_timeout; |
584 | x25->state = X25_STATE_0; | 583 | x25->state = X25_STATE_0; |
585 | x25->cudmatchlength = 0; | 584 | x25->cudmatchlength = 0; |
586 | x25->accptapprv = X25_DENY_ACCPT_APPRV; /* normally no cud */ | 585 | set_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); /* normally no cud */ |
587 | /* on call accept */ | 586 | /* on call accept */ |
588 | 587 | ||
589 | x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE; | 588 | x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE; |
@@ -632,12 +631,12 @@ static struct sock *x25_make_new(struct sock *osk) | |||
632 | x25->t22 = ox25->t22; | 631 | x25->t22 = ox25->t22; |
633 | x25->t23 = ox25->t23; | 632 | x25->t23 = ox25->t23; |
634 | x25->t2 = ox25->t2; | 633 | x25->t2 = ox25->t2; |
634 | x25->flags = ox25->flags; | ||
635 | x25->facilities = ox25->facilities; | 635 | x25->facilities = ox25->facilities; |
636 | x25->qbitincl = ox25->qbitincl; | ||
637 | x25->dte_facilities = ox25->dte_facilities; | 636 | x25->dte_facilities = ox25->dte_facilities; |
638 | x25->cudmatchlength = ox25->cudmatchlength; | 637 | x25->cudmatchlength = ox25->cudmatchlength; |
639 | x25->accptapprv = ox25->accptapprv; | ||
640 | 638 | ||
639 | clear_bit(X25_INTERRUPT_FLAG, &x25->flags); | ||
641 | x25_init_timers(sk); | 640 | x25_init_timers(sk); |
642 | out: | 641 | out: |
643 | return sk; | 642 | return sk; |
@@ -719,7 +718,7 @@ static int x25_wait_for_connection_establishment(struct sock *sk) | |||
719 | DECLARE_WAITQUEUE(wait, current); | 718 | DECLARE_WAITQUEUE(wait, current); |
720 | int rc; | 719 | int rc; |
721 | 720 | ||
722 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 721 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
723 | for (;;) { | 722 | for (;;) { |
724 | __set_current_state(TASK_INTERRUPTIBLE); | 723 | __set_current_state(TASK_INTERRUPTIBLE); |
725 | rc = -ERESTARTSYS; | 724 | rc = -ERESTARTSYS; |
@@ -739,7 +738,7 @@ static int x25_wait_for_connection_establishment(struct sock *sk) | |||
739 | break; | 738 | break; |
740 | } | 739 | } |
741 | __set_current_state(TASK_RUNNING); | 740 | __set_current_state(TASK_RUNNING); |
742 | remove_wait_queue(sk->sk_sleep, &wait); | 741 | remove_wait_queue(sk_sleep(sk), &wait); |
743 | return rc; | 742 | return rc; |
744 | } | 743 | } |
745 | 744 | ||
@@ -839,7 +838,7 @@ static int x25_wait_for_data(struct sock *sk, long timeout) | |||
839 | DECLARE_WAITQUEUE(wait, current); | 838 | DECLARE_WAITQUEUE(wait, current); |
840 | int rc = 0; | 839 | int rc = 0; |
841 | 840 | ||
842 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 841 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
843 | for (;;) { | 842 | for (;;) { |
844 | __set_current_state(TASK_INTERRUPTIBLE); | 843 | __set_current_state(TASK_INTERRUPTIBLE); |
845 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 844 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
@@ -859,7 +858,7 @@ static int x25_wait_for_data(struct sock *sk, long timeout) | |||
859 | break; | 858 | break; |
860 | } | 859 | } |
861 | __set_current_state(TASK_RUNNING); | 860 | __set_current_state(TASK_RUNNING); |
862 | remove_wait_queue(sk->sk_sleep, &wait); | 861 | remove_wait_queue(sk_sleep(sk), &wait); |
863 | return rc; | 862 | return rc; |
864 | } | 863 | } |
865 | 864 | ||
@@ -1053,8 +1052,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
1053 | makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE; | 1052 | makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE; |
1054 | makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; | 1053 | makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; |
1055 | 1054 | ||
1056 | /* Normally all calls are accepted immediatly */ | 1055 | /* Normally all calls are accepted immediately */ |
1057 | if(makex25->accptapprv & X25_DENY_ACCPT_APPRV) { | 1056 | if (test_bit(X25_ACCPT_APPRV_FLAG, &makex25->flags)) { |
1058 | x25_write_internal(make, X25_CALL_ACCEPTED); | 1057 | x25_write_internal(make, X25_CALL_ACCEPTED); |
1059 | makex25->state = X25_STATE_3; | 1058 | makex25->state = X25_STATE_3; |
1060 | } | 1059 | } |
@@ -1186,7 +1185,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1186 | * If the Q BIT Include socket option is in force, the first | 1185 | * If the Q BIT Include socket option is in force, the first |
1187 | * byte of the user data is the logical value of the Q Bit. | 1186 | * byte of the user data is the logical value of the Q Bit. |
1188 | */ | 1187 | */ |
1189 | if (x25->qbitincl) { | 1188 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { |
1190 | qbit = skb->data[0]; | 1189 | qbit = skb->data[0]; |
1191 | skb_pull(skb, 1); | 1190 | skb_pull(skb, 1); |
1192 | } | 1191 | } |
@@ -1242,7 +1241,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1242 | len = rc; | 1241 | len = rc; |
1243 | if (rc < 0) | 1242 | if (rc < 0) |
1244 | kfree_skb(skb); | 1243 | kfree_skb(skb); |
1245 | else if (x25->qbitincl) | 1244 | else if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) |
1246 | len++; | 1245 | len++; |
1247 | } | 1246 | } |
1248 | 1247 | ||
@@ -1307,7 +1306,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1307 | /* | 1306 | /* |
1308 | * No Q bit information on Interrupt data. | 1307 | * No Q bit information on Interrupt data. |
1309 | */ | 1308 | */ |
1310 | if (x25->qbitincl) { | 1309 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { |
1311 | asmptr = skb_push(skb, 1); | 1310 | asmptr = skb_push(skb, 1); |
1312 | *asmptr = 0x00; | 1311 | *asmptr = 0x00; |
1313 | } | 1312 | } |
@@ -1325,7 +1324,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1325 | skb_pull(skb, x25->neighbour->extended ? | 1324 | skb_pull(skb, x25->neighbour->extended ? |
1326 | X25_EXT_MIN_LEN : X25_STD_MIN_LEN); | 1325 | X25_EXT_MIN_LEN : X25_STD_MIN_LEN); |
1327 | 1326 | ||
1328 | if (x25->qbitincl) { | 1327 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { |
1329 | asmptr = skb_push(skb, 1); | 1328 | asmptr = skb_push(skb, 1); |
1330 | *asmptr = qbit; | 1329 | *asmptr = qbit; |
1331 | } | 1330 | } |
@@ -1576,7 +1575,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1576 | rc = -EINVAL; | 1575 | rc = -EINVAL; |
1577 | if (sk->sk_state != TCP_CLOSE) | 1576 | if (sk->sk_state != TCP_CLOSE) |
1578 | break; | 1577 | break; |
1579 | x25->accptapprv = X25_ALLOW_ACCPT_APPRV; | 1578 | clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); |
1580 | rc = 0; | 1579 | rc = 0; |
1581 | break; | 1580 | break; |
1582 | } | 1581 | } |
@@ -1585,7 +1584,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1585 | rc = -EINVAL; | 1584 | rc = -EINVAL; |
1586 | if (sk->sk_state != TCP_ESTABLISHED) | 1585 | if (sk->sk_state != TCP_ESTABLISHED) |
1587 | break; | 1586 | break; |
1588 | if (x25->accptapprv) /* must call accptapprv above */ | 1587 | /* must call accptapprv above */ |
1588 | if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags)) | ||
1589 | break; | 1589 | break; |
1590 | x25_write_internal(sk, X25_CALL_ACCEPTED); | 1590 | x25_write_internal(sk, X25_CALL_ACCEPTED); |
1591 | x25->state = X25_STATE_3; | 1591 | x25->state = X25_STATE_3; |
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index b9ef682230a0..9005f6daeab5 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <net/sock.h> | 24 | #include <net/sock.h> |
25 | #include <linux/if_arp.h> | 25 | #include <linux/if_arp.h> |
26 | #include <net/x25.h> | 26 | #include <net/x25.h> |
27 | #include <net/x25device.h> | ||
27 | 28 | ||
28 | static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) | 29 | static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) |
29 | { | 30 | { |
@@ -115,19 +116,22 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev, | |||
115 | } | 116 | } |
116 | 117 | ||
117 | switch (skb->data[0]) { | 118 | switch (skb->data[0]) { |
118 | case 0x00: | 119 | |
119 | skb_pull(skb, 1); | 120 | case X25_IFACE_DATA: |
120 | if (x25_receive_data(skb, nb)) { | 121 | skb_pull(skb, 1); |
121 | x25_neigh_put(nb); | 122 | if (x25_receive_data(skb, nb)) { |
122 | goto out; | 123 | x25_neigh_put(nb); |
123 | } | 124 | goto out; |
124 | break; | 125 | } |
125 | case 0x01: | 126 | break; |
126 | x25_link_established(nb); | 127 | |
127 | break; | 128 | case X25_IFACE_CONNECT: |
128 | case 0x02: | 129 | x25_link_established(nb); |
129 | x25_link_terminated(nb); | 130 | break; |
130 | break; | 131 | |
132 | case X25_IFACE_DISCONNECT: | ||
133 | x25_link_terminated(nb); | ||
134 | break; | ||
131 | } | 135 | } |
132 | x25_neigh_put(nb); | 136 | x25_neigh_put(nb); |
133 | drop: | 137 | drop: |
@@ -148,7 +152,7 @@ void x25_establish_link(struct x25_neigh *nb) | |||
148 | return; | 152 | return; |
149 | } | 153 | } |
150 | ptr = skb_put(skb, 1); | 154 | ptr = skb_put(skb, 1); |
151 | *ptr = 0x01; | 155 | *ptr = X25_IFACE_CONNECT; |
152 | break; | 156 | break; |
153 | 157 | ||
154 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) | 158 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) |
@@ -184,7 +188,7 @@ void x25_terminate_link(struct x25_neigh *nb) | |||
184 | } | 188 | } |
185 | 189 | ||
186 | ptr = skb_put(skb, 1); | 190 | ptr = skb_put(skb, 1); |
187 | *ptr = 0x02; | 191 | *ptr = X25_IFACE_DISCONNECT; |
188 | 192 | ||
189 | skb->protocol = htons(ETH_P_X25); | 193 | skb->protocol = htons(ETH_P_X25); |
190 | skb->dev = nb->dev; | 194 | skb->dev = nb->dev; |
@@ -200,7 +204,7 @@ void x25_send_frame(struct sk_buff *skb, struct x25_neigh *nb) | |||
200 | switch (nb->dev->type) { | 204 | switch (nb->dev->type) { |
201 | case ARPHRD_X25: | 205 | case ARPHRD_X25: |
202 | dptr = skb_push(skb, 1); | 206 | dptr = skb_push(skb, 1); |
203 | *dptr = 0x00; | 207 | *dptr = X25_IFACE_DATA; |
204 | break; | 208 | break; |
205 | 209 | ||
206 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) | 210 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) |
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 372ac226e648..63178961efac 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
@@ -273,7 +273,7 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
273 | break; | 273 | break; |
274 | 274 | ||
275 | case X25_INTERRUPT_CONFIRMATION: | 275 | case X25_INTERRUPT_CONFIRMATION: |
276 | x25->intflag = 0; | 276 | clear_bit(X25_INTERRUPT_FLAG, &x25->flags); |
277 | break; | 277 | break; |
278 | 278 | ||
279 | case X25_INTERRUPT: | 279 | case X25_INTERRUPT: |
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c index 52351a26b6fc..d00649fb251d 100644 --- a/net/x25/x25_out.c +++ b/net/x25/x25_out.c | |||
@@ -148,8 +148,9 @@ void x25_kick(struct sock *sk) | |||
148 | /* | 148 | /* |
149 | * Transmit interrupt data. | 149 | * Transmit interrupt data. |
150 | */ | 150 | */ |
151 | if (!x25->intflag && skb_peek(&x25->interrupt_out_queue) != NULL) { | 151 | if (skb_peek(&x25->interrupt_out_queue) != NULL && |
152 | x25->intflag = 1; | 152 | !test_and_set_bit(X25_INTERRUPT_FLAG, &x25->flags)) { |
153 | |||
153 | skb = skb_dequeue(&x25->interrupt_out_queue); | 154 | skb = skb_dequeue(&x25->interrupt_out_queue); |
154 | x25_transmit_link(skb, x25->neighbour); | 155 | x25_transmit_link(skb, x25->neighbour); |
155 | } | 156 | } |
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h index e5195c99f71e..8e69533d2313 100644 --- a/net/xfrm/xfrm_hash.h +++ b/net/xfrm/xfrm_hash.h | |||
@@ -16,7 +16,8 @@ static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) | |||
16 | 16 | ||
17 | static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | 17 | static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) |
18 | { | 18 | { |
19 | return ntohl(daddr->a4 + saddr->a4); | 19 | u32 sum = (__force u32)daddr->a4 + (__force u32)saddr->a4; |
20 | return ntohl((__force __be32)sum); | ||
20 | } | 21 | } |
21 | 22 | ||
22 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | 23 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) |
@@ -54,7 +55,7 @@ static inline unsigned __xfrm_src_hash(xfrm_address_t *daddr, | |||
54 | case AF_INET6: | 55 | case AF_INET6: |
55 | h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); | 56 | h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); |
56 | break; | 57 | break; |
57 | }; | 58 | } |
58 | return (h ^ (h >> 16)) & hmask; | 59 | return (h ^ (h >> 16)) & hmask; |
59 | } | 60 | } |
60 | 61 | ||
@@ -101,7 +102,7 @@ static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short | |||
101 | 102 | ||
102 | h = __xfrm6_daddr_saddr_hash(daddr, saddr); | 103 | h = __xfrm6_daddr_saddr_hash(daddr, saddr); |
103 | break; | 104 | break; |
104 | }; | 105 | } |
105 | h ^= (h >> 16); | 106 | h ^= (h >> 16); |
106 | return h & hmask; | 107 | return h & hmask; |
107 | } | 108 | } |
@@ -118,7 +119,7 @@ static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *sa | |||
118 | case AF_INET6: | 119 | case AF_INET6: |
119 | h = __xfrm6_daddr_saddr_hash(daddr, saddr); | 120 | h = __xfrm6_daddr_saddr_hash(daddr, saddr); |
120 | break; | 121 | break; |
121 | }; | 122 | } |
122 | h ^= (h >> 16); | 123 | h ^= (h >> 16); |
123 | return h & hmask; | 124 | return h & hmask; |
124 | } | 125 | } |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 843e066649cb..d965a2bad8d3 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -37,6 +37,8 @@ | |||
37 | DEFINE_MUTEX(xfrm_cfg_mutex); | 37 | DEFINE_MUTEX(xfrm_cfg_mutex); |
38 | EXPORT_SYMBOL(xfrm_cfg_mutex); | 38 | EXPORT_SYMBOL(xfrm_cfg_mutex); |
39 | 39 | ||
40 | static DEFINE_SPINLOCK(xfrm_policy_sk_bundle_lock); | ||
41 | static struct dst_entry *xfrm_policy_sk_bundles; | ||
40 | static DEFINE_RWLOCK(xfrm_policy_lock); | 42 | static DEFINE_RWLOCK(xfrm_policy_lock); |
41 | 43 | ||
42 | static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); | 44 | static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); |
@@ -44,12 +46,10 @@ static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; | |||
44 | 46 | ||
45 | static struct kmem_cache *xfrm_dst_cache __read_mostly; | 47 | static struct kmem_cache *xfrm_dst_cache __read_mostly; |
46 | 48 | ||
47 | static HLIST_HEAD(xfrm_policy_gc_list); | ||
48 | static DEFINE_SPINLOCK(xfrm_policy_gc_lock); | ||
49 | |||
50 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); | 49 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); |
51 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); | 50 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); |
52 | static void xfrm_init_pmtu(struct dst_entry *dst); | 51 | static void xfrm_init_pmtu(struct dst_entry *dst); |
52 | static int stale_bundle(struct dst_entry *dst); | ||
53 | 53 | ||
54 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | 54 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, |
55 | int dir); | 55 | int dir); |
@@ -156,7 +156,7 @@ static void xfrm_policy_timer(unsigned long data) | |||
156 | 156 | ||
157 | read_lock(&xp->lock); | 157 | read_lock(&xp->lock); |
158 | 158 | ||
159 | if (xp->walk.dead) | 159 | if (unlikely(xp->walk.dead)) |
160 | goto out; | 160 | goto out; |
161 | 161 | ||
162 | dir = xfrm_policy_id2dir(xp->index); | 162 | dir = xfrm_policy_id2dir(xp->index); |
@@ -216,6 +216,35 @@ expired: | |||
216 | xfrm_pol_put(xp); | 216 | xfrm_pol_put(xp); |
217 | } | 217 | } |
218 | 218 | ||
219 | static struct flow_cache_object *xfrm_policy_flo_get(struct flow_cache_object *flo) | ||
220 | { | ||
221 | struct xfrm_policy *pol = container_of(flo, struct xfrm_policy, flo); | ||
222 | |||
223 | if (unlikely(pol->walk.dead)) | ||
224 | flo = NULL; | ||
225 | else | ||
226 | xfrm_pol_hold(pol); | ||
227 | |||
228 | return flo; | ||
229 | } | ||
230 | |||
231 | static int xfrm_policy_flo_check(struct flow_cache_object *flo) | ||
232 | { | ||
233 | struct xfrm_policy *pol = container_of(flo, struct xfrm_policy, flo); | ||
234 | |||
235 | return !pol->walk.dead; | ||
236 | } | ||
237 | |||
238 | static void xfrm_policy_flo_delete(struct flow_cache_object *flo) | ||
239 | { | ||
240 | xfrm_pol_put(container_of(flo, struct xfrm_policy, flo)); | ||
241 | } | ||
242 | |||
243 | static const struct flow_cache_ops xfrm_policy_fc_ops = { | ||
244 | .get = xfrm_policy_flo_get, | ||
245 | .check = xfrm_policy_flo_check, | ||
246 | .delete = xfrm_policy_flo_delete, | ||
247 | }; | ||
219 | 248 | ||
220 | /* Allocate xfrm_policy. Not used here, it is supposed to be used by pfkeyv2 | 249 | /* Allocate xfrm_policy. Not used here, it is supposed to be used by pfkeyv2 |
221 | * SPD calls. | 250 | * SPD calls. |
@@ -236,6 +265,7 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp) | |||
236 | atomic_set(&policy->refcnt, 1); | 265 | atomic_set(&policy->refcnt, 1); |
237 | setup_timer(&policy->timer, xfrm_policy_timer, | 266 | setup_timer(&policy->timer, xfrm_policy_timer, |
238 | (unsigned long)policy); | 267 | (unsigned long)policy); |
268 | policy->flo.ops = &xfrm_policy_fc_ops; | ||
239 | } | 269 | } |
240 | return policy; | 270 | return policy; |
241 | } | 271 | } |
@@ -247,8 +277,6 @@ void xfrm_policy_destroy(struct xfrm_policy *policy) | |||
247 | { | 277 | { |
248 | BUG_ON(!policy->walk.dead); | 278 | BUG_ON(!policy->walk.dead); |
249 | 279 | ||
250 | BUG_ON(policy->bundles); | ||
251 | |||
252 | if (del_timer(&policy->timer)) | 280 | if (del_timer(&policy->timer)) |
253 | BUG(); | 281 | BUG(); |
254 | 282 | ||
@@ -257,63 +285,20 @@ void xfrm_policy_destroy(struct xfrm_policy *policy) | |||
257 | } | 285 | } |
258 | EXPORT_SYMBOL(xfrm_policy_destroy); | 286 | EXPORT_SYMBOL(xfrm_policy_destroy); |
259 | 287 | ||
260 | static void xfrm_policy_gc_kill(struct xfrm_policy *policy) | ||
261 | { | ||
262 | struct dst_entry *dst; | ||
263 | |||
264 | while ((dst = policy->bundles) != NULL) { | ||
265 | policy->bundles = dst->next; | ||
266 | dst_free(dst); | ||
267 | } | ||
268 | |||
269 | if (del_timer(&policy->timer)) | ||
270 | atomic_dec(&policy->refcnt); | ||
271 | |||
272 | if (atomic_read(&policy->refcnt) > 1) | ||
273 | flow_cache_flush(); | ||
274 | |||
275 | xfrm_pol_put(policy); | ||
276 | } | ||
277 | |||
278 | static void xfrm_policy_gc_task(struct work_struct *work) | ||
279 | { | ||
280 | struct xfrm_policy *policy; | ||
281 | struct hlist_node *entry, *tmp; | ||
282 | struct hlist_head gc_list; | ||
283 | |||
284 | spin_lock_bh(&xfrm_policy_gc_lock); | ||
285 | gc_list.first = xfrm_policy_gc_list.first; | ||
286 | INIT_HLIST_HEAD(&xfrm_policy_gc_list); | ||
287 | spin_unlock_bh(&xfrm_policy_gc_lock); | ||
288 | |||
289 | hlist_for_each_entry_safe(policy, entry, tmp, &gc_list, bydst) | ||
290 | xfrm_policy_gc_kill(policy); | ||
291 | } | ||
292 | static DECLARE_WORK(xfrm_policy_gc_work, xfrm_policy_gc_task); | ||
293 | |||
294 | /* Rule must be locked. Release descentant resources, announce | 288 | /* Rule must be locked. Release descentant resources, announce |
295 | * entry dead. The rule must be unlinked from lists to the moment. | 289 | * entry dead. The rule must be unlinked from lists to the moment. |
296 | */ | 290 | */ |
297 | 291 | ||
298 | static void xfrm_policy_kill(struct xfrm_policy *policy) | 292 | static void xfrm_policy_kill(struct xfrm_policy *policy) |
299 | { | 293 | { |
300 | int dead; | ||
301 | |||
302 | write_lock_bh(&policy->lock); | ||
303 | dead = policy->walk.dead; | ||
304 | policy->walk.dead = 1; | 294 | policy->walk.dead = 1; |
305 | write_unlock_bh(&policy->lock); | ||
306 | 295 | ||
307 | if (unlikely(dead)) { | 296 | atomic_inc(&policy->genid); |
308 | WARN_ON(1); | ||
309 | return; | ||
310 | } | ||
311 | 297 | ||
312 | spin_lock_bh(&xfrm_policy_gc_lock); | 298 | if (del_timer(&policy->timer)) |
313 | hlist_add_head(&policy->bydst, &xfrm_policy_gc_list); | 299 | xfrm_pol_put(policy); |
314 | spin_unlock_bh(&xfrm_policy_gc_lock); | ||
315 | 300 | ||
316 | schedule_work(&xfrm_policy_gc_work); | 301 | xfrm_pol_put(policy); |
317 | } | 302 | } |
318 | 303 | ||
319 | static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; | 304 | static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; |
@@ -555,7 +540,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
555 | struct xfrm_policy *delpol; | 540 | struct xfrm_policy *delpol; |
556 | struct hlist_head *chain; | 541 | struct hlist_head *chain; |
557 | struct hlist_node *entry, *newpos; | 542 | struct hlist_node *entry, *newpos; |
558 | struct dst_entry *gc_list; | ||
559 | u32 mark = policy->mark.v & policy->mark.m; | 543 | u32 mark = policy->mark.v & policy->mark.m; |
560 | 544 | ||
561 | write_lock_bh(&xfrm_policy_lock); | 545 | write_lock_bh(&xfrm_policy_lock); |
@@ -605,34 +589,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
605 | else if (xfrm_bydst_should_resize(net, dir, NULL)) | 589 | else if (xfrm_bydst_should_resize(net, dir, NULL)) |
606 | schedule_work(&net->xfrm.policy_hash_work); | 590 | schedule_work(&net->xfrm.policy_hash_work); |
607 | 591 | ||
608 | read_lock_bh(&xfrm_policy_lock); | ||
609 | gc_list = NULL; | ||
610 | entry = &policy->bydst; | ||
611 | hlist_for_each_entry_continue(policy, entry, bydst) { | ||
612 | struct dst_entry *dst; | ||
613 | |||
614 | write_lock(&policy->lock); | ||
615 | dst = policy->bundles; | ||
616 | if (dst) { | ||
617 | struct dst_entry *tail = dst; | ||
618 | while (tail->next) | ||
619 | tail = tail->next; | ||
620 | tail->next = gc_list; | ||
621 | gc_list = dst; | ||
622 | |||
623 | policy->bundles = NULL; | ||
624 | } | ||
625 | write_unlock(&policy->lock); | ||
626 | } | ||
627 | read_unlock_bh(&xfrm_policy_lock); | ||
628 | |||
629 | while (gc_list) { | ||
630 | struct dst_entry *dst = gc_list; | ||
631 | |||
632 | gc_list = dst->next; | ||
633 | dst_free(dst); | ||
634 | } | ||
635 | |||
636 | return 0; | 592 | return 0; |
637 | } | 593 | } |
638 | EXPORT_SYMBOL(xfrm_policy_insert); | 594 | EXPORT_SYMBOL(xfrm_policy_insert); |
@@ -671,10 +627,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type, | |||
671 | } | 627 | } |
672 | write_unlock_bh(&xfrm_policy_lock); | 628 | write_unlock_bh(&xfrm_policy_lock); |
673 | 629 | ||
674 | if (ret && delete) { | 630 | if (ret && delete) |
675 | atomic_inc(&flow_cache_genid); | ||
676 | xfrm_policy_kill(ret); | 631 | xfrm_policy_kill(ret); |
677 | } | ||
678 | return ret; | 632 | return ret; |
679 | } | 633 | } |
680 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); | 634 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); |
@@ -713,10 +667,8 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type, | |||
713 | } | 667 | } |
714 | write_unlock_bh(&xfrm_policy_lock); | 668 | write_unlock_bh(&xfrm_policy_lock); |
715 | 669 | ||
716 | if (ret && delete) { | 670 | if (ret && delete) |
717 | atomic_inc(&flow_cache_genid); | ||
718 | xfrm_policy_kill(ret); | 671 | xfrm_policy_kill(ret); |
719 | } | ||
720 | return ret; | 672 | return ret; |
721 | } | 673 | } |
722 | EXPORT_SYMBOL(xfrm_policy_byid); | 674 | EXPORT_SYMBOL(xfrm_policy_byid); |
@@ -776,7 +728,6 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audi | |||
776 | int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | 728 | int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) |
777 | { | 729 | { |
778 | int dir, err = 0, cnt = 0; | 730 | int dir, err = 0, cnt = 0; |
779 | struct xfrm_policy *dp; | ||
780 | 731 | ||
781 | write_lock_bh(&xfrm_policy_lock); | 732 | write_lock_bh(&xfrm_policy_lock); |
782 | 733 | ||
@@ -794,10 +745,9 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
794 | &net->xfrm.policy_inexact[dir], bydst) { | 745 | &net->xfrm.policy_inexact[dir], bydst) { |
795 | if (pol->type != type) | 746 | if (pol->type != type) |
796 | continue; | 747 | continue; |
797 | dp = __xfrm_policy_unlink(pol, dir); | 748 | __xfrm_policy_unlink(pol, dir); |
798 | write_unlock_bh(&xfrm_policy_lock); | 749 | write_unlock_bh(&xfrm_policy_lock); |
799 | if (dp) | 750 | cnt++; |
800 | cnt++; | ||
801 | 751 | ||
802 | xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, | 752 | xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, |
803 | audit_info->sessionid, | 753 | audit_info->sessionid, |
@@ -816,10 +766,9 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
816 | bydst) { | 766 | bydst) { |
817 | if (pol->type != type) | 767 | if (pol->type != type) |
818 | continue; | 768 | continue; |
819 | dp = __xfrm_policy_unlink(pol, dir); | 769 | __xfrm_policy_unlink(pol, dir); |
820 | write_unlock_bh(&xfrm_policy_lock); | 770 | write_unlock_bh(&xfrm_policy_lock); |
821 | if (dp) | 771 | cnt++; |
822 | cnt++; | ||
823 | 772 | ||
824 | xfrm_audit_policy_delete(pol, 1, | 773 | xfrm_audit_policy_delete(pol, 1, |
825 | audit_info->loginuid, | 774 | audit_info->loginuid, |
@@ -835,7 +784,6 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
835 | } | 784 | } |
836 | if (!cnt) | 785 | if (!cnt) |
837 | err = -ESRCH; | 786 | err = -ESRCH; |
838 | atomic_inc(&flow_cache_genid); | ||
839 | out: | 787 | out: |
840 | write_unlock_bh(&xfrm_policy_lock); | 788 | write_unlock_bh(&xfrm_policy_lock); |
841 | return err; | 789 | return err; |
@@ -989,32 +937,37 @@ fail: | |||
989 | return ret; | 937 | return ret; |
990 | } | 938 | } |
991 | 939 | ||
992 | static int xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family, | 940 | static struct xfrm_policy * |
993 | u8 dir, void **objp, atomic_t **obj_refp) | 941 | __xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family, u8 dir) |
994 | { | 942 | { |
943 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
995 | struct xfrm_policy *pol; | 944 | struct xfrm_policy *pol; |
996 | int err = 0; | ||
997 | 945 | ||
998 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
999 | pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_SUB, fl, family, dir); | 946 | pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_SUB, fl, family, dir); |
1000 | if (IS_ERR(pol)) { | 947 | if (pol != NULL) |
1001 | err = PTR_ERR(pol); | 948 | return pol; |
1002 | pol = NULL; | ||
1003 | } | ||
1004 | if (pol || err) | ||
1005 | goto end; | ||
1006 | #endif | ||
1007 | pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, fl, family, dir); | ||
1008 | if (IS_ERR(pol)) { | ||
1009 | err = PTR_ERR(pol); | ||
1010 | pol = NULL; | ||
1011 | } | ||
1012 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
1013 | end: | ||
1014 | #endif | 949 | #endif |
1015 | if ((*objp = (void *) pol) != NULL) | 950 | return xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, fl, family, dir); |
1016 | *obj_refp = &pol->refcnt; | 951 | } |
1017 | return err; | 952 | |
953 | static struct flow_cache_object * | ||
954 | xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family, | ||
955 | u8 dir, struct flow_cache_object *old_obj, void *ctx) | ||
956 | { | ||
957 | struct xfrm_policy *pol; | ||
958 | |||
959 | if (old_obj) | ||
960 | xfrm_pol_put(container_of(old_obj, struct xfrm_policy, flo)); | ||
961 | |||
962 | pol = __xfrm_policy_lookup(net, fl, family, dir); | ||
963 | if (IS_ERR_OR_NULL(pol)) | ||
964 | return ERR_CAST(pol); | ||
965 | |||
966 | /* Resolver returns two references: | ||
967 | * one for cache and one for caller of flow_cache_lookup() */ | ||
968 | xfrm_pol_hold(pol); | ||
969 | |||
970 | return &pol->flo; | ||
1018 | } | 971 | } |
1019 | 972 | ||
1020 | static inline int policy_to_flow_dir(int dir) | 973 | static inline int policy_to_flow_dir(int dir) |
@@ -1104,8 +1057,6 @@ int xfrm_policy_delete(struct xfrm_policy *pol, int dir) | |||
1104 | pol = __xfrm_policy_unlink(pol, dir); | 1057 | pol = __xfrm_policy_unlink(pol, dir); |
1105 | write_unlock_bh(&xfrm_policy_lock); | 1058 | write_unlock_bh(&xfrm_policy_lock); |
1106 | if (pol) { | 1059 | if (pol) { |
1107 | if (dir < XFRM_POLICY_MAX) | ||
1108 | atomic_inc(&flow_cache_genid); | ||
1109 | xfrm_policy_kill(pol); | 1060 | xfrm_policy_kill(pol); |
1110 | return 0; | 1061 | return 0; |
1111 | } | 1062 | } |
@@ -1132,6 +1083,9 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | |||
1132 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); | 1083 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); |
1133 | } | 1084 | } |
1134 | if (old_pol) | 1085 | if (old_pol) |
1086 | /* Unlinking succeeds always. This is the only function | ||
1087 | * allowed to delete or replace socket policy. | ||
1088 | */ | ||
1135 | __xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir); | 1089 | __xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir); |
1136 | write_unlock_bh(&xfrm_policy_lock); | 1090 | write_unlock_bh(&xfrm_policy_lock); |
1137 | 1091 | ||
@@ -1300,18 +1254,6 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl, | |||
1300 | * still valid. | 1254 | * still valid. |
1301 | */ | 1255 | */ |
1302 | 1256 | ||
1303 | static struct dst_entry * | ||
1304 | xfrm_find_bundle(struct flowi *fl, struct xfrm_policy *policy, unsigned short family) | ||
1305 | { | ||
1306 | struct dst_entry *x; | ||
1307 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | ||
1308 | if (unlikely(afinfo == NULL)) | ||
1309 | return ERR_PTR(-EINVAL); | ||
1310 | x = afinfo->find_bundle(fl, policy); | ||
1311 | xfrm_policy_put_afinfo(afinfo); | ||
1312 | return x; | ||
1313 | } | ||
1314 | |||
1315 | static inline int xfrm_get_tos(struct flowi *fl, int family) | 1257 | static inline int xfrm_get_tos(struct flowi *fl, int family) |
1316 | { | 1258 | { |
1317 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | 1259 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); |
@@ -1327,6 +1269,54 @@ static inline int xfrm_get_tos(struct flowi *fl, int family) | |||
1327 | return tos; | 1269 | return tos; |
1328 | } | 1270 | } |
1329 | 1271 | ||
1272 | static struct flow_cache_object *xfrm_bundle_flo_get(struct flow_cache_object *flo) | ||
1273 | { | ||
1274 | struct xfrm_dst *xdst = container_of(flo, struct xfrm_dst, flo); | ||
1275 | struct dst_entry *dst = &xdst->u.dst; | ||
1276 | |||
1277 | if (xdst->route == NULL) { | ||
1278 | /* Dummy bundle - if it has xfrms we were not | ||
1279 | * able to build bundle as template resolution failed. | ||
1280 | * It means we need to try again resolving. */ | ||
1281 | if (xdst->num_xfrms > 0) | ||
1282 | return NULL; | ||
1283 | } else { | ||
1284 | /* Real bundle */ | ||
1285 | if (stale_bundle(dst)) | ||
1286 | return NULL; | ||
1287 | } | ||
1288 | |||
1289 | dst_hold(dst); | ||
1290 | return flo; | ||
1291 | } | ||
1292 | |||
1293 | static int xfrm_bundle_flo_check(struct flow_cache_object *flo) | ||
1294 | { | ||
1295 | struct xfrm_dst *xdst = container_of(flo, struct xfrm_dst, flo); | ||
1296 | struct dst_entry *dst = &xdst->u.dst; | ||
1297 | |||
1298 | if (!xdst->route) | ||
1299 | return 0; | ||
1300 | if (stale_bundle(dst)) | ||
1301 | return 0; | ||
1302 | |||
1303 | return 1; | ||
1304 | } | ||
1305 | |||
1306 | static void xfrm_bundle_flo_delete(struct flow_cache_object *flo) | ||
1307 | { | ||
1308 | struct xfrm_dst *xdst = container_of(flo, struct xfrm_dst, flo); | ||
1309 | struct dst_entry *dst = &xdst->u.dst; | ||
1310 | |||
1311 | dst_free(dst); | ||
1312 | } | ||
1313 | |||
1314 | static const struct flow_cache_ops xfrm_bundle_fc_ops = { | ||
1315 | .get = xfrm_bundle_flo_get, | ||
1316 | .check = xfrm_bundle_flo_check, | ||
1317 | .delete = xfrm_bundle_flo_delete, | ||
1318 | }; | ||
1319 | |||
1330 | static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) | 1320 | static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) |
1331 | { | 1321 | { |
1332 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | 1322 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); |
@@ -1349,9 +1339,10 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) | |||
1349 | BUG(); | 1339 | BUG(); |
1350 | } | 1340 | } |
1351 | xdst = dst_alloc(dst_ops) ?: ERR_PTR(-ENOBUFS); | 1341 | xdst = dst_alloc(dst_ops) ?: ERR_PTR(-ENOBUFS); |
1352 | |||
1353 | xfrm_policy_put_afinfo(afinfo); | 1342 | xfrm_policy_put_afinfo(afinfo); |
1354 | 1343 | ||
1344 | xdst->flo.ops = &xfrm_bundle_fc_ops; | ||
1345 | |||
1355 | return xdst; | 1346 | return xdst; |
1356 | } | 1347 | } |
1357 | 1348 | ||
@@ -1389,6 +1380,7 @@ static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
1389 | return err; | 1380 | return err; |
1390 | } | 1381 | } |
1391 | 1382 | ||
1383 | |||
1392 | /* Allocate chain of dst_entry's, attach known xfrm's, calculate | 1384 | /* Allocate chain of dst_entry's, attach known xfrm's, calculate |
1393 | * all the metrics... Shortly, bundle a bundle. | 1385 | * all the metrics... Shortly, bundle a bundle. |
1394 | */ | 1386 | */ |
@@ -1452,7 +1444,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
1452 | dst_hold(dst); | 1444 | dst_hold(dst); |
1453 | 1445 | ||
1454 | dst1->xfrm = xfrm[i]; | 1446 | dst1->xfrm = xfrm[i]; |
1455 | xdst->genid = xfrm[i]->genid; | 1447 | xdst->xfrm_genid = xfrm[i]->genid; |
1456 | 1448 | ||
1457 | dst1->obsolete = -1; | 1449 | dst1->obsolete = -1; |
1458 | dst1->flags |= DST_HOST; | 1450 | dst1->flags |= DST_HOST; |
@@ -1545,7 +1537,186 @@ xfrm_dst_update_origin(struct dst_entry *dst, struct flowi *fl) | |||
1545 | #endif | 1537 | #endif |
1546 | } | 1538 | } |
1547 | 1539 | ||
1548 | static int stale_bundle(struct dst_entry *dst); | 1540 | static int xfrm_expand_policies(struct flowi *fl, u16 family, |
1541 | struct xfrm_policy **pols, | ||
1542 | int *num_pols, int *num_xfrms) | ||
1543 | { | ||
1544 | int i; | ||
1545 | |||
1546 | if (*num_pols == 0 || !pols[0]) { | ||
1547 | *num_pols = 0; | ||
1548 | *num_xfrms = 0; | ||
1549 | return 0; | ||
1550 | } | ||
1551 | if (IS_ERR(pols[0])) | ||
1552 | return PTR_ERR(pols[0]); | ||
1553 | |||
1554 | *num_xfrms = pols[0]->xfrm_nr; | ||
1555 | |||
1556 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
1557 | if (pols[0] && pols[0]->action == XFRM_POLICY_ALLOW && | ||
1558 | pols[0]->type != XFRM_POLICY_TYPE_MAIN) { | ||
1559 | pols[1] = xfrm_policy_lookup_bytype(xp_net(pols[0]), | ||
1560 | XFRM_POLICY_TYPE_MAIN, | ||
1561 | fl, family, | ||
1562 | XFRM_POLICY_OUT); | ||
1563 | if (pols[1]) { | ||
1564 | if (IS_ERR(pols[1])) { | ||
1565 | xfrm_pols_put(pols, *num_pols); | ||
1566 | return PTR_ERR(pols[1]); | ||
1567 | } | ||
1568 | (*num_pols) ++; | ||
1569 | (*num_xfrms) += pols[1]->xfrm_nr; | ||
1570 | } | ||
1571 | } | ||
1572 | #endif | ||
1573 | for (i = 0; i < *num_pols; i++) { | ||
1574 | if (pols[i]->action != XFRM_POLICY_ALLOW) { | ||
1575 | *num_xfrms = -1; | ||
1576 | break; | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1580 | return 0; | ||
1581 | |||
1582 | } | ||
1583 | |||
1584 | static struct xfrm_dst * | ||
1585 | xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, | ||
1586 | struct flowi *fl, u16 family, | ||
1587 | struct dst_entry *dst_orig) | ||
1588 | { | ||
1589 | struct net *net = xp_net(pols[0]); | ||
1590 | struct xfrm_state *xfrm[XFRM_MAX_DEPTH]; | ||
1591 | struct dst_entry *dst; | ||
1592 | struct xfrm_dst *xdst; | ||
1593 | int err; | ||
1594 | |||
1595 | /* Try to instantiate a bundle */ | ||
1596 | err = xfrm_tmpl_resolve(pols, num_pols, fl, xfrm, family); | ||
1597 | if (err < 0) { | ||
1598 | if (err != -EAGAIN) | ||
1599 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); | ||
1600 | return ERR_PTR(err); | ||
1601 | } | ||
1602 | |||
1603 | dst = xfrm_bundle_create(pols[0], xfrm, err, fl, dst_orig); | ||
1604 | if (IS_ERR(dst)) { | ||
1605 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLEGENERROR); | ||
1606 | return ERR_CAST(dst); | ||
1607 | } | ||
1608 | |||
1609 | xdst = (struct xfrm_dst *)dst; | ||
1610 | xdst->num_xfrms = err; | ||
1611 | if (num_pols > 1) | ||
1612 | err = xfrm_dst_update_parent(dst, &pols[1]->selector); | ||
1613 | else | ||
1614 | err = xfrm_dst_update_origin(dst, fl); | ||
1615 | if (unlikely(err)) { | ||
1616 | dst_free(dst); | ||
1617 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | ||
1618 | return ERR_PTR(err); | ||
1619 | } | ||
1620 | |||
1621 | xdst->num_pols = num_pols; | ||
1622 | memcpy(xdst->pols, pols, sizeof(struct xfrm_policy*) * num_pols); | ||
1623 | xdst->policy_genid = atomic_read(&pols[0]->genid); | ||
1624 | |||
1625 | return xdst; | ||
1626 | } | ||
1627 | |||
1628 | static struct flow_cache_object * | ||
1629 | xfrm_bundle_lookup(struct net *net, struct flowi *fl, u16 family, u8 dir, | ||
1630 | struct flow_cache_object *oldflo, void *ctx) | ||
1631 | { | ||
1632 | struct dst_entry *dst_orig = (struct dst_entry *)ctx; | ||
1633 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; | ||
1634 | struct xfrm_dst *xdst, *new_xdst; | ||
1635 | int num_pols = 0, num_xfrms = 0, i, err, pol_dead; | ||
1636 | |||
1637 | /* Check if the policies from old bundle are usable */ | ||
1638 | xdst = NULL; | ||
1639 | if (oldflo) { | ||
1640 | xdst = container_of(oldflo, struct xfrm_dst, flo); | ||
1641 | num_pols = xdst->num_pols; | ||
1642 | num_xfrms = xdst->num_xfrms; | ||
1643 | pol_dead = 0; | ||
1644 | for (i = 0; i < num_pols; i++) { | ||
1645 | pols[i] = xdst->pols[i]; | ||
1646 | pol_dead |= pols[i]->walk.dead; | ||
1647 | } | ||
1648 | if (pol_dead) { | ||
1649 | dst_free(&xdst->u.dst); | ||
1650 | xdst = NULL; | ||
1651 | num_pols = 0; | ||
1652 | num_xfrms = 0; | ||
1653 | oldflo = NULL; | ||
1654 | } | ||
1655 | } | ||
1656 | |||
1657 | /* Resolve policies to use if we couldn't get them from | ||
1658 | * previous cache entry */ | ||
1659 | if (xdst == NULL) { | ||
1660 | num_pols = 1; | ||
1661 | pols[0] = __xfrm_policy_lookup(net, fl, family, dir); | ||
1662 | err = xfrm_expand_policies(fl, family, pols, | ||
1663 | &num_pols, &num_xfrms); | ||
1664 | if (err < 0) | ||
1665 | goto inc_error; | ||
1666 | if (num_pols == 0) | ||
1667 | return NULL; | ||
1668 | if (num_xfrms <= 0) | ||
1669 | goto make_dummy_bundle; | ||
1670 | } | ||
1671 | |||
1672 | new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, dst_orig); | ||
1673 | if (IS_ERR(new_xdst)) { | ||
1674 | err = PTR_ERR(new_xdst); | ||
1675 | if (err != -EAGAIN) | ||
1676 | goto error; | ||
1677 | if (oldflo == NULL) | ||
1678 | goto make_dummy_bundle; | ||
1679 | dst_hold(&xdst->u.dst); | ||
1680 | return oldflo; | ||
1681 | } | ||
1682 | |||
1683 | /* Kill the previous bundle */ | ||
1684 | if (xdst) { | ||
1685 | /* The policies were stolen for newly generated bundle */ | ||
1686 | xdst->num_pols = 0; | ||
1687 | dst_free(&xdst->u.dst); | ||
1688 | } | ||
1689 | |||
1690 | /* Flow cache does not have reference, it dst_free()'s, | ||
1691 | * but we do need to return one reference for original caller */ | ||
1692 | dst_hold(&new_xdst->u.dst); | ||
1693 | return &new_xdst->flo; | ||
1694 | |||
1695 | make_dummy_bundle: | ||
1696 | /* We found policies, but there's no bundles to instantiate: | ||
1697 | * either because the policy blocks, has no transformations or | ||
1698 | * we could not build template (no xfrm_states).*/ | ||
1699 | xdst = xfrm_alloc_dst(net, family); | ||
1700 | if (IS_ERR(xdst)) { | ||
1701 | xfrm_pols_put(pols, num_pols); | ||
1702 | return ERR_CAST(xdst); | ||
1703 | } | ||
1704 | xdst->num_pols = num_pols; | ||
1705 | xdst->num_xfrms = num_xfrms; | ||
1706 | memcpy(xdst->pols, pols, sizeof(struct xfrm_policy*) * num_pols); | ||
1707 | |||
1708 | dst_hold(&xdst->u.dst); | ||
1709 | return &xdst->flo; | ||
1710 | |||
1711 | inc_error: | ||
1712 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); | ||
1713 | error: | ||
1714 | if (xdst != NULL) | ||
1715 | dst_free(&xdst->u.dst); | ||
1716 | else | ||
1717 | xfrm_pols_put(pols, num_pols); | ||
1718 | return ERR_PTR(err); | ||
1719 | } | ||
1549 | 1720 | ||
1550 | /* Main function: finds/creates a bundle for given flow. | 1721 | /* Main function: finds/creates a bundle for given flow. |
1551 | * | 1722 | * |
@@ -1555,245 +1726,152 @@ static int stale_bundle(struct dst_entry *dst); | |||
1555 | int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl, | 1726 | int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl, |
1556 | struct sock *sk, int flags) | 1727 | struct sock *sk, int flags) |
1557 | { | 1728 | { |
1558 | struct xfrm_policy *policy; | ||
1559 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; | 1729 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; |
1560 | int npols; | 1730 | struct flow_cache_object *flo; |
1561 | int pol_dead; | 1731 | struct xfrm_dst *xdst; |
1562 | int xfrm_nr; | 1732 | struct dst_entry *dst, *dst_orig = *dst_p, *route; |
1563 | int pi; | 1733 | u16 family = dst_orig->ops->family; |
1564 | struct xfrm_state *xfrm[XFRM_MAX_DEPTH]; | ||
1565 | struct dst_entry *dst, *dst_orig = *dst_p; | ||
1566 | int nx = 0; | ||
1567 | int err; | ||
1568 | u32 genid; | ||
1569 | u16 family; | ||
1570 | u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); | 1734 | u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); |
1735 | int i, err, num_pols, num_xfrms = 0, drop_pols = 0; | ||
1571 | 1736 | ||
1572 | restart: | 1737 | restart: |
1573 | genid = atomic_read(&flow_cache_genid); | 1738 | dst = NULL; |
1574 | policy = NULL; | 1739 | xdst = NULL; |
1575 | for (pi = 0; pi < ARRAY_SIZE(pols); pi++) | 1740 | route = NULL; |
1576 | pols[pi] = NULL; | ||
1577 | npols = 0; | ||
1578 | pol_dead = 0; | ||
1579 | xfrm_nr = 0; | ||
1580 | 1741 | ||
1581 | if (sk && sk->sk_policy[XFRM_POLICY_OUT]) { | 1742 | if (sk && sk->sk_policy[XFRM_POLICY_OUT]) { |
1582 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); | 1743 | num_pols = 1; |
1583 | err = PTR_ERR(policy); | 1744 | pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); |
1584 | if (IS_ERR(policy)) { | 1745 | err = xfrm_expand_policies(fl, family, pols, |
1585 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); | 1746 | &num_pols, &num_xfrms); |
1747 | if (err < 0) | ||
1586 | goto dropdst; | 1748 | goto dropdst; |
1749 | |||
1750 | if (num_pols) { | ||
1751 | if (num_xfrms <= 0) { | ||
1752 | drop_pols = num_pols; | ||
1753 | goto no_transform; | ||
1754 | } | ||
1755 | |||
1756 | xdst = xfrm_resolve_and_create_bundle( | ||
1757 | pols, num_pols, fl, | ||
1758 | family, dst_orig); | ||
1759 | if (IS_ERR(xdst)) { | ||
1760 | xfrm_pols_put(pols, num_pols); | ||
1761 | err = PTR_ERR(xdst); | ||
1762 | goto dropdst; | ||
1763 | } | ||
1764 | |||
1765 | spin_lock_bh(&xfrm_policy_sk_bundle_lock); | ||
1766 | xdst->u.dst.next = xfrm_policy_sk_bundles; | ||
1767 | xfrm_policy_sk_bundles = &xdst->u.dst; | ||
1768 | spin_unlock_bh(&xfrm_policy_sk_bundle_lock); | ||
1769 | |||
1770 | route = xdst->route; | ||
1587 | } | 1771 | } |
1588 | } | 1772 | } |
1589 | 1773 | ||
1590 | if (!policy) { | 1774 | if (xdst == NULL) { |
1591 | /* To accelerate a bit... */ | 1775 | /* To accelerate a bit... */ |
1592 | if ((dst_orig->flags & DST_NOXFRM) || | 1776 | if ((dst_orig->flags & DST_NOXFRM) || |
1593 | !net->xfrm.policy_count[XFRM_POLICY_OUT]) | 1777 | !net->xfrm.policy_count[XFRM_POLICY_OUT]) |
1594 | goto nopol; | 1778 | goto nopol; |
1595 | 1779 | ||
1596 | policy = flow_cache_lookup(net, fl, dst_orig->ops->family, | 1780 | flo = flow_cache_lookup(net, fl, family, dir, |
1597 | dir, xfrm_policy_lookup); | 1781 | xfrm_bundle_lookup, dst_orig); |
1598 | err = PTR_ERR(policy); | 1782 | if (flo == NULL) |
1599 | if (IS_ERR(policy)) { | 1783 | goto nopol; |
1600 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); | 1784 | if (IS_ERR(flo)) { |
1785 | err = PTR_ERR(flo); | ||
1601 | goto dropdst; | 1786 | goto dropdst; |
1602 | } | 1787 | } |
1788 | xdst = container_of(flo, struct xfrm_dst, flo); | ||
1789 | |||
1790 | num_pols = xdst->num_pols; | ||
1791 | num_xfrms = xdst->num_xfrms; | ||
1792 | memcpy(pols, xdst->pols, sizeof(struct xfrm_policy*) * num_pols); | ||
1793 | route = xdst->route; | ||
1794 | } | ||
1795 | |||
1796 | dst = &xdst->u.dst; | ||
1797 | if (route == NULL && num_xfrms > 0) { | ||
1798 | /* The only case when xfrm_bundle_lookup() returns a | ||
1799 | * bundle with null route, is when the template could | ||
1800 | * not be resolved. It means policies are there, but | ||
1801 | * bundle could not be created, since we don't yet | ||
1802 | * have the xfrm_state's. We need to wait for KM to | ||
1803 | * negotiate new SA's or bail out with error.*/ | ||
1804 | if (net->xfrm.sysctl_larval_drop) { | ||
1805 | /* EREMOTE tells the caller to generate | ||
1806 | * a one-shot blackhole route. */ | ||
1807 | dst_release(dst); | ||
1808 | xfrm_pols_put(pols, drop_pols); | ||
1809 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); | ||
1810 | return -EREMOTE; | ||
1811 | } | ||
1812 | if (flags & XFRM_LOOKUP_WAIT) { | ||
1813 | DECLARE_WAITQUEUE(wait, current); | ||
1814 | |||
1815 | add_wait_queue(&net->xfrm.km_waitq, &wait); | ||
1816 | set_current_state(TASK_INTERRUPTIBLE); | ||
1817 | schedule(); | ||
1818 | set_current_state(TASK_RUNNING); | ||
1819 | remove_wait_queue(&net->xfrm.km_waitq, &wait); | ||
1820 | |||
1821 | if (!signal_pending(current)) { | ||
1822 | dst_release(dst); | ||
1823 | goto restart; | ||
1824 | } | ||
1825 | |||
1826 | err = -ERESTART; | ||
1827 | } else | ||
1828 | err = -EAGAIN; | ||
1829 | |||
1830 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); | ||
1831 | goto error; | ||
1603 | } | 1832 | } |
1604 | 1833 | ||
1605 | if (!policy) | 1834 | no_transform: |
1835 | if (num_pols == 0) | ||
1606 | goto nopol; | 1836 | goto nopol; |
1607 | 1837 | ||
1608 | family = dst_orig->ops->family; | 1838 | if ((flags & XFRM_LOOKUP_ICMP) && |
1609 | pols[0] = policy; | 1839 | !(pols[0]->flags & XFRM_POLICY_ICMP)) { |
1610 | npols ++; | 1840 | err = -ENOENT; |
1611 | xfrm_nr += pols[0]->xfrm_nr; | ||
1612 | |||
1613 | err = -ENOENT; | ||
1614 | if ((flags & XFRM_LOOKUP_ICMP) && !(policy->flags & XFRM_POLICY_ICMP)) | ||
1615 | goto error; | 1841 | goto error; |
1842 | } | ||
1616 | 1843 | ||
1617 | policy->curlft.use_time = get_seconds(); | 1844 | for (i = 0; i < num_pols; i++) |
1845 | pols[i]->curlft.use_time = get_seconds(); | ||
1618 | 1846 | ||
1619 | switch (policy->action) { | 1847 | if (num_xfrms < 0) { |
1620 | default: | ||
1621 | case XFRM_POLICY_BLOCK: | ||
1622 | /* Prohibit the flow */ | 1848 | /* Prohibit the flow */ |
1623 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK); | 1849 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK); |
1624 | err = -EPERM; | 1850 | err = -EPERM; |
1625 | goto error; | 1851 | goto error; |
1626 | 1852 | } else if (num_xfrms > 0) { | |
1627 | case XFRM_POLICY_ALLOW: | 1853 | /* Flow transformed */ |
1628 | #ifndef CONFIG_XFRM_SUB_POLICY | 1854 | *dst_p = dst; |
1629 | if (policy->xfrm_nr == 0) { | 1855 | dst_release(dst_orig); |
1630 | /* Flow passes not transformed. */ | 1856 | } else { |
1631 | xfrm_pol_put(policy); | 1857 | /* Flow passes untransformed */ |
1632 | return 0; | 1858 | dst_release(dst); |
1633 | } | ||
1634 | #endif | ||
1635 | |||
1636 | /* Try to find matching bundle. | ||
1637 | * | ||
1638 | * LATER: help from flow cache. It is optional, this | ||
1639 | * is required only for output policy. | ||
1640 | */ | ||
1641 | dst = xfrm_find_bundle(fl, policy, family); | ||
1642 | if (IS_ERR(dst)) { | ||
1643 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | ||
1644 | err = PTR_ERR(dst); | ||
1645 | goto error; | ||
1646 | } | ||
1647 | |||
1648 | if (dst) | ||
1649 | break; | ||
1650 | |||
1651 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
1652 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { | ||
1653 | pols[1] = xfrm_policy_lookup_bytype(net, | ||
1654 | XFRM_POLICY_TYPE_MAIN, | ||
1655 | fl, family, | ||
1656 | XFRM_POLICY_OUT); | ||
1657 | if (pols[1]) { | ||
1658 | if (IS_ERR(pols[1])) { | ||
1659 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); | ||
1660 | err = PTR_ERR(pols[1]); | ||
1661 | goto error; | ||
1662 | } | ||
1663 | if (pols[1]->action == XFRM_POLICY_BLOCK) { | ||
1664 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK); | ||
1665 | err = -EPERM; | ||
1666 | goto error; | ||
1667 | } | ||
1668 | npols ++; | ||
1669 | xfrm_nr += pols[1]->xfrm_nr; | ||
1670 | } | ||
1671 | } | ||
1672 | |||
1673 | /* | ||
1674 | * Because neither flowi nor bundle information knows about | ||
1675 | * transformation template size. On more than one policy usage | ||
1676 | * we can realize whether all of them is bypass or not after | ||
1677 | * they are searched. See above not-transformed bypass | ||
1678 | * is surrounded by non-sub policy configuration, too. | ||
1679 | */ | ||
1680 | if (xfrm_nr == 0) { | ||
1681 | /* Flow passes not transformed. */ | ||
1682 | xfrm_pols_put(pols, npols); | ||
1683 | return 0; | ||
1684 | } | ||
1685 | |||
1686 | #endif | ||
1687 | nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); | ||
1688 | |||
1689 | if (unlikely(nx<0)) { | ||
1690 | err = nx; | ||
1691 | if (err == -EAGAIN && net->xfrm.sysctl_larval_drop) { | ||
1692 | /* EREMOTE tells the caller to generate | ||
1693 | * a one-shot blackhole route. | ||
1694 | */ | ||
1695 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); | ||
1696 | xfrm_pol_put(policy); | ||
1697 | return -EREMOTE; | ||
1698 | } | ||
1699 | if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) { | ||
1700 | DECLARE_WAITQUEUE(wait, current); | ||
1701 | |||
1702 | add_wait_queue(&net->xfrm.km_waitq, &wait); | ||
1703 | set_current_state(TASK_INTERRUPTIBLE); | ||
1704 | schedule(); | ||
1705 | set_current_state(TASK_RUNNING); | ||
1706 | remove_wait_queue(&net->xfrm.km_waitq, &wait); | ||
1707 | |||
1708 | nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); | ||
1709 | |||
1710 | if (nx == -EAGAIN && signal_pending(current)) { | ||
1711 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); | ||
1712 | err = -ERESTART; | ||
1713 | goto error; | ||
1714 | } | ||
1715 | if (nx == -EAGAIN || | ||
1716 | genid != atomic_read(&flow_cache_genid)) { | ||
1717 | xfrm_pols_put(pols, npols); | ||
1718 | goto restart; | ||
1719 | } | ||
1720 | err = nx; | ||
1721 | } | ||
1722 | if (err < 0) { | ||
1723 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); | ||
1724 | goto error; | ||
1725 | } | ||
1726 | } | ||
1727 | if (nx == 0) { | ||
1728 | /* Flow passes not transformed. */ | ||
1729 | xfrm_pols_put(pols, npols); | ||
1730 | return 0; | ||
1731 | } | ||
1732 | |||
1733 | dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig); | ||
1734 | err = PTR_ERR(dst); | ||
1735 | if (IS_ERR(dst)) { | ||
1736 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLEGENERROR); | ||
1737 | goto error; | ||
1738 | } | ||
1739 | |||
1740 | for (pi = 0; pi < npols; pi++) { | ||
1741 | read_lock_bh(&pols[pi]->lock); | ||
1742 | pol_dead |= pols[pi]->walk.dead; | ||
1743 | read_unlock_bh(&pols[pi]->lock); | ||
1744 | } | ||
1745 | |||
1746 | write_lock_bh(&policy->lock); | ||
1747 | if (unlikely(pol_dead || stale_bundle(dst))) { | ||
1748 | /* Wow! While we worked on resolving, this | ||
1749 | * policy has gone. Retry. It is not paranoia, | ||
1750 | * we just cannot enlist new bundle to dead object. | ||
1751 | * We can't enlist stable bundles either. | ||
1752 | */ | ||
1753 | write_unlock_bh(&policy->lock); | ||
1754 | dst_free(dst); | ||
1755 | |||
1756 | if (pol_dead) | ||
1757 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLDEAD); | ||
1758 | else | ||
1759 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | ||
1760 | err = -EHOSTUNREACH; | ||
1761 | goto error; | ||
1762 | } | ||
1763 | |||
1764 | if (npols > 1) | ||
1765 | err = xfrm_dst_update_parent(dst, &pols[1]->selector); | ||
1766 | else | ||
1767 | err = xfrm_dst_update_origin(dst, fl); | ||
1768 | if (unlikely(err)) { | ||
1769 | write_unlock_bh(&policy->lock); | ||
1770 | dst_free(dst); | ||
1771 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | ||
1772 | goto error; | ||
1773 | } | ||
1774 | |||
1775 | dst->next = policy->bundles; | ||
1776 | policy->bundles = dst; | ||
1777 | dst_hold(dst); | ||
1778 | write_unlock_bh(&policy->lock); | ||
1779 | } | 1859 | } |
1780 | *dst_p = dst; | 1860 | ok: |
1781 | dst_release(dst_orig); | 1861 | xfrm_pols_put(pols, drop_pols); |
1782 | xfrm_pols_put(pols, npols); | ||
1783 | return 0; | 1862 | return 0; |
1784 | 1863 | ||
1864 | nopol: | ||
1865 | if (!(flags & XFRM_LOOKUP_ICMP)) | ||
1866 | goto ok; | ||
1867 | err = -ENOENT; | ||
1785 | error: | 1868 | error: |
1786 | xfrm_pols_put(pols, npols); | 1869 | dst_release(dst); |
1787 | dropdst: | 1870 | dropdst: |
1788 | dst_release(dst_orig); | 1871 | dst_release(dst_orig); |
1789 | *dst_p = NULL; | 1872 | *dst_p = NULL; |
1873 | xfrm_pols_put(pols, drop_pols); | ||
1790 | return err; | 1874 | return err; |
1791 | |||
1792 | nopol: | ||
1793 | err = -ENOENT; | ||
1794 | if (flags & XFRM_LOOKUP_ICMP) | ||
1795 | goto dropdst; | ||
1796 | return 0; | ||
1797 | } | 1875 | } |
1798 | EXPORT_SYMBOL(__xfrm_lookup); | 1876 | EXPORT_SYMBOL(__xfrm_lookup); |
1799 | 1877 | ||
@@ -1952,9 +2030,16 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1952 | } | 2030 | } |
1953 | } | 2031 | } |
1954 | 2032 | ||
1955 | if (!pol) | 2033 | if (!pol) { |
1956 | pol = flow_cache_lookup(net, &fl, family, fl_dir, | 2034 | struct flow_cache_object *flo; |
1957 | xfrm_policy_lookup); | 2035 | |
2036 | flo = flow_cache_lookup(net, &fl, family, fl_dir, | ||
2037 | xfrm_policy_lookup, NULL); | ||
2038 | if (IS_ERR_OR_NULL(flo)) | ||
2039 | pol = ERR_CAST(flo); | ||
2040 | else | ||
2041 | pol = container_of(flo, struct xfrm_policy, flo); | ||
2042 | } | ||
1958 | 2043 | ||
1959 | if (IS_ERR(pol)) { | 2044 | if (IS_ERR(pol)) { |
1960 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); | 2045 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
@@ -2124,7 +2209,6 @@ EXPORT_SYMBOL(xfrm_dst_ifdown); | |||
2124 | static void xfrm_link_failure(struct sk_buff *skb) | 2209 | static void xfrm_link_failure(struct sk_buff *skb) |
2125 | { | 2210 | { |
2126 | /* Impossible. Such dst must be popped before reaches point of failure. */ | 2211 | /* Impossible. Such dst must be popped before reaches point of failure. */ |
2127 | return; | ||
2128 | } | 2212 | } |
2129 | 2213 | ||
2130 | static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) | 2214 | static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) |
@@ -2138,71 +2222,24 @@ static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) | |||
2138 | return dst; | 2222 | return dst; |
2139 | } | 2223 | } |
2140 | 2224 | ||
2141 | static void prune_one_bundle(struct xfrm_policy *pol, int (*func)(struct dst_entry *), struct dst_entry **gc_list_p) | 2225 | static void __xfrm_garbage_collect(struct net *net) |
2142 | { | ||
2143 | struct dst_entry *dst, **dstp; | ||
2144 | |||
2145 | write_lock(&pol->lock); | ||
2146 | dstp = &pol->bundles; | ||
2147 | while ((dst=*dstp) != NULL) { | ||
2148 | if (func(dst)) { | ||
2149 | *dstp = dst->next; | ||
2150 | dst->next = *gc_list_p; | ||
2151 | *gc_list_p = dst; | ||
2152 | } else { | ||
2153 | dstp = &dst->next; | ||
2154 | } | ||
2155 | } | ||
2156 | write_unlock(&pol->lock); | ||
2157 | } | ||
2158 | |||
2159 | static void xfrm_prune_bundles(struct net *net, int (*func)(struct dst_entry *)) | ||
2160 | { | 2226 | { |
2161 | struct dst_entry *gc_list = NULL; | 2227 | struct dst_entry *head, *next; |
2162 | int dir; | ||
2163 | 2228 | ||
2164 | read_lock_bh(&xfrm_policy_lock); | 2229 | flow_cache_flush(); |
2165 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { | ||
2166 | struct xfrm_policy *pol; | ||
2167 | struct hlist_node *entry; | ||
2168 | struct hlist_head *table; | ||
2169 | int i; | ||
2170 | 2230 | ||
2171 | hlist_for_each_entry(pol, entry, | 2231 | spin_lock_bh(&xfrm_policy_sk_bundle_lock); |
2172 | &net->xfrm.policy_inexact[dir], bydst) | 2232 | head = xfrm_policy_sk_bundles; |
2173 | prune_one_bundle(pol, func, &gc_list); | 2233 | xfrm_policy_sk_bundles = NULL; |
2234 | spin_unlock_bh(&xfrm_policy_sk_bundle_lock); | ||
2174 | 2235 | ||
2175 | table = net->xfrm.policy_bydst[dir].table; | 2236 | while (head) { |
2176 | for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) { | 2237 | next = head->next; |
2177 | hlist_for_each_entry(pol, entry, table + i, bydst) | 2238 | dst_free(head); |
2178 | prune_one_bundle(pol, func, &gc_list); | 2239 | head = next; |
2179 | } | ||
2180 | } | ||
2181 | read_unlock_bh(&xfrm_policy_lock); | ||
2182 | |||
2183 | while (gc_list) { | ||
2184 | struct dst_entry *dst = gc_list; | ||
2185 | gc_list = dst->next; | ||
2186 | dst_free(dst); | ||
2187 | } | 2240 | } |
2188 | } | 2241 | } |
2189 | 2242 | ||
2190 | static int unused_bundle(struct dst_entry *dst) | ||
2191 | { | ||
2192 | return !atomic_read(&dst->__refcnt); | ||
2193 | } | ||
2194 | |||
2195 | static void __xfrm_garbage_collect(struct net *net) | ||
2196 | { | ||
2197 | xfrm_prune_bundles(net, unused_bundle); | ||
2198 | } | ||
2199 | |||
2200 | static int xfrm_flush_bundles(struct net *net) | ||
2201 | { | ||
2202 | xfrm_prune_bundles(net, stale_bundle); | ||
2203 | return 0; | ||
2204 | } | ||
2205 | |||
2206 | static void xfrm_init_pmtu(struct dst_entry *dst) | 2243 | static void xfrm_init_pmtu(struct dst_entry *dst) |
2207 | { | 2244 | { |
2208 | do { | 2245 | do { |
@@ -2260,7 +2297,9 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, | |||
2260 | return 0; | 2297 | return 0; |
2261 | if (dst->xfrm->km.state != XFRM_STATE_VALID) | 2298 | if (dst->xfrm->km.state != XFRM_STATE_VALID) |
2262 | return 0; | 2299 | return 0; |
2263 | if (xdst->genid != dst->xfrm->genid) | 2300 | if (xdst->xfrm_genid != dst->xfrm->genid) |
2301 | return 0; | ||
2302 | if (xdst->policy_genid != atomic_read(&xdst->pols[0]->genid)) | ||
2264 | return 0; | 2303 | return 0; |
2265 | 2304 | ||
2266 | if (strict && fl && | 2305 | if (strict && fl && |
@@ -2425,7 +2464,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void | |||
2425 | 2464 | ||
2426 | switch (event) { | 2465 | switch (event) { |
2427 | case NETDEV_DOWN: | 2466 | case NETDEV_DOWN: |
2428 | xfrm_flush_bundles(dev_net(dev)); | 2467 | __xfrm_garbage_collect(dev_net(dev)); |
2429 | } | 2468 | } |
2430 | return NOTIFY_DONE; | 2469 | return NOTIFY_DONE; |
2431 | } | 2470 | } |
@@ -2531,7 +2570,6 @@ static void xfrm_policy_fini(struct net *net) | |||
2531 | audit_info.sessionid = -1; | 2570 | audit_info.sessionid = -1; |
2532 | audit_info.secid = 0; | 2571 | audit_info.secid = 0; |
2533 | xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); | 2572 | xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); |
2534 | flush_work(&xfrm_policy_gc_work); | ||
2535 | 2573 | ||
2536 | WARN_ON(!list_empty(&net->xfrm.policy_all)); | 2574 | WARN_ON(!list_empty(&net->xfrm.policy_all)); |
2537 | 2575 | ||
@@ -2757,7 +2795,6 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol, | |||
2757 | struct xfrm_migrate *m, int num_migrate) | 2795 | struct xfrm_migrate *m, int num_migrate) |
2758 | { | 2796 | { |
2759 | struct xfrm_migrate *mp; | 2797 | struct xfrm_migrate *mp; |
2760 | struct dst_entry *dst; | ||
2761 | int i, j, n = 0; | 2798 | int i, j, n = 0; |
2762 | 2799 | ||
2763 | write_lock_bh(&pol->lock); | 2800 | write_lock_bh(&pol->lock); |
@@ -2782,10 +2819,7 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol, | |||
2782 | sizeof(pol->xfrm_vec[i].saddr)); | 2819 | sizeof(pol->xfrm_vec[i].saddr)); |
2783 | pol->xfrm_vec[i].encap_family = mp->new_family; | 2820 | pol->xfrm_vec[i].encap_family = mp->new_family; |
2784 | /* flush bundles */ | 2821 | /* flush bundles */ |
2785 | while ((dst = pol->bundles) != NULL) { | 2822 | atomic_inc(&pol->genid); |
2786 | pol->bundles = dst->next; | ||
2787 | dst_free(dst); | ||
2788 | } | ||
2789 | } | 2823 | } |
2790 | } | 2824 | } |
2791 | 2825 | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index add77ecb8ac4..5208b12fbfb4 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -38,7 +38,6 @@ | |||
38 | static DEFINE_SPINLOCK(xfrm_state_lock); | 38 | static DEFINE_SPINLOCK(xfrm_state_lock); |
39 | 39 | ||
40 | static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; | 40 | static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; |
41 | static unsigned int xfrm_state_genid; | ||
42 | 41 | ||
43 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); | 42 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); |
44 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); | 43 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); |
@@ -924,8 +923,6 @@ static void __xfrm_state_insert(struct xfrm_state *x) | |||
924 | struct net *net = xs_net(x); | 923 | struct net *net = xs_net(x); |
925 | unsigned int h; | 924 | unsigned int h; |
926 | 925 | ||
927 | x->genid = ++xfrm_state_genid; | ||
928 | |||
929 | list_add(&x->km.all, &net->xfrm.state_all); | 926 | list_add(&x->km.all, &net->xfrm.state_all); |
930 | 927 | ||
931 | h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr, | 928 | h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr, |
@@ -971,7 +968,7 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew) | |||
971 | (mark & x->mark.m) == x->mark.v && | 968 | (mark & x->mark.m) == x->mark.v && |
972 | !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && | 969 | !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && |
973 | !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family)) | 970 | !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family)) |
974 | x->genid = xfrm_state_genid; | 971 | x->genid++; |
975 | } | 972 | } |
976 | } | 973 | } |
977 | 974 | ||
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 6106b72826d3..ba59983aaffe 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1741,6 +1741,10 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1741 | if (err) | 1741 | if (err) |
1742 | return err; | 1742 | return err; |
1743 | 1743 | ||
1744 | err = verify_policy_dir(p->dir); | ||
1745 | if (err) | ||
1746 | return err; | ||
1747 | |||
1744 | if (p->index) | 1748 | if (p->index) |
1745 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err); | 1749 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err); |
1746 | else { | 1750 | else { |
@@ -1766,13 +1770,9 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1766 | if (xp == NULL) | 1770 | if (xp == NULL) |
1767 | return -ENOENT; | 1771 | return -ENOENT; |
1768 | 1772 | ||
1769 | read_lock(&xp->lock); | 1773 | if (unlikely(xp->walk.dead)) |
1770 | if (xp->walk.dead) { | ||
1771 | read_unlock(&xp->lock); | ||
1772 | goto out; | 1774 | goto out; |
1773 | } | ||
1774 | 1775 | ||
1775 | read_unlock(&xp->lock); | ||
1776 | err = 0; | 1776 | err = 0; |
1777 | if (up->hard) { | 1777 | if (up->hard) { |
1778 | uid_t loginuid = NETLINK_CB(skb).loginuid; | 1778 | uid_t loginuid = NETLINK_CB(skb).loginuid; |
@@ -1783,7 +1783,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1783 | 1783 | ||
1784 | } else { | 1784 | } else { |
1785 | // reset the timers here? | 1785 | // reset the timers here? |
1786 | printk("Dont know what to do with soft policy expire\n"); | 1786 | WARN(1, "Dont know what to do with soft policy expire\n"); |
1787 | } | 1787 | } |
1788 | km_policy_expired(xp, p->dir, up->hard, current->pid); | 1788 | km_policy_expired(xp, p->dir, up->hard, current->pid); |
1789 | 1789 | ||
@@ -1883,7 +1883,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1883 | return 0; | 1883 | return 0; |
1884 | 1884 | ||
1885 | bad_policy: | 1885 | bad_policy: |
1886 | printk("BAD policy passed\n"); | 1886 | WARN(1, "BAD policy passed\n"); |
1887 | free_state: | 1887 | free_state: |
1888 | kfree(x); | 1888 | kfree(x); |
1889 | nomem: | 1889 | nomem: |
@@ -2385,8 +2385,9 @@ static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c) | |||
2385 | case XFRM_MSG_FLUSHSA: | 2385 | case XFRM_MSG_FLUSHSA: |
2386 | return xfrm_notify_sa_flush(c); | 2386 | return xfrm_notify_sa_flush(c); |
2387 | default: | 2387 | default: |
2388 | printk("xfrm_user: Unknown SA event %d\n", c->event); | 2388 | printk(KERN_NOTICE "xfrm_user: Unknown SA event %d\n", |
2389 | break; | 2389 | c->event); |
2390 | break; | ||
2390 | } | 2391 | } |
2391 | 2392 | ||
2392 | return 0; | 2393 | return 0; |
@@ -2676,7 +2677,8 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_ev | |||
2676 | case XFRM_MSG_POLEXPIRE: | 2677 | case XFRM_MSG_POLEXPIRE: |
2677 | return xfrm_exp_policy_notify(xp, dir, c); | 2678 | return xfrm_exp_policy_notify(xp, dir, c); |
2678 | default: | 2679 | default: |
2679 | printk("xfrm_user: Unknown Policy event %d\n", c->event); | 2680 | printk(KERN_NOTICE "xfrm_user: Unknown Policy event %d\n", |
2681 | c->event); | ||
2680 | } | 2682 | } |
2681 | 2683 | ||
2682 | return 0; | 2684 | return 0; |