Import 2.3.10pre5
[davej-history.git] / net / ipv4 / ip_masq_user.c
blob9264301ae23b2f5c620ed578cbf86bedd5318d11
1 /*
2 * IP_MASQ_USER user space control module
5 * $Id: ip_masq_user.c,v 1.1 1998/08/29 23:51:08 davem Exp $
6 */
8 #include <linux/config.h>
9 #include <linux/module.h>
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/skbuff.h>
14 #include <asm/system.h>
15 #include <linux/stat.h>
16 #include <linux/proc_fs.h>
17 #include <linux/in.h>
18 #include <linux/ip.h>
19 #include <linux/inet.h>
20 #include <linux/init.h>
21 #include <net/protocol.h>
22 #include <net/icmp.h>
23 #include <net/tcp.h>
24 #include <net/udp.h>
25 #include <net/checksum.h>
26 #include <net/ip_masq.h>
27 #include <net/ip_masq_mod.h>
28 #include <linux/sysctl.h>
29 #include <linux/ip_fw.h>
31 #include <linux/ip_masq.h>
34 * Debug level
36 static int debug=0;
38 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
39 MODULE_PARM(debug, "i");
42 static int check_5uple (struct ip_masq_user *ums) {
43 return 0;
46 static void masq_user_k2u(const struct ip_masq *ms, struct ip_masq_user *ums)
48 ums->protocol = ms->protocol;
49 ums->daddr = ms->daddr;
50 ums->dport = ms->dport;
51 ums->maddr = ms->maddr;
52 ums->mport = ms->mport;
53 ums->saddr = ms->saddr;
54 ums->sport = ms->sport;
55 ums->timeout = ms->timeout;
59 static int ip_masq_user_maddr(struct ip_masq_user *ums)
61 struct device *dev;
62 struct rtable *rt;
63 int ret = -EINVAL;
64 u32 rt_daddr, rt_saddr;
65 u32 tos;
68 * Did specify masq address.
70 if (ums->maddr)
71 return 0;
74 * Select address to use for routing query
77 rt_daddr = ums->rt_daddr? ums->rt_daddr : ums->daddr;
78 rt_saddr = ums->rt_saddr? ums->rt_saddr : ums->saddr;
82 * No address for routing, cannot continue
84 if (rt_daddr == 0) {
85 IP_MASQ_DEBUG(1-debug, "cannot setup maddr with daddr=%lX, rt_addr=%lX\n",
86 ntohl(ums->daddr), ntohl(ums->rt_daddr));
87 return -EINVAL;
91 * Find out rt device
94 rt_saddr = 0;
95 tos = RT_TOS(ums->ip_tos) | RTO_CONN;
97 if ((ret=ip_route_output(&rt, rt_daddr, rt_saddr, tos, 0 /* dev */))) {
98 IP_MASQ_DEBUG(0-debug, "could not setup maddr for routing daddr=%lX, saddr=%lX\n",
99 ntohl(rt_daddr), ntohl(rt_saddr));
100 return ret;
102 dev = rt->u.dst.dev;
103 ums->maddr = ip_masq_select_addr(dev, rt->rt_gateway, RT_SCOPE_UNIVERSE);
105 IP_MASQ_DEBUG(1-debug, "did setup maddr=%lX\n", ntohl(ums->maddr));
106 ip_rt_put(rt);
107 return 0;
111 * Create new entry (from uspace)
113 static int ip_masq_user_new(struct ip_masq_user *ums)
115 struct ip_masq *ms = NULL;
116 unsigned mflags = 0;
117 int ret;
119 if (masq_proto_num (ums->protocol) == -1) {
120 return EPROTONOSUPPORT;
123 if (ums->dport == 0) {
124 ums->flags |= IP_MASQ_USER_F_LISTEN;
127 if (ums->flags | IP_MASQ_USER_F_LISTEN) {
128 if ((ums->saddr == 0) || (ums->sport == 0)) {
129 return EINVAL;
131 mflags |= (IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR);
135 if ((ret = ip_masq_user_maddr(ums)) < 0) {
136 return -ret;
139 mflags |= IP_MASQ_F_USER;
140 ms = ip_masq_new(ums->protocol,
141 ums->maddr, ums->mport,
142 ums->saddr, ums->sport,
143 ums->daddr, ums->dport,
144 mflags);
146 if (ms == NULL) {
148 * FIXME: ip_masq_new() should return errno
150 return EBUSY;
154 * Setup timeouts for this new entry
157 if (ums->timeout) {
158 ms->timeout = ums->timeout;
159 } else if (ums->flags | IP_MASQ_USER_F_LISTEN) {
160 ip_masq_listen(ms);
163 masq_user_k2u(ms, ums);
164 ip_masq_put(ms);
165 return 0;
169 * Delete existing entry
171 static int ip_masq_user_del(struct ip_masq_user *ums)
173 struct ip_masq *ms=NULL;
175 if (masq_proto_num (ums->protocol) == -1) {
176 return EPROTONOSUPPORT;
178 start_bh_atomic();
179 if (ums->mport && ums->maddr) {
180 ms = ip_masq_in_get(ums->protocol,
181 ums->daddr, ums->dport,
182 ums->maddr, ums->mport);
183 end_bh_atomic();
184 } else if (ums->sport && ums->saddr) {
185 ms = ip_masq_out_get(ums->protocol,
186 ums->saddr, ums->sport,
187 ums->daddr, ums->dport);
188 end_bh_atomic();
189 } else
190 return EINVAL;
192 if (ms == NULL) {
193 return ESRCH;
197 * got (locked) entry, setup almost tiny timeout :) and
198 * give away
200 * FIXME: should use something better than S_CLOSE
202 ms->timeout = IP_MASQ_S_CLOSE;
204 masq_user_k2u(ms, ums);
205 ip_masq_put(ms);
206 return 0;
209 static struct ip_masq * ip_masq_user_locked_get (struct ip_masq_user *ums, int *err)
211 struct ip_masq *ms=NULL;
212 if (masq_proto_num (ums->protocol) == -1) {
213 *err = EPROTONOSUPPORT;
216 start_bh_atomic();
217 if (ums->mport && ums->maddr) {
218 ms = ip_masq_in_get(ums->protocol,
219 ums->daddr, ums->dport,
220 ums->maddr, ums->mport);
221 end_bh_atomic();
222 } else if (ums->sport && ums->saddr) {
223 ms = ip_masq_out_get(ums->protocol,
224 ums->saddr, ums->sport,
225 ums->daddr, ums->dport);
226 end_bh_atomic();
227 } else
228 *err = EINVAL;
230 if (ms == NULL) *err = ESRCH;
231 return ms;
235 * Get existing entry (complete full tunnel info)
237 static int ip_masq_user_get(struct ip_masq_user *ums)
239 struct ip_masq *ms=NULL;
240 int err;
242 ms = ip_masq_user_locked_get(ums, &err);
243 if (ms == NULL)
244 return err;
246 masq_user_k2u(ms, ums);
248 ip_masq_put(ms);
249 return 0;
253 * Set (some, valid) entry parameters
255 static int ip_masq_user_set(struct ip_masq_user *ums)
257 struct ip_masq *ms = NULL;
258 int err;
260 ms = ip_masq_user_locked_get(ums, &err);
261 if (ms == NULL)
262 return err;
265 * FIXME: must allow selecting what you want to set
267 ms->timeout = ums->timeout;
269 masq_user_k2u(ms, ums);
271 ip_masq_put(ms);
272 return 0;
277 * Entry point
278 * ret value:
279 * <0 err
280 * ==0 ok
281 * >0 ok, copy to user
283 static int ip_masq_user_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
285 struct ip_masq_user *ums = &mctl->u.user;
286 int ret = EINVAL;
287 int arglen = optlen - IP_MASQ_CTL_BSIZE;
288 int cmd;
290 IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n",
291 arglen,
292 sizeof (*ums),
293 optlen,
294 sizeof (*mctl));
297 * Yes, I'm a bad guy ...
299 if (arglen != sizeof(*ums) && optlen != sizeof(*mctl))
300 return EINVAL;
302 MOD_INC_USE_COUNT;
305 * Don't trust the lusers - plenty of error checking!
307 cmd = mctl->m_cmd;
308 IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(cmd=%d)\n", cmd);
310 switch (mctl->m_cmd) {
311 case IP_MASQ_CMD_ADD:
312 case IP_MASQ_CMD_INSERT:
313 ret = ip_masq_user_new(ums);
314 break;
315 case IP_MASQ_CMD_DEL:
316 ret = ip_masq_user_del(ums);
317 break;
318 case IP_MASQ_CMD_SET:
319 ret = ip_masq_user_set(ums);
320 break;
321 case IP_MASQ_CMD_GET:
322 ret = ip_masq_user_get(ums);
323 break;
327 * For all of the above, return masq tunnel info
330 ret = -ret;
332 if (ret == 0) {
333 ret = sizeof (*ums) + IP_MASQ_CTL_BSIZE;
334 IP_MASQ_DEBUG(1-debug, "will return %d bytes to user\n", ret);
337 MOD_DEC_USE_COUNT;
338 return ret;
342 #ifdef CONFIG_PROC_FS
343 static int ip_masq_user_info(char *buffer, char **start, off_t offset,
344 int length, int proto)
346 off_t pos=0, begin;
347 struct ip_masq *ms;
348 char temp[129];
349 int idx = 0;
350 int len=0;
351 int magic_control;
353 MOD_INC_USE_COUNT;
355 IP_MASQ_DEBUG(1-debug, "Entered user_info with proto=%d\n", proto);
357 if (offset < 128)
359 sprintf(temp,
360 "Prot SrcIP SPrt DstIP DPrt MAddr MPrt State Flgs Ref Ctl Expires (free=%d,%d,%d)",
361 atomic_read(ip_masq_free_ports),
362 atomic_read(ip_masq_free_ports+1),
363 atomic_read(ip_masq_free_ports+2));
364 len = sprintf(buffer, "%-127s\n", temp);
366 pos = 128;
368 for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
371 * Lock is actually only need in next loop
372 * we are called from uspace: must stop bh.
374 read_lock_bh(&__ip_masq_lock);
375 for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
377 if (ms->protocol != proto) {
378 continue;
381 pos += 128;
382 if (pos <= offset) {
383 len = 0;
384 continue;
388 * We have locked the tables, no need to del/add timers
389 * nor cli() 8)
393 magic_control = atomic_read(&ms->n_control);
394 if (!magic_control && ms->control) magic_control = -1;
395 sprintf(temp,"%-4s %08lX:%04X %08lX:%04X %08lX:%04X %-12s %3X %4d %3d %7lu",
396 masq_proto_name(ms->protocol),
397 ntohl(ms->saddr), ntohs(ms->sport),
398 ntohl(ms->daddr), ntohs(ms->dport),
399 ntohl(ms->maddr), ntohs(ms->mport),
400 ip_masq_state_name(ms->state),
401 ms->flags,
402 atomic_read(&ms->refcnt),
403 magic_control,
404 (ms->timer.expires-jiffies)/HZ);
405 len += sprintf(buffer+len, "%-127s\n", temp);
407 if(len >= length) {
408 read_unlock_bh(&__ip_masq_lock);
409 goto done;
412 read_unlock_bh(&__ip_masq_lock);
415 done:
417 if (len) {
418 begin = len - (pos - offset);
419 *start = buffer + begin;
420 len -= begin;
422 if(len>length)
423 len = length;
424 MOD_DEC_USE_COUNT;
425 return len;
427 #else
428 #define ip_masq_user_info NULL
429 #endif
431 static struct ip_masq_hook ip_masq_user = {
432 ip_masq_user_ctl,
433 ip_masq_user_info
436 int ip_masq_user_init(void)
438 if (ip_masq_user_hook != NULL)
439 return -EEXIST;
440 ip_masq_user_hook = &ip_masq_user;
441 return 0;
444 int ip_masq_user_done(void)
446 if (ip_masq_user_hook == NULL)
447 return ENOENT;
448 ip_masq_user_hook = NULL;
449 return 0;
452 #ifdef MODULE
453 EXPORT_NO_SYMBOLS;
454 int init_module(void)
456 if (ip_masq_user_init() != 0)
457 return -EIO;
458 return 0;
461 void cleanup_module(void)
463 if (ip_masq_user_done() != 0)
464 printk(KERN_INFO "ip_masq_user_done(): can't remove module");
467 #endif /* MODULE */