diff options
author | David S. Miller <davem@davemloft.net> | 2009-03-05 05:06:47 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-05 05:06:47 -0500 |
commit | 508827ff0ac3981d420edac64a70de7f4e304d38 (patch) | |
tree | b0cee8ddef9f0ceab68c388e4ae46b7295eb2cb5 /net | |
parent | 2c3c3d02f28801d7ad2da4952b2c7ca6621ef221 (diff) | |
parent | 72e2240f181871675d3a979766330c91d48a1673 (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.c | 2 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 3 | ||||
-rw-r--r-- | net/core/dev.c | 55 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 4 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 53 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 21 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 10 | ||||
-rw-r--r-- | net/sched/act_police.c | 13 | ||||
-rw-r--r-- | net/sctp/protocol.c | 16 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 54 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 16 |
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 | ||
671 | EXPORT_SYMBOL(tr_type_trans); | 671 | EXPORT_SYMBOL(tr_type_trans); |
672 | EXPORT_SYMBOL(alloc_trdev); | 672 | EXPORT_SYMBOL(alloc_trdev); |
673 | |||
674 | MODULE_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 | } |
4337 | EXPORT_SYMBOL(netdev_fix_features); | 4337 | EXPORT_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 | */ | ||
4343 | void 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 | } | ||
4370 | EXPORT_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 | ||
496 | static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | 496 | static 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 | ||
4020 | static struct addrconf_sysctl_table | 4019 | static struct addrconf_sysctl_table |
@@ -4440,25 +4439,6 @@ int unregister_inet6addr_notifier(struct notifier_block *nb) | |||
4440 | 4439 | ||
4441 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4440 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4442 | 4441 | ||
4443 | static 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 | |||
4458 | static 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: | |||
4533 | void addrconf_cleanup(void) | 4509 | void 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"); | |||
72 | static struct list_head inetsw6[SOCK_MAX]; | 72 | static struct list_head inetsw6[SOCK_MAX]; |
73 | static DEFINE_SPINLOCK(inetsw6_lock); | 73 | static DEFINE_SPINLOCK(inetsw6_lock); |
74 | 74 | ||
75 | static int disable_ipv6 = 0; | ||
76 | module_param_named(disable, disable_ipv6, int, 0); | ||
77 | MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional"); | ||
78 | |||
75 | static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) | 79 | static __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 | */ | ||
1094 | void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) | 1101 | void 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, | |||
692 | static int sctp_ctl_sock_init(void) | 692 | static 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) | |||
1297 | out: | 1302 | out: |
1298 | return status; | 1303 | return status; |
1299 | err_v6_add_protocol: | 1304 | err_v6_add_protocol: |
1300 | sctp_v6_del_protocol(); | ||
1301 | err_add_protocol: | ||
1302 | sctp_v4_del_protocol(); | 1305 | sctp_v4_del_protocol(); |
1306 | err_add_protocol: | ||
1303 | inet_ctl_sock_destroy(sctp_ctl_sock); | 1307 | inet_ctl_sock_destroy(sctp_ctl_sock); |
1304 | err_ctl_sock_init: | 1308 | err_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 | |||
3191 | nomem: | ||
3192 | return SCTP_DISPOSITION_NOMEM; | ||
3193 | } | 3181 | } |
3194 | 3182 | ||
3195 | /* | 3183 | /* |