cfg80211: fix error path in cfg80211_wext_siwscan
[safe/jmp/linux-2.6] / net / netfilter / ipvs / ip_vs_proto_ah_esp.c
1 /*
2  * ip_vs_proto_ah_esp.c:        AH/ESP IPSec load balancing support for IPVS
3  *
4  * Authors:     Julian Anastasov <ja@ssi.bg>, February 2002
5  *              Wensong Zhang <wensong@linuxvirtualserver.org>
6  *
7  *              This program is free software; you can redistribute it and/or
8  *              modify it under the terms of the GNU General Public License
9  *              version 2 as published by the Free Software Foundation;
10  *
11  */
12
13 #define KMSG_COMPONENT "IPVS"
14 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
15
16 #include <linux/in.h>
17 #include <linux/ip.h>
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/netfilter.h>
21 #include <linux/netfilter_ipv4.h>
22
23 #include <net/ip_vs.h>
24
25
26 /* TODO:
27
28 struct isakmp_hdr {
29         __u8            icookie[8];
30         __u8            rcookie[8];
31         __u8            np;
32         __u8            version;
33         __u8            xchgtype;
34         __u8            flags;
35         __u32           msgid;
36         __u32           length;
37 };
38
39 */
40
41 #define PORT_ISAKMP     500
42
43
44 static struct ip_vs_conn *
45 ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
46                    const struct ip_vs_iphdr *iph, unsigned int proto_off,
47                    int inverse)
48 {
49         struct ip_vs_conn *cp;
50
51         if (likely(!inverse)) {
52                 cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
53                                        &iph->saddr,
54                                        htons(PORT_ISAKMP),
55                                        &iph->daddr,
56                                        htons(PORT_ISAKMP));
57         } else {
58                 cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
59                                        &iph->daddr,
60                                        htons(PORT_ISAKMP),
61                                        &iph->saddr,
62                                        htons(PORT_ISAKMP));
63         }
64
65         if (!cp) {
66                 /*
67                  * We are not sure if the packet is from our
68                  * service, so our conn_schedule hook should return NF_ACCEPT
69                  */
70                 IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet "
71                               "%s%s %s->%s\n",
72                               inverse ? "ICMP+" : "",
73                               pp->name,
74                               IP_VS_DBG_ADDR(af, &iph->saddr),
75                               IP_VS_DBG_ADDR(af, &iph->daddr));
76         }
77
78         return cp;
79 }
80
81
82 static struct ip_vs_conn *
83 ah_esp_conn_out_get(int af, const struct sk_buff *skb,
84                     struct ip_vs_protocol *pp,
85                     const struct ip_vs_iphdr *iph,
86                     unsigned int proto_off,
87                     int inverse)
88 {
89         struct ip_vs_conn *cp;
90
91         if (likely(!inverse)) {
92                 cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
93                                         &iph->saddr,
94                                         htons(PORT_ISAKMP),
95                                         &iph->daddr,
96                                         htons(PORT_ISAKMP));
97         } else {
98                 cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
99                                         &iph->daddr,
100                                         htons(PORT_ISAKMP),
101                                         &iph->saddr,
102                                         htons(PORT_ISAKMP));
103         }
104
105         if (!cp) {
106                 IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet "
107                               "%s%s %s->%s\n",
108                               inverse ? "ICMP+" : "",
109                               pp->name,
110                               IP_VS_DBG_ADDR(af, &iph->saddr),
111                               IP_VS_DBG_ADDR(af, &iph->daddr));
112         }
113
114         return cp;
115 }
116
117
118 static int
119 ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
120                      int *verdict, struct ip_vs_conn **cpp)
121 {
122         /*
123          * AH/ESP is only related traffic. Pass the packet to IP stack.
124          */
125         *verdict = NF_ACCEPT;
126         return 0;
127 }
128
129
130 static void
131 ah_esp_debug_packet_v4(struct ip_vs_protocol *pp, const struct sk_buff *skb,
132                        int offset, const char *msg)
133 {
134         char buf[256];
135         struct iphdr _iph, *ih;
136
137         ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
138         if (ih == NULL)
139                 sprintf(buf, "%s TRUNCATED", pp->name);
140         else
141                 sprintf(buf, "%s %pI4->%pI4",
142                         pp->name, &ih->saddr, &ih->daddr);
143
144         pr_debug("%s: %s\n", msg, buf);
145 }
146
147 #ifdef CONFIG_IP_VS_IPV6
148 static void
149 ah_esp_debug_packet_v6(struct ip_vs_protocol *pp, const struct sk_buff *skb,
150                        int offset, const char *msg)
151 {
152         char buf[256];
153         struct ipv6hdr _iph, *ih;
154
155         ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
156         if (ih == NULL)
157                 sprintf(buf, "%s TRUNCATED", pp->name);
158         else
159                 sprintf(buf, "%s %pI6->%pI6",
160                         pp->name, &ih->saddr, &ih->daddr);
161
162         pr_debug("%s: %s\n", msg, buf);
163 }
164 #endif
165
166 static void
167 ah_esp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb,
168                     int offset, const char *msg)
169 {
170 #ifdef CONFIG_IP_VS_IPV6
171         if (skb->protocol == htons(ETH_P_IPV6))
172                 ah_esp_debug_packet_v6(pp, skb, offset, msg);
173         else
174 #endif
175                 ah_esp_debug_packet_v4(pp, skb, offset, msg);
176 }
177
178
179 static void ah_esp_init(struct ip_vs_protocol *pp)
180 {
181         /* nothing to do now */
182 }
183
184
185 static void ah_esp_exit(struct ip_vs_protocol *pp)
186 {
187         /* nothing to do now */
188 }
189
190
191 #ifdef CONFIG_IP_VS_PROTO_AH
192 struct ip_vs_protocol ip_vs_protocol_ah = {
193         .name =                 "AH",
194         .protocol =             IPPROTO_AH,
195         .num_states =           1,
196         .dont_defrag =          1,
197         .init =                 ah_esp_init,
198         .exit =                 ah_esp_exit,
199         .conn_schedule =        ah_esp_conn_schedule,
200         .conn_in_get =          ah_esp_conn_in_get,
201         .conn_out_get =         ah_esp_conn_out_get,
202         .snat_handler =         NULL,
203         .dnat_handler =         NULL,
204         .csum_check =           NULL,
205         .state_transition =     NULL,
206         .register_app =         NULL,
207         .unregister_app =       NULL,
208         .app_conn_bind =        NULL,
209         .debug_packet =         ah_esp_debug_packet,
210         .timeout_change =       NULL,           /* ISAKMP */
211         .set_state_timeout =    NULL,
212 };
213 #endif
214
215 #ifdef CONFIG_IP_VS_PROTO_ESP
216 struct ip_vs_protocol ip_vs_protocol_esp = {
217         .name =                 "ESP",
218         .protocol =             IPPROTO_ESP,
219         .num_states =           1,
220         .dont_defrag =          1,
221         .init =                 ah_esp_init,
222         .exit =                 ah_esp_exit,
223         .conn_schedule =        ah_esp_conn_schedule,
224         .conn_in_get =          ah_esp_conn_in_get,
225         .conn_out_get =         ah_esp_conn_out_get,
226         .snat_handler =         NULL,
227         .dnat_handler =         NULL,
228         .csum_check =           NULL,
229         .state_transition =     NULL,
230         .register_app =         NULL,
231         .unregister_app =       NULL,
232         .app_conn_bind =        NULL,
233         .debug_packet =         ah_esp_debug_packet,
234         .timeout_change =       NULL,           /* ISAKMP */
235 };
236 #endif