Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libipt_rpc.c
blobdbfb3962639f138a40ae9680b1457110ef54e2e1
1 /* RPC extension for IP connection matching, Version 2.2
2 * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3 * - original rpc tracking module
4 * - "recent" connection handling for kernel 2.3+ netfilter
6 * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
7 * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
9 * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
10 * - upgraded conntrack modules to newnat api - kernel 2.4.20+
11 * - extended matching to support filtering on procedures
13 * libipt_rpc.c,v 2.2 2003/01/12 18:30:00
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version
18 * 2 of the License, or (at your option) any later version.
20 * Userspace library syntax:
21 * --rpc [--rpcs procedure1,procedure2,...procedure128] [--static]
23 * Procedures can be supplied in either numeric or named formats.
24 * Without --rpcs, this module will behave as the old record-rpc.
26 * Note to all:
28 * RPCs should not be exposed to the internet - ask the Pentagon;
30 * "The unidentified crackers pleaded guilty in July to charges
31 * of juvenile delinquency stemming from a string of Pentagon
32 * network intrusions in February.
34 * The youths, going by the names TooShort and Makaveli, used
35 * a common server security hole to break in, according to
36 * Dane Jasper, owner of the California Internet service
37 * provider, Sonic. They used the hole, known as the 'statd'
38 * exploit, to attempt more than 800 break-ins, Jasper said."
40 * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
41 * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
45 #include <stdio.h>
46 #include <netdb.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include <getopt.h>
50 #include <rpc/rpc.h>
52 #include <iptables.h>
53 #include <linux/netfilter_ipv4/ipt_rpc.h>
54 #include <time.h>
57 const int IPT_RPC_RPCS = 1;
58 const int IPT_RPC_STRC = 2;
60 const int IPT_RPC_INT_LBL = 1;
61 const int IPT_RPC_INT_NUM = 2;
62 const int IPT_RPC_INT_BTH = 3;
64 const int IPT_RPC_CHAR_LEN = 11;
65 const int IPT_RPC_MAX_ENTS = 128;
67 const char preerr[11] = "RPC match:";
70 static int k_itoa(char *string, int number)
72 int maxoctet = IPT_RPC_CHAR_LEN - 1;
73 int store[IPT_RPC_CHAR_LEN];
74 int counter;
77 for (counter=0 ; maxoctet != 0 && number != 0; counter++, maxoctet--) {
78 store[counter] = number / 10;
79 store[counter] = number - ( store[counter] * 10 );
80 number = number / 10;
83 for ( ; counter != 0; counter--, string++)
84 *string = store[counter - 1] + 48;
86 *string = 0;
88 return(0);
92 static int k_atoi(char *string)
94 unsigned int result = 0;
95 int maxoctet = IPT_RPC_CHAR_LEN;
98 for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
99 if (*string < 0)
100 return(0);
101 if (*string == 0)
102 break;
103 if (*string < 48 || *string > 57) {
104 return(0);
106 result = result * 10 + ( *string - 48 );
109 return(result);
113 static void print_rpcs(char *c_procs, int i_procs, int labels)
115 int proc_ctr;
116 char *proc_ptr;
117 unsigned int proc_num;
118 struct rpcent *rpcent;
121 for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
123 if ( proc_ctr != 0 )
124 printf(",");
126 proc_ptr = c_procs;
127 proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
128 proc_num = k_atoi(proc_ptr);
130 /* labels(1) == no labels, only numbers
131 * labels(2) == no numbers, only labels
132 * labels(3) == both labels and numbers
135 if (labels == IPT_RPC_INT_LBL || labels == IPT_RPC_INT_BTH ) {
136 if ( (rpcent = getrpcbynumber(proc_num)) == NULL )
137 printf("unknown");
138 else
139 printf("%s", rpcent->r_name);
142 if (labels == IPT_RPC_INT_BTH )
143 printf("(");
145 if (labels == IPT_RPC_INT_NUM || labels == IPT_RPC_INT_BTH )
146 printf("%i", proc_num);
148 if (labels == IPT_RPC_INT_BTH )
149 printf(")");
156 static void help(void)
158 printf(
159 "RPC v%s options:\n"
160 " --rpcs list,of,procedures"
161 "\ta list of rpc program numbers to apply\n"
162 "\t\t\t\tie. 100003,mountd,rquotad (numeric or\n"
163 "\t\t\t\tname form; see /etc/rpc).\n"
164 " --strict"
165 "\t\t\ta flag to force the drop of packets\n"
166 "\t\t\t\tnot containing \"get\" portmapper requests.\n",
167 IPTABLES_VERSION);
171 static struct option opts[] = {
172 { "rpcs", 1, 0, '1'},
173 { "strict", 0, 0, '2'},
178 static void init(struct ipt_entry_match *match, unsigned int *nfcache)
180 struct ipt_rpc_info *rpcinfo = ((struct ipt_rpc_info *)match->data);
184 /* initialise those funky user vars */
185 rpcinfo->i_procs = -1;
186 rpcinfo->strict = 0;
187 memset((char *)rpcinfo->c_procs, 0, sizeof(rpcinfo->c_procs));
191 static void parse_rpcs_string(char *string, struct ipt_entry_match **match)
193 char err1[64] = "%s invalid --rpcs option-set: `%s' (at character %i)";
194 char err2[64] = "%s unable to resolve rpc name entry: `%s'";
195 char err3[64] = "%s maximum number of --rpc options (%i) exceeded";
196 char buf[256];
197 char *dup = buf;
198 int idup = 0;
199 int term = 0;
200 char *src, *dst;
201 char *c_procs;
202 struct rpcent *rpcent_ptr;
203 struct ipt_rpc_info *rpcinfo = (struct ipt_rpc_info *)(*match)->data;
206 memset(buf, 0, sizeof(buf));
208 for (src=string, dst=buf; term != 1 ; src++, dst++) {
210 if ( *src != ',' && *src != '\0' ) {
211 if ( ( *src >= 65 && *src <= 90 ) || ( *src >= 97 && *src <= 122) ) {
212 *dst = *src;
213 idup = 1;
215 } else if ( *src >= 48 && *src <= 57 ) {
216 *dst = *src;
218 } else {
219 exit_error(PARAMETER_PROBLEM, err1, preerr,
220 string, src - string + 1);
224 } else {
225 *dst = '\0';
226 if ( idup == 1 ) {
227 if ( (rpcent_ptr = getrpcbyname(dup)) == NULL )
228 exit_error(PARAMETER_PROBLEM, err2,
229 preerr, dup);
230 idup = rpcent_ptr->r_number;
231 } else {
232 idup = k_atoi(dup);
235 rpcinfo->i_procs++;
236 if ( rpcinfo->i_procs > IPT_RPC_MAX_ENTS )
237 exit_error(PARAMETER_PROBLEM, err3, preerr,
238 IPT_RPC_MAX_ENTS);
240 c_procs = (char *)rpcinfo->c_procs;
241 c_procs += rpcinfo->i_procs * IPT_RPC_CHAR_LEN;
243 memset(buf, 0, sizeof(buf));
244 k_itoa((char *)dup, idup);
246 strcpy(c_procs, dup);
248 if ( *src == '\0')
249 term = 1;
251 idup = 0;
252 memset(buf, 0, sizeof(buf));
253 dst = (char *)buf - 1;
257 return;
261 static int parse(int c, char **argv, int invert, unsigned int *flags,
262 const struct ipt_entry *entry,
263 unsigned int *nfcache,
264 struct ipt_entry_match **match)
266 struct ipt_rpc_info *rpcinfo = (struct ipt_rpc_info *)(*match)->data;
269 switch (c)
271 case '1':
272 if (invert)
273 exit_error(PARAMETER_PROBLEM,
274 "%s unexpected '!' with --rpcs\n", preerr);
275 if (*flags & IPT_RPC_RPCS)
276 exit_error(PARAMETER_PROBLEM,
277 "%s repeated use of --rpcs\n", preerr);
278 parse_rpcs_string(optarg, match);
280 *flags |= IPT_RPC_RPCS;
281 break;
283 case '2':
284 if (invert)
285 exit_error(PARAMETER_PROBLEM,
286 "%s unexpected '!' with --strict\n", preerr);
287 if (*flags & IPT_RPC_STRC)
288 exit_error(PARAMETER_PROBLEM,
289 "%s repeated use of --strict\n", preerr);
290 rpcinfo->strict = 1;
291 *flags |= IPT_RPC_STRC;
292 break;
294 default:
295 return 0;
298 return 1;
303 static void final_check(unsigned int flags)
305 if (flags != (flags | IPT_RPC_RPCS)) {
306 printf("%s option \"--rpcs\" was not used ... reverting ", preerr);
307 printf("to old \"record-rpc\" functionality ..\n");
312 static void print(const struct ipt_ip *ip,
313 const struct ipt_entry_match *match,
314 int numeric)
316 struct ipt_rpc_info *rpcinfo = ((struct ipt_rpc_info *)match->data);
319 printf("RPCs");
320 if(rpcinfo->strict == 1)
321 printf("[strict]");
323 printf(": ");
325 if(rpcinfo->i_procs == -1) {
326 printf("any(*)");
328 } else {
329 print_rpcs((char *)&rpcinfo->c_procs, rpcinfo->i_procs, IPT_RPC_INT_BTH);
331 printf(" ");
336 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
338 struct ipt_rpc_info *rpcinfo = ((struct ipt_rpc_info *)match->data);
341 if(rpcinfo->i_procs > -1) {
342 printf("--rpcs ");
343 print_rpcs((char *)&rpcinfo->c_procs, rpcinfo->i_procs, IPT_RPC_INT_NUM);
344 printf(" ");
347 if(rpcinfo->strict == 1)
348 printf("--strict ");
353 static struct iptables_match rpcstruct = {
354 .next = NULL,
355 .name = "rpc",
356 .version = IPTABLES_VERSION,
357 .size = IPT_ALIGN(sizeof(struct ipt_rpc_info)),
358 .userspacesize = IPT_ALIGN(sizeof(struct ipt_rpc_info)),
359 .help = &help,
360 .init = &init,
361 .parse = &parse,
362 .final_check = &final_check,
363 .print = &print,
364 .save = &save,
365 .extra_opts = opts
369 void _init(void)
371 register_match(&rpcstruct);