diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-05-25 18:59:33 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-18 00:26:12 -0400 |
commit | c090971326db094ed702c1f8f2dbe04b7e3b8f27 (patch) | |
tree | 9c964fc79298455eb4b45981a34a6117175ff846 /net | |
parent | 9ef513bed68534110727381ab652f06756803f5a (diff) |
[BRIDGE]: fix module startup error handling
Return address in use, if some other kernel code has the SAP.
Propogate out error codes from netfilter registration and unwind.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br.c | 26 | ||||
-rw-r--r-- | net/bridge/br_private.h | 5 |
2 files changed, 22 insertions, 9 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c index 12da21afb9ca..558d27204f60 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
@@ -30,36 +30,44 @@ static struct llc_sap *br_stp_sap; | |||
30 | 30 | ||
31 | static int __init br_init(void) | 31 | static int __init br_init(void) |
32 | { | 32 | { |
33 | int err; | ||
34 | |||
33 | br_stp_sap = llc_sap_open(LLC_SAP_BSPAN, br_stp_rcv); | 35 | br_stp_sap = llc_sap_open(LLC_SAP_BSPAN, br_stp_rcv); |
34 | if (!br_stp_sap) { | 36 | if (!br_stp_sap) { |
35 | printk(KERN_ERR "bridge: can't register sap for STP\n"); | 37 | printk(KERN_ERR "bridge: can't register sap for STP\n"); |
36 | return -EBUSY; | 38 | return -EADDRINUSE; |
37 | } | 39 | } |
38 | 40 | ||
39 | br_fdb_init(); | 41 | br_fdb_init(); |
40 | 42 | ||
41 | #ifdef CONFIG_BRIDGE_NETFILTER | 43 | err = br_netfilter_init(); |
42 | if (br_netfilter_init()) | 44 | if (err) |
43 | return 1; | 45 | goto err_out1; |
44 | #endif | 46 | |
47 | err = register_netdevice_notifier(&br_device_notifier); | ||
48 | if (err) | ||
49 | goto err_out2; | ||
50 | |||
45 | brioctl_set(br_ioctl_deviceless_stub); | 51 | brioctl_set(br_ioctl_deviceless_stub); |
46 | br_handle_frame_hook = br_handle_frame; | 52 | br_handle_frame_hook = br_handle_frame; |
47 | 53 | ||
48 | br_fdb_get_hook = br_fdb_get; | 54 | br_fdb_get_hook = br_fdb_get; |
49 | br_fdb_put_hook = br_fdb_put; | 55 | br_fdb_put_hook = br_fdb_put; |
50 | 56 | ||
51 | register_netdevice_notifier(&br_device_notifier); | ||
52 | |||
53 | return 0; | 57 | return 0; |
58 | |||
59 | err_out2: | ||
60 | br_netfilter_fini(); | ||
61 | err_out1: | ||
62 | llc_sap_put(br_stp_sap); | ||
63 | return err; | ||
54 | } | 64 | } |
55 | 65 | ||
56 | static void __exit br_deinit(void) | 66 | static void __exit br_deinit(void) |
57 | { | 67 | { |
58 | rcu_assign_pointer(br_stp_sap->rcv_func, NULL); | 68 | rcu_assign_pointer(br_stp_sap->rcv_func, NULL); |
59 | 69 | ||
60 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
61 | br_netfilter_fini(); | 70 | br_netfilter_fini(); |
62 | #endif | ||
63 | unregister_netdevice_notifier(&br_device_notifier); | 71 | unregister_netdevice_notifier(&br_device_notifier); |
64 | brioctl_set(NULL); | 72 | brioctl_set(NULL); |
65 | 73 | ||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 86ecea7ed372..22071d156828 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -192,8 +192,13 @@ extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | |||
192 | extern int br_ioctl_deviceless_stub(unsigned int cmd, void __user *arg); | 192 | extern int br_ioctl_deviceless_stub(unsigned int cmd, void __user *arg); |
193 | 193 | ||
194 | /* br_netfilter.c */ | 194 | /* br_netfilter.c */ |
195 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
195 | extern int br_netfilter_init(void); | 196 | extern int br_netfilter_init(void); |
196 | extern void br_netfilter_fini(void); | 197 | extern void br_netfilter_fini(void); |
198 | #else | ||
199 | #define br_netfilter_init() (0) | ||
200 | #define br_netfilter_fini() do { } while(0) | ||
201 | #endif | ||
197 | 202 | ||
198 | /* br_stp.c */ | 203 | /* br_stp.c */ |
199 | extern void br_log_state(const struct net_bridge_port *p); | 204 | extern void br_log_state(const struct net_bridge_port *p); |