Import 2.3.13
[davej-history.git] / net / ipv4 / ip_masq_cuseeme.c
blob9b412bafe02ec6381fafb835ce3c7c16f34fb3c8
1 /*
2 * IP_MASQ_FTP CUSeeMe masquerading module
5 * Version: @(#)$Id: ip_masq_cuseeme.c,v 1.4 1998/10/06 04:48:57 davem Exp $
7 * Author: Richard Lynch
8 *
10 * Fixes:
11 * Richard Lynch : Updated patch to conform to new module
12 * specifications
13 * Nigel Metheringham : Multiple port support
14 * Michael Owings : Fixed broken init code
15 * Added code to update inbound
16 * packets with correct local addresses.
17 * Fixes audio and "chat" problems
18 * Thanx to the CU-SeeMe Consortium for
19 * technical docs
20 * Steven Clarke : Small changes for 2.1
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * as published by the Free Software Foundation; either version
27 * 2 of the License, or (at your option) any later version.
29 * Multiple Port Support
30 * The helper can be made to handle up to MAX_MASQ_APP_PORTS (normally 12)
31 * with the port numbers being defined at module load time. The module
32 * uses the symbol "ports" to define a list of monitored ports, which can
33 * be specified on the insmod command line as
34 * ports=x1,x2,x3...
35 * where x[n] are integer port numbers. This option can be put into
36 * /etc/conf.modules (or /etc/modules.conf depending on your config)
37 * where modload will pick it up should you use modload to load your
38 * modules.
42 #include <linux/config.h>
43 #include <linux/module.h>
44 #include <asm/system.h>
45 #include <linux/types.h>
46 #include <linux/kernel.h>
47 #include <linux/skbuff.h>
48 #include <linux/in.h>
49 #include <linux/ip.h>
50 #include <linux/init.h>
51 #include <net/protocol.h>
52 #include <net/udp.h>
54 /* #define IP_MASQ_NDEBUG */
55 #include <net/ip_masq.h>
57 #pragma pack(1)
58 /* CU-SeeMe Data Header */
59 typedef struct {
60 u_short dest_family;
61 u_short dest_port;
62 u_long dest_addr;
63 short family;
64 u_short port;
65 u_long addr;
66 u_long seq;
67 u_short msg;
68 u_short data_type;
69 u_short packet_len;
70 } cu_header;
72 /* Open Continue Header */
73 typedef struct {
74 cu_header cu_head;
75 u_short client_count; /* Number of client info structs */
76 u_long seq_no;
77 char user_name[20];
78 char stuff[4]; /* flags, version stuff, etc */
79 }oc_header;
81 /* client info structures */
82 typedef struct {
83 u_long address; /* Client address */
84 char stuff[8]; /* Flags, pruning bitfield, packet counts etc */
85 } client_info;
86 #pragma pack()
89 * List of ports (up to MAX_MASQ_APP_PORTS) to be handled by helper
90 * First port is set to the default port.
92 static int ports[MAX_MASQ_APP_PORTS] = {7648}; /* I rely on the trailing items being set to zero */
93 struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
96 * Debug level
98 #ifdef CONFIG_IP_MASQ_DEBUG
99 static int debug=0;
100 MODULE_PARM(debug, "i");
101 #endif
103 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
105 static int
106 masq_cuseeme_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
108 MOD_INC_USE_COUNT;
109 return 0;
112 static int
113 masq_cuseeme_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
115 MOD_DEC_USE_COUNT;
116 return 0;
120 masq_cuseeme_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
122 struct sk_buff *skb = *skb_p;
123 struct iphdr *iph = skb->nh.iph;
124 struct udphdr *uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
125 cu_header *cu_head;
126 char *data=(char *)&uh[1];
128 if (skb->len - ((unsigned char *) data - skb->h.raw) >= sizeof(cu_header))
130 cu_head = (cu_header *) data;
131 /* cu_head->port = ms->mport; */
132 if( cu_head->addr )
133 cu_head->addr = (u_long) maddr;
134 if(ntohs(cu_head->data_type) == 257)
135 IP_MASQ_DEBUG(1-debug, "Sending talk packet!\n");
137 return 0;
141 masq_cuseeme_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
143 struct sk_buff *skb = *skb_p;
144 struct iphdr *iph = skb->nh.iph;
145 struct udphdr *uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
146 cu_header *cu_head;
147 oc_header *oc;
148 client_info *ci;
149 char *data=(char *)&uh[1];
150 u_short len = skb->len - ((unsigned char *) data - skb->h.raw);
151 int i, off;
153 if (len >= sizeof(cu_header))
155 cu_head = (cu_header *) data;
156 if(cu_head->dest_addr) /* Correct destination address */
157 cu_head->dest_addr = (u_long) ms->saddr;
158 if(ntohs(cu_head->data_type)==101 && len > sizeof(oc_header))
160 oc = (oc_header * ) data;
161 /* Spin (grovel) thru client_info structs till we find our own */
162 off=sizeof(oc_header);
163 for(i=0;
164 (i < oc->client_count && off+sizeof(client_info) <= len);
165 i++)
167 ci=(client_info *)(data+off);
168 if(ci->address==(u_long) maddr)
170 /* Update w/ our real ip address and exit */
171 ci->address = (u_long) ms->saddr;
172 break;
174 else
175 off+=sizeof(client_info);
179 return 0;
182 struct ip_masq_app ip_masq_cuseeme = {
183 NULL, /* next */
184 "cuseeme",
185 0, /* type */
186 0, /* n_attach */
187 masq_cuseeme_init_1, /* ip_masq_init_1 */
188 masq_cuseeme_done_1, /* ip_masq_done_1 */
189 masq_cuseeme_out, /* pkt_out */
190 masq_cuseeme_in /* pkt_in */
195 * ip_masq_cuseeme initialization
198 __initfunc(int ip_masq_cuseeme_init(void))
200 int i, j;
202 for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
203 if (ports[i]) {
204 if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
205 GFP_KERNEL)) == NULL)
206 return -ENOMEM;
207 memcpy(masq_incarnations[i], &ip_masq_cuseeme, sizeof(struct ip_masq_app));
208 if ((j = register_ip_masq_app(masq_incarnations[i],
209 IPPROTO_UDP,
210 ports[i]))) {
211 return j;
213 #if DEBUG_CONFIG_IP_MASQ_CUSEEME
214 IP_MASQ_DEBUG(1-debug, "CuSeeMe: loaded support on port[%d] = %d\n",
215 i, ports[i]);
216 #endif
217 } else {
218 /* To be safe, force the incarnation table entry to NULL */
219 masq_incarnations[i] = NULL;
222 return 0;
226 * ip_masq_cuseeme fin.
229 int ip_masq_cuseeme_done(void)
231 int i, j, k;
233 k=0;
234 for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
235 if (masq_incarnations[i]) {
236 if ((j = unregister_ip_masq_app(masq_incarnations[i]))) {
237 k = j;
238 } else {
239 kfree(masq_incarnations[i]);
240 masq_incarnations[i] = NULL;
241 IP_MASQ_DEBUG(1-debug, "CuSeeMe: unloaded support on port[%d] = %d\n", i, ports[i]);
245 return k;
248 #ifdef MODULE
249 EXPORT_NO_SYMBOLS;
251 int init_module(void)
253 if (ip_masq_cuseeme_init() != 0)
254 return -EIO;
255 return 0;
258 void cleanup_module(void)
260 if (ip_masq_cuseeme_done() != 0)
261 IP_MASQ_DEBUG(1-debug, "ip_masq_cuseeme: can't remove module");
264 #endif /* MODULE */