OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [ipv4/] [netfilter/] [ip_nat_irc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* IRC extension for TCP NAT alteration.
2
 * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
3
 * based on a copy of RR's ip_nat_ftp.c
4
 *
5
 * ip_nat_irc.c,v 1.16 2001/12/06 07:42:10 laforge Exp
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
 *      as published by the Free Software Foundation; either version
10
 *      2 of the License, or (at your option) any later version.
11
 *
12
 *      Module load syntax:
13
 *      insmod ip_nat_irc.o ports=port1,port2,...port<MAX_PORTS>
14
 *
15
 *      please give the ports of all IRC servers You wish to connect to.
16
 *      If You don't specify ports, the default will be port 6667
17
 */
18
 
19
#include <linux/module.h>
20
#include <linux/netfilter_ipv4.h>
21
#include <linux/ip.h>
22
#include <linux/tcp.h>
23
#include <linux/kernel.h>
24
#include <net/tcp.h>
25
#include <linux/netfilter_ipv4/ip_nat.h>
26
#include <linux/netfilter_ipv4/ip_nat_helper.h>
27
#include <linux/netfilter_ipv4/ip_nat_rule.h>
28
#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
29
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
30
 
31
#if 0
32
#define DEBUGP printk
33
#else
34
#define DEBUGP(format, args...)
35
#endif
36
 
37
#define MAX_PORTS 8
38
static int ports[MAX_PORTS];
39
static int ports_c = 0;
40
 
41
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
42
MODULE_DESCRIPTION("IRC (DCC) network address translation module");
43
MODULE_LICENSE("GPL");
44
#ifdef MODULE_PARM
45
MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
46
MODULE_PARM_DESC(ports, "port numbers of IRC servers");
47
#endif
48
 
49
/* protects irc part of conntracks */
50
DECLARE_LOCK_EXTERN(ip_irc_lock);
51
 
52
/* FIXME: Time out? --RR */
53
 
54
static unsigned int
55
irc_nat_expected(struct sk_buff **pskb,
56
                 unsigned int hooknum,
57
                 struct ip_conntrack *ct,
58
                 struct ip_nat_info *info)
59
{
60
        struct ip_nat_multi_range mr;
61
        u_int32_t newdstip, newsrcip, newip;
62
 
63
        struct ip_conntrack *master = master_ct(ct);
64
 
65
        IP_NF_ASSERT(info);
66
        IP_NF_ASSERT(master);
67
 
68
        IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
69
 
70
        DEBUGP("nat_expected: We have a connection!\n");
71
 
72
        newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
73
        newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
74
        DEBUGP("nat_expected: DCC cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
75
               NIPQUAD(newsrcip), NIPQUAD(newdstip));
76
 
77
        if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
78
                newip = newsrcip;
79
        else
80
                newip = newdstip;
81
 
82
        DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
83
 
84
        mr.rangesize = 1;
85
        /* We don't want to manip the per-protocol, just the IPs. */
86
        mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
87
        mr.range[0].min_ip = mr.range[0].max_ip = newip;
88
 
89
        return ip_nat_setup_info(ct, &mr, hooknum);
90
}
91
 
92
static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
93
                          struct ip_conntrack *ct,
94
                          struct sk_buff **pskb,
95
                          enum ip_conntrack_info ctinfo,
96
                          struct ip_conntrack_expect *expect)
97
{
98
        u_int32_t newip;
99
        struct ip_conntrack_tuple t;
100
        struct iphdr *iph = (*pskb)->nh.iph;
101
        struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
102
        u_int16_t port;
103
 
104
        /* "4294967296 65635 " */
105
        char buffer[18];
106
 
107
        MUST_BE_LOCKED(&ip_irc_lock);
108
 
109
        DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
110
               expect->seq, ct_irc_info->len,
111
               ntohl(tcph->seq));
112
 
113
        newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
114
 
115
        /* Alter conntrack's expectations. */
116
 
117
        /* We can read expect here without conntrack lock, since it's
118
           only set in ip_conntrack_irc, with ip_irc_lock held
119
           writable */
120
 
121
        t = expect->tuple;
122
        t.dst.ip = newip;
123
        for (port = ct_irc_info->port; port != 0; port++) {
124
                t.dst.u.tcp.port = htons(port);
125
                if (ip_conntrack_change_expect(expect, &t) == 0) {
126
                        DEBUGP("using port %d", port);
127
                        break;
128
                }
129
 
130
        }
131
        if (port == 0)
132
                return 0;
133
 
134
        /*      strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
135
         *      strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
136
         *      strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
137
         *      strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
138
         *      strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
139
         *              AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits,
140
         *                      255.255.255.255==4294967296, 10 digits)
141
         *              P:         bound port (min 1 d, max 5d (65635))
142
         *              F:         filename   (min 1 d )
143
         *              S:         size       (min 1 d )
144
         *              0x01, \n:  terminators
145
         */
146
 
147
        sprintf(buffer, "%u %u", ntohl(newip), port);
148
        DEBUGP("ip_nat_irc: Inserting '%s' == %u.%u.%u.%u, port %u\n",
149
               buffer, NIPQUAD(newip), port);
150
 
151
        return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
152
                                        expect->seq - ntohl(tcph->seq),
153
                                        ct_irc_info->len, buffer,
154
                                        strlen(buffer));
155
}
156
 
157
static unsigned int help(struct ip_conntrack *ct,
158
                         struct ip_conntrack_expect *exp,
159
                         struct ip_nat_info *info,
160
                         enum ip_conntrack_info ctinfo,
161
                         unsigned int hooknum,
162
                         struct sk_buff **pskb)
163
{
164
        struct iphdr *iph = (*pskb)->nh.iph;
165
        struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
166
        unsigned int datalen;
167
        int dir;
168
        struct ip_ct_irc_expect *ct_irc_info;
169
 
170
        if (!exp)
171
                DEBUGP("ip_nat_irc: no exp!!");
172
 
173
        ct_irc_info = &exp->help.exp_irc_info;
174
 
175
        /* Only mangle things once: original direction in POST_ROUTING
176
           and reply direction on PRE_ROUTING. */
177
        dir = CTINFO2DIR(ctinfo);
178
        if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
179
              || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
180
                DEBUGP("nat_irc: Not touching dir %s at hook %s\n",
181
                       dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
182
                       hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
183
                       : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
184
                       : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
185
                return NF_ACCEPT;
186
        }
187
        DEBUGP("got beyond not touching\n");
188
 
189
        datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
190
        LOCK_BH(&ip_irc_lock);
191
        /* Check wether the whole IP/address pattern is carried in the payload */
192
        if (between(exp->seq + ct_irc_info->len,
193
                    ntohl(tcph->seq),
194
                    ntohl(tcph->seq) + datalen)) {
195
                if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) {
196
                        UNLOCK_BH(&ip_irc_lock);
197
                        return NF_DROP;
198
                }
199
        } else {
200
                /* Half a match?  This means a partial retransmisison.
201
                   It's a cracker being funky. */
202
                if (net_ratelimit()) {
203
                        printk
204
                            ("IRC_NAT: partial packet %u/%u in %u/%u\n",
205
                             exp->seq, ct_irc_info->len,
206
                             ntohl(tcph->seq),
207
                             ntohl(tcph->seq) + datalen);
208
                }
209
                UNLOCK_BH(&ip_irc_lock);
210
                return NF_DROP;
211
        }
212
        UNLOCK_BH(&ip_irc_lock);
213
 
214
        return NF_ACCEPT;
215
}
216
 
217
static struct ip_nat_helper ip_nat_irc_helpers[MAX_PORTS];
218
static char irc_names[MAX_PORTS][10];
219
 
220
/* This function is intentionally _NOT_ defined as  __exit, because
221
 * it is needed by init() */
222
static void fini(void)
223
{
224
        int i;
225
 
226
        for (i = 0; i < ports_c; i++) {
227
                DEBUGP("ip_nat_irc: unregistering helper for port %d\n",
228
                       ports[i]);
229
                ip_nat_helper_unregister(&ip_nat_irc_helpers[i]);
230
        }
231
}
232
 
233
static int __init init(void)
234
{
235
        int ret = 0;
236
        int i;
237
        struct ip_nat_helper *hlpr;
238
        char *tmpname;
239
 
240
        if (ports[0] == 0) {
241
                ports[0] = IRC_PORT;
242
        }
243
 
244
        for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
245
                hlpr = &ip_nat_irc_helpers[i];
246
                hlpr->tuple.dst.protonum = IPPROTO_TCP;
247
                hlpr->tuple.src.u.tcp.port = htons(ports[i]);
248
                hlpr->mask.src.u.tcp.port = 0xFFFF;
249
                hlpr->mask.dst.protonum = 0xFFFF;
250
                hlpr->help = help;
251
                hlpr->flags = 0;
252
                hlpr->me = THIS_MODULE;
253
                hlpr->expect = irc_nat_expected;
254
 
255
                tmpname = &irc_names[i][0];
256
                if (ports[i] == IRC_PORT)
257
                        sprintf(tmpname, "irc");
258
                else
259
                        sprintf(tmpname, "irc-%d", i);
260
                hlpr->name = tmpname;
261
 
262
                DEBUGP
263
                    ("ip_nat_irc: Trying to register helper for port %d: name %s\n",
264
                     ports[i], hlpr->name);
265
                ret = ip_nat_helper_register(hlpr);
266
 
267
                if (ret) {
268
                        printk
269
                            ("ip_nat_irc: error registering helper for port %d\n",
270
                             ports[i]);
271
                        fini();
272
                        return 1;
273
                }
274
                ports_c++;
275
        }
276
        return ret;
277
}
278
 
279
 
280
module_init(init);
281
module_exit(fini);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.