diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-04-26 04:31:28 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-04-26 04:31:28 -0400 |
commit | ef2e58ea6b9931c3a4816c66593da49bb20e3b24 (patch) | |
tree | ce7432add3becbe78de4ea06425cd2d9e91f4ada /net | |
parent | 06d63cc51d47f572009138a7f3ac34d95773405d (diff) | |
parent | de46c33745f5e2ad594c72f2cf5f490861b16ce1 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'net')
78 files changed, 874 insertions, 3078 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 2fc8fe2cb366..b6e0eea1e39e 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -380,6 +380,9 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, | |||
380 | } else { | 380 | } else { |
381 | vhdr->h_vlan_encapsulated_proto = htons(len); | 381 | vhdr->h_vlan_encapsulated_proto = htons(len); |
382 | } | 382 | } |
383 | |||
384 | skb->protocol = htons(ETH_P_8021Q); | ||
385 | skb->nh.raw = skb->data; | ||
383 | } | 386 | } |
384 | 387 | ||
385 | /* Before delegating work to the lower layer, enter our MAC-address */ | 388 | /* Before delegating work to the lower layer, enter our MAC-address */ |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 113c175f1715..c8b7dc2c3257 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -1417,10 +1417,13 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1417 | /* | 1417 | /* |
1418 | * Size check to see if ddp->deh_len was crap | 1418 | * Size check to see if ddp->deh_len was crap |
1419 | * (Otherwise we'll detonate most spectacularly | 1419 | * (Otherwise we'll detonate most spectacularly |
1420 | * in the middle of recvmsg()). | 1420 | * in the middle of atalk_checksum() or recvmsg()). |
1421 | */ | 1421 | */ |
1422 | if (skb->len < sizeof(*ddp)) | 1422 | if (skb->len < sizeof(*ddp) || skb->len < (len_hops & 1023)) { |
1423 | pr_debug("AppleTalk: dropping corrupted frame (deh_len=%u, " | ||
1424 | "skb->len=%u)\n", len_hops & 1023, skb->len); | ||
1423 | goto freeit; | 1425 | goto freeit; |
1426 | } | ||
1424 | 1427 | ||
1425 | /* | 1428 | /* |
1426 | * Any checksums. Note we don't do htons() on this == is assumed to be | 1429 | * Any checksums. Note we don't do htons() on this == is assumed to be |
diff --git a/net/atm/clip.c b/net/atm/clip.c index ebb5d0ce8b6f..8c3825816085 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -261,14 +261,6 @@ static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb) | |||
261 | spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags); | 261 | spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags); |
262 | } | 262 | } |
263 | 263 | ||
264 | static void clip_neigh_destroy(struct neighbour *neigh) | ||
265 | { | ||
266 | DPRINTK("clip_neigh_destroy (neigh %p)\n", neigh); | ||
267 | if (NEIGH2ENTRY(neigh)->vccs) | ||
268 | printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n"); | ||
269 | NEIGH2ENTRY(neigh)->vccs = (void *) NEIGHBOR_DEAD; | ||
270 | } | ||
271 | |||
272 | static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb) | 264 | static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb) |
273 | { | 265 | { |
274 | DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb); | 266 | DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb); |
@@ -342,7 +334,6 @@ static struct neigh_table clip_tbl = { | |||
342 | /* parameters are copied from ARP ... */ | 334 | /* parameters are copied from ARP ... */ |
343 | .parms = { | 335 | .parms = { |
344 | .tbl = &clip_tbl, | 336 | .tbl = &clip_tbl, |
345 | .neigh_destructor = clip_neigh_destroy, | ||
346 | .base_reachable_time = 30 * HZ, | 337 | .base_reachable_time = 30 * HZ, |
347 | .retrans_time = 1 * HZ, | 338 | .retrans_time = 1 * HZ, |
348 | .gc_staletime = 60 * HZ, | 339 | .gc_staletime = 60 * HZ, |
diff --git a/net/ax25/Kconfig b/net/ax25/Kconfig index a8993a041724..43dd86fca4d3 100644 --- a/net/ax25/Kconfig +++ b/net/ax25/Kconfig | |||
@@ -1,30 +1,27 @@ | |||
1 | # | 1 | # |
2 | # Amateur Radio protocols and AX.25 device configuration | 2 | # Amateur Radio protocols and AX.25 device configuration |
3 | # | 3 | # |
4 | # 19971130 Now in an own category to make correct compilation of the | ||
5 | # AX.25 stuff easier... | ||
6 | # Joerg Reuter DL1BKE <jreuter@yaina.de> | ||
7 | # 19980129 Moved to net/ax25/Config.in, sourcing device drivers. | ||
8 | 4 | ||
9 | menuconfig HAMRADIO | 5 | menuconfig HAMRADIO |
10 | depends on NET | 6 | depends on NET |
11 | bool "Amateur Radio support" | 7 | bool "Amateur Radio support" |
12 | help | 8 | help |
13 | If you want to connect your Linux box to an amateur radio, answer Y | 9 | If you want to connect your Linux box to an amateur radio, answer Y |
14 | here. You want to read <http://www.tapr.org/tapr/html/pkthome.html> and | 10 | here. You want to read <http://www.tapr.org/tapr/html/pkthome.html> |
15 | the AX25-HOWTO, available from <http://www.tldp.org/docs.html#howto>. | 11 | and more specifically about AX.25 on Linux |
12 | <http://www.linux-ax25.org/>. | ||
16 | 13 | ||
17 | Note that the answer to this question won't directly affect the | 14 | Note that the answer to this question won't directly affect the |
18 | kernel: saying N will just cause the configurator to skip all | 15 | kernel: saying N will just cause the configurator to skip all |
19 | the questions about amateur radio. | 16 | the questions about amateur radio. |
20 | 17 | ||
21 | comment "Packet Radio protocols" | 18 | comment "Packet Radio protocols" |
22 | depends on HAMRADIO && NET | 19 | depends on HAMRADIO |
23 | 20 | ||
24 | config AX25 | 21 | config AX25 |
25 | tristate "Amateur Radio AX.25 Level 2 protocol" | 22 | tristate "Amateur Radio AX.25 Level 2 protocol" |
26 | depends on HAMRADIO && NET | 23 | depends on HAMRADIO |
27 | ---help--- | 24 | help |
28 | This is the protocol used for computer communication over amateur | 25 | This is the protocol used for computer communication over amateur |
29 | radio. It is either used by itself for point-to-point links, or to | 26 | radio. It is either used by itself for point-to-point links, or to |
30 | carry other protocols such as tcp/ip. To use it, you need a device | 27 | carry other protocols such as tcp/ip. To use it, you need a device |
@@ -52,6 +49,7 @@ config AX25 | |||
52 | 49 | ||
53 | config AX25_DAMA_SLAVE | 50 | config AX25_DAMA_SLAVE |
54 | bool "AX.25 DAMA Slave support" | 51 | bool "AX.25 DAMA Slave support" |
52 | default y | ||
55 | depends on AX25 | 53 | depends on AX25 |
56 | help | 54 | help |
57 | DAMA is a mechanism to prevent collisions when doing AX.25 | 55 | DAMA is a mechanism to prevent collisions when doing AX.25 |
@@ -59,23 +57,38 @@ config AX25_DAMA_SLAVE | |||
59 | from clients (called "slaves") and redistributes it to other slaves. | 57 | from clients (called "slaves") and redistributes it to other slaves. |
60 | If you say Y here, your Linux box will act as a DAMA slave; this is | 58 | If you say Y here, your Linux box will act as a DAMA slave; this is |
61 | transparent in that you don't have to do any special DAMA | 59 | transparent in that you don't have to do any special DAMA |
62 | configuration. (Linux cannot yet act as a DAMA server.) If unsure, | 60 | configuration. Linux cannot yet act as a DAMA server. This option |
63 | say N. | 61 | only compiles DAMA slave support into the kernel. It still needs to |
62 | be enabled at runtime. For more about DAMA see | ||
63 | <http://www.linux-ax25.org>. If unsure, say Y. | ||
64 | |||
65 | # placeholder until implemented | ||
66 | config AX25_DAMA_MASTER | ||
67 | bool 'AX.25 DAMA Master support' | ||
68 | depends on AX25_DAMA_SLAVE && BROKEN | ||
69 | help | ||
70 | DAMA is a mechanism to prevent collisions when doing AX.25 | ||
71 | networking. A DAMA server (called "master") accepts incoming traffic | ||
72 | from clients (called "slaves") and redistributes it to other slaves. | ||
73 | If you say Y here, your Linux box will act as a DAMA master; this is | ||
74 | transparent in that you don't have to do any special DAMA | ||
75 | configuration. Linux cannot yet act as a DAMA server. This option | ||
76 | only compiles DAMA slave support into the kernel. It still needs to | ||
77 | be explicitly enabled, so if unsure, say Y. | ||
64 | 78 | ||
65 | # bool ' AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER | ||
66 | config NETROM | 79 | config NETROM |
67 | tristate "Amateur Radio NET/ROM protocol" | 80 | tristate "Amateur Radio NET/ROM protocol" |
68 | depends on AX25 | 81 | depends on AX25 |
69 | ---help--- | 82 | help |
70 | NET/ROM is a network layer protocol on top of AX.25 useful for | 83 | NET/ROM is a network layer protocol on top of AX.25 useful for |
71 | routing. | 84 | routing. |
72 | 85 | ||
73 | A comprehensive listing of all the software for Linux amateur radio | 86 | A comprehensive listing of all the software for Linux amateur radio |
74 | users as well as information about how to configure an AX.25 port is | 87 | users as well as information about how to configure an AX.25 port is |
75 | contained in the AX25-HOWTO, available from | 88 | contained in the Linux Ham Wiki, available from |
76 | <http://www.tldp.org/docs.html#howto>. You also might want to | 89 | <http://www.linux-ax25.org>. You also might want to check out the |
77 | check out the file <file:Documentation/networking/ax25.txt>. More | 90 | file <file:Documentation/networking/ax25.txt>. More information about |
78 | information about digital amateur radio in general is on the WWW at | 91 | digital amateur radio in general is on the WWW at |
79 | <http://www.tapr.org/tapr/html/pkthome.html>. | 92 | <http://www.tapr.org/tapr/html/pkthome.html>. |
80 | 93 | ||
81 | To compile this driver as a module, choose M here: the | 94 | To compile this driver as a module, choose M here: the |
@@ -84,27 +97,25 @@ config NETROM | |||
84 | config ROSE | 97 | config ROSE |
85 | tristate "Amateur Radio X.25 PLP (Rose)" | 98 | tristate "Amateur Radio X.25 PLP (Rose)" |
86 | depends on AX25 | 99 | depends on AX25 |
87 | ---help--- | 100 | help |
88 | The Packet Layer Protocol (PLP) is a way to route packets over X.25 | 101 | The Packet Layer Protocol (PLP) is a way to route packets over X.25 |
89 | connections in general and amateur radio AX.25 connections in | 102 | connections in general and amateur radio AX.25 connections in |
90 | particular, essentially an alternative to NET/ROM. | 103 | particular, essentially an alternative to NET/ROM. |
91 | 104 | ||
92 | A comprehensive listing of all the software for Linux amateur radio | 105 | A comprehensive listing of all the software for Linux amateur radio |
93 | users as well as information about how to configure an AX.25 port is | 106 | users as well as information about how to configure an AX.25 port is |
94 | contained in the AX25-HOWTO, available from | 107 | contained in the Linux Ham Wiki, available from |
95 | <http://www.tldp.org/docs.html#howto>. You also might want to | 108 | <http://www.linux-ax25.org>. You also might want to check out the |
96 | check out the file <file:Documentation/networking/ax25.txt>. More | 109 | file <file:Documentation/networking/ax25.txt>. More information about |
97 | information about digital amateur radio in general is on the WWW at | 110 | digital amateur radio in general is on the WWW at |
98 | <http://www.tapr.org/tapr/html/pkthome.html>. | 111 | <http://www.tapr.org/tapr/html/pkthome.html>. |
99 | 112 | ||
100 | To compile this driver as a module, choose M here: the | 113 | To compile this driver as a module, choose M here: the |
101 | module will be called rose. | 114 | module will be called rose. |
102 | 115 | ||
103 | |||
104 | menu "AX.25 network device drivers" | 116 | menu "AX.25 network device drivers" |
105 | depends on HAMRADIO && NET && AX25!=n | 117 | depends on HAMRADIO && AX25 |
106 | 118 | ||
107 | source "drivers/net/hamradio/Kconfig" | 119 | source "drivers/net/hamradio/Kconfig" |
108 | 120 | ||
109 | endmenu | 121 | endmenu |
110 | |||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 4c914df5fd06..d342e89b8bdd 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -319,7 +319,7 @@ static int __hidp_send_ctrl_message(struct hidp_session *session, | |||
319 | return 0; | 319 | return 0; |
320 | } | 320 | } |
321 | 321 | ||
322 | static int inline hidp_send_ctrl_message(struct hidp_session *session, | 322 | static inline int hidp_send_ctrl_message(struct hidp_session *session, |
323 | unsigned char hdr, unsigned char *data, int size) | 323 | unsigned char hdr, unsigned char *data, int size) |
324 | { | 324 | { |
325 | int err; | 325 | int err; |
@@ -679,6 +679,27 @@ static void hidp_close(struct hid_device *hid) | |||
679 | { | 679 | { |
680 | } | 680 | } |
681 | 681 | ||
682 | static const struct { | ||
683 | __u16 idVendor; | ||
684 | __u16 idProduct; | ||
685 | unsigned quirks; | ||
686 | } hidp_blacklist[] = { | ||
687 | /* Apple wireless Mighty Mouse */ | ||
688 | { 0x05ac, 0x030c, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, | ||
689 | |||
690 | { } /* Terminating entry */ | ||
691 | }; | ||
692 | |||
693 | static void hidp_setup_quirks(struct hid_device *hid) | ||
694 | { | ||
695 | unsigned int n; | ||
696 | |||
697 | for (n = 0; hidp_blacklist[n].idVendor; n++) | ||
698 | if (hidp_blacklist[n].idVendor == le16_to_cpu(hid->vendor) && | ||
699 | hidp_blacklist[n].idProduct == le16_to_cpu(hid->product)) | ||
700 | hid->quirks = hidp_blacklist[n].quirks; | ||
701 | } | ||
702 | |||
682 | static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_connadd_req *req) | 703 | static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_connadd_req *req) |
683 | { | 704 | { |
684 | struct hid_device *hid = session->hid; | 705 | struct hid_device *hid = session->hid; |
@@ -708,6 +729,8 @@ static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_conn | |||
708 | 729 | ||
709 | hid->hidinput_input_event = hidp_hidinput_event; | 730 | hid->hidinput_input_event = hidp_hidinput_event; |
710 | 731 | ||
732 | hidp_setup_quirks(hid); | ||
733 | |||
711 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) | 734 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) |
712 | hidp_send_report(session, report); | 735 | hidp_send_report(session, report); |
713 | 736 | ||
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index def2e403f932..8d566c13cc73 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -197,8 +197,8 @@ struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, | |||
197 | 197 | ||
198 | rcu_read_lock(); | 198 | rcu_read_lock(); |
199 | fdb = __br_fdb_get(br, addr); | 199 | fdb = __br_fdb_get(br, addr); |
200 | if (fdb) | 200 | if (fdb && !atomic_inc_not_zero(&fdb->use_count)) |
201 | atomic_inc(&fdb->use_count); | 201 | fdb = NULL; |
202 | rcu_read_unlock(); | 202 | rcu_read_unlock(); |
203 | return fdb; | 203 | return fdb; |
204 | } | 204 | } |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 7712d76f06ba..5439a3c46c3e 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -61,7 +61,7 @@ static int brnf_filter_vlan_tagged __read_mostly = 1; | |||
61 | #define brnf_filter_vlan_tagged 1 | 61 | #define brnf_filter_vlan_tagged 1 |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | static __be16 inline vlan_proto(const struct sk_buff *skb) | 64 | static inline __be16 vlan_proto(const struct sk_buff *skb) |
65 | { | 65 | { |
66 | return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; | 66 | return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; |
67 | } | 67 | } |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 58d13f2bd121..a285897a2fb4 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -126,7 +126,9 @@ void br_stp_disable_port(struct net_bridge_port *p) | |||
126 | /* called under bridge lock */ | 126 | /* called under bridge lock */ |
127 | void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | 127 | void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) |
128 | { | 128 | { |
129 | unsigned char oldaddr[6]; | 129 | /* should be aligned on 2 bytes for compare_ether_addr() */ |
130 | unsigned short oldaddr_aligned[ETH_ALEN >> 1]; | ||
131 | unsigned char *oldaddr = (unsigned char *)oldaddr_aligned; | ||
130 | struct net_bridge_port *p; | 132 | struct net_bridge_port *p; |
131 | int wasroot; | 133 | int wasroot; |
132 | 134 | ||
@@ -151,11 +153,14 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | |||
151 | br_become_root_bridge(br); | 153 | br_become_root_bridge(br); |
152 | } | 154 | } |
153 | 155 | ||
154 | static const unsigned char br_mac_zero[6]; | 156 | /* should be aligned on 2 bytes for compare_ether_addr() */ |
157 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; | ||
155 | 158 | ||
156 | /* called under bridge lock */ | 159 | /* called under bridge lock */ |
157 | void br_stp_recalculate_bridge_id(struct net_bridge *br) | 160 | void br_stp_recalculate_bridge_id(struct net_bridge *br) |
158 | { | 161 | { |
162 | const unsigned char *br_mac_zero = | ||
163 | (const unsigned char *)br_mac_zero_aligned; | ||
159 | const unsigned char *addr = br_mac_zero; | 164 | const unsigned char *addr = br_mac_zero; |
160 | struct net_bridge_port *p; | 165 | struct net_bridge_port *p; |
161 | 166 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index cf71614dae93..4dc93cc4d5b7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -751,13 +751,10 @@ int dev_change_name(struct net_device *dev, char *newname) | |||
751 | else | 751 | else |
752 | strlcpy(dev->name, newname, IFNAMSIZ); | 752 | strlcpy(dev->name, newname, IFNAMSIZ); |
753 | 753 | ||
754 | err = device_rename(&dev->dev, dev->name); | 754 | device_rename(&dev->dev, dev->name); |
755 | if (!err) { | 755 | hlist_del(&dev->name_hlist); |
756 | hlist_del(&dev->name_hlist); | 756 | hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); |
757 | hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); | 757 | raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); |
758 | raw_notifier_call_chain(&netdev_chain, | ||
759 | NETDEV_CHANGENAME, dev); | ||
760 | } | ||
761 | 758 | ||
762 | return err; | 759 | return err; |
763 | } | 760 | } |
@@ -1741,8 +1738,8 @@ static int ing_filter(struct sk_buff *skb) | |||
1741 | if (dev->qdisc_ingress) { | 1738 | if (dev->qdisc_ingress) { |
1742 | __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd); | 1739 | __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd); |
1743 | if (MAX_RED_LOOP < ttl++) { | 1740 | if (MAX_RED_LOOP < ttl++) { |
1744 | printk(KERN_WARNING "Redir loop detected Dropping packet (%s->%s)\n", | 1741 | printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n", |
1745 | skb->input_dev->name, skb->dev->name); | 1742 | skb->iif, skb->dev->ifindex); |
1746 | return TC_ACT_SHOT; | 1743 | return TC_ACT_SHOT; |
1747 | } | 1744 | } |
1748 | 1745 | ||
@@ -1750,10 +1747,10 @@ static int ing_filter(struct sk_buff *skb) | |||
1750 | 1747 | ||
1751 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); | 1748 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); |
1752 | 1749 | ||
1753 | spin_lock(&dev->ingress_lock); | 1750 | spin_lock(&dev->queue_lock); |
1754 | if ((q = dev->qdisc_ingress) != NULL) | 1751 | if ((q = dev->qdisc_ingress) != NULL) |
1755 | result = q->enqueue(skb, q); | 1752 | result = q->enqueue(skb, q); |
1756 | spin_unlock(&dev->ingress_lock); | 1753 | spin_unlock(&dev->queue_lock); |
1757 | 1754 | ||
1758 | } | 1755 | } |
1759 | 1756 | ||
@@ -1775,8 +1772,8 @@ int netif_receive_skb(struct sk_buff *skb) | |||
1775 | if (!skb->tstamp.off_sec) | 1772 | if (!skb->tstamp.off_sec) |
1776 | net_timestamp(skb); | 1773 | net_timestamp(skb); |
1777 | 1774 | ||
1778 | if (!skb->input_dev) | 1775 | if (!skb->iif) |
1779 | skb->input_dev = skb->dev; | 1776 | skb->iif = skb->dev->ifindex; |
1780 | 1777 | ||
1781 | orig_dev = skb_bond(skb); | 1778 | orig_dev = skb_bond(skb); |
1782 | 1779 | ||
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 215f1bff048f..7174ced75efc 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -143,7 +143,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl, | |||
143 | } | 143 | } |
144 | } | 144 | } |
145 | 145 | ||
146 | err = -ENETUNREACH; | 146 | err = -ESRCH; |
147 | out: | 147 | out: |
148 | rcu_read_unlock(); | 148 | rcu_read_unlock(); |
149 | 149 | ||
@@ -152,6 +152,28 @@ out: | |||
152 | 152 | ||
153 | EXPORT_SYMBOL_GPL(fib_rules_lookup); | 153 | EXPORT_SYMBOL_GPL(fib_rules_lookup); |
154 | 154 | ||
155 | static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, | ||
156 | struct fib_rules_ops *ops) | ||
157 | { | ||
158 | int err = -EINVAL; | ||
159 | |||
160 | if (frh->src_len) | ||
161 | if (tb[FRA_SRC] == NULL || | ||
162 | frh->src_len > (ops->addr_size * 8) || | ||
163 | nla_len(tb[FRA_SRC]) != ops->addr_size) | ||
164 | goto errout; | ||
165 | |||
166 | if (frh->dst_len) | ||
167 | if (tb[FRA_DST] == NULL || | ||
168 | frh->dst_len > (ops->addr_size * 8) || | ||
169 | nla_len(tb[FRA_DST]) != ops->addr_size) | ||
170 | goto errout; | ||
171 | |||
172 | err = 0; | ||
173 | errout: | ||
174 | return err; | ||
175 | } | ||
176 | |||
155 | int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 177 | int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
156 | { | 178 | { |
157 | struct fib_rule_hdr *frh = nlmsg_data(nlh); | 179 | struct fib_rule_hdr *frh = nlmsg_data(nlh); |
@@ -173,6 +195,10 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
173 | if (err < 0) | 195 | if (err < 0) |
174 | goto errout; | 196 | goto errout; |
175 | 197 | ||
198 | err = validate_rulemsg(frh, tb, ops); | ||
199 | if (err < 0) | ||
200 | goto errout; | ||
201 | |||
176 | rule = kzalloc(ops->rule_size, GFP_KERNEL); | 202 | rule = kzalloc(ops->rule_size, GFP_KERNEL); |
177 | if (rule == NULL) { | 203 | if (rule == NULL) { |
178 | err = -ENOMEM; | 204 | err = -ENOMEM; |
@@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
260 | if (err < 0) | 286 | if (err < 0) |
261 | goto errout; | 287 | goto errout; |
262 | 288 | ||
289 | err = validate_rulemsg(frh, tb, ops); | ||
290 | if (err < 0) | ||
291 | goto errout; | ||
292 | |||
263 | list_for_each_entry(rule, ops->rules_list, list) { | 293 | list_for_each_entry(rule, ops->rules_list, list) { |
264 | if (frh->action && (frh->action != rule->action)) | 294 | if (frh->action && (frh->action != rule->action)) |
265 | continue; | 295 | continue; |
@@ -374,7 +404,7 @@ int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family) | |||
374 | return -EAFNOSUPPORT; | 404 | return -EAFNOSUPPORT; |
375 | 405 | ||
376 | rcu_read_lock(); | 406 | rcu_read_lock(); |
377 | list_for_each_entry(rule, ops->rules_list, list) { | 407 | list_for_each_entry_rcu(rule, ops->rules_list, list) { |
378 | if (idx < cb->args[0]) | 408 | if (idx < cb->args[0]) |
379 | goto skip; | 409 | goto skip; |
380 | 410 | ||
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 3183142c6044..841e3f32cab1 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -140,6 +140,8 @@ static int neigh_forced_gc(struct neigh_table *tbl) | |||
140 | n->dead = 1; | 140 | n->dead = 1; |
141 | shrunk = 1; | 141 | shrunk = 1; |
142 | write_unlock(&n->lock); | 142 | write_unlock(&n->lock); |
143 | if (n->parms->neigh_cleanup) | ||
144 | n->parms->neigh_cleanup(n); | ||
143 | neigh_release(n); | 145 | neigh_release(n); |
144 | continue; | 146 | continue; |
145 | } | 147 | } |
@@ -211,6 +213,8 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) | |||
211 | NEIGH_PRINTK2("neigh %p is stray.\n", n); | 213 | NEIGH_PRINTK2("neigh %p is stray.\n", n); |
212 | } | 214 | } |
213 | write_unlock(&n->lock); | 215 | write_unlock(&n->lock); |
216 | if (n->parms->neigh_cleanup) | ||
217 | n->parms->neigh_cleanup(n); | ||
214 | neigh_release(n); | 218 | neigh_release(n); |
215 | } | 219 | } |
216 | } | 220 | } |
@@ -582,9 +586,6 @@ void neigh_destroy(struct neighbour *neigh) | |||
582 | kfree(hh); | 586 | kfree(hh); |
583 | } | 587 | } |
584 | 588 | ||
585 | if (neigh->parms->neigh_destructor) | ||
586 | (neigh->parms->neigh_destructor)(neigh); | ||
587 | |||
588 | skb_queue_purge(&neigh->arp_queue); | 589 | skb_queue_purge(&neigh->arp_queue); |
589 | 590 | ||
590 | dev_put(neigh->dev); | 591 | dev_put(neigh->dev); |
@@ -675,6 +676,8 @@ static void neigh_periodic_timer(unsigned long arg) | |||
675 | *np = n->next; | 676 | *np = n->next; |
676 | n->dead = 1; | 677 | n->dead = 1; |
677 | write_unlock(&n->lock); | 678 | write_unlock(&n->lock); |
679 | if (n->parms->neigh_cleanup) | ||
680 | n->parms->neigh_cleanup(n); | ||
678 | neigh_release(n); | 681 | neigh_release(n); |
679 | continue; | 682 | continue; |
680 | } | 683 | } |
@@ -1328,6 +1331,8 @@ void neigh_parms_destroy(struct neigh_parms *parms) | |||
1328 | kfree(parms); | 1331 | kfree(parms); |
1329 | } | 1332 | } |
1330 | 1333 | ||
1334 | static struct lock_class_key neigh_table_proxy_queue_class; | ||
1335 | |||
1331 | void neigh_table_init_no_netlink(struct neigh_table *tbl) | 1336 | void neigh_table_init_no_netlink(struct neigh_table *tbl) |
1332 | { | 1337 | { |
1333 | unsigned long now = jiffies; | 1338 | unsigned long now = jiffies; |
@@ -1376,7 +1381,8 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
1376 | init_timer(&tbl->proxy_timer); | 1381 | init_timer(&tbl->proxy_timer); |
1377 | tbl->proxy_timer.data = (unsigned long)tbl; | 1382 | tbl->proxy_timer.data = (unsigned long)tbl; |
1378 | tbl->proxy_timer.function = neigh_proxy_process; | 1383 | tbl->proxy_timer.function = neigh_proxy_process; |
1379 | skb_queue_head_init(&tbl->proxy_queue); | 1384 | skb_queue_head_init_class(&tbl->proxy_queue, |
1385 | &neigh_table_proxy_queue_class); | ||
1380 | 1386 | ||
1381 | tbl->last_flush = now; | 1387 | tbl->last_flush = now; |
1382 | tbl->last_rand = now + tbl->parms.reachable_time * 20; | 1388 | tbl->last_rand = now + tbl->parms.reachable_time * 20; |
@@ -2088,8 +2094,11 @@ void __neigh_for_each_release(struct neigh_table *tbl, | |||
2088 | } else | 2094 | } else |
2089 | np = &n->next; | 2095 | np = &n->next; |
2090 | write_unlock(&n->lock); | 2096 | write_unlock(&n->lock); |
2091 | if (release) | 2097 | if (release) { |
2098 | if (n->parms->neigh_cleanup) | ||
2099 | n->parms->neigh_cleanup(n); | ||
2092 | neigh_release(n); | 2100 | neigh_release(n); |
2101 | } | ||
2093 | } | 2102 | } |
2094 | } | 2103 | } |
2095 | } | 2104 | } |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index da1019451ccb..4581ece48bb2 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -471,6 +471,13 @@ int __netpoll_rx(struct sk_buff *skb) | |||
471 | if (skb->len < len || len < iph->ihl*4) | 471 | if (skb->len < len || len < iph->ihl*4) |
472 | goto out; | 472 | goto out; |
473 | 473 | ||
474 | /* | ||
475 | * Our transport medium may have padded the buffer out. | ||
476 | * Now We trim to the true length of the frame. | ||
477 | */ | ||
478 | if (pskb_trim_rcsum(skb, len)) | ||
479 | goto out; | ||
480 | |||
474 | if (iph->protocol != IPPROTO_UDP) | 481 | if (iph->protocol != IPPROTO_UDP) |
475 | goto out; | 482 | goto out; |
476 | 483 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 74a9a32b906d..4b01496dc33d 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -129,6 +129,7 @@ | |||
129 | #include <linux/ioport.h> | 129 | #include <linux/ioport.h> |
130 | #include <linux/interrupt.h> | 130 | #include <linux/interrupt.h> |
131 | #include <linux/capability.h> | 131 | #include <linux/capability.h> |
132 | #include <linux/freezer.h> | ||
132 | #include <linux/delay.h> | 133 | #include <linux/delay.h> |
133 | #include <linux/timer.h> | 134 | #include <linux/timer.h> |
134 | #include <linux/list.h> | 135 | #include <linux/list.h> |
@@ -3333,6 +3334,8 @@ static int pktgen_thread_worker(void *arg) | |||
3333 | t->control &= ~(T_REMDEV); | 3334 | t->control &= ~(T_REMDEV); |
3334 | } | 3335 | } |
3335 | 3336 | ||
3337 | try_to_freeze(); | ||
3338 | |||
3336 | set_current_state(TASK_INTERRUPTIBLE); | 3339 | set_current_state(TASK_INTERRUPTIBLE); |
3337 | } | 3340 | } |
3338 | 3341 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 6055074c4b81..33ea8eac7fe0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -621,7 +621,8 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
621 | if (err < 0) | 621 | if (err < 0) |
622 | goto errout; | 622 | goto errout; |
623 | 623 | ||
624 | iw += IW_EV_POINT_OFF; | 624 | /* Payload is at an offset in buffer */ |
625 | iw = iw_buf + IW_EV_POINT_OFF; | ||
625 | } | 626 | } |
626 | #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ | 627 | #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ |
627 | 628 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 820761f9eeef..336958fbbcb2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -197,61 +197,6 @@ nodata: | |||
197 | } | 197 | } |
198 | 198 | ||
199 | /** | 199 | /** |
200 | * alloc_skb_from_cache - allocate a network buffer | ||
201 | * @cp: kmem_cache from which to allocate the data area | ||
202 | * (object size must be big enough for @size bytes + skb overheads) | ||
203 | * @size: size to allocate | ||
204 | * @gfp_mask: allocation mask | ||
205 | * | ||
206 | * Allocate a new &sk_buff. The returned buffer has no headroom and | ||
207 | * tail room of size bytes. The object has a reference count of one. | ||
208 | * The return is the buffer. On a failure the return is %NULL. | ||
209 | * | ||
210 | * Buffers may only be allocated from interrupts using a @gfp_mask of | ||
211 | * %GFP_ATOMIC. | ||
212 | */ | ||
213 | struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp, | ||
214 | unsigned int size, | ||
215 | gfp_t gfp_mask) | ||
216 | { | ||
217 | struct sk_buff *skb; | ||
218 | u8 *data; | ||
219 | |||
220 | /* Get the HEAD */ | ||
221 | skb = kmem_cache_alloc(skbuff_head_cache, | ||
222 | gfp_mask & ~__GFP_DMA); | ||
223 | if (!skb) | ||
224 | goto out; | ||
225 | |||
226 | /* Get the DATA. */ | ||
227 | size = SKB_DATA_ALIGN(size); | ||
228 | data = kmem_cache_alloc(cp, gfp_mask); | ||
229 | if (!data) | ||
230 | goto nodata; | ||
231 | |||
232 | memset(skb, 0, offsetof(struct sk_buff, truesize)); | ||
233 | skb->truesize = size + sizeof(struct sk_buff); | ||
234 | atomic_set(&skb->users, 1); | ||
235 | skb->head = data; | ||
236 | skb->data = data; | ||
237 | skb->tail = data; | ||
238 | skb->end = data + size; | ||
239 | |||
240 | atomic_set(&(skb_shinfo(skb)->dataref), 1); | ||
241 | skb_shinfo(skb)->nr_frags = 0; | ||
242 | skb_shinfo(skb)->gso_size = 0; | ||
243 | skb_shinfo(skb)->gso_segs = 0; | ||
244 | skb_shinfo(skb)->gso_type = 0; | ||
245 | skb_shinfo(skb)->frag_list = NULL; | ||
246 | out: | ||
247 | return skb; | ||
248 | nodata: | ||
249 | kmem_cache_free(skbuff_head_cache, skb); | ||
250 | skb = NULL; | ||
251 | goto out; | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * __netdev_alloc_skb - allocate an skbuff for rx on a specific device | 200 | * __netdev_alloc_skb - allocate an skbuff for rx on a specific device |
256 | * @dev: network device to receive on | 201 | * @dev: network device to receive on |
257 | * @length: length to allocate | 202 | * @length: length to allocate |
@@ -463,6 +408,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
463 | memcpy(n->cb, skb->cb, sizeof(skb->cb)); | 408 | memcpy(n->cb, skb->cb, sizeof(skb->cb)); |
464 | C(len); | 409 | C(len); |
465 | C(data_len); | 410 | C(data_len); |
411 | C(mac_len); | ||
466 | C(csum); | 412 | C(csum); |
467 | C(local_df); | 413 | C(local_df); |
468 | n->cloned = 1; | 414 | n->cloned = 1; |
@@ -495,7 +441,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
495 | n->tc_verd = SET_TC_VERD(skb->tc_verd,0); | 441 | n->tc_verd = SET_TC_VERD(skb->tc_verd,0); |
496 | n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); | 442 | n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); |
497 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); | 443 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); |
498 | C(input_dev); | 444 | C(iif); |
499 | #endif | 445 | #endif |
500 | skb_copy_secmark(n, skb); | 446 | skb_copy_secmark(n, skb); |
501 | #endif | 447 | #endif |
diff --git a/net/core/sock.c b/net/core/sock.c index 8d65d6478dcd..27c4f62382bd 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -808,7 +808,7 @@ lenout: | |||
808 | * | 808 | * |
809 | * (We also register the sk_lock with the lock validator.) | 809 | * (We also register the sk_lock with the lock validator.) |
810 | */ | 810 | */ |
811 | static void inline sock_lock_init(struct sock *sk) | 811 | static inline void sock_lock_init(struct sock *sk) |
812 | { | 812 | { |
813 | sock_lock_init_class_and_name(sk, | 813 | sock_lock_init_class_and_name(sk, |
814 | af_family_slock_key_strings[sk->sk_family], | 814 | af_family_slock_key_strings[sk->sk_family], |
diff --git a/net/core/wireless.c b/net/core/wireless.c index 9936ab11e6e0..b07fe270a508 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * This file implement the Wireless Extensions APIs. | 2 | * This file implement the Wireless Extensions APIs. |
3 | * | 3 | * |
4 | * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> | 4 | * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> |
5 | * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. | 5 | * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. |
6 | * | 6 | * |
7 | * (As all part of the Linux kernel, this file is GPL) | 7 | * (As all part of the Linux kernel, this file is GPL) |
8 | */ | 8 | */ |
@@ -76,6 +76,9 @@ | |||
76 | * o Change length in ESSID and NICK to strlen() instead of strlen()+1 | 76 | * o Change length in ESSID and NICK to strlen() instead of strlen()+1 |
77 | * o Make standard_ioctl_num and standard_event_num unsigned | 77 | * o Make standard_ioctl_num and standard_event_num unsigned |
78 | * o Remove (struct net_device *)->get_wireless_stats() | 78 | * o Remove (struct net_device *)->get_wireless_stats() |
79 | * | ||
80 | * v10 - 16.3.07 - Jean II | ||
81 | * o Prevent leaking of kernel space in stream on 64 bits. | ||
79 | */ | 82 | */ |
80 | 83 | ||
81 | /***************************** INCLUDES *****************************/ | 84 | /***************************** INCLUDES *****************************/ |
@@ -427,6 +430,21 @@ static const int event_type_size[] = { | |||
427 | IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ | 430 | IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ |
428 | }; | 431 | }; |
429 | 432 | ||
433 | /* Size (in bytes) of various events, as packed */ | ||
434 | static const int event_type_pk_size[] = { | ||
435 | IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */ | ||
436 | 0, | ||
437 | IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */ | ||
438 | 0, | ||
439 | IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */ | ||
440 | IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */ | ||
441 | IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */ | ||
442 | 0, | ||
443 | IW_EV_POINT_PK_LEN, /* Without variable payload */ | ||
444 | IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */ | ||
445 | IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */ | ||
446 | }; | ||
447 | |||
430 | /************************ COMMON SUBROUTINES ************************/ | 448 | /************************ COMMON SUBROUTINES ************************/ |
431 | /* | 449 | /* |
432 | * Stuff that may be used in various place or doesn't fit in one | 450 | * Stuff that may be used in various place or doesn't fit in one |
@@ -1217,7 +1235,7 @@ static int rtnetlink_standard_get(struct net_device * dev, | |||
1217 | memcpy(buffer + IW_EV_POINT_OFF, request, request_len); | 1235 | memcpy(buffer + IW_EV_POINT_OFF, request, request_len); |
1218 | /* Use our own copy of wrqu */ | 1236 | /* Use our own copy of wrqu */ |
1219 | wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF | 1237 | wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF |
1220 | + IW_EV_LCP_LEN); | 1238 | + IW_EV_LCP_PK_LEN); |
1221 | 1239 | ||
1222 | /* No extra arguments. Trivial to handle */ | 1240 | /* No extra arguments. Trivial to handle */ |
1223 | ret = handler(dev, &info, wrqu, NULL); | 1241 | ret = handler(dev, &info, wrqu, NULL); |
@@ -1229,8 +1247,8 @@ static int rtnetlink_standard_get(struct net_device * dev, | |||
1229 | 1247 | ||
1230 | /* Get a temp copy of wrqu (skip pointer) */ | 1248 | /* Get a temp copy of wrqu (skip pointer) */ |
1231 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, | 1249 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, |
1232 | ((char *) request) + IW_EV_LCP_LEN, | 1250 | ((char *) request) + IW_EV_LCP_PK_LEN, |
1233 | IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1251 | IW_EV_POINT_LEN - IW_EV_LCP_PK_LEN); |
1234 | 1252 | ||
1235 | /* Calculate space needed by arguments. Always allocate | 1253 | /* Calculate space needed by arguments. Always allocate |
1236 | * for max space. Easier, and won't last long... */ | 1254 | * for max space. Easier, and won't last long... */ |
@@ -1240,7 +1258,7 @@ static int rtnetlink_standard_get(struct net_device * dev, | |||
1240 | (wrqu_point.data.length > descr->max_tokens)) | 1258 | (wrqu_point.data.length > descr->max_tokens)) |
1241 | extra_size = (wrqu_point.data.length | 1259 | extra_size = (wrqu_point.data.length |
1242 | * descr->token_size); | 1260 | * descr->token_size); |
1243 | buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; | 1261 | buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF; |
1244 | #ifdef WE_RTNETLINK_DEBUG | 1262 | #ifdef WE_RTNETLINK_DEBUG |
1245 | printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", | 1263 | printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", |
1246 | dev->name, extra_size, buffer_size); | 1264 | dev->name, extra_size, buffer_size); |
@@ -1254,15 +1272,15 @@ static int rtnetlink_standard_get(struct net_device * dev, | |||
1254 | 1272 | ||
1255 | /* Put wrqu in the right place (just before extra). | 1273 | /* Put wrqu in the right place (just before extra). |
1256 | * Leave space for IWE header and dummy pointer... | 1274 | * Leave space for IWE header and dummy pointer... |
1257 | * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... | 1275 | * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned. |
1258 | */ | 1276 | */ |
1259 | memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, | 1277 | memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF, |
1260 | ((char *) &wrqu_point) + IW_EV_POINT_OFF, | 1278 | ((char *) &wrqu_point) + IW_EV_POINT_OFF, |
1261 | IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1279 | IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); |
1262 | wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); | 1280 | wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN); |
1263 | 1281 | ||
1264 | /* Extra comes logically after that. Offset +12 bytes. */ | 1282 | /* Extra comes logically after that. Offset +12 bytes. */ |
1265 | extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; | 1283 | extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN; |
1266 | 1284 | ||
1267 | /* Call the handler */ | 1285 | /* Call the handler */ |
1268 | ret = handler(dev, &info, wrqu, extra); | 1286 | ret = handler(dev, &info, wrqu, extra); |
@@ -1270,11 +1288,11 @@ static int rtnetlink_standard_get(struct net_device * dev, | |||
1270 | /* Calculate real returned length */ | 1288 | /* Calculate real returned length */ |
1271 | extra_size = (wrqu->data.length * descr->token_size); | 1289 | extra_size = (wrqu->data.length * descr->token_size); |
1272 | /* Re-adjust reply size */ | 1290 | /* Re-adjust reply size */ |
1273 | request->len = extra_size + IW_EV_POINT_LEN; | 1291 | request->len = extra_size + IW_EV_POINT_PK_LEN; |
1274 | 1292 | ||
1275 | /* Put the iwe header where it should, i.e. scrap the | 1293 | /* Put the iwe header where it should, i.e. scrap the |
1276 | * dummy pointer. */ | 1294 | * dummy pointer. */ |
1277 | memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); | 1295 | memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN); |
1278 | 1296 | ||
1279 | #ifdef WE_RTNETLINK_DEBUG | 1297 | #ifdef WE_RTNETLINK_DEBUG |
1280 | printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); | 1298 | printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); |
@@ -1331,10 +1349,10 @@ static inline int rtnetlink_standard_set(struct net_device * dev, | |||
1331 | #endif /* WE_RTNETLINK_DEBUG */ | 1349 | #endif /* WE_RTNETLINK_DEBUG */ |
1332 | 1350 | ||
1333 | /* Extract fixed header from request. This is properly aligned. */ | 1351 | /* Extract fixed header from request. This is properly aligned. */ |
1334 | wrqu = &request->u; | 1352 | wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN); |
1335 | 1353 | ||
1336 | /* Check if wrqu is complete */ | 1354 | /* Check if wrqu is complete */ |
1337 | hdr_len = event_type_size[descr->header_type]; | 1355 | hdr_len = event_type_pk_size[descr->header_type]; |
1338 | if(request_len < hdr_len) { | 1356 | if(request_len < hdr_len) { |
1339 | #ifdef WE_RTNETLINK_DEBUG | 1357 | #ifdef WE_RTNETLINK_DEBUG |
1340 | printk(KERN_DEBUG | 1358 | printk(KERN_DEBUG |
@@ -1359,7 +1377,7 @@ static inline int rtnetlink_standard_set(struct net_device * dev, | |||
1359 | 1377 | ||
1360 | /* Put wrqu in the right place (skip pointer) */ | 1378 | /* Put wrqu in the right place (skip pointer) */ |
1361 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, | 1379 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, |
1362 | wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1380 | wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); |
1363 | /* Don't forget about the event code... */ | 1381 | /* Don't forget about the event code... */ |
1364 | wrqu = &wrqu_point; | 1382 | wrqu = &wrqu_point; |
1365 | 1383 | ||
@@ -1483,7 +1501,7 @@ static inline int rtnetlink_private_get(struct net_device * dev, | |||
1483 | hdr_len = extra_size; | 1501 | hdr_len = extra_size; |
1484 | extra_size = 0; | 1502 | extra_size = 0; |
1485 | } else { | 1503 | } else { |
1486 | hdr_len = IW_EV_POINT_LEN; | 1504 | hdr_len = IW_EV_POINT_PK_LEN; |
1487 | } | 1505 | } |
1488 | 1506 | ||
1489 | /* Check if wrqu is complete */ | 1507 | /* Check if wrqu is complete */ |
@@ -1514,7 +1532,7 @@ static inline int rtnetlink_private_get(struct net_device * dev, | |||
1514 | memcpy(buffer + IW_EV_POINT_OFF, request, request_len); | 1532 | memcpy(buffer + IW_EV_POINT_OFF, request, request_len); |
1515 | /* Use our own copy of wrqu */ | 1533 | /* Use our own copy of wrqu */ |
1516 | wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF | 1534 | wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF |
1517 | + IW_EV_LCP_LEN); | 1535 | + IW_EV_LCP_PK_LEN); |
1518 | 1536 | ||
1519 | /* No extra arguments. Trivial to handle */ | 1537 | /* No extra arguments. Trivial to handle */ |
1520 | ret = handler(dev, &info, wrqu, (char *) wrqu); | 1538 | ret = handler(dev, &info, wrqu, (char *) wrqu); |
@@ -1523,7 +1541,7 @@ static inline int rtnetlink_private_get(struct net_device * dev, | |||
1523 | char * extra; | 1541 | char * extra; |
1524 | 1542 | ||
1525 | /* Buffer for full reply */ | 1543 | /* Buffer for full reply */ |
1526 | buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; | 1544 | buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF; |
1527 | 1545 | ||
1528 | #ifdef WE_RTNETLINK_DEBUG | 1546 | #ifdef WE_RTNETLINK_DEBUG |
1529 | printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", | 1547 | printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", |
@@ -1538,15 +1556,15 @@ static inline int rtnetlink_private_get(struct net_device * dev, | |||
1538 | 1556 | ||
1539 | /* Put wrqu in the right place (just before extra). | 1557 | /* Put wrqu in the right place (just before extra). |
1540 | * Leave space for IWE header and dummy pointer... | 1558 | * Leave space for IWE header and dummy pointer... |
1541 | * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... | 1559 | * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned. |
1542 | */ | 1560 | */ |
1543 | memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, | 1561 | memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF, |
1544 | ((char *) request) + IW_EV_LCP_LEN, | 1562 | ((char *) request) + IW_EV_LCP_PK_LEN, |
1545 | IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1563 | IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); |
1546 | wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); | 1564 | wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN); |
1547 | 1565 | ||
1548 | /* Extra comes logically after that. Offset +12 bytes. */ | 1566 | /* Extra comes logically after that. Offset +12 bytes. */ |
1549 | extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; | 1567 | extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN; |
1550 | 1568 | ||
1551 | /* Call the handler */ | 1569 | /* Call the handler */ |
1552 | ret = handler(dev, &info, wrqu, extra); | 1570 | ret = handler(dev, &info, wrqu, extra); |
@@ -1556,11 +1574,11 @@ static inline int rtnetlink_private_get(struct net_device * dev, | |||
1556 | if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) | 1574 | if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) |
1557 | extra_size = adjust_priv_size(descr->get_args, wrqu); | 1575 | extra_size = adjust_priv_size(descr->get_args, wrqu); |
1558 | /* Re-adjust reply size */ | 1576 | /* Re-adjust reply size */ |
1559 | request->len = extra_size + IW_EV_POINT_LEN; | 1577 | request->len = extra_size + IW_EV_POINT_PK_LEN; |
1560 | 1578 | ||
1561 | /* Put the iwe header where it should, i.e. scrap the | 1579 | /* Put the iwe header where it should, i.e. scrap the |
1562 | * dummy pointer. */ | 1580 | * dummy pointer. */ |
1563 | memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); | 1581 | memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN); |
1564 | 1582 | ||
1565 | #ifdef WE_RTNETLINK_DEBUG | 1583 | #ifdef WE_RTNETLINK_DEBUG |
1566 | printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); | 1584 | printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size); |
@@ -1641,14 +1659,14 @@ static inline int rtnetlink_private_set(struct net_device * dev, | |||
1641 | /* Does it fits in wrqu ? */ | 1659 | /* Does it fits in wrqu ? */ |
1642 | if((descr->set_args & IW_PRIV_SIZE_FIXED) && | 1660 | if((descr->set_args & IW_PRIV_SIZE_FIXED) && |
1643 | (extra_size <= IFNAMSIZ)) { | 1661 | (extra_size <= IFNAMSIZ)) { |
1644 | hdr_len = IW_EV_LCP_LEN + extra_size; | 1662 | hdr_len = IW_EV_LCP_PK_LEN + extra_size; |
1645 | extra_size = 0; | 1663 | extra_size = 0; |
1646 | } else { | 1664 | } else { |
1647 | hdr_len = IW_EV_POINT_LEN; | 1665 | hdr_len = IW_EV_POINT_PK_LEN; |
1648 | } | 1666 | } |
1649 | 1667 | ||
1650 | /* Extract fixed header from request. This is properly aligned. */ | 1668 | /* Extract fixed header from request. This is properly aligned. */ |
1651 | wrqu = &request->u; | 1669 | wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN); |
1652 | 1670 | ||
1653 | /* Check if wrqu is complete */ | 1671 | /* Check if wrqu is complete */ |
1654 | if(request_len < hdr_len) { | 1672 | if(request_len < hdr_len) { |
@@ -1675,7 +1693,7 @@ static inline int rtnetlink_private_set(struct net_device * dev, | |||
1675 | 1693 | ||
1676 | /* Put wrqu in the right place (skip pointer) */ | 1694 | /* Put wrqu in the right place (skip pointer) */ |
1677 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, | 1695 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, |
1678 | wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1696 | wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); |
1679 | 1697 | ||
1680 | /* Does it fits within bounds ? */ | 1698 | /* Does it fits within bounds ? */ |
1681 | if(wrqu_point.data.length > (descr->set_args & | 1699 | if(wrqu_point.data.length > (descr->set_args & |
@@ -1738,7 +1756,7 @@ int wireless_rtnetlink_get(struct net_device * dev, | |||
1738 | iw_handler handler; | 1756 | iw_handler handler; |
1739 | 1757 | ||
1740 | /* Check length */ | 1758 | /* Check length */ |
1741 | if(len < IW_EV_LCP_LEN) { | 1759 | if(len < IW_EV_LCP_PK_LEN) { |
1742 | printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", | 1760 | printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", |
1743 | dev->name, len); | 1761 | dev->name, len); |
1744 | return -EINVAL; | 1762 | return -EINVAL; |
@@ -1822,7 +1840,7 @@ int wireless_rtnetlink_set(struct net_device * dev, | |||
1822 | iw_handler handler; | 1840 | iw_handler handler; |
1823 | 1841 | ||
1824 | /* Check length */ | 1842 | /* Check length */ |
1825 | if(len < IW_EV_LCP_LEN) { | 1843 | if(len < IW_EV_LCP_PK_LEN) { |
1826 | printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", | 1844 | printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", |
1827 | dev->name, len); | 1845 | dev->name, len); |
1828 | return -EINVAL; | 1846 | return -EINVAL; |
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index a0e7cd183a5d..e33a9edb4036 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -191,7 +191,6 @@ extern void dccp_send_sync(struct sock *sk, const u64 seq, | |||
191 | const enum dccp_pkt_type pkt_type); | 191 | const enum dccp_pkt_type pkt_type); |
192 | 192 | ||
193 | extern void dccp_write_xmit(struct sock *sk, int block); | 193 | extern void dccp_write_xmit(struct sock *sk, int block); |
194 | extern void dccp_write_xmit_timer(unsigned long data); | ||
195 | extern void dccp_write_space(struct sock *sk); | 194 | extern void dccp_write_space(struct sock *sk); |
196 | 195 | ||
197 | extern void dccp_init_xmit_timers(struct sock *sk); | 196 | extern void dccp_init_xmit_timers(struct sock *sk); |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index cf28c53a389a..6607b7b14f34 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -575,7 +575,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname, | |||
575 | if (get_user(len, optlen)) | 575 | if (get_user(len, optlen)) |
576 | return -EFAULT; | 576 | return -EFAULT; |
577 | 577 | ||
578 | if (len < sizeof(int)) | 578 | if (len < (int)sizeof(int)) |
579 | return -EINVAL; | 579 | return -EINVAL; |
580 | 580 | ||
581 | dp = dccp_sk(sk); | 581 | dp = dccp_sk(sk); |
@@ -589,9 +589,11 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname, | |||
589 | (__be32 __user *)optval, optlen); | 589 | (__be32 __user *)optval, optlen); |
590 | case DCCP_SOCKOPT_SEND_CSCOV: | 590 | case DCCP_SOCKOPT_SEND_CSCOV: |
591 | val = dp->dccps_pcslen; | 591 | val = dp->dccps_pcslen; |
592 | len = sizeof(val); | ||
592 | break; | 593 | break; |
593 | case DCCP_SOCKOPT_RECV_CSCOV: | 594 | case DCCP_SOCKOPT_RECV_CSCOV: |
594 | val = dp->dccps_pcrlen; | 595 | val = dp->dccps_pcrlen; |
596 | len = sizeof(val); | ||
595 | break; | 597 | break; |
596 | case 128 ... 191: | 598 | case 128 ... 191: |
597 | return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, | 599 | return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, |
diff --git a/net/dccp/timer.c b/net/dccp/timer.c index b038a0a3ad40..0197a41c256a 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c | |||
@@ -262,7 +262,7 @@ out: | |||
262 | } | 262 | } |
263 | 263 | ||
264 | /* Transmit-delay timer: used by the CCIDs to delay actual send time */ | 264 | /* Transmit-delay timer: used by the CCIDs to delay actual send time */ |
265 | void dccp_write_xmit_timer(unsigned long data) | 265 | static void dccp_write_xmit_timer(unsigned long data) |
266 | { | 266 | { |
267 | struct sock *sk = (struct sock *)data; | 267 | struct sock *sk = (struct sock *)data; |
268 | struct dccp_sock *dp = dccp_sk(sk); | 268 | struct dccp_sock *dp = dccp_sk(sk); |
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index 3cbfddc98430..82d58a977e6f 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c | |||
@@ -63,7 +63,7 @@ static struct | |||
63 | { | 63 | { |
64 | int error; | 64 | int error; |
65 | u8 scope; | 65 | u8 scope; |
66 | } dn_fib_props[RTA_MAX+1] = { | 66 | } dn_fib_props[RTN_MAX+1] = { |
67 | [RTN_UNSPEC] = { .error = 0, .scope = RT_SCOPE_NOWHERE }, | 67 | [RTN_UNSPEC] = { .error = 0, .scope = RT_SCOPE_NOWHERE }, |
68 | [RTN_UNICAST] = { .error = 0, .scope = RT_SCOPE_UNIVERSE }, | 68 | [RTN_UNICAST] = { .error = 0, .scope = RT_SCOPE_UNIVERSE }, |
69 | [RTN_LOCAL] = { .error = 0, .scope = RT_SCOPE_HOST }, | 69 | [RTN_LOCAL] = { .error = 0, .scope = RT_SCOPE_HOST }, |
@@ -276,6 +276,9 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta | |||
276 | struct dn_fib_info *ofi; | 276 | struct dn_fib_info *ofi; |
277 | int nhs = 1; | 277 | int nhs = 1; |
278 | 278 | ||
279 | if (r->rtm_type > RTN_MAX) | ||
280 | goto err_inval; | ||
281 | |||
279 | if (dn_fib_props[r->rtm_type].scope > r->rtm_scope) | 282 | if (dn_fib_props[r->rtm_type].scope > r->rtm_scope) |
280 | goto err_inval; | 283 | goto err_inval; |
281 | 284 | ||
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index b6c98ac93dc8..5e86dd542302 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c | |||
@@ -109,8 +109,6 @@ errout: | |||
109 | 109 | ||
110 | static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = { | 110 | static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = { |
111 | FRA_GENERIC_POLICY, | 111 | FRA_GENERIC_POLICY, |
112 | [FRA_SRC] = { .type = NLA_U16 }, | ||
113 | [FRA_DST] = { .type = NLA_U16 }, | ||
114 | }; | 112 | }; |
115 | 113 | ||
116 | static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | 114 | static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) |
@@ -133,7 +131,7 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
133 | int err = -EINVAL; | 131 | int err = -EINVAL; |
134 | struct dn_fib_rule *r = (struct dn_fib_rule *)rule; | 132 | struct dn_fib_rule *r = (struct dn_fib_rule *)rule; |
135 | 133 | ||
136 | if (frh->src_len > 16 || frh->dst_len > 16 || frh->tos) | 134 | if (frh->tos) |
137 | goto errout; | 135 | goto errout; |
138 | 136 | ||
139 | if (rule->table == RT_TABLE_UNSPEC) { | 137 | if (rule->table == RT_TABLE_UNSPEC) { |
@@ -150,10 +148,10 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
150 | } | 148 | } |
151 | } | 149 | } |
152 | 150 | ||
153 | if (tb[FRA_SRC]) | 151 | if (frh->src_len) |
154 | r->src = nla_get_le16(tb[FRA_SRC]); | 152 | r->src = nla_get_le16(tb[FRA_SRC]); |
155 | 153 | ||
156 | if (tb[FRA_DST]) | 154 | if (frh->dst_len) |
157 | r->dst = nla_get_le16(tb[FRA_DST]); | 155 | r->dst = nla_get_le16(tb[FRA_DST]); |
158 | 156 | ||
159 | r->src_len = frh->src_len; | 157 | r->src_len = frh->src_len; |
@@ -176,10 +174,10 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | |||
176 | if (frh->dst_len && (r->dst_len != frh->dst_len)) | 174 | if (frh->dst_len && (r->dst_len != frh->dst_len)) |
177 | return 0; | 175 | return 0; |
178 | 176 | ||
179 | if (tb[FRA_SRC] && (r->src != nla_get_le16(tb[FRA_SRC]))) | 177 | if (frh->src_len && (r->src != nla_get_le16(tb[FRA_SRC]))) |
180 | return 0; | 178 | return 0; |
181 | 179 | ||
182 | if (tb[FRA_DST] && (r->dst != nla_get_le16(tb[FRA_DST]))) | 180 | if (frh->dst_len && (r->dst != nla_get_le16(tb[FRA_DST]))) |
183 | return 0; | 181 | return 0; |
184 | 182 | ||
185 | return 1; | 183 | return 1; |
@@ -249,6 +247,7 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) | |||
249 | static struct fib_rules_ops dn_fib_rules_ops = { | 247 | static struct fib_rules_ops dn_fib_rules_ops = { |
250 | .family = AF_DECnet, | 248 | .family = AF_DECnet, |
251 | .rule_size = sizeof(struct dn_fib_rule), | 249 | .rule_size = sizeof(struct dn_fib_rule), |
250 | .addr_size = sizeof(u16), | ||
252 | .action = dn_fib_rule_action, | 251 | .action = dn_fib_rule_action, |
253 | .match = dn_fib_rule_match, | 252 | .match = dn_fib_rule_match, |
254 | .configure = dn_fib_rule_configure, | 253 | .configure = dn_fib_rule_configure, |
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index a64be6cdf078..6ef766ef9618 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig | |||
@@ -38,7 +38,7 @@ config IEEE80211_CRYPT_WEP | |||
38 | Include software based cipher suites in support of IEEE | 38 | Include software based cipher suites in support of IEEE |
39 | 802.11's WEP. This is needed for WEP as well as 802.1x. | 39 | 802.11's WEP. This is needed for WEP as well as 802.1x. |
40 | 40 | ||
41 | This can be compiled as a modules and it will be called | 41 | This can be compiled as a module and it will be called |
42 | "ieee80211_crypt_wep". | 42 | "ieee80211_crypt_wep". |
43 | 43 | ||
44 | config IEEE80211_CRYPT_CCMP | 44 | config IEEE80211_CRYPT_CCMP |
@@ -51,7 +51,7 @@ config IEEE80211_CRYPT_CCMP | |||
51 | (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with CCMP enabled | 51 | (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with CCMP enabled |
52 | networks. | 52 | networks. |
53 | 53 | ||
54 | This can be compiled as a modules and it will be called | 54 | This can be compiled as a module and it will be called |
55 | "ieee80211_crypt_ccmp". | 55 | "ieee80211_crypt_ccmp". |
56 | 56 | ||
57 | config IEEE80211_CRYPT_TKIP | 57 | config IEEE80211_CRYPT_TKIP |
@@ -66,7 +66,7 @@ config IEEE80211_CRYPT_TKIP | |||
66 | (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled | 66 | (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled |
67 | networks. | 67 | networks. |
68 | 68 | ||
69 | This can be compiled as a modules and it will be called | 69 | This can be compiled as a module and it will be called |
70 | "ieee80211_crypt_tkip". | 70 | "ieee80211_crypt_tkip". |
71 | 71 | ||
72 | source "net/ieee80211/softmac/Kconfig" | 72 | source "net/ieee80211/softmac/Kconfig" |
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index c976dd7e9758..2ce5b693a8bd 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -1933,6 +1933,11 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb, | |||
1933 | &cipso_ptr[6], | 1933 | &cipso_ptr[6], |
1934 | secattr); | 1934 | secattr); |
1935 | break; | 1935 | break; |
1936 | case CIPSO_V4_TAG_RANGE: | ||
1937 | ret_val = cipso_v4_parsetag_rng(doi_def, | ||
1938 | &cipso_ptr[6], | ||
1939 | secattr); | ||
1940 | break; | ||
1936 | } | 1941 | } |
1937 | 1942 | ||
1938 | skbuff_getattr_return: | 1943 | skbuff_getattr_return: |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 1fba6439fc57..cac06c43f004 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -493,6 +493,11 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
493 | cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; | 493 | cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; |
494 | cfg->fc_nlinfo.nlh = nlh; | 494 | cfg->fc_nlinfo.nlh = nlh; |
495 | 495 | ||
496 | if (cfg->fc_type > RTN_MAX) { | ||
497 | err = -EINVAL; | ||
498 | goto errout; | ||
499 | } | ||
500 | |||
496 | nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) { | 501 | nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) { |
497 | switch (attr->nla_type) { | 502 | switch (attr->nla_type) { |
498 | case RTA_DST: | 503 | case RTA_DST: |
@@ -771,6 +776,8 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | |||
771 | .nl_u = { .ip4_u = { .daddr = frn->fl_addr, | 776 | .nl_u = { .ip4_u = { .daddr = frn->fl_addr, |
772 | .tos = frn->fl_tos, | 777 | .tos = frn->fl_tos, |
773 | .scope = frn->fl_scope } } }; | 778 | .scope = frn->fl_scope } } }; |
779 | |||
780 | frn->err = -ENOENT; | ||
774 | if (tb) { | 781 | if (tb) { |
775 | local_bh_disable(); | 782 | local_bh_disable(); |
776 | 783 | ||
@@ -782,6 +789,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | |||
782 | frn->nh_sel = res.nh_sel; | 789 | frn->nh_sel = res.nh_sel; |
783 | frn->type = res.type; | 790 | frn->type = res.type; |
784 | frn->scope = res.scope; | 791 | frn->scope = res.scope; |
792 | fib_res_put(&res); | ||
785 | } | 793 | } |
786 | local_bh_enable(); | 794 | local_bh_enable(); |
787 | } | 795 | } |
@@ -796,6 +804,9 @@ static void nl_fib_input(struct sock *sk, int len) | |||
796 | struct fib_table *tb; | 804 | struct fib_table *tb; |
797 | 805 | ||
798 | skb = skb_dequeue(&sk->sk_receive_queue); | 806 | skb = skb_dequeue(&sk->sk_receive_queue); |
807 | if (skb == NULL) | ||
808 | return; | ||
809 | |||
799 | nlh = (struct nlmsghdr *)skb->data; | 810 | nlh = (struct nlmsghdr *)skb->data; |
800 | if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len || | 811 | if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len || |
801 | nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn))) { | 812 | nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn))) { |
@@ -808,7 +819,7 @@ static void nl_fib_input(struct sock *sk, int len) | |||
808 | 819 | ||
809 | nl_fib_lookup(frn, tb); | 820 | nl_fib_lookup(frn, tb); |
810 | 821 | ||
811 | pid = nlh->nlmsg_pid; /*pid of sending process */ | 822 | pid = NETLINK_CB(skb).pid; /* pid of sending process */ |
812 | NETLINK_CB(skb).pid = 0; /* from kernel */ | 823 | NETLINK_CB(skb).pid = 0; /* from kernel */ |
813 | NETLINK_CB(skb).dst_group = 0; /* unicast */ | 824 | NETLINK_CB(skb).dst_group = 0; /* unicast */ |
814 | netlink_unicast(sk, skb, pid, MSG_DONTWAIT); | 825 | netlink_unicast(sk, skb, pid, MSG_DONTWAIT); |
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index b837c33e0404..c660c074c76c 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
@@ -171,8 +171,6 @@ static struct fib_table *fib_empty_table(void) | |||
171 | 171 | ||
172 | static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = { | 172 | static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = { |
173 | FRA_GENERIC_POLICY, | 173 | FRA_GENERIC_POLICY, |
174 | [FRA_SRC] = { .type = NLA_U32 }, | ||
175 | [FRA_DST] = { .type = NLA_U32 }, | ||
176 | [FRA_FLOW] = { .type = NLA_U32 }, | 174 | [FRA_FLOW] = { .type = NLA_U32 }, |
177 | }; | 175 | }; |
178 | 176 | ||
@@ -183,8 +181,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
183 | int err = -EINVAL; | 181 | int err = -EINVAL; |
184 | struct fib4_rule *rule4 = (struct fib4_rule *) rule; | 182 | struct fib4_rule *rule4 = (struct fib4_rule *) rule; |
185 | 183 | ||
186 | if (frh->src_len > 32 || frh->dst_len > 32 || | 184 | if (frh->tos & ~IPTOS_TOS_MASK) |
187 | (frh->tos & ~IPTOS_TOS_MASK)) | ||
188 | goto errout; | 185 | goto errout; |
189 | 186 | ||
190 | if (rule->table == RT_TABLE_UNSPEC) { | 187 | if (rule->table == RT_TABLE_UNSPEC) { |
@@ -201,10 +198,10 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
201 | } | 198 | } |
202 | } | 199 | } |
203 | 200 | ||
204 | if (tb[FRA_SRC]) | 201 | if (frh->src_len) |
205 | rule4->src = nla_get_be32(tb[FRA_SRC]); | 202 | rule4->src = nla_get_be32(tb[FRA_SRC]); |
206 | 203 | ||
207 | if (tb[FRA_DST]) | 204 | if (frh->dst_len) |
208 | rule4->dst = nla_get_be32(tb[FRA_DST]); | 205 | rule4->dst = nla_get_be32(tb[FRA_DST]); |
209 | 206 | ||
210 | #ifdef CONFIG_NET_CLS_ROUTE | 207 | #ifdef CONFIG_NET_CLS_ROUTE |
@@ -242,10 +239,10 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | |||
242 | return 0; | 239 | return 0; |
243 | #endif | 240 | #endif |
244 | 241 | ||
245 | if (tb[FRA_SRC] && (rule4->src != nla_get_be32(tb[FRA_SRC]))) | 242 | if (frh->src_len && (rule4->src != nla_get_be32(tb[FRA_SRC]))) |
246 | return 0; | 243 | return 0; |
247 | 244 | ||
248 | if (tb[FRA_DST] && (rule4->dst != nla_get_be32(tb[FRA_DST]))) | 245 | if (frh->dst_len && (rule4->dst != nla_get_be32(tb[FRA_DST]))) |
249 | return 0; | 246 | return 0; |
250 | 247 | ||
251 | return 1; | 248 | return 1; |
@@ -309,6 +306,7 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule) | |||
309 | static struct fib_rules_ops fib4_rules_ops = { | 306 | static struct fib_rules_ops fib4_rules_ops = { |
310 | .family = AF_INET, | 307 | .family = AF_INET, |
311 | .rule_size = sizeof(struct fib4_rule), | 308 | .rule_size = sizeof(struct fib4_rule), |
309 | .addr_size = sizeof(u32), | ||
312 | .action = fib4_rule_action, | 310 | .action = fib4_rule_action, |
313 | .match = fib4_rule_match, | 311 | .match = fib4_rule_match, |
314 | .configure = fib4_rule_configure, | 312 | .configure = fib4_rule_configure, |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 2f1fdae6efa6..3dad12ee76c3 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -89,7 +89,7 @@ static const struct | |||
89 | { | 89 | { |
90 | int error; | 90 | int error; |
91 | u8 scope; | 91 | u8 scope; |
92 | } fib_props[RTA_MAX + 1] = { | 92 | } fib_props[RTN_MAX + 1] = { |
93 | { | 93 | { |
94 | .error = 0, | 94 | .error = 0, |
95 | .scope = RT_SCOPE_NOWHERE, | 95 | .scope = RT_SCOPE_NOWHERE, |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 72b3036bbc09..214c34732e84 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1123,6 +1123,9 @@ err: | |||
1123 | return fa_head; | 1123 | return fa_head; |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | /* | ||
1127 | * Caller must hold RTNL. | ||
1128 | */ | ||
1126 | static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) | 1129 | static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) |
1127 | { | 1130 | { |
1128 | struct trie *t = (struct trie *) tb->tb_data; | 1131 | struct trie *t = (struct trie *) tb->tb_data; |
@@ -1527,7 +1530,6 @@ static int trie_leaf_remove(struct trie *t, t_key key) | |||
1527 | t->revision++; | 1530 | t->revision++; |
1528 | t->size--; | 1531 | t->size--; |
1529 | 1532 | ||
1530 | preempt_disable(); | ||
1531 | tp = NODE_PARENT(n); | 1533 | tp = NODE_PARENT(n); |
1532 | tnode_free((struct tnode *) n); | 1534 | tnode_free((struct tnode *) n); |
1533 | 1535 | ||
@@ -1537,11 +1539,13 @@ static int trie_leaf_remove(struct trie *t, t_key key) | |||
1537 | rcu_assign_pointer(t->trie, trie_rebalance(t, tp)); | 1539 | rcu_assign_pointer(t->trie, trie_rebalance(t, tp)); |
1538 | } else | 1540 | } else |
1539 | rcu_assign_pointer(t->trie, NULL); | 1541 | rcu_assign_pointer(t->trie, NULL); |
1540 | preempt_enable(); | ||
1541 | 1542 | ||
1542 | return 1; | 1543 | return 1; |
1543 | } | 1544 | } |
1544 | 1545 | ||
1546 | /* | ||
1547 | * Caller must hold RTNL. | ||
1548 | */ | ||
1545 | static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) | 1549 | static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) |
1546 | { | 1550 | { |
1547 | struct trie *t = (struct trie *) tb->tb_data; | 1551 | struct trie *t = (struct trie *) tb->tb_data; |
@@ -1720,6 +1724,9 @@ up: | |||
1720 | return NULL; /* Ready. Root of trie */ | 1724 | return NULL; /* Ready. Root of trie */ |
1721 | } | 1725 | } |
1722 | 1726 | ||
1727 | /* | ||
1728 | * Caller must hold RTNL. | ||
1729 | */ | ||
1723 | static int fn_trie_flush(struct fib_table *tb) | 1730 | static int fn_trie_flush(struct fib_table *tb) |
1724 | { | 1731 | { |
1725 | struct trie *t = (struct trie *) tb->tb_data; | 1732 | struct trie *t = (struct trie *) tb->tb_data; |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 1c6a084b5fb7..8cedb2a2c9df 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1255,9 +1255,9 @@ out: | |||
1255 | */ | 1255 | */ |
1256 | void ip_mc_rejoin_group(struct ip_mc_list *im) | 1256 | void ip_mc_rejoin_group(struct ip_mc_list *im) |
1257 | { | 1257 | { |
1258 | #ifdef CONFIG_IP_MULTICAST | ||
1258 | struct in_device *in_dev = im->interface; | 1259 | struct in_device *in_dev = im->interface; |
1259 | 1260 | ||
1260 | #ifdef CONFIG_IP_MULTICAST | ||
1261 | if (im->multiaddr == IGMP_ALL_HOSTS) | 1261 | if (im->multiaddr == IGMP_ALL_HOSTS) |
1262 | return; | 1262 | return; |
1263 | 1263 | ||
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 5170f5c75f9d..57b0221f9e24 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -166,13 +166,9 @@ static inline int arp_packet_match(const struct arphdr *arphdr, | |||
166 | return 0; | 166 | return 0; |
167 | } | 167 | } |
168 | 168 | ||
169 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { | 169 | for (i = 0, ret = 0; i < IFNAMSIZ; i++) { |
170 | unsigned long odev; | 170 | ret |= (outdev[i] ^ arpinfo->outiface[i]) |
171 | memcpy(&odev, outdev + i*sizeof(unsigned long), | 171 | & arpinfo->outiface_mask[i]; |
172 | sizeof(unsigned long)); | ||
173 | ret |= (odev | ||
174 | ^ ((const unsigned long *)arpinfo->outiface)[i]) | ||
175 | & ((const unsigned long *)arpinfo->outiface_mask)[i]; | ||
176 | } | 172 | } |
177 | 173 | ||
178 | if (FWINV(ret != 0, ARPT_INV_VIA_OUT)) { | 174 | if (FWINV(ret != 0, ARPT_INV_VIA_OUT)) { |
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index adf25f9f70e1..6bcfdf6dfcc9 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -253,14 +253,17 @@ ip_nat_local_fn(unsigned int hooknum, | |||
253 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 253 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
254 | 254 | ||
255 | if (ct->tuplehash[dir].tuple.dst.ip != | 255 | if (ct->tuplehash[dir].tuple.dst.ip != |
256 | ct->tuplehash[!dir].tuple.src.ip | 256 | ct->tuplehash[!dir].tuple.src.ip) { |
257 | #ifdef CONFIG_XFRM | ||
258 | || ct->tuplehash[dir].tuple.dst.u.all != | ||
259 | ct->tuplehash[!dir].tuple.src.u.all | ||
260 | #endif | ||
261 | ) | ||
262 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) | 257 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) |
263 | ret = NF_DROP; | 258 | ret = NF_DROP; |
259 | } | ||
260 | #ifdef CONFIG_XFRM | ||
261 | else if (ct->tuplehash[dir].tuple.dst.u.all != | ||
262 | ct->tuplehash[!dir].tuple.src.u.all) | ||
263 | if (ip_xfrm_me_harder(pskb)) | ||
264 | ret = NF_DROP; | ||
265 | #endif | ||
266 | |||
264 | } | 267 | } |
265 | return ret; | 268 | return ret; |
266 | } | 269 | } |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index e965b333c997..42b08029e867 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -411,12 +411,10 @@ checkentry(const char *tablename, | |||
411 | "has invalid config pointer!\n"); | 411 | "has invalid config pointer!\n"); |
412 | return 0; | 412 | return 0; |
413 | } | 413 | } |
414 | clusterip_config_entry_get(cipinfo->config); | ||
415 | } else { | 414 | } else { |
416 | /* Case B: This is a new rule referring to an existing | 415 | /* Case B: This is a new rule referring to an existing |
417 | * clusterip config. */ | 416 | * clusterip config. */ |
418 | cipinfo->config = config; | 417 | cipinfo->config = config; |
419 | clusterip_config_entry_get(cipinfo->config); | ||
420 | } | 418 | } |
421 | } else { | 419 | } else { |
422 | /* Case C: This is a completely new clusterip config */ | 420 | /* Case C: This is a completely new clusterip config */ |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index a26404dbe212..9acc018766f2 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <linux/netfilter_ipv4/ipt_ULOG.h> | 61 | #include <linux/netfilter_ipv4/ipt_ULOG.h> |
62 | #include <net/sock.h> | 62 | #include <net/sock.h> |
63 | #include <linux/bitops.h> | 63 | #include <linux/bitops.h> |
64 | #include <asm/unaligned.h> | ||
64 | 65 | ||
65 | MODULE_LICENSE("GPL"); | 66 | MODULE_LICENSE("GPL"); |
66 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | 67 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); |
@@ -236,9 +237,9 @@ static void ipt_ulog_packet(unsigned int hooknum, | |||
236 | 237 | ||
237 | /* copy hook, prefix, timestamp, payload, etc. */ | 238 | /* copy hook, prefix, timestamp, payload, etc. */ |
238 | pm->data_len = copy_len; | 239 | pm->data_len = copy_len; |
239 | pm->timestamp_sec = skb->tstamp.off_sec; | 240 | put_unaligned(skb->tstamp.off_sec, &pm->timestamp_sec); |
240 | pm->timestamp_usec = skb->tstamp.off_usec; | 241 | put_unaligned(skb->tstamp.off_usec, &pm->timestamp_usec); |
241 | pm->mark = skb->mark; | 242 | put_unaligned(skb->mark, &pm->mark); |
242 | pm->hook = hooknum; | 243 | pm->hook = hooknum; |
243 | if (prefix != NULL) | 244 | if (prefix != NULL) |
244 | strncpy(pm->prefix, prefix, sizeof(pm->prefix)); | 245 | strncpy(pm->prefix, prefix, sizeof(pm->prefix)); |
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index e4d3ef17d45b..15aa3db8cb33 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
@@ -245,14 +245,16 @@ nf_nat_local_fn(unsigned int hooknum, | |||
245 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 245 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
246 | 246 | ||
247 | if (ct->tuplehash[dir].tuple.dst.u3.ip != | 247 | if (ct->tuplehash[dir].tuple.dst.u3.ip != |
248 | ct->tuplehash[!dir].tuple.src.u3.ip | 248 | ct->tuplehash[!dir].tuple.src.u3.ip) { |
249 | #ifdef CONFIG_XFRM | ||
250 | || ct->tuplehash[dir].tuple.dst.u.all != | ||
251 | ct->tuplehash[!dir].tuple.src.u.all | ||
252 | #endif | ||
253 | ) | ||
254 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) | 249 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) |
255 | ret = NF_DROP; | 250 | ret = NF_DROP; |
251 | } | ||
252 | #ifdef CONFIG_XFRM | ||
253 | else if (ct->tuplehash[dir].tuple.dst.u.all != | ||
254 | ct->tuplehash[!dir].tuple.src.u.all) | ||
255 | if (ip_xfrm_me_harder(pskb)) | ||
256 | ret = NF_DROP; | ||
257 | #endif | ||
256 | } | 258 | } |
257 | return ret; | 259 | return ret; |
258 | } | 260 | } |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 74c4d103ebc2..3834b10b5115 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2458,11 +2458,18 @@ void __init tcp_init(void) | |||
2458 | sysctl_max_syn_backlog = 128; | 2458 | sysctl_max_syn_backlog = 128; |
2459 | } | 2459 | } |
2460 | 2460 | ||
2461 | /* Allow no more than 3/4 kernel memory (usually less) allocated to TCP */ | 2461 | /* Set the pressure threshold to be a fraction of global memory that |
2462 | sysctl_tcp_mem[0] = (1536 / sizeof (struct inet_bind_hashbucket)) << order; | 2462 | * is up to 1/2 at 256 MB, decreasing toward zero with the amount of |
2463 | sysctl_tcp_mem[1] = sysctl_tcp_mem[0] * 4 / 3; | 2463 | * memory, with a floor of 128 pages. |
2464 | */ | ||
2465 | limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); | ||
2466 | limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); | ||
2467 | limit = max(limit, 128UL); | ||
2468 | sysctl_tcp_mem[0] = limit / 4 * 3; | ||
2469 | sysctl_tcp_mem[1] = limit; | ||
2464 | sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2; | 2470 | sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2; |
2465 | 2471 | ||
2472 | /* Set per-socket limits to no more than 1/128 the pressure threshold */ | ||
2466 | limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7); | 2473 | limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7); |
2467 | max_share = min(4UL*1024*1024, limit); | 2474 | max_share = min(4UL*1024*1024, limit); |
2468 | 2475 | ||
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 5c8caf4a1244..34ae3f13483a 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
@@ -77,18 +77,19 @@ void tcp_init_congestion_control(struct sock *sk) | |||
77 | struct inet_connection_sock *icsk = inet_csk(sk); | 77 | struct inet_connection_sock *icsk = inet_csk(sk); |
78 | struct tcp_congestion_ops *ca; | 78 | struct tcp_congestion_ops *ca; |
79 | 79 | ||
80 | if (icsk->icsk_ca_ops != &tcp_init_congestion_ops) | 80 | /* if no choice made yet assign the current value set as default */ |
81 | return; | 81 | if (icsk->icsk_ca_ops == &tcp_init_congestion_ops) { |
82 | rcu_read_lock(); | ||
83 | list_for_each_entry_rcu(ca, &tcp_cong_list, list) { | ||
84 | if (try_module_get(ca->owner)) { | ||
85 | icsk->icsk_ca_ops = ca; | ||
86 | break; | ||
87 | } | ||
82 | 88 | ||
83 | rcu_read_lock(); | 89 | /* fallback to next available */ |
84 | list_for_each_entry_rcu(ca, &tcp_cong_list, list) { | ||
85 | if (try_module_get(ca->owner)) { | ||
86 | icsk->icsk_ca_ops = ca; | ||
87 | break; | ||
88 | } | 90 | } |
89 | 91 | rcu_read_unlock(); | |
90 | } | 92 | } |
91 | rcu_read_unlock(); | ||
92 | 93 | ||
93 | if (icsk->icsk_ca_ops->init) | 94 | if (icsk->icsk_ca_ops->init) |
94 | icsk->icsk_ca_ops->init(sk); | 95 | icsk->icsk_ca_ops->init(sk); |
@@ -236,6 +237,7 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
236 | 237 | ||
237 | rcu_read_lock(); | 238 | rcu_read_lock(); |
238 | ca = tcp_ca_find(name); | 239 | ca = tcp_ca_find(name); |
240 | |||
239 | /* no change asking for existing value */ | 241 | /* no change asking for existing value */ |
240 | if (ca == icsk->icsk_ca_ops) | 242 | if (ca == icsk->icsk_ca_ops) |
241 | goto out; | 243 | goto out; |
@@ -261,7 +263,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
261 | else { | 263 | else { |
262 | tcp_cleanup_congestion_control(sk); | 264 | tcp_cleanup_congestion_control(sk); |
263 | icsk->icsk_ca_ops = ca; | 265 | icsk->icsk_ca_ops = ca; |
264 | if (icsk->icsk_ca_ops->init) | 266 | |
267 | if (sk->sk_state != TCP_CLOSE && icsk->icsk_ca_ops->init) | ||
265 | icsk->icsk_ca_ops->init(sk); | 268 | icsk->icsk_ca_ops->init(sk); |
266 | } | 269 | } |
267 | out: | 270 | out: |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index dc151139b5af..3c24881f2a65 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -943,7 +943,8 @@ static void tcp_cwnd_validate(struct sock *sk, struct tcp_sock *tp) | |||
943 | if (tp->packets_out > tp->snd_cwnd_used) | 943 | if (tp->packets_out > tp->snd_cwnd_used) |
944 | tp->snd_cwnd_used = tp->packets_out; | 944 | tp->snd_cwnd_used = tp->packets_out; |
945 | 945 | ||
946 | if ((s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto) | 946 | if (sysctl_tcp_slow_start_after_idle && |
947 | (s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto) | ||
947 | tcp_cwnd_application_limited(sk); | 948 | tcp_cwnd_application_limited(sk); |
948 | } | 949 | } |
949 | } | 950 | } |
@@ -1607,6 +1608,9 @@ u32 __tcp_select_window(struct sock *sk) | |||
1607 | */ | 1608 | */ |
1608 | if (window <= free_space - mss || window > free_space) | 1609 | if (window <= free_space - mss || window > free_space) |
1609 | window = (free_space/mss)*mss; | 1610 | window = (free_space/mss)*mss; |
1611 | else if (mss == full_space && | ||
1612 | free_space > window + full_space/2) | ||
1613 | window = free_space; | ||
1610 | } | 1614 | } |
1611 | 1615 | ||
1612 | return window; | 1616 | return window; |
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index 89cf59ea7bbe..d419e15d9803 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c | |||
@@ -42,10 +42,9 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
42 | 42 | ||
43 | skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen); | 43 | skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen); |
44 | top_iph = skb->nh.iph; | 44 | top_iph = skb->nh.iph; |
45 | hdrlen = iph->ihl * 4 - optlen; | 45 | skb->h.raw += sizeof(*iph) - hdrlen; |
46 | skb->h.raw += hdrlen; | ||
47 | 46 | ||
48 | memmove(top_iph, iph, hdrlen); | 47 | memmove(top_iph, iph, sizeof(*iph)); |
49 | if (unlikely(optlen)) { | 48 | if (unlikely(optlen)) { |
50 | struct ip_beet_phdr *ph; | 49 | struct ip_beet_phdr *ph; |
51 | 50 | ||
@@ -53,8 +52,10 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
53 | 52 | ||
54 | ph = (struct ip_beet_phdr *)skb->h.raw; | 53 | ph = (struct ip_beet_phdr *)skb->h.raw; |
55 | ph->padlen = 4 - (optlen & 4); | 54 | ph->padlen = 4 - (optlen & 4); |
56 | ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; | 55 | ph->hdrlen = optlen / 8; |
57 | ph->nexthdr = top_iph->protocol; | 56 | ph->nexthdr = top_iph->protocol; |
57 | if (ph->padlen) | ||
58 | memset(ph + 1, IPOPT_NOP, ph->padlen); | ||
58 | 59 | ||
59 | top_iph->protocol = IPPROTO_BEETPH; | 60 | top_iph->protocol = IPPROTO_BEETPH; |
60 | top_iph->ihl = sizeof(struct iphdr) / 4; | 61 | top_iph->ihl = sizeof(struct iphdr) / 4; |
@@ -77,29 +78,32 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) | |||
77 | protocol = iph->protocol; | 78 | protocol = iph->protocol; |
78 | 79 | ||
79 | if (unlikely(iph->protocol == IPPROTO_BEETPH)) { | 80 | if (unlikely(iph->protocol == IPPROTO_BEETPH)) { |
80 | struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1); | 81 | struct ip_beet_phdr *ph; |
81 | 82 | ||
82 | if (!pskb_may_pull(skb, sizeof(*ph))) | 83 | if (!pskb_may_pull(skb, sizeof(*ph))) |
83 | goto out; | 84 | goto out; |
85 | ph = (struct ip_beet_phdr *)(skb->h.ipiph + 1); | ||
84 | 86 | ||
85 | phlen = ph->hdrlen * 8; | 87 | phlen = sizeof(*ph) + ph->padlen; |
86 | optlen = phlen - ph->padlen - sizeof(*ph); | 88 | optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen); |
87 | if (optlen < 0 || optlen & 3 || optlen > 250) | 89 | if (optlen < 0 || optlen & 3 || optlen > 250) |
88 | goto out; | 90 | goto out; |
89 | 91 | ||
90 | if (!pskb_may_pull(skb, phlen)) | 92 | if (!pskb_may_pull(skb, phlen + optlen)) |
91 | goto out; | 93 | goto out; |
94 | skb->len -= phlen + optlen; | ||
92 | 95 | ||
93 | ph_nexthdr = ph->nexthdr; | 96 | ph_nexthdr = ph->nexthdr; |
94 | } | 97 | } |
95 | 98 | ||
96 | skb_push(skb, sizeof(*iph) - phlen + optlen); | 99 | skb->nh.raw = skb->data + (phlen - sizeof(*iph)); |
97 | memmove(skb->data, skb->nh.raw, sizeof(*iph)); | 100 | memmove(skb->nh.raw, iph, sizeof(*iph)); |
98 | skb->nh.raw = skb->data; | 101 | skb->h.raw = skb->data + (phlen + optlen); |
102 | skb->data = skb->h.raw; | ||
99 | 103 | ||
100 | iph = skb->nh.iph; | 104 | iph = skb->nh.iph; |
101 | iph->ihl = (sizeof(*iph) + optlen) / 4; | 105 | iph->ihl = (sizeof(*iph) + optlen) / 4; |
102 | iph->tot_len = htons(skb->len); | 106 | iph->tot_len = htons(skb->len + iph->ihl * 4); |
103 | iph->daddr = x->sel.daddr.a4; | 107 | iph->daddr = x->sel.daddr.a4; |
104 | iph->saddr = x->sel.saddr.a4; | 108 | iph->saddr = x->sel.saddr.a4; |
105 | if (ph_nexthdr) | 109 | if (ph_nexthdr) |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a7fee6b27320..452a82ce4796 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -172,6 +172,7 @@ struct ipv6_devconf ipv6_devconf __read_mostly = { | |||
172 | #endif | 172 | #endif |
173 | #endif | 173 | #endif |
174 | .proxy_ndp = 0, | 174 | .proxy_ndp = 0, |
175 | .accept_source_route = 0, /* we do not accept RH0 by default. */ | ||
175 | }; | 176 | }; |
176 | 177 | ||
177 | static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | 178 | static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { |
@@ -203,6 +204,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
203 | #endif | 204 | #endif |
204 | #endif | 205 | #endif |
205 | .proxy_ndp = 0, | 206 | .proxy_ndp = 0, |
207 | .accept_source_route = 0, /* we do not accept RH0 by default. */ | ||
206 | }; | 208 | }; |
207 | 209 | ||
208 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ | 210 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ |
@@ -342,6 +344,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
342 | } | 344 | } |
343 | #endif | 345 | #endif |
344 | 346 | ||
347 | if (netif_running(dev) && netif_carrier_ok(dev)) | ||
348 | ndev->if_flags |= IF_READY; | ||
349 | |||
345 | ipv6_mc_init_dev(ndev); | 350 | ipv6_mc_init_dev(ndev); |
346 | ndev->tstamp = jiffies; | 351 | ndev->tstamp = jiffies; |
347 | #ifdef CONFIG_SYSCTL | 352 | #ifdef CONFIG_SYSCTL |
@@ -804,7 +809,7 @@ struct ipv6_saddr_score { | |||
804 | #define IPV6_SADDR_SCORE_LABEL 0x0020 | 809 | #define IPV6_SADDR_SCORE_LABEL 0x0020 |
805 | #define IPV6_SADDR_SCORE_PRIVACY 0x0040 | 810 | #define IPV6_SADDR_SCORE_PRIVACY 0x0040 |
806 | 811 | ||
807 | static int inline ipv6_saddr_preferred(int type) | 812 | static inline int ipv6_saddr_preferred(int type) |
808 | { | 813 | { |
809 | if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4| | 814 | if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4| |
810 | IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED)) | 815 | IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED)) |
@@ -813,7 +818,7 @@ static int inline ipv6_saddr_preferred(int type) | |||
813 | } | 818 | } |
814 | 819 | ||
815 | /* static matching label */ | 820 | /* static matching label */ |
816 | static int inline ipv6_saddr_label(const struct in6_addr *addr, int type) | 821 | static inline int ipv6_saddr_label(const struct in6_addr *addr, int type) |
817 | { | 822 | { |
818 | /* | 823 | /* |
819 | * prefix (longest match) label | 824 | * prefix (longest match) label |
@@ -3318,7 +3323,7 @@ errout: | |||
3318 | rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err); | 3323 | rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err); |
3319 | } | 3324 | } |
3320 | 3325 | ||
3321 | static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, | 3326 | static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, |
3322 | __s32 *array, int bytes) | 3327 | __s32 *array, int bytes) |
3323 | { | 3328 | { |
3324 | BUG_ON(bytes < (DEVCONF_MAX * 4)); | 3329 | BUG_ON(bytes < (DEVCONF_MAX * 4)); |
@@ -3353,6 +3358,7 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
3353 | #endif | 3358 | #endif |
3354 | #endif | 3359 | #endif |
3355 | array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; | 3360 | array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; |
3361 | array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route; | ||
3356 | } | 3362 | } |
3357 | 3363 | ||
3358 | static inline size_t inet6_if_nlmsg_size(void) | 3364 | static inline size_t inet6_if_nlmsg_size(void) |
@@ -3881,6 +3887,14 @@ static struct addrconf_sysctl_table | |||
3881 | .proc_handler = &proc_dointvec, | 3887 | .proc_handler = &proc_dointvec, |
3882 | }, | 3888 | }, |
3883 | { | 3889 | { |
3890 | .ctl_name = NET_IPV6_ACCEPT_SOURCE_ROUTE, | ||
3891 | .procname = "accept_source_route", | ||
3892 | .data = &ipv6_devconf.accept_source_route, | ||
3893 | .maxlen = sizeof(int), | ||
3894 | .mode = 0644, | ||
3895 | .proc_handler = &proc_dointvec, | ||
3896 | }, | ||
3897 | { | ||
3884 | .ctl_name = 0, /* sentinel */ | 3898 | .ctl_name = 0, /* sentinel */ |
3885 | } | 3899 | } |
3886 | }, | 3900 | }, |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 28e0c6568272..fb39604c3d09 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -362,10 +362,27 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
362 | struct inet6_skb_parm *opt = IP6CB(skb); | 362 | struct inet6_skb_parm *opt = IP6CB(skb); |
363 | struct in6_addr *addr = NULL; | 363 | struct in6_addr *addr = NULL; |
364 | struct in6_addr daddr; | 364 | struct in6_addr daddr; |
365 | struct inet6_dev *idev; | ||
365 | int n, i; | 366 | int n, i; |
366 | |||
367 | struct ipv6_rt_hdr *hdr; | 367 | struct ipv6_rt_hdr *hdr; |
368 | struct rt0_hdr *rthdr; | 368 | struct rt0_hdr *rthdr; |
369 | int accept_source_route = ipv6_devconf.accept_source_route; | ||
370 | |||
371 | if (accept_source_route < 0 || | ||
372 | ((idev = in6_dev_get(skb->dev)) == NULL)) { | ||
373 | kfree_skb(skb); | ||
374 | return -1; | ||
375 | } | ||
376 | if (idev->cnf.accept_source_route < 0) { | ||
377 | in6_dev_put(idev); | ||
378 | kfree_skb(skb); | ||
379 | return -1; | ||
380 | } | ||
381 | |||
382 | if (accept_source_route > idev->cnf.accept_source_route) | ||
383 | accept_source_route = idev->cnf.accept_source_route; | ||
384 | |||
385 | in6_dev_put(idev); | ||
369 | 386 | ||
370 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || | 387 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || |
371 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { | 388 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { |
@@ -377,6 +394,22 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
377 | 394 | ||
378 | hdr = (struct ipv6_rt_hdr *) skb->h.raw; | 395 | hdr = (struct ipv6_rt_hdr *) skb->h.raw; |
379 | 396 | ||
397 | switch (hdr->type) { | ||
398 | #ifdef CONFIG_IPV6_MIP6 | ||
399 | break; | ||
400 | #endif | ||
401 | case IPV6_SRCRT_TYPE_0: | ||
402 | if (accept_source_route > 0) | ||
403 | break; | ||
404 | kfree_skb(skb); | ||
405 | return -1; | ||
406 | default: | ||
407 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | ||
408 | IPSTATS_MIB_INHDRERRORS); | ||
409 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); | ||
410 | return -1; | ||
411 | } | ||
412 | |||
380 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || | 413 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || |
381 | skb->pkt_type != PACKET_HOST) { | 414 | skb->pkt_type != PACKET_HOST) { |
382 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 415 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
@@ -434,11 +467,6 @@ looped_back: | |||
434 | } | 467 | } |
435 | break; | 468 | break; |
436 | #endif | 469 | #endif |
437 | default: | ||
438 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | ||
439 | IPSTATS_MIB_INHDRERRORS); | ||
440 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); | ||
441 | return -1; | ||
442 | } | 470 | } |
443 | 471 | ||
444 | /* | 472 | /* |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 0862809ffcf7..ea3035b4e3e8 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -131,8 +131,6 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | |||
131 | 131 | ||
132 | static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { | 132 | static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { |
133 | FRA_GENERIC_POLICY, | 133 | FRA_GENERIC_POLICY, |
134 | [FRA_SRC] = { .len = sizeof(struct in6_addr) }, | ||
135 | [FRA_DST] = { .len = sizeof(struct in6_addr) }, | ||
136 | }; | 134 | }; |
137 | 135 | ||
138 | static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | 136 | static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, |
@@ -142,9 +140,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
142 | int err = -EINVAL; | 140 | int err = -EINVAL; |
143 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; | 141 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; |
144 | 142 | ||
145 | if (frh->src_len > 128 || frh->dst_len > 128) | ||
146 | goto errout; | ||
147 | |||
148 | if (rule->action == FR_ACT_TO_TBL) { | 143 | if (rule->action == FR_ACT_TO_TBL) { |
149 | if (rule->table == RT6_TABLE_UNSPEC) | 144 | if (rule->table == RT6_TABLE_UNSPEC) |
150 | goto errout; | 145 | goto errout; |
@@ -155,11 +150,11 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
155 | } | 150 | } |
156 | } | 151 | } |
157 | 152 | ||
158 | if (tb[FRA_SRC]) | 153 | if (frh->src_len) |
159 | nla_memcpy(&rule6->src.addr, tb[FRA_SRC], | 154 | nla_memcpy(&rule6->src.addr, tb[FRA_SRC], |
160 | sizeof(struct in6_addr)); | 155 | sizeof(struct in6_addr)); |
161 | 156 | ||
162 | if (tb[FRA_DST]) | 157 | if (frh->dst_len) |
163 | nla_memcpy(&rule6->dst.addr, tb[FRA_DST], | 158 | nla_memcpy(&rule6->dst.addr, tb[FRA_DST], |
164 | sizeof(struct in6_addr)); | 159 | sizeof(struct in6_addr)); |
165 | 160 | ||
@@ -186,11 +181,11 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | |||
186 | if (frh->tos && (rule6->tclass != frh->tos)) | 181 | if (frh->tos && (rule6->tclass != frh->tos)) |
187 | return 0; | 182 | return 0; |
188 | 183 | ||
189 | if (tb[FRA_SRC] && | 184 | if (frh->src_len && |
190 | nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr))) | 185 | nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr))) |
191 | return 0; | 186 | return 0; |
192 | 187 | ||
193 | if (tb[FRA_DST] && | 188 | if (frh->dst_len && |
194 | nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) | 189 | nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) |
195 | return 0; | 190 | return 0; |
196 | 191 | ||
@@ -240,6 +235,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) | |||
240 | static struct fib_rules_ops fib6_rules_ops = { | 235 | static struct fib_rules_ops fib6_rules_ops = { |
241 | .family = AF_INET6, | 236 | .family = AF_INET6, |
242 | .rule_size = sizeof(struct fib6_rule), | 237 | .rule_size = sizeof(struct fib6_rule), |
238 | .addr_size = sizeof(struct in6_addr), | ||
243 | .action = fib6_rule_action, | 239 | .action = fib6_rule_action, |
244 | .match = fib6_rule_match, | 240 | .match = fib6_rule_match, |
245 | .configure = fib6_rule_configure, | 241 | .configure = fib6_rule_configure, |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f4d7be77eb0f..268f476ef3db 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -658,6 +658,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
658 | ins = &iter->u.dst.rt6_next; | 658 | ins = &iter->u.dst.rt6_next; |
659 | } | 659 | } |
660 | 660 | ||
661 | /* Reset round-robin state, if necessary */ | ||
662 | if (ins == &fn->leaf) | ||
663 | fn->rr_ptr = NULL; | ||
664 | |||
661 | /* | 665 | /* |
662 | * insert node | 666 | * insert node |
663 | */ | 667 | */ |
@@ -1109,6 +1113,10 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1109 | rt6_stats.fib_rt_entries--; | 1113 | rt6_stats.fib_rt_entries--; |
1110 | rt6_stats.fib_discarded_routes++; | 1114 | rt6_stats.fib_discarded_routes++; |
1111 | 1115 | ||
1116 | /* Reset round-robin state, if necessary */ | ||
1117 | if (fn->rr_ptr == rt) | ||
1118 | fn->rr_ptr = NULL; | ||
1119 | |||
1112 | /* Adjust walkers */ | 1120 | /* Adjust walkers */ |
1113 | read_lock(&fib6_walker_lock); | 1121 | read_lock(&fib6_walker_lock); |
1114 | FOR_WALKERS(w) { | 1122 | FOR_WALKERS(w) { |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 11bfc7c43182..61e7a6c8141d 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -108,8 +108,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
108 | 108 | ||
109 | /* pkt_len may be zero if Jumbo payload option is present */ | 109 | /* pkt_len may be zero if Jumbo payload option is present */ |
110 | if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { | 110 | if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { |
111 | if (pkt_len + sizeof(struct ipv6hdr) > skb->len) | 111 | if (pkt_len + sizeof(struct ipv6hdr) > skb->len) { |
112 | goto truncated; | 112 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INTRUNCATEDPKTS); |
113 | goto drop; | ||
114 | } | ||
113 | if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { | 115 | if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { |
114 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); | 116 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
115 | goto drop; | 117 | goto drop; |
@@ -128,8 +130,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
128 | rcu_read_unlock(); | 130 | rcu_read_unlock(); |
129 | 131 | ||
130 | return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); | 132 | return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); |
131 | truncated: | ||
132 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INTRUNCATEDPKTS); | ||
133 | err: | 133 | err: |
134 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); | 134 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
135 | drop: | 135 | drop: |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 306d5d83c068..203e069e7fe9 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -687,9 +687,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
687 | int err; | 687 | int err; |
688 | 688 | ||
689 | /* Rough check on arithmetic overflow, | 689 | /* Rough check on arithmetic overflow, |
690 | better check is made in ip6_build_xmit | 690 | better check is made in ip6_append_data(). |
691 | */ | 691 | */ |
692 | if (len < 0) | 692 | if (len > INT_MAX) |
693 | return -EMSGSIZE; | 693 | return -EMSGSIZE; |
694 | 694 | ||
695 | /* Mirror BSD error message compatibility */ | 695 | /* Mirror BSD error message compatibility */ |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 0e1f4b2cd3dd..aebb4e2d5ae3 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -308,27 +308,18 @@ static inline void rt6_probe(struct rt6_info *rt) | |||
308 | /* | 308 | /* |
309 | * Default Router Selection (RFC 2461 6.3.6) | 309 | * Default Router Selection (RFC 2461 6.3.6) |
310 | */ | 310 | */ |
311 | static int inline rt6_check_dev(struct rt6_info *rt, int oif) | 311 | static inline int rt6_check_dev(struct rt6_info *rt, int oif) |
312 | { | 312 | { |
313 | struct net_device *dev = rt->rt6i_dev; | 313 | struct net_device *dev = rt->rt6i_dev; |
314 | int ret = 0; | 314 | if (!oif || dev->ifindex == oif) |
315 | |||
316 | if (!oif) | ||
317 | return 2; | ||
318 | if (dev->flags & IFF_LOOPBACK) { | ||
319 | if (!WARN_ON(rt->rt6i_idev == NULL) && | ||
320 | rt->rt6i_idev->dev->ifindex == oif) | ||
321 | ret = 1; | ||
322 | else | ||
323 | return 0; | ||
324 | } | ||
325 | if (dev->ifindex == oif) | ||
326 | return 2; | 315 | return 2; |
327 | 316 | if ((dev->flags & IFF_LOOPBACK) && | |
328 | return ret; | 317 | rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif) |
318 | return 1; | ||
319 | return 0; | ||
329 | } | 320 | } |
330 | 321 | ||
331 | static int inline rt6_check_neigh(struct rt6_info *rt) | 322 | static inline int rt6_check_neigh(struct rt6_info *rt) |
332 | { | 323 | { |
333 | struct neighbour *neigh = rt->rt6i_nexthop; | 324 | struct neighbour *neigh = rt->rt6i_nexthop; |
334 | int m = 0; | 325 | int m = 0; |
@@ -363,55 +354,76 @@ static int rt6_score_route(struct rt6_info *rt, int oif, | |||
363 | return m; | 354 | return m; |
364 | } | 355 | } |
365 | 356 | ||
366 | static struct rt6_info *rt6_select(struct rt6_info **head, int oif, | 357 | static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict, |
367 | int strict) | 358 | int *mpri, struct rt6_info *match) |
368 | { | 359 | { |
369 | struct rt6_info *match = NULL, *last = NULL; | 360 | int m; |
370 | struct rt6_info *rt, *rt0 = *head; | 361 | |
371 | u32 metric; | 362 | if (rt6_check_expired(rt)) |
363 | goto out; | ||
364 | |||
365 | m = rt6_score_route(rt, oif, strict); | ||
366 | if (m < 0) | ||
367 | goto out; | ||
368 | |||
369 | if (m > *mpri) { | ||
370 | if (strict & RT6_LOOKUP_F_REACHABLE) | ||
371 | rt6_probe(match); | ||
372 | *mpri = m; | ||
373 | match = rt; | ||
374 | } else if (strict & RT6_LOOKUP_F_REACHABLE) { | ||
375 | rt6_probe(rt); | ||
376 | } | ||
377 | |||
378 | out: | ||
379 | return match; | ||
380 | } | ||
381 | |||
382 | static struct rt6_info *find_rr_leaf(struct fib6_node *fn, | ||
383 | struct rt6_info *rr_head, | ||
384 | u32 metric, int oif, int strict) | ||
385 | { | ||
386 | struct rt6_info *rt, *match; | ||
372 | int mpri = -1; | 387 | int mpri = -1; |
373 | 388 | ||
374 | RT6_TRACE("%s(head=%p(*head=%p), oif=%d)\n", | 389 | match = NULL; |
375 | __FUNCTION__, head, head ? *head : NULL, oif); | 390 | for (rt = rr_head; rt && rt->rt6i_metric == metric; |
391 | rt = rt->u.dst.rt6_next) | ||
392 | match = find_match(rt, oif, strict, &mpri, match); | ||
393 | for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric; | ||
394 | rt = rt->u.dst.rt6_next) | ||
395 | match = find_match(rt, oif, strict, &mpri, match); | ||
376 | 396 | ||
377 | for (rt = rt0, metric = rt0->rt6i_metric; | 397 | return match; |
378 | rt && rt->rt6i_metric == metric && (!last || rt != rt0); | 398 | } |
379 | rt = rt->u.dst.rt6_next) { | ||
380 | int m; | ||
381 | 399 | ||
382 | if (rt6_check_expired(rt)) | 400 | static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) |
383 | continue; | 401 | { |
402 | struct rt6_info *match, *rt0; | ||
384 | 403 | ||
385 | last = rt; | 404 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", |
405 | __FUNCTION__, fn->leaf, oif); | ||
386 | 406 | ||
387 | m = rt6_score_route(rt, oif, strict); | 407 | rt0 = fn->rr_ptr; |
388 | if (m < 0) | 408 | if (!rt0) |
389 | continue; | 409 | fn->rr_ptr = rt0 = fn->leaf; |
390 | 410 | ||
391 | if (m > mpri) { | 411 | match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict); |
392 | if (strict & RT6_LOOKUP_F_REACHABLE) | ||
393 | rt6_probe(match); | ||
394 | match = rt; | ||
395 | mpri = m; | ||
396 | } else if (strict & RT6_LOOKUP_F_REACHABLE) { | ||
397 | rt6_probe(rt); | ||
398 | } | ||
399 | } | ||
400 | 412 | ||
401 | if (!match && | 413 | if (!match && |
402 | (strict & RT6_LOOKUP_F_REACHABLE) && | 414 | (strict & RT6_LOOKUP_F_REACHABLE)) { |
403 | last && last != rt0) { | 415 | struct rt6_info *next = rt0->u.dst.rt6_next; |
416 | |||
404 | /* no entries matched; do round-robin */ | 417 | /* no entries matched; do round-robin */ |
405 | static DEFINE_SPINLOCK(lock); | 418 | if (!next || next->rt6i_metric != rt0->rt6i_metric) |
406 | spin_lock(&lock); | 419 | next = fn->leaf; |
407 | *head = rt0->u.dst.rt6_next; | 420 | |
408 | rt0->u.dst.rt6_next = last->u.dst.rt6_next; | 421 | if (next != rt0) |
409 | last->u.dst.rt6_next = rt0; | 422 | fn->rr_ptr = next; |
410 | spin_unlock(&lock); | ||
411 | } | 423 | } |
412 | 424 | ||
413 | RT6_TRACE("%s() => %p, score=%d\n", | 425 | RT6_TRACE("%s() => %p\n", |
414 | __FUNCTION__, match, mpri); | 426 | __FUNCTION__, match); |
415 | 427 | ||
416 | return (match ? match : &ip6_null_entry); | 428 | return (match ? match : &ip6_null_entry); |
417 | } | 429 | } |
@@ -657,7 +669,7 @@ restart_2: | |||
657 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 669 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
658 | 670 | ||
659 | restart: | 671 | restart: |
660 | rt = rt6_select(&fn->leaf, fl->iif, strict | reachable); | 672 | rt = rt6_select(fn, fl->iif, strict | reachable); |
661 | BACKTRACK(&fl->fl6_src); | 673 | BACKTRACK(&fl->fl6_src); |
662 | if (rt == &ip6_null_entry || | 674 | if (rt == &ip6_null_entry || |
663 | rt->rt6i_flags & RTF_CACHE) | 675 | rt->rt6i_flags & RTF_CACHE) |
@@ -752,7 +764,7 @@ restart_2: | |||
752 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 764 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
753 | 765 | ||
754 | restart: | 766 | restart: |
755 | rt = rt6_select(&fn->leaf, fl->oif, strict | reachable); | 767 | rt = rt6_select(fn, fl->oif, strict | reachable); |
756 | BACKTRACK(&fl->fl6_src); | 768 | BACKTRACK(&fl->fl6_src); |
757 | if (rt == &ip6_null_entry || | 769 | if (rt == &ip6_null_entry || |
758 | rt->rt6i_flags & RTF_CACHE) | 770 | rt->rt6i_flags & RTF_CACHE) |
@@ -1754,13 +1766,22 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | |||
1754 | * Drop the packet on the floor | 1766 | * Drop the packet on the floor |
1755 | */ | 1767 | */ |
1756 | 1768 | ||
1757 | static inline int ip6_pkt_drop(struct sk_buff *skb, int code) | 1769 | static inline int ip6_pkt_drop(struct sk_buff *skb, int code, |
1770 | int ipstats_mib_noroutes) | ||
1758 | { | 1771 | { |
1759 | int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); | 1772 | int type; |
1760 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) | 1773 | switch (ipstats_mib_noroutes) { |
1761 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); | 1774 | case IPSTATS_MIB_INNOROUTES: |
1762 | 1775 | type = ipv6_addr_type(&skb->nh.ipv6h->daddr); | |
1763 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTNOROUTES); | 1776 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) { |
1777 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); | ||
1778 | break; | ||
1779 | } | ||
1780 | /* FALLTHROUGH */ | ||
1781 | case IPSTATS_MIB_OUTNOROUTES: | ||
1782 | IP6_INC_STATS(ip6_dst_idev(skb->dst), ipstats_mib_noroutes); | ||
1783 | break; | ||
1784 | } | ||
1764 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); | 1785 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); |
1765 | kfree_skb(skb); | 1786 | kfree_skb(skb); |
1766 | return 0; | 1787 | return 0; |
@@ -1768,26 +1789,26 @@ static inline int ip6_pkt_drop(struct sk_buff *skb, int code) | |||
1768 | 1789 | ||
1769 | static int ip6_pkt_discard(struct sk_buff *skb) | 1790 | static int ip6_pkt_discard(struct sk_buff *skb) |
1770 | { | 1791 | { |
1771 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE); | 1792 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES); |
1772 | } | 1793 | } |
1773 | 1794 | ||
1774 | static int ip6_pkt_discard_out(struct sk_buff *skb) | 1795 | static int ip6_pkt_discard_out(struct sk_buff *skb) |
1775 | { | 1796 | { |
1776 | skb->dev = skb->dst->dev; | 1797 | skb->dev = skb->dst->dev; |
1777 | return ip6_pkt_discard(skb); | 1798 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); |
1778 | } | 1799 | } |
1779 | 1800 | ||
1780 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 1801 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
1781 | 1802 | ||
1782 | static int ip6_pkt_prohibit(struct sk_buff *skb) | 1803 | static int ip6_pkt_prohibit(struct sk_buff *skb) |
1783 | { | 1804 | { |
1784 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED); | 1805 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); |
1785 | } | 1806 | } |
1786 | 1807 | ||
1787 | static int ip6_pkt_prohibit_out(struct sk_buff *skb) | 1808 | static int ip6_pkt_prohibit_out(struct sk_buff *skb) |
1788 | { | 1809 | { |
1789 | skb->dev = skb->dst->dev; | 1810 | skb->dev = skb->dst->dev; |
1790 | return ip6_pkt_prohibit(skb); | 1811 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); |
1791 | } | 1812 | } |
1792 | 1813 | ||
1793 | static int ip6_pkt_blk_hole(struct sk_buff *skb) | 1814 | static int ip6_pkt_blk_hole(struct sk_buff *skb) |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f57a9baa6b27..92f99927d12d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1453,6 +1453,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1453 | First: no IPv4 options. | 1453 | First: no IPv4 options. |
1454 | */ | 1454 | */ |
1455 | newinet->opt = NULL; | 1455 | newinet->opt = NULL; |
1456 | newnp->ipv6_fl_list = NULL; | ||
1456 | 1457 | ||
1457 | /* Clone RX bits */ | 1458 | /* Clone RX bits */ |
1458 | newnp->rxopt.all = np->rxopt.all; | 1459 | newnp->rxopt.all = np->rxopt.all; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 0ad471909881..f590db57a7c9 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -615,7 +615,7 @@ do_udp_sendmsg: | |||
615 | return udp_sendmsg(iocb, sk, msg, len); | 615 | return udp_sendmsg(iocb, sk, msg, len); |
616 | 616 | ||
617 | /* Rough check on arithmetic overflow, | 617 | /* Rough check on arithmetic overflow, |
618 | better check is made in ip6_build_xmit | 618 | better check is made in ip6_append_data(). |
619 | */ | 619 | */ |
620 | if (len > INT_MAX - sizeof(struct udphdr)) | 620 | if (len > INT_MAX - sizeof(struct udphdr)) |
621 | return -EMSGSIZE; | 621 | return -EMSGSIZE; |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index ee4b84a33ff4..93c42232aa39 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -58,7 +58,7 @@ static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly; | |||
58 | static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE]; | 58 | static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE]; |
59 | static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE]; | 59 | static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE]; |
60 | 60 | ||
61 | static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) | 61 | static inline unsigned xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) |
62 | { | 62 | { |
63 | unsigned h; | 63 | unsigned h; |
64 | 64 | ||
@@ -70,7 +70,7 @@ static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) | |||
70 | return h; | 70 | return h; |
71 | } | 71 | } |
72 | 72 | ||
73 | static unsigned inline xfrm6_tunnel_spi_hash_byspi(u32 spi) | 73 | static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) |
74 | { | 74 | { |
75 | return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; | 75 | return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; |
76 | } | 76 | } |
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index eabd6838f50a..0eb7d596d470 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -138,7 +138,6 @@ static void irda_disconnect_indication(void *instance, void *sap, | |||
138 | sk->sk_shutdown |= SEND_SHUTDOWN; | 138 | sk->sk_shutdown |= SEND_SHUTDOWN; |
139 | 139 | ||
140 | sk->sk_state_change(sk); | 140 | sk->sk_state_change(sk); |
141 | sock_orphan(sk); | ||
142 | release_sock(sk); | 141 | release_sock(sk); |
143 | 142 | ||
144 | /* Close our TSAP. | 143 | /* Close our TSAP. |
@@ -1446,7 +1445,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1446 | */ | 1445 | */ |
1447 | ret = sock_error(sk); | 1446 | ret = sock_error(sk); |
1448 | if (ret) | 1447 | if (ret) |
1449 | break; | 1448 | ; |
1450 | else if (sk->sk_shutdown & RCV_SHUTDOWN) | 1449 | else if (sk->sk_shutdown & RCV_SHUTDOWN) |
1451 | ; | 1450 | ; |
1452 | else if (noblock) | 1451 | else if (noblock) |
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index 873ae189e37a..bc2e15ce7004 100644 --- a/net/irda/irnet/irnet.h +++ b/net/irda/irnet/irnet.h | |||
@@ -419,7 +419,7 @@ typedef struct irnet_socket | |||
419 | u32 raccm; /* to please pppd - dummy) */ | 419 | u32 raccm; /* to please pppd - dummy) */ |
420 | unsigned int flags; /* PPP flags (compression, ...) */ | 420 | unsigned int flags; /* PPP flags (compression, ...) */ |
421 | unsigned int rbits; /* Unused receive flags ??? */ | 421 | unsigned int rbits; /* Unused receive flags ??? */ |
422 | 422 | struct work_struct disconnect_work; /* Process context disconnection */ | |
423 | /* ------------------------ IrTTP part ------------------------ */ | 423 | /* ------------------------ IrTTP part ------------------------ */ |
424 | /* We create a pseudo "socket" over the IrDA tranport */ | 424 | /* We create a pseudo "socket" over the IrDA tranport */ |
425 | unsigned long ttp_open; /* Set when IrTTP is ready */ | 425 | unsigned long ttp_open; /* Set when IrTTP is ready */ |
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c index c378e668af0c..a4f1439ffdd8 100644 --- a/net/irda/irnet/irnet_irda.c +++ b/net/irda/irnet/irnet_irda.c | |||
@@ -10,6 +10,27 @@ | |||
10 | 10 | ||
11 | #include "irnet_irda.h" /* Private header */ | 11 | #include "irnet_irda.h" /* Private header */ |
12 | 12 | ||
13 | /* | ||
14 | * PPP disconnect work: we need to make sure we're in | ||
15 | * process context when calling ppp_unregister_channel(). | ||
16 | */ | ||
17 | static void irnet_ppp_disconnect(struct work_struct *work) | ||
18 | { | ||
19 | irnet_socket * self = | ||
20 | container_of(work, irnet_socket, disconnect_work); | ||
21 | |||
22 | if (self == NULL) | ||
23 | return; | ||
24 | /* | ||
25 | * If we were connected, cleanup & close the PPP | ||
26 | * channel, which will kill pppd (hangup) and the rest. | ||
27 | */ | ||
28 | if (self->ppp_open && !self->ttp_open && !self->ttp_connect) { | ||
29 | ppp_unregister_channel(&self->chan); | ||
30 | self->ppp_open = 0; | ||
31 | } | ||
32 | } | ||
33 | |||
13 | /************************* CONTROL CHANNEL *************************/ | 34 | /************************* CONTROL CHANNEL *************************/ |
14 | /* | 35 | /* |
15 | * When ppp is not active, /dev/irnet act as a control channel. | 36 | * When ppp is not active, /dev/irnet act as a control channel. |
@@ -499,6 +520,8 @@ irda_irnet_create(irnet_socket * self) | |||
499 | #endif /* DISCOVERY_NOMASK */ | 520 | #endif /* DISCOVERY_NOMASK */ |
500 | self->tx_flow = FLOW_START; /* Flow control from IrTTP */ | 521 | self->tx_flow = FLOW_START; /* Flow control from IrTTP */ |
501 | 522 | ||
523 | INIT_WORK(&self->disconnect_work, irnet_ppp_disconnect); | ||
524 | |||
502 | DEXIT(IRDA_SOCK_TRACE, "\n"); | 525 | DEXIT(IRDA_SOCK_TRACE, "\n"); |
503 | return(0); | 526 | return(0); |
504 | } | 527 | } |
@@ -1134,15 +1157,8 @@ irnet_disconnect_indication(void * instance, | |||
1134 | { | 1157 | { |
1135 | if(test_open) | 1158 | if(test_open) |
1136 | { | 1159 | { |
1137 | #ifdef MISSING_PPP_API | 1160 | /* ppp_unregister_channel() wants a user context. */ |
1138 | /* ppp_unregister_channel() wants a user context, which we | 1161 | schedule_work(&self->disconnect_work); |
1139 | * are guaranteed to NOT have here. What are we supposed | ||
1140 | * to do here ? Jean II */ | ||
1141 | /* If we were connected, cleanup & close the PPP channel, | ||
1142 | * which will kill pppd (hangup) and the rest */ | ||
1143 | ppp_unregister_channel(&self->chan); | ||
1144 | self->ppp_open = 0; | ||
1145 | #endif | ||
1146 | } | 1162 | } |
1147 | else | 1163 | else |
1148 | { | 1164 | { |
diff --git a/net/irda/irttp.c b/net/irda/irttp.c index a7486b3bddcb..da3f2bc1b6f6 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c | |||
@@ -1455,6 +1455,7 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance) | |||
1455 | 1455 | ||
1456 | /* Not everything should be copied */ | 1456 | /* Not everything should be copied */ |
1457 | new->notify.instance = instance; | 1457 | new->notify.instance = instance; |
1458 | spin_lock_init(&new->lock); | ||
1458 | init_timer(&new->todo_timer); | 1459 | init_timer(&new->todo_timer); |
1459 | 1460 | ||
1460 | skb_queue_head_init(&new->rx_queue); | 1461 | skb_queue_head_init(&new->rx_queue); |
diff --git a/net/key/af_key.c b/net/key/af_key.c index a4e7e2db0ff3..345019345f09 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -630,6 +630,35 @@ pfkey_sockaddr_size(sa_family_t family) | |||
630 | /* NOTREACHED */ | 630 | /* NOTREACHED */ |
631 | } | 631 | } |
632 | 632 | ||
633 | static inline int pfkey_mode_from_xfrm(int mode) | ||
634 | { | ||
635 | switch(mode) { | ||
636 | case XFRM_MODE_TRANSPORT: | ||
637 | return IPSEC_MODE_TRANSPORT; | ||
638 | case XFRM_MODE_TUNNEL: | ||
639 | return IPSEC_MODE_TUNNEL; | ||
640 | case XFRM_MODE_BEET: | ||
641 | return IPSEC_MODE_BEET; | ||
642 | default: | ||
643 | return -1; | ||
644 | } | ||
645 | } | ||
646 | |||
647 | static inline int pfkey_mode_to_xfrm(int mode) | ||
648 | { | ||
649 | switch(mode) { | ||
650 | case IPSEC_MODE_ANY: /*XXX*/ | ||
651 | case IPSEC_MODE_TRANSPORT: | ||
652 | return XFRM_MODE_TRANSPORT; | ||
653 | case IPSEC_MODE_TUNNEL: | ||
654 | return XFRM_MODE_TUNNEL; | ||
655 | case IPSEC_MODE_BEET: | ||
656 | return XFRM_MODE_BEET; | ||
657 | default: | ||
658 | return -1; | ||
659 | } | ||
660 | } | ||
661 | |||
633 | static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc) | 662 | static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc) |
634 | { | 663 | { |
635 | struct sk_buff *skb; | 664 | struct sk_buff *skb; |
@@ -651,6 +680,7 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, | |||
651 | int encrypt_key_size = 0; | 680 | int encrypt_key_size = 0; |
652 | int sockaddr_size; | 681 | int sockaddr_size; |
653 | struct xfrm_encap_tmpl *natt = NULL; | 682 | struct xfrm_encap_tmpl *natt = NULL; |
683 | int mode; | ||
654 | 684 | ||
655 | /* address family check */ | 685 | /* address family check */ |
656 | sockaddr_size = pfkey_sockaddr_size(x->props.family); | 686 | sockaddr_size = pfkey_sockaddr_size(x->props.family); |
@@ -928,7 +958,11 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, | |||
928 | sa2 = (struct sadb_x_sa2 *) skb_put(skb, sizeof(struct sadb_x_sa2)); | 958 | sa2 = (struct sadb_x_sa2 *) skb_put(skb, sizeof(struct sadb_x_sa2)); |
929 | sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2)/sizeof(uint64_t); | 959 | sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2)/sizeof(uint64_t); |
930 | sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2; | 960 | sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2; |
931 | sa2->sadb_x_sa2_mode = x->props.mode + 1; | 961 | if ((mode = pfkey_mode_from_xfrm(x->props.mode)) < 0) { |
962 | kfree_skb(skb); | ||
963 | return ERR_PTR(-EINVAL); | ||
964 | } | ||
965 | sa2->sadb_x_sa2_mode = mode; | ||
932 | sa2->sadb_x_sa2_reserved1 = 0; | 966 | sa2->sadb_x_sa2_reserved1 = 0; |
933 | sa2->sadb_x_sa2_reserved2 = 0; | 967 | sa2->sadb_x_sa2_reserved2 = 0; |
934 | sa2->sadb_x_sa2_sequence = 0; | 968 | sa2->sadb_x_sa2_sequence = 0; |
@@ -1155,9 +1189,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
1155 | 1189 | ||
1156 | if (ext_hdrs[SADB_X_EXT_SA2-1]) { | 1190 | if (ext_hdrs[SADB_X_EXT_SA2-1]) { |
1157 | struct sadb_x_sa2 *sa2 = (void*)ext_hdrs[SADB_X_EXT_SA2-1]; | 1191 | struct sadb_x_sa2 *sa2 = (void*)ext_hdrs[SADB_X_EXT_SA2-1]; |
1158 | x->props.mode = sa2->sadb_x_sa2_mode; | 1192 | int mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode); |
1159 | if (x->props.mode) | 1193 | if (mode < 0) { |
1160 | x->props.mode--; | 1194 | err = -EINVAL; |
1195 | goto out; | ||
1196 | } | ||
1197 | x->props.mode = mode; | ||
1161 | x->props.reqid = sa2->sadb_x_sa2_reqid; | 1198 | x->props.reqid = sa2->sadb_x_sa2_reqid; |
1162 | } | 1199 | } |
1163 | 1200 | ||
@@ -1218,7 +1255,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
1218 | struct sadb_address *saddr, *daddr; | 1255 | struct sadb_address *saddr, *daddr; |
1219 | struct sadb_msg *out_hdr; | 1256 | struct sadb_msg *out_hdr; |
1220 | struct xfrm_state *x = NULL; | 1257 | struct xfrm_state *x = NULL; |
1221 | u8 mode; | 1258 | int mode; |
1222 | u32 reqid; | 1259 | u32 reqid; |
1223 | u8 proto; | 1260 | u8 proto; |
1224 | unsigned short family; | 1261 | unsigned short family; |
@@ -1233,7 +1270,9 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
1233 | return -EINVAL; | 1270 | return -EINVAL; |
1234 | 1271 | ||
1235 | if ((sa2 = ext_hdrs[SADB_X_EXT_SA2-1]) != NULL) { | 1272 | if ((sa2 = ext_hdrs[SADB_X_EXT_SA2-1]) != NULL) { |
1236 | mode = sa2->sadb_x_sa2_mode - 1; | 1273 | mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode); |
1274 | if (mode < 0) | ||
1275 | return -EINVAL; | ||
1237 | reqid = sa2->sadb_x_sa2_reqid; | 1276 | reqid = sa2->sadb_x_sa2_reqid; |
1238 | } else { | 1277 | } else { |
1239 | mode = 0; | 1278 | mode = 0; |
@@ -1756,6 +1795,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | |||
1756 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 1795 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
1757 | struct sockaddr_in6 *sin6; | 1796 | struct sockaddr_in6 *sin6; |
1758 | #endif | 1797 | #endif |
1798 | int mode; | ||
1759 | 1799 | ||
1760 | if (xp->xfrm_nr >= XFRM_MAX_DEPTH) | 1800 | if (xp->xfrm_nr >= XFRM_MAX_DEPTH) |
1761 | return -ELOOP; | 1801 | return -ELOOP; |
@@ -1764,7 +1804,9 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | |||
1764 | return -EINVAL; | 1804 | return -EINVAL; |
1765 | 1805 | ||
1766 | t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */ | 1806 | t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */ |
1767 | t->mode = rq->sadb_x_ipsecrequest_mode-1; | 1807 | if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0) |
1808 | return -EINVAL; | ||
1809 | t->mode = mode; | ||
1768 | if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) | 1810 | if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) |
1769 | t->optional = 1; | 1811 | t->optional = 1; |
1770 | else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) { | 1812 | else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) { |
@@ -1877,7 +1919,7 @@ static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp) | |||
1877 | return skb; | 1919 | return skb; |
1878 | } | 1920 | } |
1879 | 1921 | ||
1880 | static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, int dir) | 1922 | static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, int dir) |
1881 | { | 1923 | { |
1882 | struct sadb_msg *hdr; | 1924 | struct sadb_msg *hdr; |
1883 | struct sadb_address *addr; | 1925 | struct sadb_address *addr; |
@@ -2014,6 +2056,7 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i | |||
2014 | struct sadb_x_ipsecrequest *rq; | 2056 | struct sadb_x_ipsecrequest *rq; |
2015 | struct xfrm_tmpl *t = xp->xfrm_vec + i; | 2057 | struct xfrm_tmpl *t = xp->xfrm_vec + i; |
2016 | int req_size; | 2058 | int req_size; |
2059 | int mode; | ||
2017 | 2060 | ||
2018 | req_size = sizeof(struct sadb_x_ipsecrequest); | 2061 | req_size = sizeof(struct sadb_x_ipsecrequest); |
2019 | if (t->mode == XFRM_MODE_TUNNEL) | 2062 | if (t->mode == XFRM_MODE_TUNNEL) |
@@ -2027,7 +2070,9 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i | |||
2027 | memset(rq, 0, sizeof(*rq)); | 2070 | memset(rq, 0, sizeof(*rq)); |
2028 | rq->sadb_x_ipsecrequest_len = req_size; | 2071 | rq->sadb_x_ipsecrequest_len = req_size; |
2029 | rq->sadb_x_ipsecrequest_proto = t->id.proto; | 2072 | rq->sadb_x_ipsecrequest_proto = t->id.proto; |
2030 | rq->sadb_x_ipsecrequest_mode = t->mode+1; | 2073 | if ((mode = pfkey_mode_from_xfrm(t->mode)) < 0) |
2074 | return -EINVAL; | ||
2075 | rq->sadb_x_ipsecrequest_mode = mode; | ||
2031 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE; | 2076 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE; |
2032 | if (t->reqid) | 2077 | if (t->reqid) |
2033 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE; | 2078 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE; |
@@ -2089,6 +2134,8 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i | |||
2089 | 2134 | ||
2090 | hdr->sadb_msg_len = size / sizeof(uint64_t); | 2135 | hdr->sadb_msg_len = size / sizeof(uint64_t); |
2091 | hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); | 2136 | hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); |
2137 | |||
2138 | return 0; | ||
2092 | } | 2139 | } |
2093 | 2140 | ||
2094 | static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) | 2141 | static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) |
@@ -2102,7 +2149,9 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c | |||
2102 | err = PTR_ERR(out_skb); | 2149 | err = PTR_ERR(out_skb); |
2103 | goto out; | 2150 | goto out; |
2104 | } | 2151 | } |
2105 | pfkey_xfrm_policy2msg(out_skb, xp, dir); | 2152 | err = pfkey_xfrm_policy2msg(out_skb, xp, dir); |
2153 | if (err < 0) | ||
2154 | return err; | ||
2106 | 2155 | ||
2107 | out_hdr = (struct sadb_msg *) out_skb->data; | 2156 | out_hdr = (struct sadb_msg *) out_skb->data; |
2108 | out_hdr->sadb_msg_version = PF_KEY_V2; | 2157 | out_hdr->sadb_msg_version = PF_KEY_V2; |
@@ -2327,7 +2376,9 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb | |||
2327 | err = PTR_ERR(out_skb); | 2376 | err = PTR_ERR(out_skb); |
2328 | goto out; | 2377 | goto out; |
2329 | } | 2378 | } |
2330 | pfkey_xfrm_policy2msg(out_skb, xp, dir); | 2379 | err = pfkey_xfrm_policy2msg(out_skb, xp, dir); |
2380 | if (err < 0) | ||
2381 | goto out; | ||
2331 | 2382 | ||
2332 | out_hdr = (struct sadb_msg *) out_skb->data; | 2383 | out_hdr = (struct sadb_msg *) out_skb->data; |
2333 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; | 2384 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; |
@@ -2409,6 +2460,7 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, | |||
2409 | { | 2460 | { |
2410 | int err; | 2461 | int err; |
2411 | struct sadb_x_ipsecrequest *rq2; | 2462 | struct sadb_x_ipsecrequest *rq2; |
2463 | int mode; | ||
2412 | 2464 | ||
2413 | if (len <= sizeof(struct sadb_x_ipsecrequest) || | 2465 | if (len <= sizeof(struct sadb_x_ipsecrequest) || |
2414 | len < rq1->sadb_x_ipsecrequest_len) | 2466 | len < rq1->sadb_x_ipsecrequest_len) |
@@ -2439,7 +2491,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, | |||
2439 | return -EINVAL; | 2491 | return -EINVAL; |
2440 | 2492 | ||
2441 | m->proto = rq1->sadb_x_ipsecrequest_proto; | 2493 | m->proto = rq1->sadb_x_ipsecrequest_proto; |
2442 | m->mode = rq1->sadb_x_ipsecrequest_mode - 1; | 2494 | if ((mode = pfkey_mode_to_xfrm(rq1->sadb_x_ipsecrequest_mode)) < 0) |
2495 | return -EINVAL; | ||
2496 | m->mode = mode; | ||
2443 | m->reqid = rq1->sadb_x_ipsecrequest_reqid; | 2497 | m->reqid = rq1->sadb_x_ipsecrequest_reqid; |
2444 | 2498 | ||
2445 | return ((int)(rq1->sadb_x_ipsecrequest_len + | 2499 | return ((int)(rq1->sadb_x_ipsecrequest_len + |
@@ -2579,12 +2633,15 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr) | |||
2579 | struct pfkey_dump_data *data = ptr; | 2633 | struct pfkey_dump_data *data = ptr; |
2580 | struct sk_buff *out_skb; | 2634 | struct sk_buff *out_skb; |
2581 | struct sadb_msg *out_hdr; | 2635 | struct sadb_msg *out_hdr; |
2636 | int err; | ||
2582 | 2637 | ||
2583 | out_skb = pfkey_xfrm_policy2msg_prep(xp); | 2638 | out_skb = pfkey_xfrm_policy2msg_prep(xp); |
2584 | if (IS_ERR(out_skb)) | 2639 | if (IS_ERR(out_skb)) |
2585 | return PTR_ERR(out_skb); | 2640 | return PTR_ERR(out_skb); |
2586 | 2641 | ||
2587 | pfkey_xfrm_policy2msg(out_skb, xp, dir); | 2642 | err = pfkey_xfrm_policy2msg(out_skb, xp, dir); |
2643 | if (err < 0) | ||
2644 | return err; | ||
2588 | 2645 | ||
2589 | out_hdr = (struct sadb_msg *) out_skb->data; | 2646 | out_hdr = (struct sadb_msg *) out_skb->data; |
2590 | out_hdr->sadb_msg_version = data->hdr->sadb_msg_version; | 2647 | out_hdr->sadb_msg_version = data->hdr->sadb_msg_version; |
@@ -3513,7 +3570,10 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
3513 | 3570 | ||
3514 | for (i = 0, mp = m; i < num_bundles; i++, mp++) { | 3571 | for (i = 0, mp = m; i < num_bundles; i++, mp++) { |
3515 | /* old ipsecrequest */ | 3572 | /* old ipsecrequest */ |
3516 | if (set_ipsecrequest(skb, mp->proto, mp->mode + 1, | 3573 | int mode = pfkey_mode_from_xfrm(mp->mode); |
3574 | if (mode < 0) | ||
3575 | return -EINVAL; | ||
3576 | if (set_ipsecrequest(skb, mp->proto, mode, | ||
3517 | (mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE), | 3577 | (mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE), |
3518 | mp->reqid, mp->old_family, | 3578 | mp->reqid, mp->old_family, |
3519 | &mp->old_saddr, &mp->old_daddr) < 0) { | 3579 | &mp->old_saddr, &mp->old_daddr) < 0) { |
@@ -3521,7 +3581,7 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
3521 | } | 3581 | } |
3522 | 3582 | ||
3523 | /* new ipsecrequest */ | 3583 | /* new ipsecrequest */ |
3524 | if (set_ipsecrequest(skb, mp->proto, mp->mode + 1, | 3584 | if (set_ipsecrequest(skb, mp->proto, mode, |
3525 | (mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE), | 3585 | (mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE), |
3526 | mp->reqid, mp->new_family, | 3586 | mp->reqid, mp->new_family, |
3527 | &mp->new_saddr, &mp->new_daddr) < 0) { | 3587 | &mp->new_saddr, &mp->new_daddr) < 0) { |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 253fce3ad2d3..54698af6d0af 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -275,6 +275,7 @@ config NF_CT_NETLINK | |||
275 | tristate 'Connection tracking netlink interface (EXPERIMENTAL)' | 275 | tristate 'Connection tracking netlink interface (EXPERIMENTAL)' |
276 | depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK | 276 | depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK |
277 | depends on NF_CONNTRACK!=y || NETFILTER_NETLINK!=m | 277 | depends on NF_CONNTRACK!=y || NETFILTER_NETLINK!=m |
278 | depends on NF_NAT=n || NF_NAT | ||
278 | help | 279 | help |
279 | This option enables support for a netlink-based userspace interface | 280 | This option enables support for a netlink-based userspace interface |
280 | 281 | ||
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index e73d8f546c6b..c48b0f49f003 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -443,6 +443,7 @@ static int netlink_release(struct socket *sock) | |||
443 | return 0; | 443 | return 0; |
444 | 444 | ||
445 | netlink_remove(sk); | 445 | netlink_remove(sk); |
446 | sock_orphan(sk); | ||
446 | nlk = nlk_sk(sk); | 447 | nlk = nlk_sk(sk); |
447 | 448 | ||
448 | spin_lock(&nlk->cb_lock); | 449 | spin_lock(&nlk->cb_lock); |
@@ -457,7 +458,6 @@ static int netlink_release(struct socket *sock) | |||
457 | /* OK. Socket is unlinked, and, therefore, | 458 | /* OK. Socket is unlinked, and, therefore, |
458 | no new packets will arrive */ | 459 | no new packets will arrive */ |
459 | 460 | ||
460 | sock_orphan(sk); | ||
461 | sock->sk = NULL; | 461 | sock->sk = NULL; |
462 | wake_up_interruptible_all(&nlk->wait); | 462 | wake_up_interruptible_all(&nlk->wait); |
463 | 463 | ||
@@ -1412,9 +1412,9 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
1412 | return -ECONNREFUSED; | 1412 | return -ECONNREFUSED; |
1413 | } | 1413 | } |
1414 | nlk = nlk_sk(sk); | 1414 | nlk = nlk_sk(sk); |
1415 | /* A dump is in progress... */ | 1415 | /* A dump or destruction is in progress... */ |
1416 | spin_lock(&nlk->cb_lock); | 1416 | spin_lock(&nlk->cb_lock); |
1417 | if (nlk->cb) { | 1417 | if (nlk->cb || sock_flag(sk, SOCK_DEAD)) { |
1418 | spin_unlock(&nlk->cb_lock); | 1418 | spin_unlock(&nlk->cb_lock); |
1419 | netlink_destroy_callback(cb); | 1419 | netlink_destroy_callback(cb); |
1420 | sock_put(sk); | 1420 | sock_put(sk); |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 8c34f1ca6c8c..f92d5310847b 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -700,23 +700,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le | |||
700 | unsigned char cause, diagnostic; | 700 | unsigned char cause, diagnostic; |
701 | struct net_device *dev; | 701 | struct net_device *dev; |
702 | ax25_uid_assoc *user; | 702 | ax25_uid_assoc *user; |
703 | int n; | 703 | int n, err = 0; |
704 | |||
705 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { | ||
706 | sock->state = SS_CONNECTED; | ||
707 | return 0; /* Connect completed during a ERESTARTSYS event */ | ||
708 | } | ||
709 | |||
710 | if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) { | ||
711 | sock->state = SS_UNCONNECTED; | ||
712 | return -ECONNREFUSED; | ||
713 | } | ||
714 | |||
715 | if (sk->sk_state == TCP_ESTABLISHED) | ||
716 | return -EISCONN; /* No reconnect on a seqpacket socket */ | ||
717 | |||
718 | sk->sk_state = TCP_CLOSE; | ||
719 | sock->state = SS_UNCONNECTED; | ||
720 | 704 | ||
721 | if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose)) | 705 | if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose)) |
722 | return -EINVAL; | 706 | return -EINVAL; |
@@ -734,24 +718,53 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le | |||
734 | if ((rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS) | 718 | if ((rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS) |
735 | return -EINVAL; | 719 | return -EINVAL; |
736 | 720 | ||
721 | lock_sock(sk); | ||
722 | |||
723 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { | ||
724 | /* Connect completed during a ERESTARTSYS event */ | ||
725 | sock->state = SS_CONNECTED; | ||
726 | goto out_release; | ||
727 | } | ||
728 | |||
729 | if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) { | ||
730 | sock->state = SS_UNCONNECTED; | ||
731 | err = -ECONNREFUSED; | ||
732 | goto out_release; | ||
733 | } | ||
734 | |||
735 | if (sk->sk_state == TCP_ESTABLISHED) { | ||
736 | /* No reconnect on a seqpacket socket */ | ||
737 | err = -EISCONN; | ||
738 | goto out_release; | ||
739 | } | ||
740 | |||
741 | sk->sk_state = TCP_CLOSE; | ||
742 | sock->state = SS_UNCONNECTED; | ||
743 | |||
737 | rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, | 744 | rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, |
738 | &diagnostic); | 745 | &diagnostic); |
739 | if (!rose->neighbour) | 746 | if (!rose->neighbour) |
740 | return -ENETUNREACH; | 747 | return -ENETUNREACH; |
741 | 748 | ||
742 | rose->lci = rose_new_lci(rose->neighbour); | 749 | rose->lci = rose_new_lci(rose->neighbour); |
743 | if (!rose->lci) | 750 | if (!rose->lci) { |
744 | return -ENETUNREACH; | 751 | err = -ENETUNREACH; |
752 | goto out_release; | ||
753 | } | ||
745 | 754 | ||
746 | if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */ | 755 | if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */ |
747 | sock_reset_flag(sk, SOCK_ZAPPED); | 756 | sock_reset_flag(sk, SOCK_ZAPPED); |
748 | 757 | ||
749 | if ((dev = rose_dev_first()) == NULL) | 758 | if ((dev = rose_dev_first()) == NULL) { |
750 | return -ENETUNREACH; | 759 | err = -ENETUNREACH; |
760 | goto out_release; | ||
761 | } | ||
751 | 762 | ||
752 | user = ax25_findbyuid(current->euid); | 763 | user = ax25_findbyuid(current->euid); |
753 | if (!user) | 764 | if (!user) { |
754 | return -EINVAL; | 765 | err = -EINVAL; |
766 | goto out_release; | ||
767 | } | ||
755 | 768 | ||
756 | memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN); | 769 | memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN); |
757 | rose->source_call = user->call; | 770 | rose->source_call = user->call; |
@@ -789,8 +802,10 @@ rose_try_next_neigh: | |||
789 | rose_start_t1timer(sk); | 802 | rose_start_t1timer(sk); |
790 | 803 | ||
791 | /* Now the loop */ | 804 | /* Now the loop */ |
792 | if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) | 805 | if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) { |
793 | return -EINPROGRESS; | 806 | err = -EINPROGRESS; |
807 | goto out_release; | ||
808 | } | ||
794 | 809 | ||
795 | /* | 810 | /* |
796 | * A Connect Ack with Choke or timeout or failed routing will go to | 811 | * A Connect Ack with Choke or timeout or failed routing will go to |
@@ -805,8 +820,10 @@ rose_try_next_neigh: | |||
805 | set_current_state(TASK_INTERRUPTIBLE); | 820 | set_current_state(TASK_INTERRUPTIBLE); |
806 | if (sk->sk_state != TCP_SYN_SENT) | 821 | if (sk->sk_state != TCP_SYN_SENT) |
807 | break; | 822 | break; |
823 | release_sock(sk); | ||
808 | if (!signal_pending(tsk)) { | 824 | if (!signal_pending(tsk)) { |
809 | schedule(); | 825 | schedule(); |
826 | lock_sock(sk); | ||
810 | continue; | 827 | continue; |
811 | } | 828 | } |
812 | current->state = TASK_RUNNING; | 829 | current->state = TASK_RUNNING; |
@@ -822,14 +839,19 @@ rose_try_next_neigh: | |||
822 | rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic); | 839 | rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic); |
823 | if (rose->neighbour) | 840 | if (rose->neighbour) |
824 | goto rose_try_next_neigh; | 841 | goto rose_try_next_neigh; |
825 | /* No more neighbour */ | 842 | |
843 | /* No more neighbours */ | ||
826 | sock->state = SS_UNCONNECTED; | 844 | sock->state = SS_UNCONNECTED; |
827 | return sock_error(sk); /* Always set at this point */ | 845 | err = sock_error(sk); /* Always set at this point */ |
846 | goto out_release; | ||
828 | } | 847 | } |
829 | 848 | ||
830 | sock->state = SS_CONNECTED; | 849 | sock->state = SS_CONNECTED; |
831 | 850 | ||
832 | return 0; | 851 | out_release: |
852 | release_sock(sk); | ||
853 | |||
854 | return err; | ||
833 | } | 855 | } |
834 | 856 | ||
835 | static int rose_accept(struct socket *sock, struct socket *newsock, int flags) | 857 | static int rose_accept(struct socket *sock, struct socket *newsock, int flags) |
@@ -877,6 +899,8 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) | |||
877 | lock_sock(sk); | 899 | lock_sock(sk); |
878 | continue; | 900 | continue; |
879 | } | 901 | } |
902 | current->state = TASK_RUNNING; | ||
903 | remove_wait_queue(sk->sk_sleep, &wait); | ||
880 | return -ERESTARTSYS; | 904 | return -ERESTARTSYS; |
881 | } | 905 | } |
882 | current->state = TASK_RUNNING; | 906 | current->state = TASK_RUNNING; |
diff --git a/net/sched/Makefile b/net/sched/Makefile index ff2d6e5e282c..020767a204d4 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile | |||
@@ -17,7 +17,6 @@ obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o | |||
17 | obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o | 17 | obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o |
18 | obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o | 18 | obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o |
19 | obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o | 19 | obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o |
20 | obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o | ||
21 | obj-$(CONFIG_NET_SCH_HFSC) += sch_hfsc.o | 20 | obj-$(CONFIG_NET_SCH_HFSC) += sch_hfsc.o |
22 | obj-$(CONFIG_NET_SCH_RED) += sch_red.o | 21 | obj-$(CONFIG_NET_SCH_RED) += sch_red.o |
23 | obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o | 22 | obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 68f26cb278f9..3e93683e9ab3 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -198,7 +198,7 @@ bad_mirred: | |||
198 | skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at); | 198 | skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at); |
199 | 199 | ||
200 | skb2->dev = dev; | 200 | skb2->dev = dev; |
201 | skb2->input_dev = skb->dev; | 201 | skb2->iif = skb->dev->ifindex; |
202 | dev_queue_xmit(skb2); | 202 | dev_queue_xmit(skb2); |
203 | spin_unlock(&m->tcf_lock); | 203 | spin_unlock(&m->tcf_lock); |
204 | return m->tcf_action; | 204 | return m->tcf_action; |
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index fad08e521c24..4a91f082a81d 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -81,6 +81,13 @@ static void basic_put(struct tcf_proto *tp, unsigned long f) | |||
81 | 81 | ||
82 | static int basic_init(struct tcf_proto *tp) | 82 | static int basic_init(struct tcf_proto *tp) |
83 | { | 83 | { |
84 | struct basic_head *head; | ||
85 | |||
86 | head = kzalloc(sizeof(*head), GFP_KERNEL); | ||
87 | if (head == NULL) | ||
88 | return -ENOBUFS; | ||
89 | INIT_LIST_HEAD(&head->flist); | ||
90 | tp->root = head; | ||
84 | return 0; | 91 | return 0; |
85 | } | 92 | } |
86 | 93 | ||
@@ -102,6 +109,7 @@ static void basic_destroy(struct tcf_proto *tp) | |||
102 | list_del(&f->link); | 109 | list_del(&f->link); |
103 | basic_delete_filter(tp, f); | 110 | basic_delete_filter(tp, f); |
104 | } | 111 | } |
112 | kfree(head); | ||
105 | } | 113 | } |
106 | 114 | ||
107 | static int basic_delete(struct tcf_proto *tp, unsigned long arg) | 115 | static int basic_delete(struct tcf_proto *tp, unsigned long arg) |
@@ -176,15 +184,6 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle, | |||
176 | } | 184 | } |
177 | 185 | ||
178 | err = -ENOBUFS; | 186 | err = -ENOBUFS; |
179 | if (head == NULL) { | ||
180 | head = kzalloc(sizeof(*head), GFP_KERNEL); | ||
181 | if (head == NULL) | ||
182 | goto errout; | ||
183 | |||
184 | INIT_LIST_HEAD(&head->flist); | ||
185 | tp->root = head; | ||
186 | } | ||
187 | |||
188 | f = kzalloc(sizeof(*f), GFP_KERNEL); | 187 | f = kzalloc(sizeof(*f), GFP_KERNEL); |
189 | if (f == NULL) | 188 | if (f == NULL) |
190 | goto errout; | 189 | goto errout; |
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index e85df07d8ce7..abc47cc48ad0 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c | |||
@@ -93,7 +93,7 @@ void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 | |||
93 | spin_unlock_bh(&dev->queue_lock); | 93 | spin_unlock_bh(&dev->queue_lock); |
94 | } | 94 | } |
95 | 95 | ||
96 | static void __inline__ | 96 | static inline void |
97 | route4_set_fastmap(struct route4_head *head, u32 id, int iif, | 97 | route4_set_fastmap(struct route4_head *head, u32 id, int iif, |
98 | struct route4_filter *f) | 98 | struct route4_filter *f) |
99 | { | 99 | { |
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 040e2d2d281a..7563fdcef4b7 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -245,9 +245,9 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle, | |||
245 | } | 245 | } |
246 | 246 | ||
247 | if (tb[TCA_TCINDEX_SHIFT-1]) { | 247 | if (tb[TCA_TCINDEX_SHIFT-1]) { |
248 | if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(u16)) | 248 | if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(int)) |
249 | goto errout; | 249 | goto errout; |
250 | cp.shift = *(u16 *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]); | 250 | cp.shift = *(int *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]); |
251 | } | 251 | } |
252 | 252 | ||
253 | err = -EBUSY; | 253 | err = -EBUSY; |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 396deb71480f..407c6fb1ba14 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -1184,10 +1184,12 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg) | |||
1184 | 1184 | ||
1185 | sch_tree_lock(sch); | 1185 | sch_tree_lock(sch); |
1186 | 1186 | ||
1187 | list_del(&cl->hlist); | ||
1188 | list_del(&cl->siblings); | 1187 | list_del(&cl->siblings); |
1189 | hfsc_adjust_levels(cl->cl_parent); | 1188 | hfsc_adjust_levels(cl->cl_parent); |
1189 | |||
1190 | hfsc_purge_queue(sch, cl); | 1190 | hfsc_purge_queue(sch, cl); |
1191 | list_del(&cl->hlist); | ||
1192 | |||
1191 | if (--cl->refcnt == 0) | 1193 | if (--cl->refcnt == 0) |
1192 | hfsc_destroy_class(sch, cl); | 1194 | hfsc_destroy_class(sch, cl); |
1193 | 1195 | ||
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 97cbb9aec946..3c3294d01041 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -1380,15 +1380,15 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) | |||
1380 | 1380 | ||
1381 | sch_tree_lock(sch); | 1381 | sch_tree_lock(sch); |
1382 | 1382 | ||
1383 | /* delete from hash and active; remainder in destroy_class */ | ||
1384 | hlist_del_init(&cl->hlist); | ||
1385 | |||
1386 | if (!cl->level) { | 1383 | if (!cl->level) { |
1387 | qlen = cl->un.leaf.q->q.qlen; | 1384 | qlen = cl->un.leaf.q->q.qlen; |
1388 | qdisc_reset(cl->un.leaf.q); | 1385 | qdisc_reset(cl->un.leaf.q); |
1389 | qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen); | 1386 | qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen); |
1390 | } | 1387 | } |
1391 | 1388 | ||
1389 | /* delete from hash and active; remainder in destroy_class */ | ||
1390 | hlist_del_init(&cl->hlist); | ||
1391 | |||
1392 | if (cl->prio_activity) | 1392 | if (cl->prio_activity) |
1393 | htb_deactivate(q, cl); | 1393 | htb_deactivate(q, cl); |
1394 | 1394 | ||
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index fa82b73c965b..78d2ddb5ca18 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -1046,6 +1046,9 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
1046 | trans = list_entry(pos, struct sctp_transport, transports); | 1046 | trans = list_entry(pos, struct sctp_transport, transports); |
1047 | if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr)) | 1047 | if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr)) |
1048 | sctp_assoc_del_peer(asoc, &trans->ipaddr); | 1048 | sctp_assoc_del_peer(asoc, &trans->ipaddr); |
1049 | |||
1050 | if (asoc->state >= SCTP_STATE_ESTABLISHED) | ||
1051 | sctp_transport_reset(trans); | ||
1049 | } | 1052 | } |
1050 | 1053 | ||
1051 | /* If the case is A (association restart), use | 1054 | /* If the case is A (association restart), use |
@@ -1063,6 +1066,18 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
1063 | */ | 1066 | */ |
1064 | sctp_ssnmap_clear(asoc->ssnmap); | 1067 | sctp_ssnmap_clear(asoc->ssnmap); |
1065 | 1068 | ||
1069 | /* Flush the ULP reassembly and ordered queue. | ||
1070 | * Any data there will now be stale and will | ||
1071 | * cause problems. | ||
1072 | */ | ||
1073 | sctp_ulpq_flush(&asoc->ulpq); | ||
1074 | |||
1075 | /* reset the overall association error count so | ||
1076 | * that the restarted association doesn't get torn | ||
1077 | * down on the next retransmission timer. | ||
1078 | */ | ||
1079 | asoc->overall_error_count = 0; | ||
1080 | |||
1066 | } else { | 1081 | } else { |
1067 | /* Add any peer addresses from the new association. */ | 1082 | /* Add any peer addresses from the new association. */ |
1068 | list_for_each(pos, &new->peer.transport_addr_list) { | 1083 | list_for_each(pos, &new->peer.transport_addr_list) { |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 70c39eac0581..e9097cf614ba 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -4342,8 +4342,24 @@ sctp_disposition_t sctp_sf_do_prm_requestheartbeat( | |||
4342 | void *arg, | 4342 | void *arg, |
4343 | sctp_cmd_seq_t *commands) | 4343 | sctp_cmd_seq_t *commands) |
4344 | { | 4344 | { |
4345 | return sctp_sf_heartbeat(ep, asoc, type, (struct sctp_transport *)arg, | 4345 | if (SCTP_DISPOSITION_NOMEM == sctp_sf_heartbeat(ep, asoc, type, |
4346 | commands); | 4346 | (struct sctp_transport *)arg, commands)) |
4347 | return SCTP_DISPOSITION_NOMEM; | ||
4348 | |||
4349 | /* | ||
4350 | * RFC 2960 (bis), section 8.3 | ||
4351 | * | ||
4352 | * D) Request an on-demand HEARTBEAT on a specific destination | ||
4353 | * transport address of a given association. | ||
4354 | * | ||
4355 | * The endpoint should increment the respective error counter of | ||
4356 | * the destination transport address each time a HEARTBEAT is sent | ||
4357 | * to that address and not acknowledged within one RTO. | ||
4358 | * | ||
4359 | */ | ||
4360 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_RESET, | ||
4361 | SCTP_TRANSPORT(arg)); | ||
4362 | return SCTP_DISPOSITION_CONSUME; | ||
4347 | } | 4363 | } |
4348 | 4364 | ||
4349 | /* | 4365 | /* |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 536298c2eda2..a1d026f12b0e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -627,6 +627,12 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) | |||
627 | retval = -EINVAL; | 627 | retval = -EINVAL; |
628 | goto err_bindx_rem; | 628 | goto err_bindx_rem; |
629 | } | 629 | } |
630 | |||
631 | if (!af->addr_valid(sa_addr, sp, NULL)) { | ||
632 | retval = -EADDRNOTAVAIL; | ||
633 | goto err_bindx_rem; | ||
634 | } | ||
635 | |||
630 | if (sa_addr->v4.sin_port != htons(bp->port)) { | 636 | if (sa_addr->v4.sin_port != htons(bp->port)) { |
631 | retval = -EINVAL; | 637 | retval = -EINVAL; |
632 | goto err_bindx_rem; | 638 | goto err_bindx_rem; |
@@ -5638,6 +5644,36 @@ void sctp_wait_for_close(struct sock *sk, long timeout) | |||
5638 | finish_wait(sk->sk_sleep, &wait); | 5644 | finish_wait(sk->sk_sleep, &wait); |
5639 | } | 5645 | } |
5640 | 5646 | ||
5647 | static void sctp_sock_rfree_frag(struct sk_buff *skb) | ||
5648 | { | ||
5649 | struct sk_buff *frag; | ||
5650 | |||
5651 | if (!skb->data_len) | ||
5652 | goto done; | ||
5653 | |||
5654 | /* Don't forget the fragments. */ | ||
5655 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) | ||
5656 | sctp_sock_rfree_frag(frag); | ||
5657 | |||
5658 | done: | ||
5659 | sctp_sock_rfree(skb); | ||
5660 | } | ||
5661 | |||
5662 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) | ||
5663 | { | ||
5664 | struct sk_buff *frag; | ||
5665 | |||
5666 | if (!skb->data_len) | ||
5667 | goto done; | ||
5668 | |||
5669 | /* Don't forget the fragments. */ | ||
5670 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) | ||
5671 | sctp_skb_set_owner_r_frag(frag, sk); | ||
5672 | |||
5673 | done: | ||
5674 | sctp_skb_set_owner_r(skb, sk); | ||
5675 | } | ||
5676 | |||
5641 | /* Populate the fields of the newsk from the oldsk and migrate the assoc | 5677 | /* Populate the fields of the newsk from the oldsk and migrate the assoc |
5642 | * and its messages to the newsk. | 5678 | * and its messages to the newsk. |
5643 | */ | 5679 | */ |
@@ -5692,10 +5728,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
5692 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { | 5728 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { |
5693 | event = sctp_skb2event(skb); | 5729 | event = sctp_skb2event(skb); |
5694 | if (event->asoc == assoc) { | 5730 | if (event->asoc == assoc) { |
5695 | sctp_sock_rfree(skb); | 5731 | sctp_sock_rfree_frag(skb); |
5696 | __skb_unlink(skb, &oldsk->sk_receive_queue); | 5732 | __skb_unlink(skb, &oldsk->sk_receive_queue); |
5697 | __skb_queue_tail(&newsk->sk_receive_queue, skb); | 5733 | __skb_queue_tail(&newsk->sk_receive_queue, skb); |
5698 | sctp_skb_set_owner_r(skb, newsk); | 5734 | sctp_skb_set_owner_r_frag(skb, newsk); |
5699 | } | 5735 | } |
5700 | } | 5736 | } |
5701 | 5737 | ||
@@ -5723,10 +5759,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
5723 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { | 5759 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { |
5724 | event = sctp_skb2event(skb); | 5760 | event = sctp_skb2event(skb); |
5725 | if (event->asoc == assoc) { | 5761 | if (event->asoc == assoc) { |
5726 | sctp_sock_rfree(skb); | 5762 | sctp_sock_rfree_frag(skb); |
5727 | __skb_unlink(skb, &oldsp->pd_lobby); | 5763 | __skb_unlink(skb, &oldsp->pd_lobby); |
5728 | __skb_queue_tail(queue, skb); | 5764 | __skb_queue_tail(queue, skb); |
5729 | sctp_skb_set_owner_r(skb, newsk); | 5765 | sctp_skb_set_owner_r_frag(skb, newsk); |
5730 | } | 5766 | } |
5731 | } | 5767 | } |
5732 | 5768 | ||
@@ -5738,6 +5774,16 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
5738 | 5774 | ||
5739 | } | 5775 | } |
5740 | 5776 | ||
5777 | sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) { | ||
5778 | sctp_sock_rfree_frag(skb); | ||
5779 | sctp_skb_set_owner_r_frag(skb, newsk); | ||
5780 | } | ||
5781 | |||
5782 | sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) { | ||
5783 | sctp_sock_rfree_frag(skb); | ||
5784 | sctp_skb_set_owner_r_frag(skb, newsk); | ||
5785 | } | ||
5786 | |||
5741 | /* Set the type of socket to indicate that it is peeled off from the | 5787 | /* Set the type of socket to indicate that it is peeled off from the |
5742 | * original UDP-style socket or created with the accept() call on a | 5788 | * original UDP-style socket or created with the accept() call on a |
5743 | * TCP-style socket.. | 5789 | * TCP-style socket.. |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index a596f5308cb1..4d8c2ab864fc 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -526,3 +526,35 @@ unsigned long sctp_transport_timeout(struct sctp_transport *t) | |||
526 | timeout += jiffies; | 526 | timeout += jiffies; |
527 | return timeout; | 527 | return timeout; |
528 | } | 528 | } |
529 | |||
530 | /* Reset transport variables to their initial values */ | ||
531 | void sctp_transport_reset(struct sctp_transport *t) | ||
532 | { | ||
533 | struct sctp_association *asoc = t->asoc; | ||
534 | |||
535 | /* RFC 2960 (bis), Section 5.2.4 | ||
536 | * All the congestion control parameters (e.g., cwnd, ssthresh) | ||
537 | * related to this peer MUST be reset to their initial values | ||
538 | * (see Section 6.2.1) | ||
539 | */ | ||
540 | t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); | ||
541 | t->ssthresh = asoc->peer.i.a_rwnd; | ||
542 | t->rto = asoc->rto_initial; | ||
543 | t->rtt = 0; | ||
544 | t->srtt = 0; | ||
545 | t->rttvar = 0; | ||
546 | |||
547 | /* Reset these additional varibles so that we have a clean | ||
548 | * slate. | ||
549 | */ | ||
550 | t->partial_bytes_acked = 0; | ||
551 | t->flight_size = 0; | ||
552 | t->error_count = 0; | ||
553 | t->rto_pending = 0; | ||
554 | |||
555 | /* Initialize the state information for SFR-CACC */ | ||
556 | t->cacc.changeover_active = 0; | ||
557 | t->cacc.cycling_changeover = 0; | ||
558 | t->cacc.next_tsn_at_change = 0; | ||
559 | t->cacc.cacc_saw_newack = 0; | ||
560 | } | ||
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index f4759a9bdaee..b29e3e4b72c9 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -73,7 +73,7 @@ struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq, | |||
73 | 73 | ||
74 | 74 | ||
75 | /* Flush the reassembly and ordering queues. */ | 75 | /* Flush the reassembly and ordering queues. */ |
76 | static void sctp_ulpq_flush(struct sctp_ulpq *ulpq) | 76 | void sctp_ulpq_flush(struct sctp_ulpq *ulpq) |
77 | { | 77 | { |
78 | struct sk_buff *skb; | 78 | struct sk_buff *skb; |
79 | struct sctp_ulpevent *event; | 79 | struct sctp_ulpevent *event; |
@@ -190,7 +190,14 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) | |||
190 | if (!sctp_sk(sk)->pd_mode) { | 190 | if (!sctp_sk(sk)->pd_mode) { |
191 | queue = &sk->sk_receive_queue; | 191 | queue = &sk->sk_receive_queue; |
192 | } else if (ulpq->pd_mode) { | 192 | } else if (ulpq->pd_mode) { |
193 | if (event->msg_flags & MSG_NOTIFICATION) | 193 | /* If the association is in partial delivery, we |
194 | * need to finish delivering the partially processed | ||
195 | * packet before passing any other data. This is | ||
196 | * because we don't truly support stream interleaving. | ||
197 | */ | ||
198 | if ((event->msg_flags & MSG_NOTIFICATION) || | ||
199 | (SCTP_DATA_NOT_FRAG == | ||
200 | (event->msg_flags & SCTP_DATA_FRAG_MASK))) | ||
194 | queue = &sctp_sk(sk)->pd_lobby; | 201 | queue = &sctp_sk(sk)->pd_lobby; |
195 | else { | 202 | else { |
196 | clear_pd = event->msg_flags & MSG_EOR; | 203 | clear_pd = event->msg_flags & MSG_EOR; |
diff --git a/net/socket.c b/net/socket.c index 9566e57ac7f5..ea8f81abc45c 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -1381,7 +1381,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, | |||
1381 | 1381 | ||
1382 | err = sock_attach_fd(newsock, newfile); | 1382 | err = sock_attach_fd(newsock, newfile); |
1383 | if (err < 0) | 1383 | if (err < 0) |
1384 | goto out_fd; | 1384 | goto out_fd_simple; |
1385 | 1385 | ||
1386 | err = security_socket_accept(sock, newsock); | 1386 | err = security_socket_accept(sock, newsock); |
1387 | if (err) | 1387 | if (err) |
@@ -1414,6 +1414,11 @@ out_put: | |||
1414 | fput_light(sock->file, fput_needed); | 1414 | fput_light(sock->file, fput_needed); |
1415 | out: | 1415 | out: |
1416 | return err; | 1416 | return err; |
1417 | out_fd_simple: | ||
1418 | sock_release(newsock); | ||
1419 | put_filp(newfile); | ||
1420 | put_unused_fd(newfd); | ||
1421 | goto out_put; | ||
1417 | out_fd: | 1422 | out_fd: |
1418 | fput(newfile); | 1423 | fput(newfile); |
1419 | put_unused_fd(newfd); | 1424 | put_unused_fd(newfd); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 6d7221fe990a..396cdbe249d1 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -1046,6 +1046,8 @@ call_status(struct rpc_task *task) | |||
1046 | rpc_delay(task, 3*HZ); | 1046 | rpc_delay(task, 3*HZ); |
1047 | case -ETIMEDOUT: | 1047 | case -ETIMEDOUT: |
1048 | task->tk_action = call_timeout; | 1048 | task->tk_action = call_timeout; |
1049 | if (task->tk_client->cl_discrtry) | ||
1050 | xprt_disconnect(task->tk_xprt); | ||
1049 | break; | 1051 | break; |
1050 | case -ECONNREFUSED: | 1052 | case -ECONNREFUSED: |
1051 | case -ENOTCONN: | 1053 | case -ENOTCONN: |
@@ -1169,6 +1171,8 @@ call_decode(struct rpc_task *task) | |||
1169 | out_retry: | 1171 | out_retry: |
1170 | req->rq_received = req->rq_private_buf.len = 0; | 1172 | req->rq_received = req->rq_private_buf.len = 0; |
1171 | task->tk_status = 0; | 1173 | task->tk_status = 0; |
1174 | if (task->tk_client->cl_discrtry) | ||
1175 | xprt_disconnect(task->tk_xprt); | ||
1172 | } | 1176 | } |
1173 | 1177 | ||
1174 | /* | 1178 | /* |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 9bae4090254c..2bd23ea2aa8b 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -383,7 +383,10 @@ void svcauth_unix_purge(void) | |||
383 | static inline struct ip_map * | 383 | static inline struct ip_map * |
384 | ip_map_cached_get(struct svc_rqst *rqstp) | 384 | ip_map_cached_get(struct svc_rqst *rqstp) |
385 | { | 385 | { |
386 | struct ip_map *ipm = rqstp->rq_sock->sk_info_authunix; | 386 | struct ip_map *ipm; |
387 | struct svc_sock *svsk = rqstp->rq_sock; | ||
388 | spin_lock_bh(&svsk->sk_defer_lock); | ||
389 | ipm = svsk->sk_info_authunix; | ||
387 | if (ipm != NULL) { | 390 | if (ipm != NULL) { |
388 | if (!cache_valid(&ipm->h)) { | 391 | if (!cache_valid(&ipm->h)) { |
389 | /* | 392 | /* |
@@ -391,12 +394,14 @@ ip_map_cached_get(struct svc_rqst *rqstp) | |||
391 | * remembered, e.g. by a second mount from the | 394 | * remembered, e.g. by a second mount from the |
392 | * same IP address. | 395 | * same IP address. |
393 | */ | 396 | */ |
394 | rqstp->rq_sock->sk_info_authunix = NULL; | 397 | svsk->sk_info_authunix = NULL; |
398 | spin_unlock_bh(&svsk->sk_defer_lock); | ||
395 | cache_put(&ipm->h, &ip_map_cache); | 399 | cache_put(&ipm->h, &ip_map_cache); |
396 | return NULL; | 400 | return NULL; |
397 | } | 401 | } |
398 | cache_get(&ipm->h); | 402 | cache_get(&ipm->h); |
399 | } | 403 | } |
404 | spin_unlock_bh(&svsk->sk_defer_lock); | ||
400 | return ipm; | 405 | return ipm; |
401 | } | 406 | } |
402 | 407 | ||
@@ -405,9 +410,15 @@ ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm) | |||
405 | { | 410 | { |
406 | struct svc_sock *svsk = rqstp->rq_sock; | 411 | struct svc_sock *svsk = rqstp->rq_sock; |
407 | 412 | ||
408 | if (svsk->sk_sock->type == SOCK_STREAM && svsk->sk_info_authunix == NULL) | 413 | spin_lock_bh(&svsk->sk_defer_lock); |
409 | svsk->sk_info_authunix = ipm; /* newly cached, keep the reference */ | 414 | if (svsk->sk_sock->type == SOCK_STREAM && |
410 | else | 415 | svsk->sk_info_authunix == NULL) { |
416 | /* newly cached, keep the reference */ | ||
417 | svsk->sk_info_authunix = ipm; | ||
418 | ipm = NULL; | ||
419 | } | ||
420 | spin_unlock_bh(&svsk->sk_defer_lock); | ||
421 | if (ipm) | ||
411 | cache_put(&ipm->h, &ip_map_cache); | 422 | cache_put(&ipm->h, &ip_map_cache); |
412 | } | 423 | } |
413 | 424 | ||
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index f6e1eb1ea720..2772fee93881 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -452,6 +452,8 @@ union svc_pktinfo_u { | |||
452 | struct in_pktinfo pkti; | 452 | struct in_pktinfo pkti; |
453 | struct in6_pktinfo pkti6; | 453 | struct in6_pktinfo pkti6; |
454 | }; | 454 | }; |
455 | #define SVC_PKTINFO_SPACE \ | ||
456 | CMSG_SPACE(sizeof(union svc_pktinfo_u)) | ||
455 | 457 | ||
456 | static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) | 458 | static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) |
457 | { | 459 | { |
@@ -491,8 +493,11 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) | |||
491 | struct svc_sock *svsk = rqstp->rq_sock; | 493 | struct svc_sock *svsk = rqstp->rq_sock; |
492 | struct socket *sock = svsk->sk_sock; | 494 | struct socket *sock = svsk->sk_sock; |
493 | int slen; | 495 | int slen; |
494 | char buffer[CMSG_SPACE(sizeof(union svc_pktinfo_u))]; | 496 | union { |
495 | struct cmsghdr *cmh = (struct cmsghdr *)buffer; | 497 | struct cmsghdr hdr; |
498 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; | ||
499 | } buffer; | ||
500 | struct cmsghdr *cmh = &buffer.hdr; | ||
496 | int len = 0; | 501 | int len = 0; |
497 | int result; | 502 | int result; |
498 | int size; | 503 | int size; |
@@ -745,8 +750,11 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
745 | struct svc_sock *svsk = rqstp->rq_sock; | 750 | struct svc_sock *svsk = rqstp->rq_sock; |
746 | struct svc_serv *serv = svsk->sk_server; | 751 | struct svc_serv *serv = svsk->sk_server; |
747 | struct sk_buff *skb; | 752 | struct sk_buff *skb; |
748 | char buffer[CMSG_SPACE(sizeof(union svc_pktinfo_u))]; | 753 | union { |
749 | struct cmsghdr *cmh = (struct cmsghdr *)buffer; | 754 | struct cmsghdr hdr; |
755 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; | ||
756 | } buffer; | ||
757 | struct cmsghdr *cmh = &buffer.hdr; | ||
750 | int err, len; | 758 | int err, len; |
751 | struct msghdr msg = { | 759 | struct msghdr msg = { |
752 | .msg_name = svc_addr(rqstp), | 760 | .msg_name = svc_addr(rqstp), |
@@ -779,8 +787,8 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
779 | } | 787 | } |
780 | 788 | ||
781 | clear_bit(SK_DATA, &svsk->sk_flags); | 789 | clear_bit(SK_DATA, &svsk->sk_flags); |
782 | while ((err == kernel_recvmsg(svsk->sk_sock, &msg, NULL, | 790 | while ((err = kernel_recvmsg(svsk->sk_sock, &msg, NULL, |
783 | 0, 0, MSG_PEEK | MSG_DONTWAIT)) < 0 || | 791 | 0, 0, MSG_PEEK | MSG_DONTWAIT)) < 0 || |
784 | (skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) { | 792 | (skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) { |
785 | if (err == -EAGAIN) { | 793 | if (err == -EAGAIN) { |
786 | svc_sock_received(svsk); | 794 | svc_sock_received(svsk); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index ee6ffa01dfb1..456a14510308 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -735,16 +735,6 @@ void xprt_transmit(struct rpc_task *task) | |||
735 | xprt_reset_majortimeo(req); | 735 | xprt_reset_majortimeo(req); |
736 | /* Turn off autodisconnect */ | 736 | /* Turn off autodisconnect */ |
737 | del_singleshot_timer_sync(&xprt->timer); | 737 | del_singleshot_timer_sync(&xprt->timer); |
738 | } else { | ||
739 | /* If all request bytes have been sent, | ||
740 | * then we must be retransmitting this one */ | ||
741 | if (!req->rq_bytes_sent) { | ||
742 | if (task->tk_client->cl_discrtry) { | ||
743 | xprt_disconnect(xprt); | ||
744 | task->tk_status = -ENOTCONN; | ||
745 | return; | ||
746 | } | ||
747 | } | ||
748 | } | 738 | } |
749 | } else if (!req->rq_bytes_sent) | 739 | } else if (!req->rq_bytes_sent) |
750 | return; | 740 | return; |
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c deleted file mode 100644 index 41d7e32be70d..000000000000 --- a/net/wanrouter/af_wanpipe.c +++ /dev/null | |||
@@ -1,2600 +0,0 @@ | |||
1 | /***************************************************************************** | ||
2 | * af_wanpipe.c WANPIPE(tm) Secure Socket Layer. | ||
3 | * | ||
4 | * Author: Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * | ||
6 | * Copyright: (c) 2000 Sangoma Technologies Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * ============================================================================ | ||
13 | * Due Credit: | ||
14 | * Wanpipe socket layer is based on Packet and | ||
15 | * the X25 socket layers. The above sockets were | ||
16 | * used for the specific use of Sangoma Technologies | ||
17 | * API programs. | ||
18 | * Packet socket Authors: Ross Biro, Fred N. van Kempen and | ||
19 | * Alan Cox. | ||
20 | * X25 socket Author: Jonathan Naylor. | ||
21 | * ============================================================================ | ||
22 | * Mar 15, 2002 Arnaldo C. Melo o Use wp_sk()->num, as it isnt anymore in sock | ||
23 | * Apr 25, 2000 Nenad Corbic o Added the ability to send zero length packets. | ||
24 | * Mar 13, 2000 Nenad Corbic o Added a tx buffer check via ioctl call. | ||
25 | * Mar 06, 2000 Nenad Corbic o Fixed the corrupt sock lcn problem. | ||
26 | * Server and client application can run | ||
27 | * simultaneously without conflicts. | ||
28 | * Feb 29, 2000 Nenad Corbic o Added support for PVC protocols, such as | ||
29 | * CHDLC, Frame Relay and HDLC API. | ||
30 | * Jan 17, 2000 Nenad Corbic o Initial version, based on AF_PACKET socket. | ||
31 | * X25API support only. | ||
32 | * | ||
33 | ******************************************************************************/ | ||
34 | |||
35 | #include <linux/types.h> | ||
36 | #include <linux/sched.h> | ||
37 | #include <linux/mm.h> | ||
38 | #include <linux/capability.h> | ||
39 | #include <linux/fcntl.h> | ||
40 | #include <linux/socket.h> | ||
41 | #include <linux/in.h> | ||
42 | #include <linux/inet.h> | ||
43 | #include <linux/netdevice.h> | ||
44 | #include <linux/poll.h> | ||
45 | #include <linux/wireless.h> | ||
46 | #include <linux/kmod.h> | ||
47 | #include <net/ip.h> | ||
48 | #include <net/protocol.h> | ||
49 | #include <linux/skbuff.h> | ||
50 | #include <net/sock.h> | ||
51 | #include <linux/errno.h> | ||
52 | #include <linux/timer.h> | ||
53 | #include <asm/system.h> | ||
54 | #include <asm/uaccess.h> | ||
55 | #include <linux/module.h> | ||
56 | #include <linux/init.h> | ||
57 | #include <linux/if_wanpipe.h> | ||
58 | #include <linux/pkt_sched.h> | ||
59 | #include <linux/tcp_states.h> | ||
60 | #include <linux/if_wanpipe_common.h> | ||
61 | |||
62 | #ifdef CONFIG_INET | ||
63 | #include <net/inet_common.h> | ||
64 | #endif | ||
65 | |||
66 | #define SLOW_BACKOFF 0.1*HZ | ||
67 | #define FAST_BACKOFF 0.01*HZ | ||
68 | |||
69 | //#define PRINT_DEBUG | ||
70 | #ifdef PRINT_DEBUG | ||
71 | #define DBG_PRINTK(format, a...) printk(format, ## a) | ||
72 | #else | ||
73 | #define DBG_PRINTK(format, a...) | ||
74 | #endif | ||
75 | |||
76 | |||
77 | /* SECURE SOCKET IMPLEMENTATION | ||
78 | * | ||
79 | * TRANSMIT: | ||
80 | * | ||
81 | * When the user sends a packet via send() system call | ||
82 | * the wanpipe_sendmsg() function is executed. | ||
83 | * | ||
84 | * Each packet is enqueud into sk->sk_write_queue transmit | ||
85 | * queue. When the packet is enqueued, a delayed transmit | ||
86 | * timer is triggerd which acts as a Bottom Half hander. | ||
87 | * | ||
88 | * wanpipe_delay_transmit() function (BH), dequeues packets | ||
89 | * from the sk->sk_write_queue transmit queue and sends it | ||
90 | * to the deriver via dev->hard_start_xmit(skb, dev) function. | ||
91 | * Note, this function is actual a function pointer of if_send() | ||
92 | * routine in the wanpipe driver. | ||
93 | * | ||
94 | * X25API GUARANTEED DELIVERY: | ||
95 | * | ||
96 | * In order to provide 100% guaranteed packet delivery, | ||
97 | * an atomic 'packet_sent' counter is implemented. Counter | ||
98 | * is incremented for each packet enqueued | ||
99 | * into sk->sk_write_queue. Counter is decremented each | ||
100 | * time wanpipe_delayed_transmit() function successfuly | ||
101 | * passes the packet to the driver. Before each send(), a poll | ||
102 | * routine checks the sock resources The maximum value of | ||
103 | * packet sent counter is 1, thus if one packet is queued, the | ||
104 | * application will block until that packet is passed to the | ||
105 | * driver. | ||
106 | * | ||
107 | * RECEIVE: | ||
108 | * | ||
109 | * Wanpipe device drivers call the socket bottom half | ||
110 | * function, wanpipe_rcv() to queue the incoming packets | ||
111 | * into an AF_WANPIPE socket queue. Based on wanpipe_rcv() | ||
112 | * return code, the driver knows whether the packet was | ||
113 | * successfully queued. If the socket queue is full, | ||
114 | * protocol flow control is used by the driver, if any, | ||
115 | * to slow down the traffic until the sock queue is free. | ||
116 | * | ||
117 | * Every time a packet arrives into a socket queue the | ||
118 | * socket wakes up processes which are waiting to receive | ||
119 | * data. | ||
120 | * | ||
121 | * If the socket queue is full, the driver sets a block | ||
122 | * bit which signals the socket to kick the wanpipe driver | ||
123 | * bottom half hander when the socket queue is partialy | ||
124 | * empty. wanpipe_recvmsg() function performs this action. | ||
125 | * | ||
126 | * In case of x25api, packets will never be dropped, since | ||
127 | * flow control is available. | ||
128 | * | ||
129 | * In case of streaming protocols like CHDLC, packets will | ||
130 | * be dropped but the statistics will be generated. | ||
131 | */ | ||
132 | |||
133 | |||
134 | /* The code below is used to test memory leaks. It prints out | ||
135 | * a message every time kmalloc and kfree system calls get executed. | ||
136 | * If the calls match there is no leak :) | ||
137 | */ | ||
138 | |||
139 | /***********FOR DEBUGGING PURPOSES********************************************* | ||
140 | #define KMEM_SAFETYZONE 8 | ||
141 | |||
142 | static void * dbg_kmalloc(unsigned int size, int prio, int line) { | ||
143 | void * v = kmalloc(size,prio); | ||
144 | printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v); | ||
145 | return v; | ||
146 | } | ||
147 | static void dbg_kfree(void * v, int line) { | ||
148 | printk(KERN_INFO "line %d kfree(%p)\n",line,v); | ||
149 | kfree(v); | ||
150 | } | ||
151 | |||
152 | #define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__) | ||
153 | #define kfree(x) dbg_kfree(x,__LINE__) | ||
154 | ******************************************************************************/ | ||
155 | |||
156 | |||
157 | /* List of all wanpipe sockets. */ | ||
158 | HLIST_HEAD(wanpipe_sklist); | ||
159 | static DEFINE_RWLOCK(wanpipe_sklist_lock); | ||
160 | |||
161 | atomic_t wanpipe_socks_nr; | ||
162 | static unsigned long wanpipe_tx_critical; | ||
163 | |||
164 | #if 0 | ||
165 | /* Private wanpipe socket structures. */ | ||
166 | struct wanpipe_opt | ||
167 | { | ||
168 | void *mbox; /* Mail box */ | ||
169 | void *card; /* Card bouded to */ | ||
170 | struct net_device *dev; /* Bounded device */ | ||
171 | unsigned short lcn; /* Binded LCN */ | ||
172 | unsigned char svc; /* 0=pvc, 1=svc */ | ||
173 | unsigned char timer; /* flag for delayed transmit*/ | ||
174 | struct timer_list tx_timer; | ||
175 | unsigned poll_cnt; | ||
176 | unsigned char force; /* Used to force sock release */ | ||
177 | atomic_t packet_sent; | ||
178 | }; | ||
179 | #endif | ||
180 | |||
181 | static int sk_count; | ||
182 | extern const struct proto_ops wanpipe_ops; | ||
183 | static unsigned long find_free_critical; | ||
184 | |||
185 | static void wanpipe_unlink_driver(struct sock *sk); | ||
186 | static void wanpipe_link_driver(struct net_device *dev, struct sock *sk); | ||
187 | static void wanpipe_wakeup_driver(struct sock *sk); | ||
188 | static int execute_command(struct sock *, unsigned char, unsigned int); | ||
189 | static int check_dev(struct net_device *dev, sdla_t *card); | ||
190 | struct net_device *wanpipe_find_free_dev(sdla_t *card); | ||
191 | static void wanpipe_unlink_card (struct sock *); | ||
192 | static int wanpipe_link_card (struct sock *); | ||
193 | static struct sock *wanpipe_make_new(struct sock *); | ||
194 | static struct sock *wanpipe_alloc_socket(void); | ||
195 | static inline int get_atomic_device(struct net_device *dev); | ||
196 | static int wanpipe_exec_cmd(struct sock *, int, unsigned int); | ||
197 | static int get_ioctl_cmd (struct sock *, void *); | ||
198 | static int set_ioctl_cmd (struct sock *, void *); | ||
199 | static void release_device(struct net_device *dev); | ||
200 | static void wanpipe_kill_sock_timer (unsigned long data); | ||
201 | static void wanpipe_kill_sock_irq (struct sock *); | ||
202 | static void wanpipe_kill_sock_accept (struct sock *); | ||
203 | static int wanpipe_do_bind(struct sock *sk, struct net_device *dev, | ||
204 | int protocol); | ||
205 | struct sock * get_newsk_from_skb (struct sk_buff *); | ||
206 | static int wanpipe_debug (struct sock *, void *); | ||
207 | static void wanpipe_delayed_transmit (unsigned long data); | ||
208 | static void release_driver(struct sock *); | ||
209 | static void start_cleanup_timer (struct sock *); | ||
210 | static void check_write_queue(struct sock *); | ||
211 | static int check_driver_busy (struct sock *); | ||
212 | |||
213 | /*============================================================ | ||
214 | * wanpipe_rcv | ||
215 | * | ||
216 | * Wanpipe socket bottom half handler. This function | ||
217 | * is called by the WANPIPE device drivers to queue a | ||
218 | * incoming packet into the socket receive queue. | ||
219 | * Once the packet is queued, all processes waiting to | ||
220 | * read are woken up. | ||
221 | * | ||
222 | * During socket bind, this function is bounded into | ||
223 | * WANPIPE driver private. | ||
224 | *===========================================================*/ | ||
225 | |||
226 | static int wanpipe_rcv(struct sk_buff *skb, struct net_device *dev, | ||
227 | struct sock *sk) | ||
228 | { | ||
229 | struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)skb->cb; | ||
230 | wanpipe_common_t *chan = dev->priv; | ||
231 | /* | ||
232 | * When we registered the protocol we saved the socket in the data | ||
233 | * field for just this event. | ||
234 | */ | ||
235 | |||
236 | skb->dev = dev; | ||
237 | |||
238 | sll->sll_family = AF_WANPIPE; | ||
239 | sll->sll_hatype = dev->type; | ||
240 | sll->sll_protocol = skb->protocol; | ||
241 | sll->sll_pkttype = skb->pkt_type; | ||
242 | sll->sll_ifindex = dev->ifindex; | ||
243 | sll->sll_halen = 0; | ||
244 | |||
245 | if (dev->hard_header_parse) | ||
246 | sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr); | ||
247 | |||
248 | /* | ||
249 | * WAN_PACKET_DATA : Data which should be passed up the receive queue. | ||
250 | * WAN_PACKET_ASYC : Asynchronous data like place call, which should | ||
251 | * be passed up the listening sock. | ||
252 | * WAN_PACKET_ERR : Asynchronous data like clear call or restart | ||
253 | * which should go into an error queue. | ||
254 | */ | ||
255 | switch (skb->pkt_type){ | ||
256 | |||
257 | case WAN_PACKET_DATA: | ||
258 | if (sock_queue_rcv_skb(sk,skb)<0){ | ||
259 | return -ENOMEM; | ||
260 | } | ||
261 | break; | ||
262 | case WAN_PACKET_CMD: | ||
263 | sk->sk_state = chan->state; | ||
264 | /* Bug fix: update Mar6. | ||
265 | * Do not set the sock lcn number here, since | ||
266 | * cmd is not guaranteed to be executed on the | ||
267 | * board, thus Lcn could be wrong */ | ||
268 | sk->sk_data_ready(sk, skb->len); | ||
269 | kfree_skb(skb); | ||
270 | break; | ||
271 | case WAN_PACKET_ERR: | ||
272 | sk->sk_state = chan->state; | ||
273 | if (sock_queue_err_skb(sk,skb)<0){ | ||
274 | return -ENOMEM; | ||
275 | } | ||
276 | break; | ||
277 | default: | ||
278 | printk(KERN_INFO "wansock: BH Illegal Packet Type Dropping\n"); | ||
279 | kfree_skb(skb); | ||
280 | break; | ||
281 | } | ||
282 | |||
283 | //?????????????????????? | ||
284 | // if (sk->sk_state == WANSOCK_DISCONNECTED){ | ||
285 | // if (sk->sk_zapped) { | ||
286 | // //printk(KERN_INFO "wansock: Disconnected, killing early\n"); | ||
287 | // wanpipe_unlink_driver(sk); | ||
288 | // sk->sk_bound_dev_if = 0; | ||
289 | // } | ||
290 | // } | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | /*============================================================ | ||
296 | * wanpipe_listen_rcv | ||
297 | * | ||
298 | * Wanpipe LISTEN socket bottom half handler. This function | ||
299 | * is called by the WANPIPE device drivers to queue an | ||
300 | * incoming call into the socket listening queue. | ||
301 | * Once the packet is queued, the waiting accept() process | ||
302 | * is woken up. | ||
303 | * | ||
304 | * During socket bind, this function is bounded into | ||
305 | * WANPIPE driver private. | ||
306 | * | ||
307 | * IMPORTANT NOTE: | ||
308 | * The accept call() is waiting for an skb packet | ||
309 | * which contains a pointer to a device structure. | ||
310 | * | ||
311 | * When we do a bind to a device structre, we | ||
312 | * bind a newly created socket into "chan->sk". Thus, | ||
313 | * when accept receives the skb packet, it will know | ||
314 | * from which dev it came form, and in turn it will know | ||
315 | * the address of the new sock. | ||
316 | * | ||
317 | * NOTE: This function gets called from driver ISR. | ||
318 | *===========================================================*/ | ||
319 | |||
320 | static int wanpipe_listen_rcv (struct sk_buff *skb, struct sock *sk) | ||
321 | { | ||
322 | wanpipe_opt *wp = wp_sk(sk), *newwp; | ||
323 | struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)skb->cb; | ||
324 | struct sock *newsk; | ||
325 | struct net_device *dev; | ||
326 | sdla_t *card; | ||
327 | mbox_cmd_t *mbox_ptr; | ||
328 | wanpipe_common_t *chan; | ||
329 | |||
330 | /* Find a free device, if none found, all svc's are busy | ||
331 | */ | ||
332 | |||
333 | card = (sdla_t*)wp->card; | ||
334 | if (!card){ | ||
335 | printk(KERN_INFO "wansock: LISTEN ERROR, No Card\n"); | ||
336 | return -ENODEV; | ||
337 | } | ||
338 | |||
339 | dev = wanpipe_find_free_dev(card); | ||
340 | if (!dev){ | ||
341 | printk(KERN_INFO "wansock: LISTEN ERROR, No Free Device\n"); | ||
342 | return -ENODEV; | ||
343 | } | ||
344 | |||
345 | chan=dev->priv; | ||
346 | chan->state = WANSOCK_CONNECTING; | ||
347 | |||
348 | /* Allocate a new sock, which accept will bind | ||
349 | * and pass up to the user | ||
350 | */ | ||
351 | if ((newsk = wanpipe_make_new(sk)) == NULL){ | ||
352 | release_device(dev); | ||
353 | return -ENOMEM; | ||
354 | } | ||
355 | |||
356 | |||
357 | /* Initialize the new sock structure | ||
358 | */ | ||
359 | newsk->sk_bound_dev_if = dev->ifindex; | ||
360 | newwp = wp_sk(newsk); | ||
361 | newwp->card = wp->card; | ||
362 | |||
363 | /* Insert the sock into the main wanpipe | ||
364 | * sock list. | ||
365 | */ | ||
366 | atomic_inc(&wanpipe_socks_nr); | ||
367 | |||
368 | /* Allocate and fill in the new Mail Box. Then | ||
369 | * bind the mail box to the sock. It will be | ||
370 | * used by the ioctl call to read call information | ||
371 | * and to execute commands. | ||
372 | */ | ||
373 | if ((mbox_ptr = kzalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL) { | ||
374 | wanpipe_kill_sock_irq (newsk); | ||
375 | release_device(dev); | ||
376 | return -ENOMEM; | ||
377 | } | ||
378 | memcpy(mbox_ptr,skb->data,skb->len); | ||
379 | |||
380 | /* Register the lcn on which incoming call came | ||
381 | * from. Thus, if we have to clear it, we know | ||
382 | * which lcn to clear | ||
383 | */ | ||
384 | |||
385 | newwp->lcn = mbox_ptr->cmd.lcn; | ||
386 | newwp->mbox = (void *)mbox_ptr; | ||
387 | |||
388 | DBG_PRINTK(KERN_INFO "NEWSOCK : Device %s, bind to lcn %i\n", | ||
389 | dev->name,mbox_ptr->cmd.lcn); | ||
390 | |||
391 | chan->lcn = mbox_ptr->cmd.lcn; | ||
392 | card->u.x.svc_to_dev_map[(chan->lcn%MAX_X25_LCN)] = dev; | ||
393 | |||
394 | sock_reset_flag(newsk, SOCK_ZAPPED); | ||
395 | newwp->num = htons(X25_PROT); | ||
396 | |||
397 | if (wanpipe_do_bind(newsk, dev, newwp->num)) { | ||
398 | wanpipe_kill_sock_irq (newsk); | ||
399 | release_device(dev); | ||
400 | return -EINVAL; | ||
401 | } | ||
402 | newsk->sk_state = WANSOCK_CONNECTING; | ||
403 | |||
404 | |||
405 | /* Fill in the standard sock address info */ | ||
406 | |||
407 | sll->sll_family = AF_WANPIPE; | ||
408 | sll->sll_hatype = dev->type; | ||
409 | sll->sll_protocol = skb->protocol; | ||
410 | sll->sll_pkttype = skb->pkt_type; | ||
411 | sll->sll_ifindex = dev->ifindex; | ||
412 | sll->sll_halen = 0; | ||
413 | |||
414 | skb->dev = dev; | ||
415 | sk->sk_ack_backlog++; | ||
416 | |||
417 | /* We must do this manually, since the sock_queue_rcv_skb() | ||
418 | * function sets the skb->dev to NULL. However, we use | ||
419 | * the dev field in the accept function.*/ | ||
420 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= | ||
421 | (unsigned)sk->sk_rcvbuf) { | ||
422 | |||
423 | wanpipe_unlink_driver(newsk); | ||
424 | wanpipe_kill_sock_irq (newsk); | ||
425 | --sk->sk_ack_backlog; | ||
426 | return -ENOMEM; | ||
427 | } | ||
428 | |||
429 | skb_set_owner_r(skb, sk); | ||
430 | skb_queue_tail(&sk->sk_receive_queue, skb); | ||
431 | sk->sk_data_ready(sk, skb->len); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | |||
437 | |||
438 | /*============================================================ | ||
439 | * wanpipe_make_new | ||
440 | * | ||
441 | * Create a new sock, and allocate a wanpipe private | ||
442 | * structure to it. Also, copy the important data | ||
443 | * from the original sock to the new sock. | ||
444 | * | ||
445 | * This function is used by wanpipe_listen_rcv() listen | ||
446 | * bottom half handler. A copy of the listening sock | ||
447 | * is created using this function. | ||
448 | * | ||
449 | *===========================================================*/ | ||
450 | |||
451 | static struct sock *wanpipe_make_new(struct sock *osk) | ||
452 | { | ||
453 | struct sock *sk; | ||
454 | |||
455 | if (osk->sk_type != SOCK_RAW) | ||
456 | return NULL; | ||
457 | |||
458 | if ((sk = wanpipe_alloc_socket()) == NULL) | ||
459 | return NULL; | ||
460 | |||
461 | sk->sk_type = osk->sk_type; | ||
462 | sk->sk_socket = osk->sk_socket; | ||
463 | sk->sk_priority = osk->sk_priority; | ||
464 | sk->sk_protocol = osk->sk_protocol; | ||
465 | wp_sk(sk)->num = wp_sk(osk)->num; | ||
466 | sk->sk_rcvbuf = osk->sk_rcvbuf; | ||
467 | sk->sk_sndbuf = osk->sk_sndbuf; | ||
468 | sk->sk_state = WANSOCK_CONNECTING; | ||
469 | sk->sk_sleep = osk->sk_sleep; | ||
470 | |||
471 | if (sock_flag(osk, SOCK_DBG)) | ||
472 | sock_set_flag(sk, SOCK_DBG); | ||
473 | |||
474 | return sk; | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * FIXME: wanpipe_opt has to include a sock in its definition and stop using | ||
479 | * sk_protinfo, but this code is not even compilable now, so lets leave it for | ||
480 | * later. | ||
481 | */ | ||
482 | static struct proto wanpipe_proto = { | ||
483 | .name = "WANPIPE", | ||
484 | .owner = THIS_MODULE, | ||
485 | .obj_size = sizeof(struct sock), | ||
486 | }; | ||
487 | |||
488 | /*============================================================ | ||
489 | * wanpipe_make_new | ||
490 | * | ||
491 | * Allocate memory for the a new sock, and sock | ||
492 | * private data. | ||
493 | * | ||
494 | * Increment the module use count. | ||
495 | * | ||
496 | * This function is used by wanpipe_create() and | ||
497 | * wanpipe_make_new() functions. | ||
498 | * | ||
499 | *===========================================================*/ | ||
500 | |||
501 | static struct sock *wanpipe_alloc_socket(void) | ||
502 | { | ||
503 | struct sock *sk; | ||
504 | struct wanpipe_opt *wan_opt; | ||
505 | |||
506 | if ((sk = sk_alloc(PF_WANPIPE, GFP_ATOMIC, &wanpipe_proto, 1)) == NULL) | ||
507 | return NULL; | ||
508 | |||
509 | if ((wan_opt = kzalloc(sizeof(struct wanpipe_opt), GFP_ATOMIC)) == NULL) { | ||
510 | sk_free(sk); | ||
511 | return NULL; | ||
512 | } | ||
513 | |||
514 | wp_sk(sk) = wan_opt; | ||
515 | |||
516 | /* Use timer to send data to the driver. This will act | ||
517 | * as a BH handler for sendmsg functions */ | ||
518 | init_timer(&wan_opt->tx_timer); | ||
519 | wan_opt->tx_timer.data = (unsigned long)sk; | ||
520 | wan_opt->tx_timer.function = wanpipe_delayed_transmit; | ||
521 | |||
522 | sock_init_data(NULL, sk); | ||
523 | return sk; | ||
524 | } | ||
525 | |||
526 | |||
527 | /*============================================================ | ||
528 | * wanpipe_sendmsg | ||
529 | * | ||
530 | * This function implements a sendto() system call, | ||
531 | * for AF_WANPIPE socket family. | ||
532 | * During socket bind() sk->sk_bound_dev_if is initialized | ||
533 | * to a correct network device. This number is used | ||
534 | * to find a network device to which the packet should | ||
535 | * be passed to. | ||
536 | * | ||
537 | * Each packet is queued into sk->sk_write_queue and | ||
538 | * delayed transmit bottom half handler is marked for | ||
539 | * execution. | ||
540 | * | ||
541 | * A socket must be in WANSOCK_CONNECTED state before | ||
542 | * a packet is queued into sk->sk_write_queue. | ||
543 | *===========================================================*/ | ||
544 | |||
545 | static int wanpipe_sendmsg(struct kiocb *iocb, struct socket *sock, | ||
546 | struct msghdr *msg, int len) | ||
547 | { | ||
548 | wanpipe_opt *wp; | ||
549 | struct sock *sk = sock->sk; | ||
550 | struct wan_sockaddr_ll *saddr=(struct wan_sockaddr_ll *)msg->msg_name; | ||
551 | struct sk_buff *skb; | ||
552 | struct net_device *dev; | ||
553 | unsigned short proto; | ||
554 | unsigned char *addr; | ||
555 | int ifindex, err, reserve = 0; | ||
556 | |||
557 | |||
558 | if (!sock_flag(sk, SOCK_ZAPPED)) | ||
559 | return -ENETDOWN; | ||
560 | |||
561 | if (sk->sk_state != WANSOCK_CONNECTED) | ||
562 | return -ENOTCONN; | ||
563 | |||
564 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) | ||
565 | return(-EINVAL); | ||
566 | |||
567 | /* it was <=, now one can send | ||
568 | * zero length packets */ | ||
569 | if (len < sizeof(x25api_hdr_t)) | ||
570 | return -EINVAL; | ||
571 | |||
572 | wp = wp_sk(sk); | ||
573 | |||
574 | if (saddr == NULL) { | ||
575 | ifindex = sk->sk_bound_dev_if; | ||
576 | proto = wp->num; | ||
577 | addr = NULL; | ||
578 | |||
579 | }else{ | ||
580 | if (msg->msg_namelen < sizeof(struct wan_sockaddr_ll)){ | ||
581 | return -EINVAL; | ||
582 | } | ||
583 | |||
584 | ifindex = sk->sk_bound_dev_if; | ||
585 | proto = saddr->sll_protocol; | ||
586 | addr = saddr->sll_addr; | ||
587 | } | ||
588 | |||
589 | dev = dev_get_by_index(ifindex); | ||
590 | if (dev == NULL){ | ||
591 | printk(KERN_INFO "wansock: Send failed, dev index: %i\n",ifindex); | ||
592 | return -ENXIO; | ||
593 | } | ||
594 | dev_put(dev); | ||
595 | |||
596 | if (sock->type == SOCK_RAW) | ||
597 | reserve = dev->hard_header_len; | ||
598 | |||
599 | if (len > dev->mtu+reserve){ | ||
600 | return -EMSGSIZE; | ||
601 | } | ||
602 | |||
603 | skb = sock_alloc_send_skb(sk, len + LL_RESERVED_SPACE(dev), | ||
604 | msg->msg_flags & MSG_DONTWAIT, &err); | ||
605 | |||
606 | if (skb==NULL){ | ||
607 | goto out_unlock; | ||
608 | } | ||
609 | |||
610 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | ||
611 | skb->nh.raw = skb->data; | ||
612 | |||
613 | /* Returns -EFAULT on error */ | ||
614 | err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); | ||
615 | if (err){ | ||
616 | goto out_free; | ||
617 | } | ||
618 | |||
619 | if (dev->hard_header) { | ||
620 | int res; | ||
621 | err = -EINVAL; | ||
622 | res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len); | ||
623 | if (res<0){ | ||
624 | goto out_free; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | skb->protocol = proto; | ||
629 | skb->dev = dev; | ||
630 | skb->priority = sk->sk_priority; | ||
631 | skb->pkt_type = WAN_PACKET_DATA; | ||
632 | |||
633 | err = -ENETDOWN; | ||
634 | if (!(dev->flags & IFF_UP)) | ||
635 | goto out_free; | ||
636 | |||
637 | if (atomic_read(&sk->sk_wmem_alloc) + skb->truesize > | ||
638 | (unsigned int)sk->sk_sndbuf){ | ||
639 | kfree_skb(skb); | ||
640 | return -ENOBUFS; | ||
641 | } | ||
642 | |||
643 | skb_queue_tail(&sk->sk_write_queue,skb); | ||
644 | atomic_inc(&wp->packet_sent); | ||
645 | |||
646 | if (!(test_and_set_bit(0, &wp->timer))) | ||
647 | mod_timer(&wp->tx_timer, jiffies + 1); | ||
648 | |||
649 | return(len); | ||
650 | |||
651 | out_free: | ||
652 | kfree_skb(skb); | ||
653 | out_unlock: | ||
654 | return err; | ||
655 | } | ||
656 | |||
657 | /*============================================================ | ||
658 | * wanpipe_delayed_tarnsmit | ||
659 | * | ||
660 | * Transmit bottom half handler. It dequeues packets | ||
661 | * from sk->sk_write_queue and passes them to the | ||
662 | * driver. If the driver is busy, the packet is | ||
663 | * re-enqueued. | ||
664 | * | ||
665 | * Packet Sent counter is decremented on successful | ||
666 | * transmission. | ||
667 | *===========================================================*/ | ||
668 | |||
669 | |||
670 | static void wanpipe_delayed_transmit (unsigned long data) | ||
671 | { | ||
672 | struct sock *sk=(struct sock *)data; | ||
673 | struct sk_buff *skb; | ||
674 | wanpipe_opt *wp = wp_sk(sk); | ||
675 | struct net_device *dev = wp->dev; | ||
676 | sdla_t *card = (sdla_t*)wp->card; | ||
677 | |||
678 | if (!card || !dev){ | ||
679 | clear_bit(0, &wp->timer); | ||
680 | DBG_PRINTK(KERN_INFO "wansock: Transmit delay, no dev or card\n"); | ||
681 | return; | ||
682 | } | ||
683 | |||
684 | if (sk->sk_state != WANSOCK_CONNECTED || !sock_flag(sk, SOCK_ZAPPED)) { | ||
685 | clear_bit(0, &wp->timer); | ||
686 | DBG_PRINTK(KERN_INFO "wansock: Tx Timer, State not CONNECTED\n"); | ||
687 | return; | ||
688 | } | ||
689 | |||
690 | /* If driver is executing command, we must offload | ||
691 | * the board by not sending data. Otherwise a | ||
692 | * pending command will never get a free buffer | ||
693 | * to execute */ | ||
694 | if (atomic_read(&card->u.x.command_busy)){ | ||
695 | wp->tx_timer.expires = jiffies + SLOW_BACKOFF; | ||
696 | add_timer(&wp->tx_timer); | ||
697 | DBG_PRINTK(KERN_INFO "wansock: Tx Timer, command bys BACKOFF\n"); | ||
698 | return; | ||
699 | } | ||
700 | |||
701 | |||
702 | if (test_and_set_bit(0,&wanpipe_tx_critical)){ | ||
703 | printk(KERN_INFO "WanSock: Tx timer critical %s\n",dev->name); | ||
704 | wp->tx_timer.expires = jiffies + SLOW_BACKOFF; | ||
705 | add_timer(&wp->tx_timer); | ||
706 | return; | ||
707 | } | ||
708 | |||
709 | /* Check for a packet in the fifo and send */ | ||
710 | if ((skb = skb_dequeue(&sk->sk_write_queue)) != NULL){ | ||
711 | |||
712 | if (dev->hard_start_xmit(skb, dev) != 0){ | ||
713 | |||
714 | /* Driver failed to transmit, re-enqueue | ||
715 | * the packet and retry again later */ | ||
716 | skb_queue_head(&sk->sk_write_queue,skb); | ||
717 | clear_bit(0,&wanpipe_tx_critical); | ||
718 | return; | ||
719 | }else{ | ||
720 | |||
721 | /* Packet Sent successful. Check for more packets | ||
722 | * if more packets, re-trigger the transmit routine | ||
723 | * other wise exit | ||
724 | */ | ||
725 | atomic_dec(&wp->packet_sent); | ||
726 | |||
727 | if (skb_peek(&sk->sk_write_queue) == NULL) { | ||
728 | /* If there is nothing to send, kick | ||
729 | * the poll routine, which will trigger | ||
730 | * the application to send more data */ | ||
731 | sk->sk_data_ready(sk, 0); | ||
732 | clear_bit(0, &wp->timer); | ||
733 | }else{ | ||
734 | /* Reschedule as fast as possible */ | ||
735 | wp->tx_timer.expires = jiffies + 1; | ||
736 | add_timer(&wp->tx_timer); | ||
737 | } | ||
738 | } | ||
739 | } | ||
740 | clear_bit(0,&wanpipe_tx_critical); | ||
741 | } | ||
742 | |||
743 | /*============================================================ | ||
744 | * execute_command | ||
745 | * | ||
746 | * Execute x25api commands. The atomic variable | ||
747 | * chan->command is used to indicate to the driver that | ||
748 | * command is pending for execution. The acutal command | ||
749 | * structure is placed into a sock mbox structure | ||
750 | * (wp_sk(sk)->mbox). | ||
751 | * | ||
752 | * The sock private structure, mbox is | ||
753 | * used as shared memory between sock and the driver. | ||
754 | * Driver uses the sock mbox to execute the command | ||
755 | * and return the result. | ||
756 | * | ||
757 | * For all command except PLACE CALL, the function | ||
758 | * waits for the result. PLACE CALL can be ether | ||
759 | * blocking or nonblocking. The user sets this option | ||
760 | * via ioctl call. | ||
761 | *===========================================================*/ | ||
762 | |||
763 | |||
764 | static int execute_command(struct sock *sk, unsigned char cmd, unsigned int flags) | ||
765 | { | ||
766 | wanpipe_opt *wp = wp_sk(sk); | ||
767 | struct net_device *dev; | ||
768 | wanpipe_common_t *chan=NULL; | ||
769 | int err=0; | ||
770 | DECLARE_WAITQUEUE(wait, current); | ||
771 | |||
772 | dev = dev_get_by_index(sk->sk_bound_dev_if); | ||
773 | if (dev == NULL){ | ||
774 | printk(KERN_INFO "wansock: Exec failed no dev %i\n", | ||
775 | sk->sk_bound_dev_if); | ||
776 | return -ENODEV; | ||
777 | } | ||
778 | dev_put(dev); | ||
779 | |||
780 | if ((chan=dev->priv) == NULL){ | ||
781 | printk(KERN_INFO "wansock: Exec cmd failed no priv area\n"); | ||
782 | return -ENODEV; | ||
783 | } | ||
784 | |||
785 | if (atomic_read(&chan->command)){ | ||
786 | printk(KERN_INFO "wansock: ERROR: Command already running %x, %s\n", | ||
787 | atomic_read(&chan->command),dev->name); | ||
788 | return -EINVAL; | ||
789 | } | ||
790 | |||
791 | if (!wp->mbox) { | ||
792 | printk(KERN_INFO "wansock: In execute without MBOX\n"); | ||
793 | return -EINVAL; | ||
794 | } | ||
795 | |||
796 | ((mbox_cmd_t*)wp->mbox)->cmd.command = cmd; | ||
797 | ((mbox_cmd_t*)wp->mbox)->cmd.lcn = wp->lcn; | ||
798 | ((mbox_cmd_t*)wp->mbox)->cmd.result = 0x7F; | ||
799 | |||
800 | |||
801 | if (flags & O_NONBLOCK){ | ||
802 | cmd |= 0x80; | ||
803 | atomic_set(&chan->command, cmd); | ||
804 | }else{ | ||
805 | atomic_set(&chan->command, cmd); | ||
806 | } | ||
807 | |||
808 | add_wait_queue(sk->sk_sleep,&wait); | ||
809 | current->state = TASK_INTERRUPTIBLE; | ||
810 | for (;;){ | ||
811 | if (((mbox_cmd_t*)wp->mbox)->cmd.result != 0x7F) { | ||
812 | err = 0; | ||
813 | break; | ||
814 | } | ||
815 | if (signal_pending(current)) { | ||
816 | err = -ERESTARTSYS; | ||
817 | break; | ||
818 | } | ||
819 | schedule(); | ||
820 | } | ||
821 | current->state = TASK_RUNNING; | ||
822 | remove_wait_queue(sk->sk_sleep,&wait); | ||
823 | |||
824 | return err; | ||
825 | } | ||
826 | |||
827 | /*============================================================ | ||
828 | * wanpipe_destroy_timer | ||
829 | * | ||
830 | * Used by wanpipe_release, to delay release of | ||
831 | * the socket. | ||
832 | *===========================================================*/ | ||
833 | |||
834 | static void wanpipe_destroy_timer(unsigned long data) | ||
835 | { | ||
836 | struct sock *sk=(struct sock *)data; | ||
837 | wanpipe_opt *wp = wp_sk(sk); | ||
838 | |||
839 | if ((!atomic_read(&sk->sk_wmem_alloc) && | ||
840 | !atomic_read(&sk->sk_rmem_alloc)) || | ||
841 | (++wp->force == 5)) { | ||
842 | |||
843 | if (atomic_read(&sk->sk_wmem_alloc) || | ||
844 | atomic_read(&sk->sk_rmem_alloc)) | ||
845 | printk(KERN_INFO "wansock: Warning, Packet Discarded due to sock shutdown!\n"); | ||
846 | |||
847 | kfree(wp); | ||
848 | wp_sk(sk) = NULL; | ||
849 | |||
850 | if (atomic_read(&sk->sk_refcnt) != 1) { | ||
851 | atomic_set(&sk->sk_refcnt, 1); | ||
852 | DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :delay.\n", | ||
853 | atomic_read(&sk->sk_refcnt)); | ||
854 | } | ||
855 | sock_put(sk); | ||
856 | atomic_dec(&wanpipe_socks_nr); | ||
857 | return; | ||
858 | } | ||
859 | |||
860 | sk->sk_timer.expires = jiffies + 5 * HZ; | ||
861 | add_timer(&sk->sk_timer); | ||
862 | printk(KERN_INFO "wansock: packet sk destroy delayed\n"); | ||
863 | } | ||
864 | |||
865 | /*============================================================ | ||
866 | * wanpipe_unlink_driver | ||
867 | * | ||
868 | * When the socket is released, this function is | ||
869 | * used to remove links that bind the sock and the | ||
870 | * driver together. | ||
871 | *===========================================================*/ | ||
872 | static void wanpipe_unlink_driver (struct sock *sk) | ||
873 | { | ||
874 | struct net_device *dev; | ||
875 | wanpipe_common_t *chan=NULL; | ||
876 | |||
877 | sock_reset_flag(sk, SOCK_ZAPPED); | ||
878 | sk->sk_state = WANSOCK_DISCONNECTED; | ||
879 | wp_sk(sk)->dev = NULL; | ||
880 | |||
881 | dev = dev_get_by_index(sk->sk_bound_dev_if); | ||
882 | if (!dev){ | ||
883 | printk(KERN_INFO "wansock: No dev on release\n"); | ||
884 | return; | ||
885 | } | ||
886 | dev_put(dev); | ||
887 | |||
888 | if ((chan = dev->priv) == NULL){ | ||
889 | printk(KERN_INFO "wansock: No Priv Area on release\n"); | ||
890 | return; | ||
891 | } | ||
892 | |||
893 | set_bit(0,&chan->common_critical); | ||
894 | chan->sk=NULL; | ||
895 | chan->func=NULL; | ||
896 | chan->mbox=NULL; | ||
897 | chan->tx_timer=NULL; | ||
898 | clear_bit(0,&chan->common_critical); | ||
899 | release_device(dev); | ||
900 | |||
901 | return; | ||
902 | } | ||
903 | |||
904 | /*============================================================ | ||
905 | * wanpipe_link_driver | ||
906 | * | ||
907 | * Upon successful bind(), sock is linked to a driver | ||
908 | * by binding in the wanpipe_rcv() bottom half handler | ||
909 | * to the driver function pointer, as well as sock and | ||
910 | * sock mailbox addresses. This way driver can pass | ||
911 | * data up the socket. | ||
912 | *===========================================================*/ | ||
913 | |||
914 | static void wanpipe_link_driver(struct net_device *dev, struct sock *sk) | ||
915 | { | ||
916 | wanpipe_opt *wp = wp_sk(sk); | ||
917 | wanpipe_common_t *chan = dev->priv; | ||
918 | if (!chan) | ||
919 | return; | ||
920 | set_bit(0,&chan->common_critical); | ||
921 | chan->sk=sk; | ||
922 | chan->func=wanpipe_rcv; | ||
923 | chan->mbox = wp->mbox; | ||
924 | chan->tx_timer = &wp->tx_timer; | ||
925 | wp->dev = dev; | ||
926 | sock_set_flag(sk, SOCK_ZAPPED); | ||
927 | clear_bit(0,&chan->common_critical); | ||
928 | } | ||
929 | |||
930 | |||
931 | /*============================================================ | ||
932 | * release_device | ||
933 | * | ||
934 | * During sock release, clear a critical bit, which | ||
935 | * marks the device a being taken. | ||
936 | *===========================================================*/ | ||
937 | |||
938 | |||
939 | static void release_device(struct net_device *dev) | ||
940 | { | ||
941 | wanpipe_common_t *chan=dev->priv; | ||
942 | clear_bit(0,(void*)&chan->rw_bind); | ||
943 | } | ||
944 | |||
945 | /*============================================================ | ||
946 | * wanpipe_release | ||
947 | * | ||
948 | * Close a PACKET socket. This is fairly simple. We | ||
949 | * immediately go to 'closed' state and remove our | ||
950 | * protocol entry in the device list. | ||
951 | *===========================================================*/ | ||
952 | |||
953 | static int wanpipe_release(struct socket *sock) | ||
954 | { | ||
955 | wanpipe_opt *wp; | ||
956 | struct sock *sk = sock->sk; | ||
957 | |||
958 | if (!sk) | ||
959 | return 0; | ||
960 | |||
961 | wp = wp_sk(sk); | ||
962 | check_write_queue(sk); | ||
963 | |||
964 | /* Kill the tx timer, if we don't kill it now, the timer | ||
965 | * will run after we kill the sock. Timer code will | ||
966 | * try to access the sock which has been killed and cause | ||
967 | * kernel panic */ | ||
968 | |||
969 | del_timer(&wp->tx_timer); | ||
970 | |||
971 | /* | ||
972 | * Unhook packet receive handler. | ||
973 | */ | ||
974 | |||
975 | if (wp->num == htons(X25_PROT) && | ||
976 | sk->sk_state != WANSOCK_DISCONNECTED && sock_flag(sk, SOCK_ZAPPED)) { | ||
977 | struct net_device *dev = dev_get_by_index(sk->sk_bound_dev_if); | ||
978 | wanpipe_common_t *chan; | ||
979 | if (dev){ | ||
980 | chan=dev->priv; | ||
981 | atomic_set(&chan->disconnect,1); | ||
982 | DBG_PRINTK(KERN_INFO "wansock: Sending Clear Indication %i\n", | ||
983 | sk->sk_state); | ||
984 | dev_put(dev); | ||
985 | } | ||
986 | } | ||
987 | |||
988 | set_bit(1,&wanpipe_tx_critical); | ||
989 | write_lock(&wanpipe_sklist_lock); | ||
990 | sk_del_node_init(sk); | ||
991 | write_unlock(&wanpipe_sklist_lock); | ||
992 | clear_bit(1,&wanpipe_tx_critical); | ||
993 | |||
994 | |||
995 | |||
996 | release_driver(sk); | ||
997 | |||
998 | |||
999 | /* | ||
1000 | * Now the socket is dead. No more input will appear. | ||
1001 | */ | ||
1002 | |||
1003 | sk->sk_state_change(sk); /* It is useless. Just for sanity. */ | ||
1004 | |||
1005 | sock->sk = NULL; | ||
1006 | sk->sk_socket = NULL; | ||
1007 | sock_set_flag(sk, SOCK_DEAD); | ||
1008 | |||
1009 | /* Purge queues */ | ||
1010 | skb_queue_purge(&sk->sk_receive_queue); | ||
1011 | skb_queue_purge(&sk->sk_write_queue); | ||
1012 | skb_queue_purge(&sk->sk_error_queue); | ||
1013 | |||
1014 | if (atomic_read(&sk->sk_rmem_alloc) || | ||
1015 | atomic_read(&sk->sk_wmem_alloc)) { | ||
1016 | del_timer(&sk->sk_timer); | ||
1017 | printk(KERN_INFO "wansock: Killing in Timer R %i , W %i\n", | ||
1018 | atomic_read(&sk->sk_rmem_alloc), | ||
1019 | atomic_read(&sk->sk_wmem_alloc)); | ||
1020 | sk->sk_timer.data = (unsigned long)sk; | ||
1021 | sk->sk_timer.expires = jiffies + HZ; | ||
1022 | sk->sk_timer.function = wanpipe_destroy_timer; | ||
1023 | add_timer(&sk->sk_timer); | ||
1024 | return 0; | ||
1025 | } | ||
1026 | |||
1027 | kfree(wp); | ||
1028 | wp_sk(sk) = NULL; | ||
1029 | |||
1030 | if (atomic_read(&sk->sk_refcnt) != 1) { | ||
1031 | DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:release.\n", | ||
1032 | atomic_read(&sk->sk_refcnt)); | ||
1033 | atomic_set(&sk->sk_refcnt, 1); | ||
1034 | } | ||
1035 | sock_put(sk); | ||
1036 | atomic_dec(&wanpipe_socks_nr); | ||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | /*============================================================ | ||
1041 | * check_write_queue | ||
1042 | * | ||
1043 | * During sock shutdown, if the sock state is | ||
1044 | * WANSOCK_CONNECTED and there is transmit data | ||
1045 | * pending. Wait until data is released | ||
1046 | * before proceeding. | ||
1047 | *===========================================================*/ | ||
1048 | |||
1049 | static void check_write_queue(struct sock *sk) | ||
1050 | { | ||
1051 | |||
1052 | if (sk->sk_state != WANSOCK_CONNECTED) | ||
1053 | return; | ||
1054 | |||
1055 | if (!atomic_read(&sk->sk_wmem_alloc)) | ||
1056 | return; | ||
1057 | |||
1058 | printk(KERN_INFO "wansock: MAJOR ERROR, Data lost on sock release !!!\n"); | ||
1059 | |||
1060 | } | ||
1061 | |||
1062 | /*============================================================ | ||
1063 | * release_driver | ||
1064 | * | ||
1065 | * This function is called during sock shutdown, to | ||
1066 | * release any resources and links that bind the sock | ||
1067 | * to the driver. It also changes the state of the | ||
1068 | * sock to WANSOCK_DISCONNECTED | ||
1069 | *===========================================================*/ | ||
1070 | |||
1071 | static void release_driver(struct sock *sk) | ||
1072 | { | ||
1073 | wanpipe_opt *wp; | ||
1074 | struct sk_buff *skb=NULL; | ||
1075 | struct sock *deadsk=NULL; | ||
1076 | |||
1077 | if (sk->sk_state == WANSOCK_LISTEN || | ||
1078 | sk->sk_state == WANSOCK_BIND_LISTEN) { | ||
1079 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { | ||
1080 | if ((deadsk = get_newsk_from_skb(skb))){ | ||
1081 | DBG_PRINTK (KERN_INFO "wansock: RELEASE: FOUND DEAD SOCK\n"); | ||
1082 | sock_set_flag(deadsk, SOCK_DEAD); | ||
1083 | start_cleanup_timer(deadsk); | ||
1084 | } | ||
1085 | kfree_skb(skb); | ||
1086 | } | ||
1087 | if (sock_flag(sk, SOCK_ZAPPED)) | ||
1088 | wanpipe_unlink_card(sk); | ||
1089 | }else{ | ||
1090 | if (sock_flag(sk, SOCK_ZAPPED)) | ||
1091 | wanpipe_unlink_driver(sk); | ||
1092 | } | ||
1093 | sk->sk_state = WANSOCK_DISCONNECTED; | ||
1094 | sk->sk_bound_dev_if = 0; | ||
1095 | sock_reset_flag(sk, SOCK_ZAPPED); | ||
1096 | wp = wp_sk(sk); | ||
1097 | |||
1098 | if (wp) { | ||
1099 | kfree(wp->mbox); | ||
1100 | wp->mbox = NULL; | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | /*============================================================ | ||
1105 | * start_cleanup_timer | ||
1106 | * | ||
1107 | * If new incoming call's are pending but the socket | ||
1108 | * is being released, start the timer which will | ||
1109 | * envoke the kill routines for pending socks. | ||
1110 | *===========================================================*/ | ||
1111 | |||
1112 | |||
1113 | static void start_cleanup_timer (struct sock *sk) | ||
1114 | { | ||
1115 | del_timer(&sk->sk_timer); | ||
1116 | sk->sk_timer.data = (unsigned long)sk; | ||
1117 | sk->sk_timer.expires = jiffies + HZ; | ||
1118 | sk->sk_timer.function = wanpipe_kill_sock_timer; | ||
1119 | add_timer(&sk->sk_timer); | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | /*============================================================ | ||
1124 | * wanpipe_kill_sock | ||
1125 | * | ||
1126 | * This is a function which performs actual killing | ||
1127 | * of the sock. It releases socket resources, | ||
1128 | * and unlinks the sock from the driver. | ||
1129 | *===========================================================*/ | ||
1130 | |||
1131 | static void wanpipe_kill_sock_timer (unsigned long data) | ||
1132 | { | ||
1133 | |||
1134 | struct sock *sk = (struct sock *)data; | ||
1135 | struct sock **skp; | ||
1136 | |||
1137 | if (!sk) | ||
1138 | return; | ||
1139 | |||
1140 | /* This function can be called from interrupt. We must use | ||
1141 | * appropriate locks */ | ||
1142 | |||
1143 | if (test_bit(1,&wanpipe_tx_critical)){ | ||
1144 | sk->sk_timer.expires = jiffies + 10; | ||
1145 | add_timer(&sk->sk_timer); | ||
1146 | return; | ||
1147 | } | ||
1148 | |||
1149 | write_lock(&wanpipe_sklist_lock); | ||
1150 | sk_del_node_init(sk); | ||
1151 | write_unlock(&wanpipe_sklist_lock); | ||
1152 | |||
1153 | |||
1154 | if (wp_sk(sk)->num == htons(X25_PROT) && | ||
1155 | sk->sk_state != WANSOCK_DISCONNECTED) { | ||
1156 | struct net_device *dev = dev_get_by_index(sk->sk_bound_dev_if); | ||
1157 | wanpipe_common_t *chan; | ||
1158 | if (dev){ | ||
1159 | chan=dev->priv; | ||
1160 | atomic_set(&chan->disconnect,1); | ||
1161 | dev_put(dev); | ||
1162 | } | ||
1163 | } | ||
1164 | |||
1165 | release_driver(sk); | ||
1166 | |||
1167 | sk->sk_socket = NULL; | ||
1168 | |||
1169 | /* Purge queues */ | ||
1170 | skb_queue_purge(&sk->sk_receive_queue); | ||
1171 | skb_queue_purge(&sk->sk_write_queue); | ||
1172 | skb_queue_purge(&sk->sk_error_queue); | ||
1173 | |||
1174 | if (atomic_read(&sk->sk_rmem_alloc) || | ||
1175 | atomic_read(&sk->sk_wmem_alloc)) { | ||
1176 | del_timer(&sk->sk_timer); | ||
1177 | printk(KERN_INFO "wansock: Killing SOCK in Timer\n"); | ||
1178 | sk->sk_timer.data = (unsigned long)sk; | ||
1179 | sk->sk_timer.expires = jiffies + HZ; | ||
1180 | sk->sk_timer.function = wanpipe_destroy_timer; | ||
1181 | add_timer(&sk->sk_timer); | ||
1182 | return; | ||
1183 | } | ||
1184 | |||
1185 | kfree(wp_sk(sk)); | ||
1186 | wp_sk(sk) = NULL; | ||
1187 | |||
1188 | if (atomic_read(&sk->sk_refcnt) != 1) { | ||
1189 | atomic_set(&sk->sk_refcnt, 1); | ||
1190 | DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n", | ||
1191 | atomic_read(&sk->sk_refcnt)); | ||
1192 | } | ||
1193 | sock_put(sk); | ||
1194 | atomic_dec(&wanpipe_socks_nr); | ||
1195 | return; | ||
1196 | } | ||
1197 | |||
1198 | static void wanpipe_kill_sock_accept (struct sock *sk) | ||
1199 | { | ||
1200 | |||
1201 | struct sock **skp; | ||
1202 | |||
1203 | if (!sk) | ||
1204 | return; | ||
1205 | |||
1206 | /* This function can be called from interrupt. We must use | ||
1207 | * appropriate locks */ | ||
1208 | |||
1209 | write_lock(&wanpipe_sklist_lock); | ||
1210 | sk_del_node_init(sk); | ||
1211 | write_unlock(&wanpipe_sklist_lock); | ||
1212 | |||
1213 | sk->sk_socket = NULL; | ||
1214 | |||
1215 | |||
1216 | kfree(wp_sk(sk)); | ||
1217 | wp_sk(sk) = NULL; | ||
1218 | |||
1219 | if (atomic_read(&sk->sk_refcnt) != 1) { | ||
1220 | atomic_set(&sk->sk_refcnt, 1); | ||
1221 | DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n", | ||
1222 | atomic_read(&sk->sk_refcnt)); | ||
1223 | } | ||
1224 | sock_put(sk); | ||
1225 | atomic_dec(&wanpipe_socks_nr); | ||
1226 | return; | ||
1227 | } | ||
1228 | |||
1229 | |||
1230 | static void wanpipe_kill_sock_irq (struct sock *sk) | ||
1231 | { | ||
1232 | |||
1233 | if (!sk) | ||
1234 | return; | ||
1235 | |||
1236 | sk->sk_socket = NULL; | ||
1237 | |||
1238 | kfree(wp_sk(sk)); | ||
1239 | wp_sk(sk) = NULL; | ||
1240 | |||
1241 | if (atomic_read(&sk->sk_refcnt) != 1) { | ||
1242 | atomic_set(&sk->sk_refcnt, 1); | ||
1243 | DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:listen.\n", | ||
1244 | atomic_read(&sk->sk_refcnt)); | ||
1245 | } | ||
1246 | sock_put(sk); | ||
1247 | atomic_dec(&wanpipe_socks_nr); | ||
1248 | } | ||
1249 | |||
1250 | |||
1251 | /*============================================================ | ||
1252 | * wanpipe_do_bind | ||
1253 | * | ||
1254 | * Bottom half of the binding system call. | ||
1255 | * Once the wanpipe_bind() function checks the | ||
1256 | * legality of the call, this function binds the | ||
1257 | * sock to the driver. | ||
1258 | *===========================================================*/ | ||
1259 | |||
1260 | static int wanpipe_do_bind(struct sock *sk, struct net_device *dev, | ||
1261 | int protocol) | ||
1262 | { | ||
1263 | wanpipe_opt *wp = wp_sk(sk); | ||
1264 | wanpipe_common_t *chan=NULL; | ||
1265 | int err=0; | ||
1266 | |||
1267 | if (sock_flag(sk, SOCK_ZAPPED)) { | ||
1268 | err = -EALREADY; | ||
1269 | goto bind_unlock_exit; | ||
1270 | } | ||
1271 | |||
1272 | wp->num = protocol; | ||
1273 | |||
1274 | if (protocol == 0){ | ||
1275 | release_device(dev); | ||
1276 | err = -EINVAL; | ||
1277 | goto bind_unlock_exit; | ||
1278 | } | ||
1279 | |||
1280 | if (dev) { | ||
1281 | if (dev->flags&IFF_UP) { | ||
1282 | chan=dev->priv; | ||
1283 | sk->sk_state = chan->state; | ||
1284 | |||
1285 | if (wp->num == htons(X25_PROT) && | ||
1286 | sk->sk_state != WANSOCK_DISCONNECTED && | ||
1287 | sk->sk_state != WANSOCK_CONNECTING) { | ||
1288 | DBG_PRINTK(KERN_INFO | ||
1289 | "wansock: Binding to Device not DISCONNECTED %i\n", | ||
1290 | sk->sk_state); | ||
1291 | release_device(dev); | ||
1292 | err = -EAGAIN; | ||
1293 | goto bind_unlock_exit; | ||
1294 | } | ||
1295 | |||
1296 | wanpipe_link_driver(dev,sk); | ||
1297 | sk->sk_bound_dev_if = dev->ifindex; | ||
1298 | |||
1299 | /* X25 Specific option */ | ||
1300 | if (wp->num == htons(X25_PROT)) | ||
1301 | wp_sk(sk)->svc = chan->svc; | ||
1302 | |||
1303 | } else { | ||
1304 | sk->sk_err = ENETDOWN; | ||
1305 | sk->sk_error_report(sk); | ||
1306 | release_device(dev); | ||
1307 | err = -EINVAL; | ||
1308 | } | ||
1309 | } else { | ||
1310 | err = -ENODEV; | ||
1311 | } | ||
1312 | bind_unlock_exit: | ||
1313 | /* FIXME where is this lock */ | ||
1314 | |||
1315 | return err; | ||
1316 | } | ||
1317 | |||
1318 | /*============================================================ | ||
1319 | * wanpipe_bind | ||
1320 | * | ||
1321 | * BIND() System call, which is bound to the AF_WANPIPE | ||
1322 | * operations structure. It checks for correct wanpipe | ||
1323 | * card name, and cross references interface names with | ||
1324 | * the card names. Thus, interface name must belong to | ||
1325 | * the actual card. | ||
1326 | *===========================================================*/ | ||
1327 | |||
1328 | |||
1329 | static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | ||
1330 | { | ||
1331 | struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)uaddr; | ||
1332 | struct sock *sk=sock->sk; | ||
1333 | wanpipe_opt *wp = wp_sk(sk); | ||
1334 | struct net_device *dev = NULL; | ||
1335 | sdla_t *card=NULL; | ||
1336 | char name[15]; | ||
1337 | |||
1338 | /* | ||
1339 | * Check legality | ||
1340 | */ | ||
1341 | |||
1342 | if (addr_len < sizeof(struct wan_sockaddr_ll)){ | ||
1343 | printk(KERN_INFO "wansock: Address length error\n"); | ||
1344 | return -EINVAL; | ||
1345 | } | ||
1346 | if (sll->sll_family != AF_WANPIPE){ | ||
1347 | printk(KERN_INFO "wansock: Illegal family name specified.\n"); | ||
1348 | return -EINVAL; | ||
1349 | } | ||
1350 | |||
1351 | card = wanpipe_find_card (sll->sll_card); | ||
1352 | if (!card){ | ||
1353 | printk(KERN_INFO "wansock: Wanpipe card not found: %s\n",sll->sll_card); | ||
1354 | return -ENODEV; | ||
1355 | }else{ | ||
1356 | wp_sk(sk)->card = (void *)card; | ||
1357 | } | ||
1358 | |||
1359 | if (!strcmp(sll->sll_device,"svc_listen")){ | ||
1360 | |||
1361 | /* Bind a sock to a card structure for listening | ||
1362 | */ | ||
1363 | int err=0; | ||
1364 | |||
1365 | /* This is x25 specific area if protocol doesn't | ||
1366 | * match, return error */ | ||
1367 | if (sll->sll_protocol != htons(X25_PROT)) | ||
1368 | return -EINVAL; | ||
1369 | |||
1370 | err= wanpipe_link_card (sk); | ||
1371 | if (err < 0) | ||
1372 | return err; | ||
1373 | |||
1374 | if (sll->sll_protocol) | ||
1375 | wp->num = sll->sll_protocol; | ||
1376 | sk->sk_state = WANSOCK_BIND_LISTEN; | ||
1377 | return 0; | ||
1378 | |||
1379 | }else if (!strcmp(sll->sll_device,"svc_connect")){ | ||
1380 | |||
1381 | /* This is x25 specific area if protocol doesn't | ||
1382 | * match, return error */ | ||
1383 | if (sll->sll_protocol != htons(X25_PROT)) | ||
1384 | return -EINVAL; | ||
1385 | |||
1386 | /* Find a free device | ||
1387 | */ | ||
1388 | dev = wanpipe_find_free_dev(card); | ||
1389 | if (dev == NULL){ | ||
1390 | DBG_PRINTK(KERN_INFO "wansock: No free network devices for card %s\n", | ||
1391 | card->devname); | ||
1392 | return -EINVAL; | ||
1393 | } | ||
1394 | }else{ | ||
1395 | /* Bind a socket to a interface name | ||
1396 | * This is used by PVC mostly | ||
1397 | */ | ||
1398 | strlcpy(name,sll->sll_device,sizeof(name)); | ||
1399 | dev = dev_get_by_name(name); | ||
1400 | if (dev == NULL){ | ||
1401 | printk(KERN_INFO "wansock: Failed to get Dev from name: %s,\n", | ||
1402 | name); | ||
1403 | return -ENODEV; | ||
1404 | } | ||
1405 | |||
1406 | dev_put(dev); | ||
1407 | |||
1408 | if (check_dev(dev, card)){ | ||
1409 | printk(KERN_INFO "wansock: Device %s, doesn't belong to card %s\n", | ||
1410 | dev->name, card->devname); | ||
1411 | return -EINVAL; | ||
1412 | } | ||
1413 | if (get_atomic_device (dev)) | ||
1414 | return -EINVAL; | ||
1415 | } | ||
1416 | |||
1417 | return wanpipe_do_bind(sk, dev, sll->sll_protocol ? : wp->num); | ||
1418 | } | ||
1419 | |||
1420 | /*============================================================ | ||
1421 | * get_atomic_device | ||
1422 | * | ||
1423 | * Sets a bit atomically which indicates that | ||
1424 | * the interface is taken. This avoids race conditions. | ||
1425 | *===========================================================*/ | ||
1426 | |||
1427 | |||
1428 | static inline int get_atomic_device(struct net_device *dev) | ||
1429 | { | ||
1430 | wanpipe_common_t *chan = dev->priv; | ||
1431 | if (!test_and_set_bit(0,(void *)&chan->rw_bind)){ | ||
1432 | return 0; | ||
1433 | } | ||
1434 | return 1; | ||
1435 | } | ||
1436 | |||
1437 | /*============================================================ | ||
1438 | * check_dev | ||
1439 | * | ||
1440 | * Check that device name belongs to a particular card. | ||
1441 | *===========================================================*/ | ||
1442 | |||
1443 | static int check_dev(struct net_device *dev, sdla_t *card) | ||
1444 | { | ||
1445 | struct net_device* tmp_dev; | ||
1446 | |||
1447 | for (tmp_dev = card->wandev.dev; tmp_dev; | ||
1448 | tmp_dev = *((struct net_device **)tmp_dev->priv)) { | ||
1449 | if (tmp_dev->ifindex == dev->ifindex){ | ||
1450 | return 0; | ||
1451 | } | ||
1452 | } | ||
1453 | return 1; | ||
1454 | } | ||
1455 | |||
1456 | /*============================================================ | ||
1457 | * wanpipe_find_free_dev | ||
1458 | * | ||
1459 | * Find a free network interface. If found set atomic | ||
1460 | * bit indicating that the interface is taken. | ||
1461 | * X25API Specific. | ||
1462 | *===========================================================*/ | ||
1463 | |||
1464 | struct net_device *wanpipe_find_free_dev(sdla_t *card) | ||
1465 | { | ||
1466 | struct net_device* dev; | ||
1467 | volatile wanpipe_common_t *chan; | ||
1468 | |||
1469 | if (test_and_set_bit(0,&find_free_critical)){ | ||
1470 | printk(KERN_INFO "CRITICAL in Find Free\n"); | ||
1471 | } | ||
1472 | |||
1473 | for (dev = card->wandev.dev; dev; | ||
1474 | dev = *((struct net_device **)dev->priv)) { | ||
1475 | chan = dev->priv; | ||
1476 | if (!chan) | ||
1477 | continue; | ||
1478 | if (chan->usedby == API && chan->svc){ | ||
1479 | if (!get_atomic_device (dev)){ | ||
1480 | if (chan->state != WANSOCK_DISCONNECTED){ | ||
1481 | release_device(dev); | ||
1482 | }else{ | ||
1483 | clear_bit(0,&find_free_critical); | ||
1484 | return dev; | ||
1485 | } | ||
1486 | } | ||
1487 | } | ||
1488 | } | ||
1489 | clear_bit(0,&find_free_critical); | ||
1490 | return NULL; | ||
1491 | } | ||
1492 | |||
1493 | /*============================================================ | ||
1494 | * wanpipe_create | ||
1495 | * | ||
1496 | * SOCKET() System call. It allocates a sock structure | ||
1497 | * and adds the socket to the wanpipe_sk_list. | ||
1498 | * Crates AF_WANPIPE socket. | ||
1499 | *===========================================================*/ | ||
1500 | |||
1501 | static int wanpipe_create(struct socket *sock, int protocol) | ||
1502 | { | ||
1503 | struct sock *sk; | ||
1504 | |||
1505 | //FIXME: This checks for root user, SECURITY ? | ||
1506 | //if (!capable(CAP_NET_RAW)) | ||
1507 | // return -EPERM; | ||
1508 | |||
1509 | if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) | ||
1510 | return -ESOCKTNOSUPPORT; | ||
1511 | |||
1512 | sock->state = SS_UNCONNECTED; | ||
1513 | |||
1514 | if ((sk = wanpipe_alloc_socket()) == NULL) | ||
1515 | return -ENOBUFS; | ||
1516 | |||
1517 | sk->sk_reuse = 1; | ||
1518 | sock->ops = &wanpipe_ops; | ||
1519 | sock_init_data(sock,sk); | ||
1520 | |||
1521 | sock_reset_flag(sk, SOCK_ZAPPED); | ||
1522 | sk->sk_family = PF_WANPIPE; | ||
1523 | wp_sk(sk)->num = protocol; | ||
1524 | sk->sk_state = WANSOCK_DISCONNECTED; | ||
1525 | sk->sk_ack_backlog = 0; | ||
1526 | sk->sk_bound_dev_if = 0; | ||
1527 | |||
1528 | atomic_inc(&wanpipe_socks_nr); | ||
1529 | |||
1530 | /* We must disable interrupts because the ISR | ||
1531 | * can also change the list */ | ||
1532 | set_bit(1,&wanpipe_tx_critical); | ||
1533 | write_lock(&wanpipe_sklist_lock); | ||
1534 | sk_add_node(sk, &wanpipe_sklist); | ||
1535 | write_unlock(&wanpipe_sklist_lock); | ||
1536 | clear_bit(1,&wanpipe_tx_critical); | ||
1537 | |||
1538 | return(0); | ||
1539 | } | ||
1540 | |||
1541 | |||
1542 | /*============================================================ | ||
1543 | * wanpipe_recvmsg | ||
1544 | * | ||
1545 | * Pull a packet from our receive queue and hand it | ||
1546 | * to the user. If necessary we block. | ||
1547 | *===========================================================*/ | ||
1548 | |||
1549 | static int wanpipe_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
1550 | struct msghdr *msg, int len, int flags) | ||
1551 | { | ||
1552 | struct sock *sk = sock->sk; | ||
1553 | struct sk_buff *skb; | ||
1554 | int copied, err=-ENOBUFS; | ||
1555 | |||
1556 | |||
1557 | /* | ||
1558 | * If the address length field is there to be filled in, we fill | ||
1559 | * it in now. | ||
1560 | */ | ||
1561 | |||
1562 | msg->msg_namelen = sizeof(struct wan_sockaddr_ll); | ||
1563 | |||
1564 | /* | ||
1565 | * Call the generic datagram receiver. This handles all sorts | ||
1566 | * of horrible races and re-entrancy so we can forget about it | ||
1567 | * in the protocol layers. | ||
1568 | * | ||
1569 | * Now it will return ENETDOWN, if device have just gone down, | ||
1570 | * but then it will block. | ||
1571 | */ | ||
1572 | |||
1573 | if (flags & MSG_OOB){ | ||
1574 | skb = skb_dequeue(&sk->sk_error_queue); | ||
1575 | }else{ | ||
1576 | skb=skb_recv_datagram(sk,flags,1,&err); | ||
1577 | } | ||
1578 | /* | ||
1579 | * An error occurred so return it. Because skb_recv_datagram() | ||
1580 | * handles the blocking we don't see and worry about blocking | ||
1581 | * retries. | ||
1582 | */ | ||
1583 | |||
1584 | if(skb==NULL) | ||
1585 | goto out; | ||
1586 | |||
1587 | /* | ||
1588 | * You lose any data beyond the buffer you gave. If it worries a | ||
1589 | * user program they can ask the device for its MTU anyway. | ||
1590 | */ | ||
1591 | |||
1592 | copied = skb->len; | ||
1593 | if (copied > len) | ||
1594 | { | ||
1595 | copied=len; | ||
1596 | msg->msg_flags|=MSG_TRUNC; | ||
1597 | } | ||
1598 | |||
1599 | wanpipe_wakeup_driver(sk); | ||
1600 | |||
1601 | /* We can't use skb_copy_datagram here */ | ||
1602 | err = memcpy_toiovec(msg->msg_iov, skb->data, copied); | ||
1603 | if (err) | ||
1604 | goto out_free; | ||
1605 | |||
1606 | sock_recv_timestamp(msg, sk, skb); | ||
1607 | |||
1608 | if (msg->msg_name) | ||
1609 | memcpy(msg->msg_name, skb->cb, msg->msg_namelen); | ||
1610 | |||
1611 | /* | ||
1612 | * Free or return the buffer as appropriate. Again this | ||
1613 | * hides all the races and re-entrancy issues from us. | ||
1614 | */ | ||
1615 | err = (flags&MSG_TRUNC) ? skb->len : copied; | ||
1616 | |||
1617 | out_free: | ||
1618 | skb_free_datagram(sk, skb); | ||
1619 | out: | ||
1620 | return err; | ||
1621 | } | ||
1622 | |||
1623 | |||
1624 | /*============================================================ | ||
1625 | * wanpipe_wakeup_driver | ||
1626 | * | ||
1627 | * If socket receive buffer is full and driver cannot | ||
1628 | * pass data up the sock, it sets a packet_block flag. | ||
1629 | * This function check that flag and if sock receive | ||
1630 | * queue has room it kicks the driver BH handler. | ||
1631 | * | ||
1632 | * This way, driver doesn't have to poll the sock | ||
1633 | * receive queue. | ||
1634 | *===========================================================*/ | ||
1635 | |||
1636 | static void wanpipe_wakeup_driver(struct sock *sk) | ||
1637 | { | ||
1638 | struct net_device *dev = NULL; | ||
1639 | wanpipe_common_t *chan=NULL; | ||
1640 | |||
1641 | dev = dev_get_by_index(sk->sk_bound_dev_if); | ||
1642 | if (!dev) | ||
1643 | return; | ||
1644 | |||
1645 | dev_put(dev); | ||
1646 | |||
1647 | if ((chan = dev->priv) == NULL) | ||
1648 | return; | ||
1649 | |||
1650 | if (atomic_read(&chan->receive_block)){ | ||
1651 | if (atomic_read(&sk->sk_rmem_alloc) < | ||
1652 | ((unsigned)sk->sk_rcvbuf * 0.9)) { | ||
1653 | printk(KERN_INFO "wansock: Queuing task for wanpipe\n"); | ||
1654 | atomic_set(&chan->receive_block,0); | ||
1655 | wanpipe_queue_tq(&chan->wanpipe_task); | ||
1656 | wanpipe_mark_bh(); | ||
1657 | } | ||
1658 | } | ||
1659 | } | ||
1660 | |||
1661 | /*============================================================ | ||
1662 | * wanpipe_getname | ||
1663 | * | ||
1664 | * I don't know what to do with this yet. | ||
1665 | * User can use this function to get sock address | ||
1666 | * information. Not very useful for Sangoma's purposes. | ||
1667 | *===========================================================*/ | ||
1668 | |||
1669 | |||
1670 | static int wanpipe_getname(struct socket *sock, struct sockaddr *uaddr, | ||
1671 | int *uaddr_len, int peer) | ||
1672 | { | ||
1673 | struct net_device *dev; | ||
1674 | struct sock *sk = sock->sk; | ||
1675 | struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)uaddr; | ||
1676 | |||
1677 | sll->sll_family = AF_WANPIPE; | ||
1678 | sll->sll_ifindex = sk->sk_bound_dev_if; | ||
1679 | sll->sll_protocol = wp_sk(sk)->num; | ||
1680 | dev = dev_get_by_index(sk->sk_bound_dev_if); | ||
1681 | if (dev) { | ||
1682 | sll->sll_hatype = dev->type; | ||
1683 | sll->sll_halen = dev->addr_len; | ||
1684 | memcpy(sll->sll_addr, dev->dev_addr, dev->addr_len); | ||
1685 | } else { | ||
1686 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ | ||
1687 | sll->sll_halen = 0; | ||
1688 | } | ||
1689 | *uaddr_len = sizeof(*sll); | ||
1690 | |||
1691 | dev_put(dev); | ||
1692 | |||
1693 | return 0; | ||
1694 | } | ||
1695 | |||
1696 | /*============================================================ | ||
1697 | * wanpipe_notifier | ||
1698 | * | ||
1699 | * If driver turns off network interface, this function | ||
1700 | * will be envoked. Currently I treate it as a | ||
1701 | * call disconnect. More thought should go into this | ||
1702 | * function. | ||
1703 | * | ||
1704 | * FIXME: More thought should go into this function. | ||
1705 | * | ||
1706 | *===========================================================*/ | ||
1707 | |||
1708 | static int wanpipe_notifier(struct notifier_block *this, unsigned long msg, void *data) | ||
1709 | { | ||
1710 | struct sock *sk; | ||
1711 | hlist_node *node; | ||
1712 | struct net_device *dev = (struct net_device *)data; | ||
1713 | |||
1714 | sk_for_each(sk, node, &wanpipe_sklist) { | ||
1715 | struct wanpipe_opt *po = wp_sk(sk); | ||
1716 | |||
1717 | if (!po) | ||
1718 | continue; | ||
1719 | if (dev == NULL) | ||
1720 | continue; | ||
1721 | |||
1722 | switch (msg) { | ||
1723 | case NETDEV_DOWN: | ||
1724 | case NETDEV_UNREGISTER: | ||
1725 | if (dev->ifindex == sk->sk_bound_dev_if) { | ||
1726 | printk(KERN_INFO "wansock: Device down %s\n",dev->name); | ||
1727 | if (sock_flag(sk, SOCK_ZAPPED)) { | ||
1728 | wanpipe_unlink_driver(sk); | ||
1729 | sk->sk_err = ENETDOWN; | ||
1730 | sk->sk_error_report(sk); | ||
1731 | } | ||
1732 | |||
1733 | if (msg == NETDEV_UNREGISTER) { | ||
1734 | printk(KERN_INFO "wansock: Unregistering Device: %s\n", | ||
1735 | dev->name); | ||
1736 | wanpipe_unlink_driver(sk); | ||
1737 | sk->sk_bound_dev_if = 0; | ||
1738 | } | ||
1739 | } | ||
1740 | break; | ||
1741 | case NETDEV_UP: | ||
1742 | if (dev->ifindex == sk->sk_bound_dev_if && | ||
1743 | po->num && !sock_flag(sk, SOCK_ZAPPED)) { | ||
1744 | printk(KERN_INFO "wansock: Registering Device: %s\n", | ||
1745 | dev->name); | ||
1746 | wanpipe_link_driver(dev,sk); | ||
1747 | } | ||
1748 | break; | ||
1749 | } | ||
1750 | } | ||
1751 | return NOTIFY_DONE; | ||
1752 | } | ||
1753 | |||
1754 | /*============================================================ | ||
1755 | * wanpipe_ioctl | ||
1756 | * | ||
1757 | * Execute a user commands, and set socket options. | ||
1758 | * | ||
1759 | * FIXME: More thought should go into this function. | ||
1760 | * | ||
1761 | *===========================================================*/ | ||
1762 | |||
1763 | static int wanpipe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
1764 | { | ||
1765 | struct sock *sk = sock->sk; | ||
1766 | int err; | ||
1767 | |||
1768 | switch(cmd) | ||
1769 | { | ||
1770 | case SIOCGSTAMP: | ||
1771 | return sock_get_timestamp(sk, (struct timeval __user *)arg); | ||
1772 | |||
1773 | case SIOC_WANPIPE_CHECK_TX: | ||
1774 | |||
1775 | return atomic_read(&sk->sk_wmem_alloc); | ||
1776 | |||
1777 | case SIOC_WANPIPE_SOCK_STATE: | ||
1778 | |||
1779 | if (sk->sk_state == WANSOCK_CONNECTED) | ||
1780 | return 0; | ||
1781 | |||
1782 | return 1; | ||
1783 | |||
1784 | |||
1785 | case SIOC_WANPIPE_GET_CALL_DATA: | ||
1786 | |||
1787 | return get_ioctl_cmd (sk,(void*)arg); | ||
1788 | |||
1789 | case SIOC_WANPIPE_SET_CALL_DATA: | ||
1790 | |||
1791 | return set_ioctl_cmd (sk,(void*)arg); | ||
1792 | |||
1793 | case SIOC_WANPIPE_ACCEPT_CALL: | ||
1794 | case SIOC_WANPIPE_CLEAR_CALL: | ||
1795 | case SIOC_WANPIPE_RESET_CALL: | ||
1796 | |||
1797 | if ((err=set_ioctl_cmd(sk,(void*)arg)) < 0) | ||
1798 | return err; | ||
1799 | |||
1800 | err=wanpipe_exec_cmd(sk,cmd,0); | ||
1801 | get_ioctl_cmd(sk,(void*)arg); | ||
1802 | return err; | ||
1803 | |||
1804 | case SIOC_WANPIPE_DEBUG: | ||
1805 | |||
1806 | return wanpipe_debug(sk,(void*)arg); | ||
1807 | |||
1808 | case SIOC_WANPIPE_SET_NONBLOCK: | ||
1809 | |||
1810 | if (sk->sk_state != WANSOCK_DISCONNECTED) | ||
1811 | return -EINVAL; | ||
1812 | |||
1813 | sock->file->f_flags |= O_NONBLOCK; | ||
1814 | return 0; | ||
1815 | |||
1816 | #ifdef CONFIG_INET | ||
1817 | case SIOCADDRT: | ||
1818 | case SIOCDELRT: | ||
1819 | case SIOCDARP: | ||
1820 | case SIOCGARP: | ||
1821 | case SIOCSARP: | ||
1822 | case SIOCDRARP: | ||
1823 | case SIOCGRARP: | ||
1824 | case SIOCSRARP: | ||
1825 | case SIOCGIFADDR: | ||
1826 | case SIOCSIFADDR: | ||
1827 | case SIOCGIFBRDADDR: | ||
1828 | case SIOCSIFBRDADDR: | ||
1829 | case SIOCGIFNETMASK: | ||
1830 | case SIOCSIFNETMASK: | ||
1831 | case SIOCGIFDSTADDR: | ||
1832 | case SIOCSIFDSTADDR: | ||
1833 | case SIOCSIFFLAGS: | ||
1834 | return inet_dgram_ops.ioctl(sock, cmd, arg); | ||
1835 | #endif | ||
1836 | |||
1837 | default: | ||
1838 | return -ENOIOCTLCMD; | ||
1839 | } | ||
1840 | /*NOTREACHED*/ | ||
1841 | } | ||
1842 | |||
1843 | /*============================================================ | ||
1844 | * wanpipe_debug | ||
1845 | * | ||
1846 | * This function will pass up information about all | ||
1847 | * active sockets. | ||
1848 | * | ||
1849 | * FIXME: More thought should go into this function. | ||
1850 | * | ||
1851 | *===========================================================*/ | ||
1852 | |||
1853 | static int wanpipe_debug (struct sock *origsk, void *arg) | ||
1854 | { | ||
1855 | struct sock *sk; | ||
1856 | struct hlist_node *node; | ||
1857 | struct net_device *dev = NULL; | ||
1858 | wanpipe_common_t *chan=NULL; | ||
1859 | int cnt=0, err=0; | ||
1860 | wan_debug_t *dbg_data = (wan_debug_t *)arg; | ||
1861 | |||
1862 | sk_for_each(sk, node, &wanpipe_sklist) { | ||
1863 | wanpipe_opt *wp = wp_sk(sk); | ||
1864 | |||
1865 | if (sk == origsk){ | ||
1866 | continue; | ||
1867 | } | ||
1868 | |||
1869 | if ((err=put_user(1, &dbg_data->debug[cnt].free))) | ||
1870 | return err; | ||
1871 | if ((err = put_user(sk->sk_state, | ||
1872 | &dbg_data->debug[cnt].state_sk))) | ||
1873 | return err; | ||
1874 | if ((err = put_user(sk->sk_rcvbuf, | ||
1875 | &dbg_data->debug[cnt].rcvbuf))) | ||
1876 | return err; | ||
1877 | if ((err = put_user(atomic_read(&sk->sk_rmem_alloc), | ||
1878 | &dbg_data->debug[cnt].rmem))) | ||
1879 | return err; | ||
1880 | if ((err = put_user(atomic_read(&sk->sk_wmem_alloc), | ||
1881 | &dbg_data->debug[cnt].wmem))) | ||
1882 | return err; | ||
1883 | if ((err = put_user(sk->sk_sndbuf, | ||
1884 | &dbg_data->debug[cnt].sndbuf))) | ||
1885 | return err; | ||
1886 | if ((err=put_user(sk_count, &dbg_data->debug[cnt].sk_count))) | ||
1887 | return err; | ||
1888 | if ((err=put_user(wp->poll_cnt, &dbg_data->debug[cnt].poll_cnt))) | ||
1889 | return err; | ||
1890 | if ((err = put_user(sk->sk_bound_dev_if, | ||
1891 | &dbg_data->debug[cnt].bound))) | ||
1892 | return err; | ||
1893 | |||
1894 | if (sk->sk_bound_dev_if) { | ||
1895 | dev = dev_get_by_index(sk->sk_bound_dev_if); | ||
1896 | if (!dev) | ||
1897 | continue; | ||
1898 | |||
1899 | chan=dev->priv; | ||
1900 | dev_put(dev); | ||
1901 | |||
1902 | if ((err=put_user(chan->state, &dbg_data->debug[cnt].d_state))) | ||
1903 | return err; | ||
1904 | if ((err=put_user(chan->svc, &dbg_data->debug[cnt].svc))) | ||
1905 | return err; | ||
1906 | |||
1907 | if ((err=put_user(atomic_read(&chan->command), | ||
1908 | &dbg_data->debug[cnt].command))) | ||
1909 | return err; | ||
1910 | |||
1911 | |||
1912 | if (wp){ | ||
1913 | sdla_t *card = (sdla_t*)wp->card; | ||
1914 | |||
1915 | if (card){ | ||
1916 | if ((err=put_user(atomic_read(&card->u.x.command_busy), | ||
1917 | &dbg_data->debug[cnt].cmd_busy))) | ||
1918 | return err; | ||
1919 | } | ||
1920 | |||
1921 | if ((err=put_user(wp->lcn, | ||
1922 | &dbg_data->debug[cnt].lcn))) | ||
1923 | return err; | ||
1924 | |||
1925 | if (wp->mbox) { | ||
1926 | if ((err=put_user(1, &dbg_data->debug[cnt].mbox))) | ||
1927 | return err; | ||
1928 | } | ||
1929 | } | ||
1930 | |||
1931 | if ((err=put_user(atomic_read(&chan->receive_block), | ||
1932 | &dbg_data->debug[cnt].rblock))) | ||
1933 | return err; | ||
1934 | |||
1935 | if (copy_to_user(dbg_data->debug[cnt].name, dev->name, strlen(dev->name))) | ||
1936 | return -EFAULT; | ||
1937 | } | ||
1938 | |||
1939 | if (++cnt == MAX_NUM_DEBUG) | ||
1940 | break; | ||
1941 | } | ||
1942 | return 0; | ||
1943 | } | ||
1944 | |||
1945 | /*============================================================ | ||
1946 | * get_ioctl_cmd | ||
1947 | * | ||
1948 | * Pass up the contents of socket MBOX to the user. | ||
1949 | *===========================================================*/ | ||
1950 | |||
1951 | static int get_ioctl_cmd (struct sock *sk, void *arg) | ||
1952 | { | ||
1953 | x25api_t *usr_data = (x25api_t *)arg; | ||
1954 | mbox_cmd_t *mbox_ptr; | ||
1955 | int err; | ||
1956 | |||
1957 | if (usr_data == NULL) | ||
1958 | return -EINVAL; | ||
1959 | |||
1960 | if (!wp_sk(sk)->mbox) { | ||
1961 | return -EINVAL; | ||
1962 | } | ||
1963 | |||
1964 | mbox_ptr = (mbox_cmd_t *)wp_sk(sk)->mbox; | ||
1965 | |||
1966 | if ((err=put_user(mbox_ptr->cmd.qdm, &usr_data->hdr.qdm))) | ||
1967 | return err; | ||
1968 | if ((err=put_user(mbox_ptr->cmd.cause, &usr_data->hdr.cause))) | ||
1969 | return err; | ||
1970 | if ((err=put_user(mbox_ptr->cmd.diagn, &usr_data->hdr.diagn))) | ||
1971 | return err; | ||
1972 | if ((err=put_user(mbox_ptr->cmd.length, &usr_data->hdr.length))) | ||
1973 | return err; | ||
1974 | if ((err=put_user(mbox_ptr->cmd.result, &usr_data->hdr.result))) | ||
1975 | return err; | ||
1976 | if ((err=put_user(mbox_ptr->cmd.lcn, &usr_data->hdr.lcn))) | ||
1977 | return err; | ||
1978 | |||
1979 | if (mbox_ptr->cmd.length > 0){ | ||
1980 | if (mbox_ptr->cmd.length > X25_MAX_DATA) | ||
1981 | return -EINVAL; | ||
1982 | |||
1983 | if (copy_to_user(usr_data->data, mbox_ptr->data, mbox_ptr->cmd.length)){ | ||
1984 | printk(KERN_INFO "wansock: Copy failed !!!\n"); | ||
1985 | return -EFAULT; | ||
1986 | } | ||
1987 | } | ||
1988 | return 0; | ||
1989 | } | ||
1990 | |||
1991 | /*============================================================ | ||
1992 | * set_ioctl_cmd | ||
1993 | * | ||
1994 | * Before command can be execute, socket MBOX must | ||
1995 | * be created, and initialized with user data. | ||
1996 | *===========================================================*/ | ||
1997 | |||
1998 | static int set_ioctl_cmd (struct sock *sk, void *arg) | ||
1999 | { | ||
2000 | x25api_t *usr_data = (x25api_t *)arg; | ||
2001 | mbox_cmd_t *mbox_ptr; | ||
2002 | int err; | ||
2003 | |||
2004 | if (!wp_sk(sk)->mbox) { | ||
2005 | void *mbox_ptr; | ||
2006 | struct net_device *dev = dev_get_by_index(sk->sk_bound_dev_if); | ||
2007 | if (!dev) | ||
2008 | return -ENODEV; | ||
2009 | |||
2010 | dev_put(dev); | ||
2011 | |||
2012 | if ((mbox_ptr = kzalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL) | ||
2013 | return -ENOMEM; | ||
2014 | |||
2015 | wp_sk(sk)->mbox = mbox_ptr; | ||
2016 | |||
2017 | wanpipe_link_driver(dev,sk); | ||
2018 | } | ||
2019 | |||
2020 | mbox_ptr = (mbox_cmd_t*)wp_sk(sk)->mbox; | ||
2021 | memset(mbox_ptr, 0, sizeof(mbox_cmd_t)); | ||
2022 | |||
2023 | if (usr_data == NULL){ | ||
2024 | return 0; | ||
2025 | } | ||
2026 | if ((err=get_user(mbox_ptr->cmd.qdm, &usr_data->hdr.qdm))) | ||
2027 | return err; | ||
2028 | if ((err=get_user(mbox_ptr->cmd.cause, &usr_data->hdr.cause))) | ||
2029 | return err; | ||
2030 | if ((err=get_user(mbox_ptr->cmd.diagn, &usr_data->hdr.diagn))) | ||
2031 | return err; | ||
2032 | if ((err=get_user(mbox_ptr->cmd.length, &usr_data->hdr.length))) | ||
2033 | return err; | ||
2034 | if ((err=get_user(mbox_ptr->cmd.result, &usr_data->hdr.result))) | ||
2035 | return err; | ||
2036 | |||
2037 | if (mbox_ptr->cmd.length > 0){ | ||
2038 | if (mbox_ptr->cmd.length > X25_MAX_DATA) | ||
2039 | return -EINVAL; | ||
2040 | |||
2041 | if (copy_from_user(mbox_ptr->data, usr_data->data, mbox_ptr->cmd.length)){ | ||
2042 | printk(KERN_INFO "Copy failed\n"); | ||
2043 | return -EFAULT; | ||
2044 | } | ||
2045 | } | ||
2046 | return 0; | ||
2047 | } | ||
2048 | |||
2049 | |||
2050 | /*====================================================================== | ||
2051 | * wanpipe_poll | ||
2052 | * | ||
2053 | * Datagram poll: Again totally generic. This also handles | ||
2054 | * sequenced packet sockets providing the socket receive queue | ||
2055 | * is only ever holding data ready to receive. | ||
2056 | * | ||
2057 | * Note: when you _don't_ use this routine for this protocol, | ||
2058 | * and you use a different write policy from sock_writeable() | ||
2059 | * then please supply your own write_space callback. | ||
2060 | *=====================================================================*/ | ||
2061 | |||
2062 | unsigned int wanpipe_poll(struct file * file, struct socket *sock, poll_table *wait) | ||
2063 | { | ||
2064 | struct sock *sk = sock->sk; | ||
2065 | unsigned int mask; | ||
2066 | |||
2067 | ++wp_sk(sk)->poll_cnt; | ||
2068 | |||
2069 | poll_wait(file, sk->sk_sleep, wait); | ||
2070 | mask = 0; | ||
2071 | |||
2072 | /* exceptional events? */ | ||
2073 | if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) { | ||
2074 | mask |= POLLPRI; | ||
2075 | return mask; | ||
2076 | } | ||
2077 | if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
2078 | mask |= POLLHUP; | ||
2079 | |||
2080 | /* readable? */ | ||
2081 | if (!skb_queue_empty(&sk->sk_receive_queue)) { | ||
2082 | mask |= POLLIN | POLLRDNORM; | ||
2083 | } | ||
2084 | |||
2085 | /* connection hasn't started yet */ | ||
2086 | if (sk->sk_state == WANSOCK_CONNECTING) { | ||
2087 | return mask; | ||
2088 | } | ||
2089 | |||
2090 | if (sk->sk_state == WANSOCK_DISCONNECTED) { | ||
2091 | mask = POLLPRI; | ||
2092 | return mask; | ||
2093 | } | ||
2094 | |||
2095 | /* This check blocks the user process if there is | ||
2096 | * a packet already queued in the socket write queue. | ||
2097 | * This option is only for X25API protocol, for other | ||
2098 | * protocol like chdlc enable streaming mode, | ||
2099 | * where multiple packets can be pending in the socket | ||
2100 | * transmit queue */ | ||
2101 | |||
2102 | if (wp_sk(sk)->num == htons(X25_PROT)) { | ||
2103 | if (atomic_read(&wp_sk(sk)->packet_sent)) | ||
2104 | return mask; | ||
2105 | } | ||
2106 | |||
2107 | /* writable? */ | ||
2108 | if (sock_writeable(sk)){ | ||
2109 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | ||
2110 | }else{ | ||
2111 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | ||
2112 | } | ||
2113 | |||
2114 | return mask; | ||
2115 | } | ||
2116 | |||
2117 | /*====================================================================== | ||
2118 | * wanpipe_listen | ||
2119 | * | ||
2120 | * X25API Specific function. Set a socket into LISTENING MODE. | ||
2121 | *=====================================================================*/ | ||
2122 | |||
2123 | |||
2124 | static int wanpipe_listen(struct socket *sock, int backlog) | ||
2125 | { | ||
2126 | struct sock *sk = sock->sk; | ||
2127 | |||
2128 | /* This is x25 specific area if protocol doesn't | ||
2129 | * match, return error */ | ||
2130 | if (wp_sk(sk)->num != htons(X25_PROT)) | ||
2131 | return -EINVAL; | ||
2132 | |||
2133 | if (sk->sk_state == WANSOCK_BIND_LISTEN) { | ||
2134 | |||
2135 | sk->sk_max_ack_backlog = backlog; | ||
2136 | sk->sk_state = WANSOCK_LISTEN; | ||
2137 | return 0; | ||
2138 | }else{ | ||
2139 | printk(KERN_INFO "wansock: Listening sock was not binded\n"); | ||
2140 | } | ||
2141 | |||
2142 | return -EINVAL; | ||
2143 | } | ||
2144 | |||
2145 | /*====================================================================== | ||
2146 | * wanpipe_link_card | ||
2147 | * | ||
2148 | * Connects the listening socket to the driver | ||
2149 | *=====================================================================*/ | ||
2150 | |||
2151 | static int wanpipe_link_card (struct sock *sk) | ||
2152 | { | ||
2153 | sdla_t *card = (sdla_t*)wp_sk(sk)->card; | ||
2154 | |||
2155 | if (!card) | ||
2156 | return -ENOMEM; | ||
2157 | |||
2158 | if ((card->sk != NULL) || (card->func != NULL)){ | ||
2159 | printk(KERN_INFO "wansock: Listening queue is already established\n"); | ||
2160 | return -EINVAL; | ||
2161 | } | ||
2162 | |||
2163 | card->sk=sk; | ||
2164 | card->func=wanpipe_listen_rcv; | ||
2165 | sock_set_flag(sk, SOCK_ZAPPED); | ||
2166 | |||
2167 | return 0; | ||
2168 | } | ||
2169 | |||
2170 | /*====================================================================== | ||
2171 | * wanpipe_listen | ||
2172 | * | ||
2173 | * X25API Specific function. Disconnect listening socket from | ||
2174 | * the driver. | ||
2175 | *=====================================================================*/ | ||
2176 | |||
2177 | static void wanpipe_unlink_card (struct sock *sk) | ||
2178 | { | ||
2179 | sdla_t *card = (sdla_t*)wp_sk(sk)->card; | ||
2180 | |||
2181 | if (card){ | ||
2182 | card->sk=NULL; | ||
2183 | card->func=NULL; | ||
2184 | } | ||
2185 | } | ||
2186 | |||
2187 | /*====================================================================== | ||
2188 | * wanpipe_exec_cmd | ||
2189 | * | ||
2190 | * Ioctl function calls this function to execute user command. | ||
2191 | * Connect() sytem call also calls this function to execute | ||
2192 | * place call. This function blocks until command is executed. | ||
2193 | *=====================================================================*/ | ||
2194 | |||
2195 | static int wanpipe_exec_cmd(struct sock *sk, int cmd, unsigned int flags) | ||
2196 | { | ||
2197 | int err = -EINVAL; | ||
2198 | wanpipe_opt *wp = wp_sk(sk); | ||
2199 | mbox_cmd_t *mbox_ptr = (mbox_cmd_t*)wp->mbox; | ||
2200 | |||
2201 | if (!mbox_ptr){ | ||
2202 | printk(KERN_INFO "NO MBOX PTR !!!!!\n"); | ||
2203 | return -EINVAL; | ||
2204 | } | ||
2205 | |||
2206 | /* This is x25 specific area if protocol doesn't | ||
2207 | * match, return error */ | ||
2208 | if (wp->num != htons(X25_PROT)) | ||
2209 | return -EINVAL; | ||
2210 | |||
2211 | |||
2212 | switch (cmd){ | ||
2213 | |||
2214 | case SIOC_WANPIPE_ACCEPT_CALL: | ||
2215 | |||
2216 | if (sk->sk_state != WANSOCK_CONNECTING) { | ||
2217 | err = -EHOSTDOWN; | ||
2218 | break; | ||
2219 | } | ||
2220 | |||
2221 | err = execute_command(sk,X25_ACCEPT_CALL,0); | ||
2222 | if (err < 0) | ||
2223 | break; | ||
2224 | |||
2225 | /* Update. Mar6 2000. | ||
2226 | * Do not set the sock lcn number here, since | ||
2227 | * it is done in wanpipe_listen_rcv(). | ||
2228 | */ | ||
2229 | if (sk->sk_state == WANSOCK_CONNECTED) { | ||
2230 | wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn; | ||
2231 | DBG_PRINTK(KERN_INFO "\nwansock: Accept OK %i\n", | ||
2232 | wp->lcn); | ||
2233 | err = 0; | ||
2234 | |||
2235 | }else{ | ||
2236 | DBG_PRINTK (KERN_INFO "\nwansock: Accept Failed %i\n", | ||
2237 | wp->lcn); | ||
2238 | wp->lcn = 0; | ||
2239 | err = -ECONNREFUSED; | ||
2240 | } | ||
2241 | break; | ||
2242 | |||
2243 | case SIOC_WANPIPE_CLEAR_CALL: | ||
2244 | |||
2245 | if (sk->sk_state == WANSOCK_DISCONNECTED) { | ||
2246 | err = -EINVAL; | ||
2247 | break; | ||
2248 | } | ||
2249 | |||
2250 | |||
2251 | /* Check if data buffers are pending for transmission, | ||
2252 | * if so, check whether user wants to wait until data | ||
2253 | * is transmitted, or clear a call and drop packets */ | ||
2254 | |||
2255 | if (atomic_read(&sk->sk_wmem_alloc) || | ||
2256 | check_driver_busy(sk)) { | ||
2257 | mbox_cmd_t *mbox = wp->mbox; | ||
2258 | if (mbox->cmd.qdm & 0x80){ | ||
2259 | mbox->cmd.result = 0x35; | ||
2260 | err = -EAGAIN; | ||
2261 | break; | ||
2262 | } | ||
2263 | } | ||
2264 | |||
2265 | sk->sk_state = WANSOCK_DISCONNECTING; | ||
2266 | |||
2267 | err = execute_command(sk,X25_CLEAR_CALL,0); | ||
2268 | if (err < 0) | ||
2269 | break; | ||
2270 | |||
2271 | err = -ECONNREFUSED; | ||
2272 | if (sk->sk_state == WANSOCK_DISCONNECTED) { | ||
2273 | DBG_PRINTK(KERN_INFO "\nwansock: CLEAR OK %i\n", | ||
2274 | wp->lcn); | ||
2275 | wp->lcn = 0; | ||
2276 | err = 0; | ||
2277 | } | ||
2278 | break; | ||
2279 | |||
2280 | case SIOC_WANPIPE_RESET_CALL: | ||
2281 | |||
2282 | if (sk->sk_state != WANSOCK_CONNECTED) { | ||
2283 | err = -EINVAL; | ||
2284 | break; | ||
2285 | } | ||
2286 | |||
2287 | |||
2288 | /* Check if data buffers are pending for transmission, | ||
2289 | * if so, check whether user wants to wait until data | ||
2290 | * is transmitted, or reset a call and drop packets */ | ||
2291 | |||
2292 | if (atomic_read(&sk->sk_wmem_alloc) || | ||
2293 | check_driver_busy(sk)) { | ||
2294 | mbox_cmd_t *mbox = wp->mbox; | ||
2295 | if (mbox->cmd.qdm & 0x80){ | ||
2296 | mbox->cmd.result = 0x35; | ||
2297 | err = -EAGAIN; | ||
2298 | break; | ||
2299 | } | ||
2300 | } | ||
2301 | |||
2302 | |||
2303 | err = execute_command(sk, X25_RESET,0); | ||
2304 | if (err < 0) | ||
2305 | break; | ||
2306 | |||
2307 | err = mbox_ptr->cmd.result; | ||
2308 | break; | ||
2309 | |||
2310 | |||
2311 | case X25_PLACE_CALL: | ||
2312 | |||
2313 | err=execute_command(sk,X25_PLACE_CALL,flags); | ||
2314 | if (err < 0) | ||
2315 | break; | ||
2316 | |||
2317 | if (sk->sk_state == WANSOCK_CONNECTED) { | ||
2318 | |||
2319 | wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn; | ||
2320 | |||
2321 | DBG_PRINTK(KERN_INFO "\nwansock: PLACE CALL OK %i\n", | ||
2322 | wp->lcn); | ||
2323 | err = 0; | ||
2324 | |||
2325 | } else if (sk->sk_state == WANSOCK_CONNECTING && | ||
2326 | (flags & O_NONBLOCK)) { | ||
2327 | wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn; | ||
2328 | DBG_PRINTK(KERN_INFO "\nwansock: Place Call OK: Waiting %i\n", | ||
2329 | wp->lcn); | ||
2330 | |||
2331 | err = 0; | ||
2332 | |||
2333 | }else{ | ||
2334 | DBG_PRINTK(KERN_INFO "\nwansock: Place call Failed\n"); | ||
2335 | err = -ECONNREFUSED; | ||
2336 | } | ||
2337 | |||
2338 | break; | ||
2339 | |||
2340 | default: | ||
2341 | return -EINVAL; | ||
2342 | } | ||
2343 | |||
2344 | return err; | ||
2345 | } | ||
2346 | |||
2347 | static int check_driver_busy (struct sock *sk) | ||
2348 | { | ||
2349 | struct net_device *dev = dev_get_by_index(sk->sk_bound_dev_if); | ||
2350 | wanpipe_common_t *chan; | ||
2351 | |||
2352 | if (!dev) | ||
2353 | return 0; | ||
2354 | |||
2355 | dev_put(dev); | ||
2356 | |||
2357 | if ((chan=dev->priv) == NULL) | ||
2358 | return 0; | ||
2359 | |||
2360 | return atomic_read(&chan->driver_busy); | ||
2361 | } | ||
2362 | |||
2363 | |||
2364 | /*====================================================================== | ||
2365 | * wanpipe_accept | ||
2366 | * | ||
2367 | * ACCEPT() System call. X25API Specific function. | ||
2368 | * For each incoming call, create a new socket and | ||
2369 | * return it to the user. | ||
2370 | *=====================================================================*/ | ||
2371 | |||
2372 | static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags) | ||
2373 | { | ||
2374 | struct sock *sk; | ||
2375 | struct sock *newsk; | ||
2376 | struct sk_buff *skb; | ||
2377 | DECLARE_WAITQUEUE(wait, current); | ||
2378 | int err=0; | ||
2379 | |||
2380 | if (newsock->sk != NULL){ | ||
2381 | wanpipe_kill_sock_accept(newsock->sk); | ||
2382 | newsock->sk=NULL; | ||
2383 | } | ||
2384 | |||
2385 | if ((sk = sock->sk) == NULL) | ||
2386 | return -EINVAL; | ||
2387 | |||
2388 | if (sk->sk_type != SOCK_RAW) | ||
2389 | return -EOPNOTSUPP; | ||
2390 | |||
2391 | if (sk->sk_state != WANSOCK_LISTEN) | ||
2392 | return -EINVAL; | ||
2393 | |||
2394 | if (wp_sk(sk)->num != htons(X25_PROT)) | ||
2395 | return -EINVAL; | ||
2396 | |||
2397 | add_wait_queue(sk->sk_sleep,&wait); | ||
2398 | current->state = TASK_INTERRUPTIBLE; | ||
2399 | for (;;){ | ||
2400 | skb = skb_dequeue(&sk->sk_receive_queue); | ||
2401 | if (skb){ | ||
2402 | err=0; | ||
2403 | break; | ||
2404 | } | ||
2405 | if (signal_pending(current)) { | ||
2406 | err = -ERESTARTSYS; | ||
2407 | break; | ||
2408 | } | ||
2409 | schedule(); | ||
2410 | } | ||
2411 | current->state = TASK_RUNNING; | ||
2412 | remove_wait_queue(sk->sk_sleep,&wait); | ||
2413 | |||
2414 | if (err != 0) | ||
2415 | return err; | ||
2416 | |||
2417 | newsk = get_newsk_from_skb(skb); | ||
2418 | if (!newsk){ | ||
2419 | return -EINVAL; | ||
2420 | } | ||
2421 | |||
2422 | set_bit(1,&wanpipe_tx_critical); | ||
2423 | write_lock(&wanpipe_sklist_lock); | ||
2424 | sk_add_node(newsk, &wanpipe_sklist); | ||
2425 | write_unlock(&wanpipe_sklist_lock); | ||
2426 | clear_bit(1,&wanpipe_tx_critical); | ||
2427 | |||
2428 | newsk->sk_socket = newsock; | ||
2429 | newsk->sk_sleep = &newsock->wait; | ||
2430 | |||
2431 | /* Now attach up the new socket */ | ||
2432 | sk->sk_ack_backlog--; | ||
2433 | newsock->sk = newsk; | ||
2434 | |||
2435 | kfree_skb(skb); | ||
2436 | |||
2437 | DBG_PRINTK(KERN_INFO "\nwansock: ACCEPT Got LCN %i\n", | ||
2438 | wp_sk(newsk)->lcn); | ||
2439 | return 0; | ||
2440 | } | ||
2441 | |||
2442 | /*====================================================================== | ||
2443 | * get_newsk_from_skb | ||
2444 | * | ||
2445 | * Accept() uses this function to get the address of the new | ||
2446 | * socket structure. | ||
2447 | *=====================================================================*/ | ||
2448 | |||
2449 | struct sock * get_newsk_from_skb (struct sk_buff *skb) | ||
2450 | { | ||
2451 | struct net_device *dev = skb->dev; | ||
2452 | wanpipe_common_t *chan; | ||
2453 | |||
2454 | if (!dev){ | ||
2455 | return NULL; | ||
2456 | } | ||
2457 | |||
2458 | if ((chan = dev->priv) == NULL){ | ||
2459 | return NULL; | ||
2460 | } | ||
2461 | |||
2462 | if (!chan->sk){ | ||
2463 | return NULL; | ||
2464 | } | ||
2465 | return (struct sock *)chan->sk; | ||
2466 | } | ||
2467 | |||
2468 | /*====================================================================== | ||
2469 | * wanpipe_connect | ||
2470 | * | ||
2471 | * CONNECT() System Call. X25API specific function | ||
2472 | * Check the state of the sock, and execute PLACE_CALL command. | ||
2473 | * Connect can ether block or return without waiting for connection, | ||
2474 | * if specified by user. | ||
2475 | *=====================================================================*/ | ||
2476 | |||
2477 | static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) | ||
2478 | { | ||
2479 | struct sock *sk = sock->sk; | ||
2480 | struct wan_sockaddr_ll *addr = (struct wan_sockaddr_ll*)uaddr; | ||
2481 | struct net_device *dev; | ||
2482 | int err; | ||
2483 | |||
2484 | if (wp_sk(sk)->num != htons(X25_PROT)) | ||
2485 | return -EINVAL; | ||
2486 | |||
2487 | if (sk->sk_state == WANSOCK_CONNECTED) | ||
2488 | return -EISCONN; /* No reconnect on a seqpacket socket */ | ||
2489 | |||
2490 | if (sk->sk_state != WAN_DISCONNECTED) { | ||
2491 | printk(KERN_INFO "wansock: Trying to connect on channel NON DISCONNECT\n"); | ||
2492 | return -ECONNREFUSED; | ||
2493 | } | ||
2494 | |||
2495 | sk->sk_state = WANSOCK_DISCONNECTED; | ||
2496 | sock->state = SS_UNCONNECTED; | ||
2497 | |||
2498 | if (addr_len != sizeof(struct wan_sockaddr_ll)) | ||
2499 | return -EINVAL; | ||
2500 | |||
2501 | if (addr->sll_family != AF_WANPIPE) | ||
2502 | return -EINVAL; | ||
2503 | |||
2504 | if ((dev = dev_get_by_index(sk->sk_bound_dev_if)) == NULL) | ||
2505 | return -ENETUNREACH; | ||
2506 | |||
2507 | dev_put(dev); | ||
2508 | |||
2509 | if (!sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */ | ||
2510 | return -EINVAL; | ||
2511 | |||
2512 | sock->state = SS_CONNECTING; | ||
2513 | sk->sk_state = WANSOCK_CONNECTING; | ||
2514 | |||
2515 | if (!wp_sk(sk)->mbox) { | ||
2516 | if (wp_sk (sk)->svc) | ||
2517 | return -EINVAL; | ||
2518 | else { | ||
2519 | int err; | ||
2520 | if ((err=set_ioctl_cmd(sk,NULL)) < 0) | ||
2521 | return err; | ||
2522 | } | ||
2523 | } | ||
2524 | |||
2525 | if ((err=wanpipe_exec_cmd(sk, X25_PLACE_CALL,flags)) != 0){ | ||
2526 | sock->state = SS_UNCONNECTED; | ||
2527 | sk->sk_state = WANSOCK_CONNECTED; | ||
2528 | return err; | ||
2529 | } | ||
2530 | |||
2531 | if (sk->sk_state != WANSOCK_CONNECTED && (flags & O_NONBLOCK)) { | ||
2532 | return 0; | ||
2533 | } | ||
2534 | |||
2535 | if (sk->sk_state != WANSOCK_CONNECTED) { | ||
2536 | sock->state = SS_UNCONNECTED; | ||
2537 | return -ECONNREFUSED; | ||
2538 | } | ||
2539 | |||
2540 | sock->state = SS_CONNECTED; | ||
2541 | return 0; | ||
2542 | } | ||
2543 | |||
2544 | const struct proto_ops wanpipe_ops = { | ||
2545 | .family = PF_WANPIPE, | ||
2546 | .owner = THIS_MODULE, | ||
2547 | .release = wanpipe_release, | ||
2548 | .bind = wanpipe_bind, | ||
2549 | .connect = wanpipe_connect, | ||
2550 | .socketpair = sock_no_socketpair, | ||
2551 | .accept = wanpipe_accept, | ||
2552 | .getname = wanpipe_getname, | ||
2553 | .poll = wanpipe_poll, | ||
2554 | .ioctl = wanpipe_ioctl, | ||
2555 | .listen = wanpipe_listen, | ||
2556 | .shutdown = sock_no_shutdown, | ||
2557 | .setsockopt = sock_no_setsockopt, | ||
2558 | .getsockopt = sock_no_getsockopt, | ||
2559 | .sendmsg = wanpipe_sendmsg, | ||
2560 | .recvmsg = wanpipe_recvmsg | ||
2561 | }; | ||
2562 | |||
2563 | static struct net_proto_family wanpipe_family_ops = { | ||
2564 | .family = PF_WANPIPE, | ||
2565 | .create = wanpipe_create, | ||
2566 | .owner = THIS_MODULE, | ||
2567 | }; | ||
2568 | |||
2569 | struct notifier_block wanpipe_netdev_notifier = { | ||
2570 | .notifier_call = wanpipe_notifier, | ||
2571 | }; | ||
2572 | |||
2573 | |||
2574 | #ifdef MODULE | ||
2575 | void cleanup_module(void) | ||
2576 | { | ||
2577 | printk(KERN_INFO "wansock: Cleaning up \n"); | ||
2578 | unregister_netdevice_notifier(&wanpipe_netdev_notifier); | ||
2579 | sock_unregister(PF_WANPIPE); | ||
2580 | proto_unregister(&wanpipe_proto); | ||
2581 | } | ||
2582 | |||
2583 | int init_module(void) | ||
2584 | { | ||
2585 | int rc; | ||
2586 | |||
2587 | printk(KERN_INFO "wansock: Registering Socket \n"); | ||
2588 | |||
2589 | rc = proto_register(&wanpipe_proto, 0); | ||
2590 | if (rc != 0) | ||
2591 | goto out; | ||
2592 | |||
2593 | sock_register(&wanpipe_family_ops); | ||
2594 | register_netdevice_notifier(&wanpipe_netdev_notifier); | ||
2595 | out: | ||
2596 | return rc; | ||
2597 | } | ||
2598 | #endif | ||
2599 | MODULE_LICENSE("GPL"); | ||
2600 | MODULE_ALIAS_NETPROTO(PF_WANPIPE); | ||
diff --git a/net/x25/x25_forward.c b/net/x25/x25_forward.c index d339e0c810a8..8738ec7ce693 100644 --- a/net/x25/x25_forward.c +++ b/net/x25/x25_forward.c | |||
@@ -26,64 +26,66 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, | |||
26 | short same_lci = 0; | 26 | short same_lci = 0; |
27 | int rc = 0; | 27 | int rc = 0; |
28 | 28 | ||
29 | if ((rt = x25_get_route(dest_addr)) != NULL) { | 29 | if ((rt = x25_get_route(dest_addr)) == NULL) |
30 | goto out_no_route; | ||
30 | 31 | ||
31 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { | 32 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { |
32 | /* This shouldnt happen, if it occurs somehow | 33 | /* This shouldnt happen, if it occurs somehow |
33 | * do something sensible | 34 | * do something sensible |
34 | */ | ||
35 | goto out_put_route; | ||
36 | } | ||
37 | |||
38 | /* Avoid a loop. This is the normal exit path for a | ||
39 | * system with only one x.25 iface and default route | ||
40 | */ | 35 | */ |
41 | if (rt->dev == from->dev) { | 36 | goto out_put_route; |
42 | goto out_put_nb; | 37 | } |
43 | } | ||
44 | 38 | ||
45 | /* Remote end sending a call request on an already | 39 | /* Avoid a loop. This is the normal exit path for a |
46 | * established LCI? It shouldnt happen, just in case.. | 40 | * system with only one x.25 iface and default route |
47 | */ | 41 | */ |
48 | read_lock_bh(&x25_forward_list_lock); | 42 | if (rt->dev == from->dev) { |
49 | list_for_each(entry, &x25_forward_list) { | 43 | goto out_put_nb; |
50 | x25_frwd = list_entry(entry, struct x25_forward, node); | 44 | } |
51 | if (x25_frwd->lci == lci) { | 45 | |
52 | printk(KERN_WARNING "X.25: call request for lci which is already registered!, transmitting but not registering new pair\n"); | 46 | /* Remote end sending a call request on an already |
53 | same_lci = 1; | 47 | * established LCI? It shouldnt happen, just in case.. |
54 | } | 48 | */ |
55 | } | 49 | read_lock_bh(&x25_forward_list_lock); |
56 | read_unlock_bh(&x25_forward_list_lock); | 50 | list_for_each(entry, &x25_forward_list) { |
57 | 51 | x25_frwd = list_entry(entry, struct x25_forward, node); | |
58 | /* Save the forwarding details for future traffic */ | 52 | if (x25_frwd->lci == lci) { |
59 | if (!same_lci){ | 53 | printk(KERN_WARNING "X.25: call request for lci which is already registered!, transmitting but not registering new pair\n"); |
60 | if ((new_frwd = kmalloc(sizeof(struct x25_forward), | 54 | same_lci = 1; |
61 | GFP_ATOMIC)) == NULL){ | ||
62 | rc = -ENOMEM; | ||
63 | goto out_put_nb; | ||
64 | } | ||
65 | new_frwd->lci = lci; | ||
66 | new_frwd->dev1 = rt->dev; | ||
67 | new_frwd->dev2 = from->dev; | ||
68 | write_lock_bh(&x25_forward_list_lock); | ||
69 | list_add(&new_frwd->node, &x25_forward_list); | ||
70 | write_unlock_bh(&x25_forward_list_lock); | ||
71 | } | 55 | } |
56 | } | ||
57 | read_unlock_bh(&x25_forward_list_lock); | ||
72 | 58 | ||
73 | /* Forward the call request */ | 59 | /* Save the forwarding details for future traffic */ |
74 | if ( (skbn = skb_clone(skb, GFP_ATOMIC)) == NULL){ | 60 | if (!same_lci){ |
61 | if ((new_frwd = kmalloc(sizeof(struct x25_forward), | ||
62 | GFP_ATOMIC)) == NULL){ | ||
63 | rc = -ENOMEM; | ||
75 | goto out_put_nb; | 64 | goto out_put_nb; |
76 | } | 65 | } |
77 | x25_transmit_link(skbn, neigh_new); | 66 | new_frwd->lci = lci; |
78 | rc = 1; | 67 | new_frwd->dev1 = rt->dev; |
68 | new_frwd->dev2 = from->dev; | ||
69 | write_lock_bh(&x25_forward_list_lock); | ||
70 | list_add(&new_frwd->node, &x25_forward_list); | ||
71 | write_unlock_bh(&x25_forward_list_lock); | ||
79 | } | 72 | } |
80 | 73 | ||
74 | /* Forward the call request */ | ||
75 | if ( (skbn = skb_clone(skb, GFP_ATOMIC)) == NULL){ | ||
76 | goto out_put_nb; | ||
77 | } | ||
78 | x25_transmit_link(skbn, neigh_new); | ||
79 | rc = 1; | ||
80 | |||
81 | 81 | ||
82 | out_put_nb: | 82 | out_put_nb: |
83 | x25_neigh_put(neigh_new); | 83 | x25_neigh_put(neigh_new); |
84 | 84 | ||
85 | out_put_route: | 85 | out_put_route: |
86 | x25_route_put(rt); | 86 | x25_route_put(rt); |
87 | |||
88 | out_no_route: | ||
87 | return rc; | 89 | return rc; |
88 | } | 90 | } |
89 | 91 | ||
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0c3a70ac5075..785c3e39f062 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -2089,7 +2089,7 @@ void xfrm_audit_log(uid_t auid, u32 sid, int type, int result, | |||
2089 | sizeof(struct in6_addr)); | 2089 | sizeof(struct in6_addr)); |
2090 | } | 2090 | } |
2091 | audit_log_format(audit_buf, | 2091 | audit_log_format(audit_buf, |
2092 | " src=" NIP6_FMT "dst=" NIP6_FMT, | 2092 | " src=" NIP6_FMT " dst=" NIP6_FMT, |
2093 | NIP6(saddr6), NIP6(daddr6)); | 2093 | NIP6(saddr6), NIP6(daddr6)); |
2094 | } | 2094 | } |
2095 | break; | 2095 | break; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a35f9e4ede26..e3a0bcfa5df1 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -704,7 +704,8 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
704 | x->props.mode != mode || | 704 | x->props.mode != mode || |
705 | x->props.family != family || | 705 | x->props.family != family || |
706 | x->km.state != XFRM_STATE_ACQ || | 706 | x->km.state != XFRM_STATE_ACQ || |
707 | x->id.spi != 0) | 707 | x->id.spi != 0 || |
708 | x->id.proto != proto) | ||
708 | continue; | 709 | continue; |
709 | 710 | ||
710 | switch (family) { | 711 | switch (family) { |
@@ -801,7 +802,8 @@ int xfrm_state_add(struct xfrm_state *x) | |||
801 | 802 | ||
802 | if (use_spi && x->km.seq) { | 803 | if (use_spi && x->km.seq) { |
803 | x1 = __xfrm_find_acq_byseq(x->km.seq); | 804 | x1 = __xfrm_find_acq_byseq(x->km.seq); |
804 | if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) { | 805 | if (x1 && ((x1->id.proto != x->id.proto) || |
806 | xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { | ||
805 | xfrm_state_put(x1); | 807 | xfrm_state_put(x1); |
806 | x1 = NULL; | 808 | x1 = NULL; |
807 | } | 809 | } |
@@ -1369,7 +1371,8 @@ int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq) | |||
1369 | return 0; | 1371 | return 0; |
1370 | 1372 | ||
1371 | diff = x->replay.seq - seq; | 1373 | diff = x->replay.seq - seq; |
1372 | if (diff >= x->props.replay_window) { | 1374 | if (diff >= min_t(unsigned int, x->props.replay_window, |
1375 | sizeof(x->replay.bitmap) * 8)) { | ||
1373 | x->stats.replay_window++; | 1376 | x->stats.replay_window++; |
1374 | return -EINVAL; | 1377 | return -EINVAL; |
1375 | } | 1378 | } |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 96789952f6a3..816e3690b60f 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -272,9 +272,8 @@ static int attach_encap_tmpl(struct xfrm_encap_tmpl **encapp, struct rtattr *u_a | |||
272 | } | 272 | } |
273 | 273 | ||
274 | 274 | ||
275 | static inline int xfrm_user_sec_ctx_size(struct xfrm_policy *xp) | 275 | static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx) |
276 | { | 276 | { |
277 | struct xfrm_sec_ctx *xfrm_ctx = xp->security; | ||
278 | int len = 0; | 277 | int len = 0; |
279 | 278 | ||
280 | if (xfrm_ctx) { | 279 | if (xfrm_ctx) { |
@@ -2025,7 +2024,7 @@ nlmsg_failure: | |||
2025 | return -1; | 2024 | return -1; |
2026 | } | 2025 | } |
2027 | 2026 | ||
2028 | static int inline xfrm_sa_len(struct xfrm_state *x) | 2027 | static inline int xfrm_sa_len(struct xfrm_state *x) |
2029 | { | 2028 | { |
2030 | int l = 0; | 2029 | int l = 0; |
2031 | if (x->aalg) | 2030 | if (x->aalg) |
@@ -2170,7 +2169,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, | |||
2170 | 2169 | ||
2171 | len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); | 2170 | len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); |
2172 | len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire)); | 2171 | len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire)); |
2173 | len += RTA_SPACE(xfrm_user_sec_ctx_size(xp)); | 2172 | len += RTA_SPACE(xfrm_user_sec_ctx_size(x->security)); |
2174 | #ifdef CONFIG_XFRM_SUB_POLICY | 2173 | #ifdef CONFIG_XFRM_SUB_POLICY |
2175 | len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); | 2174 | len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); |
2176 | #endif | 2175 | #endif |
@@ -2280,7 +2279,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve | |||
2280 | 2279 | ||
2281 | len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); | 2280 | len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); |
2282 | len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire)); | 2281 | len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire)); |
2283 | len += RTA_SPACE(xfrm_user_sec_ctx_size(xp)); | 2282 | len += RTA_SPACE(xfrm_user_sec_ctx_size(xp->security)); |
2284 | #ifdef CONFIG_XFRM_SUB_POLICY | 2283 | #ifdef CONFIG_XFRM_SUB_POLICY |
2285 | len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); | 2284 | len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); |
2286 | #endif | 2285 | #endif |