aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-03-05 05:06:47 -0500
committerDavid S. Miller <davem@davemloft.net>2009-03-05 05:06:47 -0500
commit508827ff0ac3981d420edac64a70de7f4e304d38 (patch)
treeb0cee8ddef9f0ceab68c388e4ae46b7295eb2cb5 /net
parent2c3c3d02f28801d7ad2da4952b2c7ca6621ef221 (diff)
parent72e2240f181871675d3a979766330c91d48a1673 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/tokenring/tmspci.c drivers/net/ucc_geth_mii.c
Diffstat (limited to 'net')
-rw-r--r--net/802/tr.c2
-rw-r--r--net/8021q/vlan_dev.c3
-rw-r--r--net/core/dev.c55
-rw-r--r--net/core/net-sysfs.c4
-rw-r--r--net/ipv6/addrconf.c53
-rw-r--r--net/ipv6/af_inet6.c21
-rw-r--r--net/netlink/af_netlink.c10
-rw-r--r--net/sched/act_police.c13
-rw-r--r--net/sctp/protocol.c16
-rw-r--r--net/sctp/sm_sideeffect.c54
-rw-r--r--net/sctp/sm_statefuns.c16
11 files changed, 133 insertions, 114 deletions
diff --git a/net/802/tr.c b/net/802/tr.c
index dab6334b6258..e7eb13084d71 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -670,3 +670,5 @@ module_init(rif_init);
670 670
671EXPORT_SYMBOL(tr_type_trans); 671EXPORT_SYMBOL(tr_type_trans);
672EXPORT_SYMBOL(alloc_trdev); 672EXPORT_SYMBOL(alloc_trdev);
673
674MODULE_LICENSE("GPL");
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 4a19acd3a32b..1b34135cf990 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -553,7 +553,7 @@ static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa)
553 int err = 0; 553 int err = 0;
554 554
555 if (netif_device_present(real_dev) && ops->ndo_neigh_setup) 555 if (netif_device_present(real_dev) && ops->ndo_neigh_setup)
556 err = ops->ndo_neigh_setup(dev, pa); 556 err = ops->ndo_neigh_setup(real_dev, pa);
557 557
558 return err; 558 return err;
559} 559}
@@ -639,6 +639,7 @@ static int vlan_dev_init(struct net_device *dev)
639 dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; 639 dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
640 dev->netdev_ops = &vlan_netdev_ops; 640 dev->netdev_ops = &vlan_netdev_ops;
641 } 641 }
642 netdev_resync_ops(dev);
642 643
643 if (is_vlan_dev(real_dev)) 644 if (is_vlan_dev(real_dev))
644 subclass = 1; 645 subclass = 1;
diff --git a/net/core/dev.c b/net/core/dev.c
index bcd0c2154bb2..033d7ca28e6e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4336,6 +4336,39 @@ unsigned long netdev_fix_features(unsigned long features, const char *name)
4336} 4336}
4337EXPORT_SYMBOL(netdev_fix_features); 4337EXPORT_SYMBOL(netdev_fix_features);
4338 4338
4339/* Some devices need to (re-)set their netdev_ops inside
4340 * ->init() or similar. If that happens, we have to setup
4341 * the compat pointers again.
4342 */
4343void netdev_resync_ops(struct net_device *dev)
4344{
4345#ifdef CONFIG_COMPAT_NET_DEV_OPS
4346 const struct net_device_ops *ops = dev->netdev_ops;
4347
4348 dev->init = ops->ndo_init;
4349 dev->uninit = ops->ndo_uninit;
4350 dev->open = ops->ndo_open;
4351 dev->change_rx_flags = ops->ndo_change_rx_flags;
4352 dev->set_rx_mode = ops->ndo_set_rx_mode;
4353 dev->set_multicast_list = ops->ndo_set_multicast_list;
4354 dev->set_mac_address = ops->ndo_set_mac_address;
4355 dev->validate_addr = ops->ndo_validate_addr;
4356 dev->do_ioctl = ops->ndo_do_ioctl;
4357 dev->set_config = ops->ndo_set_config;
4358 dev->change_mtu = ops->ndo_change_mtu;
4359 dev->neigh_setup = ops->ndo_neigh_setup;
4360 dev->tx_timeout = ops->ndo_tx_timeout;
4361 dev->get_stats = ops->ndo_get_stats;
4362 dev->vlan_rx_register = ops->ndo_vlan_rx_register;
4363 dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
4364 dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
4365#ifdef CONFIG_NET_POLL_CONTROLLER
4366 dev->poll_controller = ops->ndo_poll_controller;
4367#endif
4368#endif
4369}
4370EXPORT_SYMBOL(netdev_resync_ops);
4371
4339/** 4372/**
4340 * register_netdevice - register a network device 4373 * register_netdevice - register a network device
4341 * @dev: device to register 4374 * @dev: device to register
@@ -4380,27 +4413,7 @@ int register_netdevice(struct net_device *dev)
4380 * This is temporary until all network devices are converted. 4413 * This is temporary until all network devices are converted.
4381 */ 4414 */
4382 if (dev->netdev_ops) { 4415 if (dev->netdev_ops) {
4383 const struct net_device_ops *ops = dev->netdev_ops; 4416 netdev_resync_ops(dev);
4384
4385 dev->init = ops->ndo_init;
4386 dev->uninit = ops->ndo_uninit;
4387 dev->open = ops->ndo_open;
4388 dev->change_rx_flags = ops->ndo_change_rx_flags;
4389 dev->set_rx_mode = ops->ndo_set_rx_mode;
4390 dev->set_multicast_list = ops->ndo_set_multicast_list;
4391 dev->set_mac_address = ops->ndo_set_mac_address;
4392 dev->validate_addr = ops->ndo_validate_addr;
4393 dev->do_ioctl = ops->ndo_do_ioctl;
4394 dev->set_config = ops->ndo_set_config;
4395 dev->change_mtu = ops->ndo_change_mtu;
4396 dev->tx_timeout = ops->ndo_tx_timeout;
4397 dev->get_stats = ops->ndo_get_stats;
4398 dev->vlan_rx_register = ops->ndo_vlan_rx_register;
4399 dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
4400 dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
4401#ifdef CONFIG_NET_POLL_CONTROLLER
4402 dev->poll_controller = ops->ndo_poll_controller;
4403#endif
4404 } else { 4417 } else {
4405 char drivername[64]; 4418 char drivername[64];
4406 pr_info("%s (%s): not using net_device_ops yet\n", 4419 pr_info("%s (%s): not using net_device_ops yet\n",
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 6ac29a46e23e..484f58750eba 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -77,7 +77,9 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
77 if (endp == buf) 77 if (endp == buf)
78 goto err; 78 goto err;
79 79
80 rtnl_lock(); 80 if (!rtnl_trylock())
81 return -ERESTARTSYS;
82
81 if (dev_isalive(net)) { 83 if (dev_isalive(net)) {
82 if ((ret = (*set)(net, new)) == 0) 84 if ((ret = (*set)(net, new)) == 0)
83 ret = len; 85 ret = len;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f8f76d6e21cb..e83852ab4dc8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -493,15 +493,17 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
493 read_unlock(&dev_base_lock); 493 read_unlock(&dev_base_lock);
494} 494}
495 495
496static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) 496static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
497{ 497{
498 struct net *net; 498 struct net *net;
499 499
500 net = (struct net *)table->extra2; 500 net = (struct net *)table->extra2;
501 if (p == &net->ipv6.devconf_dflt->forwarding) 501 if (p == &net->ipv6.devconf_dflt->forwarding)
502 return; 502 return 0;
503
504 if (!rtnl_trylock())
505 return -ERESTARTSYS;
503 506
504 rtnl_lock();
505 if (p == &net->ipv6.devconf_all->forwarding) { 507 if (p == &net->ipv6.devconf_all->forwarding) {
506 __s32 newf = net->ipv6.devconf_all->forwarding; 508 __s32 newf = net->ipv6.devconf_all->forwarding;
507 net->ipv6.devconf_dflt->forwarding = newf; 509 net->ipv6.devconf_dflt->forwarding = newf;
@@ -512,6 +514,7 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
512 514
513 if (*p) 515 if (*p)
514 rt6_purge_dflt_routers(net); 516 rt6_purge_dflt_routers(net);
517 return 1;
515} 518}
516#endif 519#endif
517 520
@@ -2599,9 +2602,6 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2599 2602
2600 ASSERT_RTNL(); 2603 ASSERT_RTNL();
2601 2604
2602 if ((dev->flags & IFF_LOOPBACK) && how == 1)
2603 how = 0;
2604
2605 rt6_ifdown(net, dev); 2605 rt6_ifdown(net, dev);
2606 neigh_ifdown(&nd_tbl, dev); 2606 neigh_ifdown(&nd_tbl, dev);
2607 2607
@@ -3977,7 +3977,7 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
3977 ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); 3977 ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
3978 3978
3979 if (write) 3979 if (write)
3980 addrconf_fixup_forwarding(ctl, valp, val); 3980 ret = addrconf_fixup_forwarding(ctl, valp, val);
3981 return ret; 3981 return ret;
3982} 3982}
3983 3983
@@ -4013,8 +4013,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
4013 } 4013 }
4014 4014
4015 *valp = new; 4015 *valp = new;
4016 addrconf_fixup_forwarding(table, valp, val); 4016 return addrconf_fixup_forwarding(table, valp, val);
4017 return 1;
4018} 4017}
4019 4018
4020static struct addrconf_sysctl_table 4019static struct addrconf_sysctl_table
@@ -4440,25 +4439,6 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
4440 4439
4441EXPORT_SYMBOL(unregister_inet6addr_notifier); 4440EXPORT_SYMBOL(unregister_inet6addr_notifier);
4442 4441
4443static void addrconf_net_exit(struct net *net)
4444{
4445 struct net_device *dev;
4446
4447 rtnl_lock();
4448 /* clean dev list */
4449 for_each_netdev(net, dev) {
4450 if (__in6_dev_get(dev) == NULL)
4451 continue;
4452 addrconf_ifdown(dev, 1);
4453 }
4454 addrconf_ifdown(net->loopback_dev, 2);
4455 rtnl_unlock();
4456}
4457
4458static struct pernet_operations addrconf_net_ops = {
4459 .exit = addrconf_net_exit,
4460};
4461
4462/* 4442/*
4463 * Init / cleanup code 4443 * Init / cleanup code
4464 */ 4444 */
@@ -4500,10 +4480,6 @@ int __init addrconf_init(void)
4500 if (err) 4480 if (err)
4501 goto errlo; 4481 goto errlo;
4502 4482
4503 err = register_pernet_device(&addrconf_net_ops);
4504 if (err)
4505 return err;
4506
4507 register_netdevice_notifier(&ipv6_dev_notf); 4483 register_netdevice_notifier(&ipv6_dev_notf);
4508 4484
4509 addrconf_verify(0); 4485 addrconf_verify(0);
@@ -4533,15 +4509,22 @@ errlo:
4533void addrconf_cleanup(void) 4509void addrconf_cleanup(void)
4534{ 4510{
4535 struct inet6_ifaddr *ifa; 4511 struct inet6_ifaddr *ifa;
4512 struct net_device *dev;
4536 int i; 4513 int i;
4537 4514
4538 unregister_netdevice_notifier(&ipv6_dev_notf); 4515 unregister_netdevice_notifier(&ipv6_dev_notf);
4539 unregister_pernet_device(&addrconf_net_ops);
4540
4541 unregister_pernet_subsys(&addrconf_ops); 4516 unregister_pernet_subsys(&addrconf_ops);
4542 4517
4543 rtnl_lock(); 4518 rtnl_lock();
4544 4519
4520 /* clean dev list */
4521 for_each_netdev(&init_net, dev) {
4522 if (__in6_dev_get(dev) == NULL)
4523 continue;
4524 addrconf_ifdown(dev, 1);
4525 }
4526 addrconf_ifdown(init_net.loopback_dev, 2);
4527
4545 /* 4528 /*
4546 * Check hash table. 4529 * Check hash table.
4547 */ 4530 */
@@ -4562,6 +4545,4 @@ void addrconf_cleanup(void)
4562 4545
4563 del_timer(&addr_chk_timer); 4546 del_timer(&addr_chk_timer);
4564 rtnl_unlock(); 4547 rtnl_unlock();
4565
4566 unregister_pernet_subsys(&addrconf_net_ops);
4567} 4548}
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index fa2ac7ee662f..57b07da1212a 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -72,6 +72,10 @@ MODULE_LICENSE("GPL");
72static struct list_head inetsw6[SOCK_MAX]; 72static struct list_head inetsw6[SOCK_MAX];
73static DEFINE_SPINLOCK(inetsw6_lock); 73static DEFINE_SPINLOCK(inetsw6_lock);
74 74
75static int disable_ipv6 = 0;
76module_param_named(disable, disable_ipv6, int, 0);
77MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional");
78
75static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) 79static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
76{ 80{
77 const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo); 81 const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo);
@@ -1001,10 +1005,21 @@ static int __init inet6_init(void)
1001{ 1005{
1002 struct sk_buff *dummy_skb; 1006 struct sk_buff *dummy_skb;
1003 struct list_head *r; 1007 struct list_head *r;
1004 int err; 1008 int err = 0;
1005 1009
1006 BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)); 1010 BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb));
1007 1011
1012 /* Register the socket-side information for inet6_create. */
1013 for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
1014 INIT_LIST_HEAD(r);
1015
1016 if (disable_ipv6) {
1017 printk(KERN_INFO
1018 "IPv6: Loaded, but administratively disabled, "
1019 "reboot required to enable\n");
1020 goto out;
1021 }
1022
1008 err = proto_register(&tcpv6_prot, 1); 1023 err = proto_register(&tcpv6_prot, 1);
1009 if (err) 1024 if (err)
1010 goto out; 1025 goto out;
@@ -1022,10 +1037,6 @@ static int __init inet6_init(void)
1022 goto out_unregister_udplite_proto; 1037 goto out_unregister_udplite_proto;
1023 1038
1024 1039
1025 /* Register the socket-side information for inet6_create. */
1026 for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
1027 INIT_LIST_HEAD(r);
1028
1029 /* We MUST register RAW sockets before we create the ICMP6, 1040 /* We MUST register RAW sockets before we create the ICMP6,
1030 * IGMP6, or NDISC control sockets. 1041 * IGMP6, or NDISC control sockets.
1031 */ 1042 */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index e57d700bf6d9..a007dbb4c9f1 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1091,6 +1091,13 @@ out:
1091 return 0; 1091 return 0;
1092} 1092}
1093 1093
1094/**
1095 * netlink_set_err - report error to broadcast listeners
1096 * @ssk: the kernel netlink socket, as returned by netlink_kernel_create()
1097 * @pid: the PID of a process that we want to skip (if any)
1098 * @groups: the broadcast group that will notice the error
1099 * @code: error code, must be negative (as usual in kernelspace)
1100 */
1094void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) 1101void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
1095{ 1102{
1096 struct netlink_set_err_data info; 1103 struct netlink_set_err_data info;
@@ -1100,7 +1107,8 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
1100 info.exclude_sk = ssk; 1107 info.exclude_sk = ssk;
1101 info.pid = pid; 1108 info.pid = pid;
1102 info.group = group; 1109 info.group = group;
1103 info.code = code; 1110 /* sk->sk_err wants a positive error value */
1111 info.code = -code;
1104 1112
1105 read_lock(&nl_table_lock); 1113 read_lock(&nl_table_lock);
1106 1114
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 5c72a116b1a4..f8f047b61245 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -183,13 +183,6 @@ override:
183 if (R_tab == NULL) 183 if (R_tab == NULL)
184 goto failure; 184 goto failure;
185 185
186 if (!est && (ret == ACT_P_CREATED ||
187 !gen_estimator_active(&police->tcf_bstats,
188 &police->tcf_rate_est))) {
189 err = -EINVAL;
190 goto failure;
191 }
192
193 if (parm->peakrate.rate) { 186 if (parm->peakrate.rate) {
194 P_tab = qdisc_get_rtab(&parm->peakrate, 187 P_tab = qdisc_get_rtab(&parm->peakrate,
195 tb[TCA_POLICE_PEAKRATE]); 188 tb[TCA_POLICE_PEAKRATE]);
@@ -205,6 +198,12 @@ override:
205 &police->tcf_lock, est); 198 &police->tcf_lock, est);
206 if (err) 199 if (err)
207 goto failure_unlock; 200 goto failure_unlock;
201 } else if (tb[TCA_POLICE_AVRATE] &&
202 (ret == ACT_P_CREATED ||
203 !gen_estimator_active(&police->tcf_bstats,
204 &police->tcf_rate_est))) {
205 err = -EINVAL;
206 goto failure_unlock;
208 } 207 }
209 208
210 /* No failure allowed after this point */ 209 /* No failure allowed after this point */
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index c1e316ee7155..cb198af8887c 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -692,15 +692,20 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
692static int sctp_ctl_sock_init(void) 692static int sctp_ctl_sock_init(void)
693{ 693{
694 int err; 694 int err;
695 sa_family_t family; 695 sa_family_t family = PF_INET;
696 696
697 if (sctp_get_pf_specific(PF_INET6)) 697 if (sctp_get_pf_specific(PF_INET6))
698 family = PF_INET6; 698 family = PF_INET6;
699 else
700 family = PF_INET;
701 699
702 err = inet_ctl_sock_create(&sctp_ctl_sock, family, 700 err = inet_ctl_sock_create(&sctp_ctl_sock, family,
703 SOCK_SEQPACKET, IPPROTO_SCTP, &init_net); 701 SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
702
703 /* If IPv6 socket could not be created, try the IPv4 socket */
704 if (err < 0 && family == PF_INET6)
705 err = inet_ctl_sock_create(&sctp_ctl_sock, AF_INET,
706 SOCK_SEQPACKET, IPPROTO_SCTP,
707 &init_net);
708
704 if (err < 0) { 709 if (err < 0) {
705 printk(KERN_ERR 710 printk(KERN_ERR
706 "SCTP: Failed to create the SCTP control socket.\n"); 711 "SCTP: Failed to create the SCTP control socket.\n");
@@ -1297,9 +1302,8 @@ SCTP_STATIC __init int sctp_init(void)
1297out: 1302out:
1298 return status; 1303 return status;
1299err_v6_add_protocol: 1304err_v6_add_protocol:
1300 sctp_v6_del_protocol();
1301err_add_protocol:
1302 sctp_v4_del_protocol(); 1305 sctp_v4_del_protocol();
1306err_add_protocol:
1303 inet_ctl_sock_destroy(sctp_ctl_sock); 1307 inet_ctl_sock_destroy(sctp_ctl_sock);
1304err_ctl_sock_init: 1308err_ctl_sock_init:
1305 sctp_v6_protosw_exit(); 1309 sctp_v6_protosw_exit();
@@ -1310,7 +1314,6 @@ err_protosw_init:
1310 sctp_v4_pf_exit(); 1314 sctp_v4_pf_exit();
1311 sctp_v6_pf_exit(); 1315 sctp_v6_pf_exit();
1312 sctp_sysctl_unregister(); 1316 sctp_sysctl_unregister();
1313 list_del(&sctp_af_inet.list);
1314 free_pages((unsigned long)sctp_port_hashtable, 1317 free_pages((unsigned long)sctp_port_hashtable,
1315 get_order(sctp_port_hashsize * 1318 get_order(sctp_port_hashsize *
1316 sizeof(struct sctp_bind_hashbucket))); 1319 sizeof(struct sctp_bind_hashbucket)));
@@ -1358,7 +1361,6 @@ SCTP_STATIC __exit void sctp_exit(void)
1358 sctp_v4_pf_exit(); 1361 sctp_v4_pf_exit();
1359 1362
1360 sctp_sysctl_unregister(); 1363 sctp_sysctl_unregister();
1361 list_del(&sctp_af_inet.list);
1362 1364
1363 free_pages((unsigned long)sctp_assoc_hashtable, 1365 free_pages((unsigned long)sctp_assoc_hashtable,
1364 get_order(sctp_assoc_hashsize * 1366 get_order(sctp_assoc_hashsize *
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 5385150df296..e2020eb2c8ca 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -787,36 +787,48 @@ static void sctp_cmd_process_operr(sctp_cmd_seq_t *cmds,
787 struct sctp_association *asoc, 787 struct sctp_association *asoc,
788 struct sctp_chunk *chunk) 788 struct sctp_chunk *chunk)
789{ 789{
790 struct sctp_operr_chunk *operr_chunk;
791 struct sctp_errhdr *err_hdr; 790 struct sctp_errhdr *err_hdr;
791 struct sctp_ulpevent *ev;
792 792
793 operr_chunk = (struct sctp_operr_chunk *)chunk->chunk_hdr; 793 while (chunk->chunk_end > chunk->skb->data) {
794 err_hdr = &operr_chunk->err_hdr; 794 err_hdr = (struct sctp_errhdr *)(chunk->skb->data);
795 795
796 switch (err_hdr->cause) { 796 ev = sctp_ulpevent_make_remote_error(asoc, chunk, 0,
797 case SCTP_ERROR_UNKNOWN_CHUNK: 797 GFP_ATOMIC);
798 { 798 if (!ev)
799 struct sctp_chunkhdr *unk_chunk_hdr; 799 return;
800 800
801 unk_chunk_hdr = (struct sctp_chunkhdr *)err_hdr->variable; 801 sctp_ulpq_tail_event(&asoc->ulpq, ev);
802 switch (unk_chunk_hdr->type) { 802
803 /* ADDIP 4.1 A9) If the peer responds to an ASCONF with an 803 switch (err_hdr->cause) {
804 * ERROR chunk reporting that it did not recognized the ASCONF 804 case SCTP_ERROR_UNKNOWN_CHUNK:
805 * chunk type, the sender of the ASCONF MUST NOT send any 805 {
806 * further ASCONF chunks and MUST stop its T-4 timer. 806 sctp_chunkhdr_t *unk_chunk_hdr;
807 */ 807
808 case SCTP_CID_ASCONF: 808 unk_chunk_hdr = (sctp_chunkhdr_t *)err_hdr->variable;
809 asoc->peer.asconf_capable = 0; 809 switch (unk_chunk_hdr->type) {
810 sctp_add_cmd_sf(cmds, SCTP_CMD_TIMER_STOP, 810 /* ADDIP 4.1 A9) If the peer responds to an ASCONF with
811 * an ERROR chunk reporting that it did not recognized
812 * the ASCONF chunk type, the sender of the ASCONF MUST
813 * NOT send any further ASCONF chunks and MUST stop its
814 * T-4 timer.
815 */
816 case SCTP_CID_ASCONF:
817 if (asoc->peer.asconf_capable == 0)
818 break;
819
820 asoc->peer.asconf_capable = 0;
821 sctp_add_cmd_sf(cmds, SCTP_CMD_TIMER_STOP,
811 SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 822 SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
823 break;
824 default:
825 break;
826 }
812 break; 827 break;
828 }
813 default: 829 default:
814 break; 830 break;
815 } 831 }
816 break;
817 }
818 default:
819 break;
820 } 832 }
821} 833}
822 834
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index a907bab0963d..55a61aa69662 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3165,7 +3165,6 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
3165 sctp_cmd_seq_t *commands) 3165 sctp_cmd_seq_t *commands)
3166{ 3166{
3167 struct sctp_chunk *chunk = arg; 3167 struct sctp_chunk *chunk = arg;
3168 struct sctp_ulpevent *ev;
3169 3168
3170 if (!sctp_vtag_verify(chunk, asoc)) 3169 if (!sctp_vtag_verify(chunk, asoc))
3171 return sctp_sf_pdiscard(ep, asoc, type, arg, commands); 3170 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -3175,21 +3174,10 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
3175 return sctp_sf_violation_chunklen(ep, asoc, type, arg, 3174 return sctp_sf_violation_chunklen(ep, asoc, type, arg,
3176 commands); 3175 commands);
3177 3176
3178 while (chunk->chunk_end > chunk->skb->data) { 3177 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
3179 ev = sctp_ulpevent_make_remote_error(asoc, chunk, 0, 3178 SCTP_CHUNK(chunk));
3180 GFP_ATOMIC);
3181 if (!ev)
3182 goto nomem;
3183 3179
3184 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
3185 SCTP_ULPEVENT(ev));
3186 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
3187 SCTP_CHUNK(chunk));
3188 }
3189 return SCTP_DISPOSITION_CONSUME; 3180 return SCTP_DISPOSITION_CONSUME;
3190
3191nomem:
3192 return SCTP_DISPOSITION_NOMEM;
3193} 3181}
3194 3182
3195/* 3183/*