Deleted Added
full compact
1/*
2 * PPP Filter command Interface
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan. The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id$
20 * $Id: filter.c,v 1.8 1997/02/22 16:10:12 peter Exp $
21 *
22 * TODO: Shoud send ICMP error message when we discard packets.
23 */
24
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/param.h>
28#include <netinet/in.h>
29#include <arpa/inet.h>
30#include <netdb.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <strings.h>
34#include "command.h"
35#include "filter.h"
36
37static struct filterent filterdata;
38
39static u_long netmasks[33] = {
40 0x00000000,
41 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,
42 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000,
43 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000,
44 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
45 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000,
46 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00,
47 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0,
48 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF,
49};
50
51int
52ParseAddr(argc, argv, paddr, pmask, pwidth)
53int argc;
54char **argv;
55struct in_addr *paddr;
56struct in_addr *pmask;
57int *pwidth;
58{
59 u_long addr;
60 int bits;
61 char *cp, *wp;
62
63 if (argc < 1) {
64#ifdef notdef
65 printf("address/mask is expected.\n");
66#endif
67 return(0);
68 }
69
70 pmask->s_addr = -1; /* Assume 255.255.255.255 as default */
70 pmask->s_addr = 0xffffffff; /* Assume 255.255.255.255 as default */
71 cp = index(*argv, '/');
72 if (cp) *cp++ = '\0';
73 addr = inet_addr(*argv);
74 paddr->s_addr = addr;
75 if (cp && *cp) {
76 bits = strtol(cp, &wp, 0);
77 if (cp == wp || bits < 0 || bits > 32) {
78 printf("bad mask width.\n");
79 return(0);
80 }
81 } else {
82 /* if width is not given, assume whole 32 bits are meaningfull */
83 bits = 32;
84 }
85
86 *pwidth = bits;
87 pmask->s_addr = htonl(netmasks[bits]);
88
89 return(1);
90}
91
92static int
93ParseProto(argc, argv)
94int argc;
95char **argv;
96{
97 int proto;
98
99 if (argc < 1)
100 return(P_NONE);
101
102 if (STREQ(*argv, "tcp"))
103 proto = P_TCP;
104 else if (STREQ(*argv, "udp"))
105 proto = P_UDP;
106 else if (STREQ(*argv, "icmp"))
107 proto = P_ICMP;
108 else
109 proto = P_NONE;
110 return(proto);
111}
112
113static int
114ParsePort(service, proto)
115char *service;
116int proto;
117{
118 char *protocol_name, *cp;
119 struct servent *servent;
120 int port;
121
122 switch (proto) {
123 case P_UDP:
124 protocol_name = "udp";
125 break;
126 case P_TCP:
127 protocol_name = "tcp";
128 break;
129 default:
130 protocol_name = 0;
131 }
132
133 servent = getservbyname (service, protocol_name);
134 if (servent != 0)
135 return(ntohs(servent->s_port));
136
137 port = strtol(service, &cp, 0);
138 if (cp == service) {
139 printf("%s is not a port name or number.\n", service);
140 return(0);
141 }
142 return(port);
143}
144
145/*
146 * ICMP Syntax: src eq icmp_message_type
147 */
148static int
149ParseIcmp(argc, argv)
150int argc;
151char **argv;
152{
153 int type;
154 char *cp;
155
156 switch (argc) {
157 case 0:
158 /* permit/deny all ICMP types */
159 filterdata.opt.srcop = OP_NONE;
160 break;
161 default:
162 printf("bad icmp syntax.\n");
163 return(0);
164 case 3:
165 if (STREQ(*argv, "src") && STREQ(argv[1], "eq")) {
166 type = strtol(argv[2], &cp, 0);
167 if (cp == argv[2]) {
168 printf("type is expected.\n");
169 return(0);
170 }
171 filterdata.opt.srcop = OP_EQ;
172 filterdata.opt.srcport = type;
173 }
174 break;
175 }
176 return(1);
177}
178
179static int
180ParseOp(cp)
181char *cp;
182{
183 int op = OP_NONE;
184
185 if (STREQ(cp, "eq"))
186 op = OP_EQ;
187 else if (STREQ(cp, "gt"))
188 op = OP_GT;
189 else if (STREQ(cp, "lt"))
190 op = OP_LT;
191 return(op);
192}
193
194/*
195 * UDP Syntax: [src op port] [dst op port]
196 */
197static int
198ParseUdpOrTcp(argc, argv, proto)
199int argc;
200char **argv;
201int proto;
202{
203
204 if (argc == 0) {
205 /* permit/deny all tcp traffic */
206 filterdata.opt.srcop = filterdata.opt.dstop = A_NONE;
207 return(1);
208 }
209 if (argc < 3) {
210#ifdef notdef
211 printf("bad udp syntax.\n");
212#endif
213 return(0);
214 }
215 if (argc >= 3 && STREQ(*argv, "src")) {
216 filterdata.opt.srcop = ParseOp(argv[1]);
217 if (filterdata.opt.srcop == OP_NONE) {
218 printf("bad operation\n");
219 return(0);
220 }
221 filterdata.opt.srcport = ParsePort(argv[2], proto);
222 if (filterdata.opt.srcport == 0)
223 return(0);
224 argc -= 3; argv += 3;
225 if (argc == 0)
226 return(1);
227 }
228 if (argc >= 3 && STREQ(argv[0], "dst")) {
229 filterdata.opt.dstop = ParseOp(argv[1]);
230 if (filterdata.opt.dstop == OP_NONE) {
231 printf("bad operation\n");
232 return(0);
233 }
234 filterdata.opt.dstport = ParsePort(argv[2], proto);
235 if (filterdata.opt.dstport == 0)
236 return(0);
237 argc -= 3; argv += 3;
238 if (argc == 0)
239 return(1);
240 }
241 if (argc == 1) {
242 if (STREQ(*argv, "estab")) {
243 filterdata.opt.estab = 1;
244 return(1);
245 }
246 printf("estab is expected: %s\n", *argv);
247 return(0);
248 }
249 if (argc > 0)
250 printf("bad src/dst port syntax: %s\n", *argv);
251 return(0);
252}
253
254char *opname[] = { "none", "eq", "gt", "lt" };
255
256static int
257Parse(argc, argv, ofp)
258int argc;
259char **argv;
260struct filterent *ofp;
261{
262 int action, proto;
263 int val;
264 char *wp;
265 struct filterent *fp = &filterdata;
266
267 val = strtol(*argv, &wp, 0);
268 if (*argv == wp || val > MAXFILTERS) {
269 printf("invalid filter number.\n");
270 return(0);
271 }
272 if (val < 0) {
273 for (val = 0; val < MAXFILTERS; val++) {
274 ofp->action = A_NONE;
275 ofp++;
276 }
277 printf("filter cleard.\n");
278 return(1);
279 }
280 ofp += val;
281
282 if (--argc == 0) {
283 printf("missing action.\n");
284 return(0);
285 }
286 argv++;
287
288 proto = P_NONE;
289 bzero(&filterdata, sizeof(filterdata));
290
291 if (STREQ(*argv, "permit")) {
292 action = A_PERMIT;
293 } else if (STREQ(*argv, "deny")) {
294 action = A_DENY;
295 } else if (STREQ(*argv, "clear")) {
296 ofp->action = A_NONE;
297 return(1);
298 } else {
299 printf("bad action: %s\n", *argv);
300 return(0);
301 }
302 fp->action = action;
303
304 argc--; argv++;
305
306 if (ofp->action == A_DENY) {
307 if (STREQ(*argv, "host")) {
308 fp->action |= A_UHOST;
309 argc--; argv++;
310 } else if (STREQ(*argv, "port")) {
311 fp->action |= A_UPORT;
312 argc--; argv++;
313 }
314 }
315
316 proto = ParseProto(argc, argv);
317 if (proto == P_NONE) {
318 if (ParseAddr(argc, argv, &fp->saddr, &fp->smask, &fp->swidth)) {
319 argc--; argv++;
320 proto = ParseProto(argc, argv);
321 if (proto == P_NONE) {
322 if (ParseAddr(argc, argv, &fp->daddr, &fp->dmask, &fp->dwidth)) {
323 argc--; argv++;
324 }
325 proto = ParseProto(argc, argv);
326 if (proto) {
327 argc--; argv++;
328 }
329 }
330 } else {
331 printf("Address/protocol expected.\n");
332 return(0);
333 }
334 } else {
335 argc--; argv++;
336 }
337
338 val = 1;
339 fp->proto = proto;
340
341 switch (proto) {
342 case P_TCP:
343 val = ParseUdpOrTcp(argc, argv, P_TCP);
344 break;
345 case P_UDP:
346 val = ParseUdpOrTcp(argc, argv, P_UDP);
347 break;
348 case P_ICMP:
349 val = ParseIcmp(argc, argv);
350 break;
351 }
352
353#ifdef DEBUG
354 printf("src: %s/", inet_ntoa(fp->saddr));
355 printf("%s ", inet_ntoa(fp->smask));
356 printf("dst: %s/", inet_ntoa(fp->daddr));
357 printf("%s proto = %d\n", inet_ntoa(fp->dmask), proto);
358
359 printf("src: %s (%d)\n", opname[fp->opt.srcop], fp->opt.srcport);
360 printf("dst: %s (%d)\n", opname[fp->opt.dstop], fp->opt.dstport);
361 printf("estab: %d\n", fp->opt.estab);
362#endif
363
364 if (val)
365 *ofp = *fp;
366 return(val);
367}
368
369int
370SetIfilter(list, argc, argv)
371struct cmdtab *list;
372int argc;
373char **argv;
374{
375 if (argc > 0)
376 (void) Parse(argc, argv, ifilters);
377 else
378 printf("syntax error.\n");
379
380 return(1);
381}
382
383int
384SetOfilter(list, argc, argv)
385struct cmdtab *list;
386int argc;
387char **argv;
388{
389 if (argc > 0)
390 (void) Parse(argc, argv, ofilters);
391 else
392 printf("syntax error.\n");
393 return(1);
394}
395
396int
397SetDfilter(list, argc, argv)
398struct cmdtab *list;
399int argc;
400char **argv;
401{
402 if (argc > 0)
403 (void) Parse(argc, argv, dfilters);
404 else
405 printf("syntax error.\n");
406 return(1);
407}
408
409int
410SetAfilter(list, argc, argv)
411struct cmdtab *list;
412int argc;
413char **argv;
414{
415 if (argc > 0)
416 (void) Parse(argc, argv, afilters);
417 else
418 printf("syntax error.\n");
419 return(1);
420}
421
422static char *protoname[] = {
423 "none", "tcp", "udp", "icmp",
424};
425
426static char *actname[] = {
427 "none ", "permit ", "deny ",
428};
429
430static void
431ShowFilter(fp)
432struct filterent *fp;
433{
434 int n;
435
436 for (n = 0; n < MAXFILTERS; n++, fp++) {
437 if (fp->action != A_NONE) {
438 printf("%2d %s", n, actname[fp->action]);
439
440 printf("%s/%d ", inet_ntoa(fp->saddr), fp->swidth);
441 printf("%s/%d ", inet_ntoa(fp->daddr), fp->dwidth);
442 if (fp->proto) {
443 printf("%s", protoname[fp->proto]);
444
445 if (fp->opt.srcop)
446 printf(" src %s %d", opname[fp->opt.srcop], fp->opt.srcport);
447 if (fp->opt.dstop)
448 printf(" dst %s %d", opname[fp->opt.dstop], fp->opt.dstport);
449 if (fp->opt.estab)
450 printf(" estab");
451
452 }
453 printf("\n");
454 }
455 }
456}
457
458int
459ShowIfilter(list, argc, argv)
460struct cmdtab *list;
461int argc;
462char **argv;
463{
464 ShowFilter(ifilters);
465 return(1);
466}
467
468int
469ShowOfilter(list, argc, argv)
470struct cmdtab *list;
471int argc;
472char **argv;
473{
474 ShowFilter(ofilters);
475 return(1);
476}
477
478int
479ShowDfilter(list, argc, argv)
480struct cmdtab *list;
481int argc;
482char **argv;
483{
484 ShowFilter(dfilters);
485 return(1);
486}
487
488int
489ShowAfilter(list, argc, argv)
490struct cmdtab *list;
491int argc;
492char **argv;
493{
494 ShowFilter(afilters);
495 return(1);
496}