filter.c revision 28974
1284990Scy/* 2294569Sdelphij * PPP Filter command Interface 3284990Scy * 4284990Scy * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5284990Scy * 6284990Scy * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7284990Scy * 8330141Sdelphij * Redistribution and use in source and binary forms are permitted 9330141Sdelphij * provided that the above copyright notice and this paragraph are 10289997Sglebius * duplicated in all such forms and that any documentation, 11330141Sdelphij * advertising materials, and other materials related to such 12284990Scy * distribution and use acknowledge that the software was developed 13284990Scy * by the Internet Initiative Japan. The name of the 14309008Sdelphij * IIJ may not be used to endorse or promote products derived 15284990Scy * from this software without specific prior written permission. 16284990Scy * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17284990Scy * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18284990Scy * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19289997Sglebius * 20289997Sglebius * $Id: filter.c,v 1.13 1997/08/25 00:29:11 brian Exp $ 21289997Sglebius * 22289997Sglebius * TODO: Shoud send ICMP error message when we discard packets. 23289997Sglebius */ 24289997Sglebius 25289997Sglebius#include <sys/types.h> 26289997Sglebius#include <sys/socket.h> 27289997Sglebius#include <sys/param.h> 28289997Sglebius#include <netinet/in.h> 29289997Sglebius#include <arpa/inet.h> 30289997Sglebius#include <netdb.h> 31289997Sglebius#include <stdio.h> 32289997Sglebius#include <stdlib.h> 33289997Sglebius#include <strings.h> 34289997Sglebius#include "command.h" 35289997Sglebius#include "mbuf.h" 36289997Sglebius#include "log.h" 37289997Sglebius#include "filter.h" 38289997Sglebius#include "loadalias.h" 39289997Sglebius#include "vars.h" 40289997Sglebius#include "ipcp.h" 41330141Sdelphij 42289997Sglebiusstatic struct filterent filterdata; 43309008Sdelphij 44309008Sdelphijstatic u_long netmasks[33] = { 45309008Sdelphij 0x00000000, 46309008Sdelphij 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, 47309008Sdelphij 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, 48309008Sdelphij 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, 49309008Sdelphij 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000, 50309008Sdelphij 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 51309008Sdelphij 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 52309008Sdelphij 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, 53309008Sdelphij 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF, 54289997Sglebius}; 55309008Sdelphij 56309008Sdelphijint 57309008SdelphijParseAddr(int argc, 58309008Sdelphij char **argv, 59309008Sdelphij struct in_addr * paddr, 60309008Sdelphij struct in_addr * pmask, 61309008Sdelphij int *pwidth) 62284990Scy{ 63284990Scy int bits; 64284990Scy char *cp, *wp; 65289997Sglebius 66289997Sglebius if (argc < 1) { 67294569Sdelphij LogPrintf(LogWARN, "ParseAddr: address/mask is expected.\n"); 68294569Sdelphij return (0); 69294569Sdelphij } 70294569Sdelphij pmask->s_addr = 0xffffffff; /* Assume 255.255.255.255 as default */ 71294569Sdelphij cp = index(*argv, '/'); 72294569Sdelphij if (cp) 73294569Sdelphij *cp++ = '\0'; 74284990Scy if (strcasecmp(*argv, "HISADDR") == 0) 75289997Sglebius *paddr = IpcpInfo.his_ipaddr; 76284990Scy else if (strcasecmp(*argv, "MYADDR") == 0) 77284990Scy *paddr = IpcpInfo.want_ipaddr; 78284990Scy else 79289997Sglebius paddr->s_addr = inet_addr(*argv); 80284990Scy if (cp && *cp) { 81284990Scy bits = strtol(cp, &wp, 0); 82284990Scy if (cp == wp || bits < 0 || bits > 32) { 83330141Sdelphij LogPrintf(LogWARN, "ParseAddr: bad mask width.\n"); 84284990Scy return (0); 85284990Scy } 86284990Scy } else { 87284990Scy /* if width is not given, assume whole 32 bits are meaningfull */ 88284990Scy bits = 32; 89284990Scy } 90284990Scy 91289997Sglebius *pwidth = bits; 92289997Sglebius pmask->s_addr = htonl(netmasks[bits]); 93294569Sdelphij 94294569Sdelphij return (1); 95294569Sdelphij} 96294569Sdelphij 97294569Sdelphijstatic int 98294569SdelphijParseProto(int argc, char **argv) 99284990Scy{ 100284990Scy int proto; 101284990Scy 102284990Scy if (argc < 1) 103289997Sglebius return (P_NONE); 104294569Sdelphij 105294569Sdelphij if (STREQ(*argv, "tcp")) 106289997Sglebius proto = P_TCP; 107284990Scy else if (STREQ(*argv, "udp")) 108284990Scy proto = P_UDP; 109284990Scy else if (STREQ(*argv, "icmp")) 110284990Scy proto = P_ICMP; 111294569Sdelphij else 112294569Sdelphij proto = P_NONE; 113309008Sdelphij return (proto); 114284990Scy} 115309008Sdelphij 116309008Sdelphijstatic int 117284990ScyParsePort(char *service, int proto) 118284990Scy{ 119294569Sdelphij char *protocol_name, *cp; 120294569Sdelphij struct servent *servent; 121284990Scy int port; 122284990Scy 123284990Scy switch (proto) { 124284990Scy case P_UDP: 125309008Sdelphij protocol_name = "udp"; 126309008Sdelphij break; 127284990Scy case P_TCP: 128284990Scy protocol_name = "tcp"; 129289997Sglebius break; 130289997Sglebius default: 131294569Sdelphij protocol_name = 0; 132294569Sdelphij } 133284990Scy 134284990Scy servent = getservbyname(service, protocol_name); 135284990Scy if (servent != 0) 136284990Scy return (ntohs(servent->s_port)); 137284990Scy 138284990Scy port = strtol(service, &cp, 0); 139294569Sdelphij if (cp == service) { 140284990Scy LogPrintf(LogWARN, "ParsePort: %s is not a port name or number.\n", 141284990Scy service); 142284990Scy return (0); 143289997Sglebius } 144294569Sdelphij return (port); 145294569Sdelphij} 146284990Scy 147309008Sdelphij/* 148309008Sdelphij * ICMP Syntax: src eq icmp_message_type 149284990Scy */ 150309008Sdelphijstatic int 151309008SdelphijParseIcmp(int argc, char **argv) 152284990Scy{ 153284990Scy int type; 154289997Sglebius char *cp; 155289997Sglebius 156294569Sdelphij switch (argc) { 157294569Sdelphij case 0: 158284990Scy /* permit/deny all ICMP types */ 159309008Sdelphij filterdata.opt.srcop = OP_NONE; 160309008Sdelphij break; 161284990Scy default: 162309008Sdelphij LogPrintf(LogWARN, "ParseIcmp: bad icmp syntax.\n"); 163309008Sdelphij return (0); 164284990Scy case 3: 165284990Scy if (STREQ(*argv, "src") && STREQ(argv[1], "eq")) { 166289997Sglebius type = strtol(argv[2], &cp, 0); 167289997Sglebius if (cp == argv[2]) { 168294569Sdelphij LogPrintf(LogWARN, "ParseIcmp: type is expected.\n"); 169294569Sdelphij return (0); 170309008Sdelphij } 171309008Sdelphij filterdata.opt.srcop = OP_EQ; 172309008Sdelphij filterdata.opt.srcport = type; 173309008Sdelphij } 174309008Sdelphij break; 175309008Sdelphij } 176309008Sdelphij return (1); 177284990Scy} 178284990Scy 179294569Sdelphijstatic int 180294569SdelphijParseOp(char *cp) 181309008Sdelphij{ 182284990Scy int op = OP_NONE; 183284990Scy 184284990Scy if (STREQ(cp, "eq")) 185294569Sdelphij op = OP_EQ; 186294569Sdelphij else if (STREQ(cp, "gt")) 187284990Scy op = OP_GT; 188284990Scy else if (STREQ(cp, "lt")) 189284990Scy op = OP_LT; 190309008Sdelphij return (op); 191309008Sdelphij} 192284990Scy 193284990Scy/* 194289997Sglebius * UDP Syntax: [src op port] [dst op port] 195289997Sglebius */ 196294569Sdelphijstatic int 197294569SdelphijParseUdpOrTcp(int argc, char **argv, int proto) 198294569Sdelphij{ 199284990Scy if (argc == 0) { 200284990Scy /* permit/deny all tcp traffic */ 201284990Scy filterdata.opt.srcop = filterdata.opt.dstop = A_NONE; 202284990Scy return (1); 203284990Scy } 204294569Sdelphij if (argc < 3) { 205284990Scy LogPrintf(LogWARN, "ParseUdpOrTcp: bad udp/tcp syntax.\n"); 206309008Sdelphij return (0); 207309008Sdelphij } 208284990Scy if (argc >= 3 && STREQ(*argv, "src")) { 209284990Scy filterdata.opt.srcop = ParseOp(argv[1]); 210289997Sglebius if (filterdata.opt.srcop == OP_NONE) { 211289997Sglebius LogPrintf(LogWARN, "ParseUdpOrTcp: bad operation\n"); 212294569Sdelphij return (0); 213294569Sdelphij } 214294569Sdelphij filterdata.opt.srcport = ParsePort(argv[2], proto); 215284990Scy if (filterdata.opt.srcport == 0) 216284990Scy return (0); 217284990Scy argc -= 3; 218294569Sdelphij argv += 3; 219284990Scy if (argc == 0) 220284990Scy return (1); 221309008Sdelphij } 222309008Sdelphij if (argc >= 3 && STREQ(argv[0], "dst")) { 223284990Scy filterdata.opt.dstop = ParseOp(argv[1]); 224284990Scy if (filterdata.opt.dstop == OP_NONE) { 225289997Sglebius LogPrintf(LogWARN, "ParseUdpOrTcp: bad operation\n"); 226289997Sglebius return (0); 227294569Sdelphij } 228294569Sdelphij filterdata.opt.dstport = ParsePort(argv[2], proto); 229294569Sdelphij if (filterdata.opt.dstport == 0) 230284990Scy return (0); 231284990Scy argc -= 3; 232284990Scy argv += 3; 233294569Sdelphij if (argc == 0) 234284990Scy return (1); 235284990Scy } 236309008Sdelphij if (argc == 1) { 237309008Sdelphij if (STREQ(*argv, "estab")) { 238330141Sdelphij filterdata.opt.estab = 1; 239309008Sdelphij return (1); 240284990Scy } 241284990Scy LogPrintf(LogWARN, "ParseUdpOrTcp: estab is expected: %s\n", *argv); 242284990Scy return (0); 243294569Sdelphij } 244309008Sdelphij if (argc > 0) 245284990Scy LogPrintf(LogWARN, "ParseUdpOrTcp: bad src/dst port syntax: %s\n", *argv); 246284990Scy return (0); 247309008Sdelphij} 248309008Sdelphij 249284990Scychar *opname[] = {"none", "eq", "gt", "lt"}; 250284990Scy 251289997Sglebiusstatic int 252289997SglebiusParse(int argc, char **argv, struct filterent * ofp) 253294569Sdelphij{ 254294569Sdelphij int action, proto; 255294569Sdelphij int val; 256284990Scy char *wp; 257284990Scy struct filterent *fp = &filterdata; 258284990Scy 259294569Sdelphij val = strtol(*argv, &wp, 0); 260294569Sdelphij if (*argv == wp || val > MAXFILTERS) { 261294569Sdelphij LogPrintf(LogWARN, "Parse: invalid filter number.\n"); 262284990Scy return (0); 263284990Scy } 264309008Sdelphij if (val < 0) { 265309008Sdelphij for (val = 0; val < MAXFILTERS; val++) { 266330141Sdelphij ofp->action = A_NONE; 267309008Sdelphij ofp++; 268330141Sdelphij } 269284990Scy LogPrintf(LogWARN, "Parse: filter cleared.\n"); 270284990Scy return (1); 271309008Sdelphij } 272309008Sdelphij ofp += val; 273284990Scy 274284990Scy if (--argc == 0) { 275289997Sglebius LogPrintf(LogWARN, "Parse: missing action.\n"); 276289997Sglebius return (0); 277294569Sdelphij } 278294569Sdelphij argv++; 279284990Scy 280284990Scy proto = P_NONE; 281309008Sdelphij bzero(&filterdata, sizeof(filterdata)); 282309008Sdelphij 283309008Sdelphij if (STREQ(*argv, "permit")) { 284309008Sdelphij action = A_PERMIT; 285284990Scy } else if (STREQ(*argv, "deny")) { 286284990Scy action = A_DENY; 287284990Scy } else if (STREQ(*argv, "clear")) { 288284990Scy ofp->action = A_NONE; 289309008Sdelphij return (1); 290309008Sdelphij } else { 291284990Scy LogPrintf(LogWARN, "Parse: bad action: %s\n", *argv); 292284990Scy return (0); 293289997Sglebius } 294289997Sglebius fp->action = action; 295294569Sdelphij 296294569Sdelphij argc--; 297284990Scy argv++; 298284990Scy 299309008Sdelphij if (fp->action == A_DENY) { 300309008Sdelphij if (STREQ(*argv, "host")) { 301309008Sdelphij fp->action |= A_UHOST; 302309008Sdelphij argc--; 303284990Scy argv++; 304284990Scy } else if (STREQ(*argv, "port")) { 305284990Scy fp->action |= A_UPORT; 306284990Scy argc--; 307309008Sdelphij argv++; 308309008Sdelphij } 309284990Scy } 310284990Scy proto = ParseProto(argc, argv); 311289997Sglebius if (proto == P_NONE) { 312289997Sglebius if (ParseAddr(argc, argv, &fp->saddr, &fp->smask, &fp->swidth)) { 313294569Sdelphij argc--; 314294569Sdelphij argv++; 315284990Scy proto = ParseProto(argc, argv); 316284990Scy if (proto == P_NONE) { 317309008Sdelphij if (ParseAddr(argc, argv, &fp->daddr, &fp->dmask, &fp->dwidth)) { 318309008Sdelphij argc--; 319309008Sdelphij argv++; 320284990Scy } 321294569Sdelphij proto = ParseProto(argc, argv); 322294569Sdelphij if (proto) { 323294569Sdelphij argc--; 324284990Scy argv++; 325309008Sdelphij } 326309008Sdelphij } else { 327284990Scy argc--; 328284990Scy argv++; 329289997Sglebius } 330284990Scy } else { 331289997Sglebius LogPrintf(LogWARN, "Parse: Address/protocol expected.\n"); 332294569Sdelphij return (0); 333294569Sdelphij } 334284990Scy } else { 335284990Scy argc--; 336309008Sdelphij argv++; 337309008Sdelphij } 338284990Scy 339284990Scy val = 1; 340309008Sdelphij fp->proto = proto; 341309008Sdelphij 342284990Scy switch (proto) { 343284990Scy case P_TCP: 344289997Sglebius val = ParseUdpOrTcp(argc, argv, P_TCP); 345289997Sglebius break; 346294569Sdelphij case P_UDP: 347294569Sdelphij val = ParseUdpOrTcp(argc, argv, P_UDP); 348284990Scy break; 349284990Scy case P_ICMP: 350309008Sdelphij val = ParseIcmp(argc, argv); 351309008Sdelphij break; 352284990Scy } 353284990Scy 354309008Sdelphij LogPrintf(LogDEBUG, "Parse: Src: %s\n", inet_ntoa(fp->saddr)); 355309008Sdelphij LogPrintf(LogDEBUG, "Parse: Src mask: %s\n", inet_ntoa(fp->smask)); 356284990Scy LogPrintf(LogDEBUG, "Parse: Dst: %s\n", inet_ntoa(fp->daddr)); 357284990Scy LogPrintf(LogDEBUG, "Parse: Dst mask: %s\n", inet_ntoa(fp->dmask)); 358289997Sglebius LogPrintf(LogDEBUG, "Parse: Proto = %d\n", proto); 359289997Sglebius 360294569Sdelphij LogPrintf(LogDEBUG, "Parse: src: %s (%d)\n", opname[fp->opt.srcop], 361294569Sdelphij fp->opt.srcport); 362284990Scy LogPrintf(LogDEBUG, "Parse: dst: %s (%d)\n", opname[fp->opt.dstop], 363284990Scy fp->opt.dstport); 364309008Sdelphij LogPrintf(LogDEBUG, "Parse: estab: %d\n", fp->opt.estab); 365309008Sdelphij 366309008Sdelphij if (val) 367284990Scy *ofp = *fp; 368284990Scy return (val); 369309008Sdelphij} 370309008Sdelphij 371284990Scyint 372284990ScySetIfilter(struct cmdtab * list, int argc, char **argv) 373289997Sglebius{ 374289997Sglebius if (argc > 0) { 375294569Sdelphij (void) Parse(argc, argv, ifilters); 376294569Sdelphij return 0; 377284990Scy } 378284990Scy return -1; 379284990Scy} 380284990Scy 381284990Scyint 382309008SdelphijSetOfilter(struct cmdtab * list, int argc, char **argv) 383284990Scy{ 384284990Scy if (argc > 0) { 385284990Scy (void) Parse(argc, argv, ofilters); 386309008Sdelphij return 0; 387284990Scy } 388284990Scy return -1; 389309008Sdelphij} 390309008Sdelphij 391284990Scyint 392284990ScySetDfilter(struct cmdtab * list, int argc, char **argv) 393289997Sglebius{ 394289997Sglebius if (argc > 0) { 395294569Sdelphij (void) Parse(argc, argv, dfilters); 396294569Sdelphij return 0; 397284990Scy } 398284990Scy return -1; 399309008Sdelphij} 400309008Sdelphij 401309008Sdelphijint 402284990ScySetAfilter(struct cmdtab * list, int argc, char **argv) 403284990Scy{ 404309008Sdelphij if (argc > 0) { 405284990Scy (void) Parse(argc, argv, afilters); 406284990Scy return 0; 407284990Scy } 408289997Sglebius return -1; 409289997Sglebius} 410294569Sdelphij 411294569Sdelphijstatic char *protoname[] = { 412284990Scy "none", "tcp", "udp", "icmp", 413284990Scy}; 414284990Scy 415309008Sdelphijstatic char *actname[] = { 416309008Sdelphij "none ", "permit ", "deny ", 417284990Scy}; 418284990Scy 419289997Sglebiusstatic void 420289997SglebiusShowFilter(struct filterent * fp) 421294569Sdelphij{ 422294569Sdelphij int n; 423284990Scy 424284990Scy if (!VarTerm) 425284990Scy return; 426284990Scy 427284990Scy for (n = 0; n < MAXFILTERS; n++, fp++) { 428294569Sdelphij if (fp->action != A_NONE) { 429309008Sdelphij fprintf(VarTerm, "%2d %s", n, actname[fp->action]); 430309008Sdelphij fprintf(VarTerm, "%s/%d ", inet_ntoa(fp->saddr), fp->swidth); 431330141Sdelphij fprintf(VarTerm, "%s/%d ", inet_ntoa(fp->daddr), fp->dwidth); 432309008Sdelphij if (fp->proto) { 433284990Scy fprintf(VarTerm, "%s", protoname[fp->proto]); 434330141Sdelphij 435284990Scy if (fp->opt.srcop) 436284990Scy fprintf(VarTerm, " src %s %d", opname[fp->opt.srcop], 437309008Sdelphij fp->opt.srcport); 438309008Sdelphij if (fp->opt.dstop) 439284990Scy fprintf(VarTerm, " dst %s %d", opname[fp->opt.dstop], 440284990Scy fp->opt.dstport); 441289997Sglebius if (fp->opt.estab) 442289997Sglebius fprintf(VarTerm, " estab"); 443294569Sdelphij 444294569Sdelphij } 445284990Scy fprintf(VarTerm, "\n"); 446284990Scy } 447284990Scy } 448284990Scy} 449284990Scy 450294569Sdelphijint 451309008SdelphijShowIfilter(struct cmdtab * list, int argc, char **argv) 452309008Sdelphij{ 453330141Sdelphij ShowFilter(ifilters); 454330141Sdelphij return 0; 455330141Sdelphij} 456330141Sdelphij 457330141Sdelphijint 458330141SdelphijShowOfilter(struct cmdtab * list, int argc, char **argv) 459330141Sdelphij{ 460330141Sdelphij ShowFilter(ofilters); 461330141Sdelphij return 0; 462330141Sdelphij} 463330141Sdelphij 464330141Sdelphijint 465330141SdelphijShowDfilter(struct cmdtab * list, int argc, char **argv) 466330141Sdelphij{ 467338531Sdelphij ShowFilter(dfilters); 468338531Sdelphij return 0; 469330141Sdelphij} 470330141Sdelphij 471330141Sdelphijint 472330141SdelphijShowAfilter(struct cmdtab * list, int argc, char **argv) 473330141Sdelphij{ 474330141Sdelphij ShowFilter(afilters); 475330141Sdelphij return 0; 476330141Sdelphij} 477294569Sdelphij