filter.c revision 27723
1250003Sadrian/* 2250003Sadrian * PPP Filter command Interface 3250003Sadrian * 4250003Sadrian * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5250003Sadrian * 6250003Sadrian * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7250003Sadrian * 8250003Sadrian * Redistribution and use in source and binary forms are permitted 9250003Sadrian * provided that the above copyright notice and this paragraph are 10250003Sadrian * duplicated in all such forms and that any documentation, 11250003Sadrian * advertising materials, and other materials related to such 12250003Sadrian * distribution and use acknowledge that the software was developed 13250003Sadrian * by the Internet Initiative Japan. The name of the 14250003Sadrian * IIJ may not be used to endorse or promote products derived 15250003Sadrian * from this software without specific prior written permission. 16250003Sadrian * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17250003Sadrian * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18250003Sadrian * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19250003Sadrian * 20250003Sadrian * $Id: filter.c,v 1.11 1997/06/28 01:34:03 brian Exp $ 21250003Sadrian * 22250003Sadrian * TODO: Shoud send ICMP error message when we discard packets. 23250003Sadrian */ 24250003Sadrian 25250003Sadrian#include <sys/types.h> 26250003Sadrian#include <sys/socket.h> 27250003Sadrian#include <sys/param.h> 28250003Sadrian#include <netinet/in.h> 29250003Sadrian#include <arpa/inet.h> 30250003Sadrian#include <netdb.h> 31250003Sadrian#include <stdio.h> 32250003Sadrian#include <stdlib.h> 33250003Sadrian#include <strings.h> 34250003Sadrian#include "command.h" 35250003Sadrian#include "mbuf.h" 36250003Sadrian#include "log.h" 37250003Sadrian#include "filter.h" 38250003Sadrian#include "loadalias.h" 39250003Sadrian#include "vars.h" 40250003Sadrian#include "ipcp.h" 41250003Sadrian 42250003Sadrianstatic struct filterent filterdata; 43250003Sadrian 44250003Sadrianstatic u_long netmasks[33] = { 45250003Sadrian 0x00000000, 46250003Sadrian 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, 47250003Sadrian 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000, 48250003Sadrian 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, 49250003Sadrian 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000, 50250003Sadrian 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 51250008Sadrian 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 52250003Sadrian 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0, 53250008Sadrian 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF, 54250008Sadrian}; 55250003Sadrian 56250003Sadrianint 57250003SadrianParseAddr(argc, argv, paddr, pmask, pwidth) 58250003Sadrianint argc; 59250003Sadrianchar **argv; 60250003Sadrianstruct in_addr *paddr; 61250003Sadrianstruct in_addr *pmask; 62250003Sadrianint *pwidth; 63250003Sadrian{ 64250003Sadrian int bits; 65250003Sadrian char *cp, *wp; 66250003Sadrian 67250003Sadrian if (argc < 1) { 68250003Sadrian LogPrintf(LogWARN, "ParseAddr: address/mask is expected.\n"); 69250003Sadrian return(0); 70250003Sadrian } 71250003Sadrian 72250003Sadrian pmask->s_addr = 0xffffffff; /* Assume 255.255.255.255 as default */ 73250003Sadrian cp = index(*argv, '/'); 74250003Sadrian if (cp) *cp++ = '\0'; 75250003Sadrian if (strcasecmp(*argv, "HISADDR") == 0) 76250003Sadrian *paddr = IpcpInfo.his_ipaddr; 77250003Sadrian else if (strcasecmp(*argv, "MYADDR") == 0) 78250008Sadrian *paddr = IpcpInfo.want_ipaddr; 79250003Sadrian else 80250003Sadrian paddr->s_addr = inet_addr(*argv); 81250003Sadrian if (cp && *cp) { 82250003Sadrian bits = strtol(cp, &wp, 0); 83250003Sadrian if (cp == wp || bits < 0 || bits > 32) { 84250003Sadrian LogPrintf(LogWARN, "ParseAddr: bad mask width.\n"); 85250003Sadrian return(0); 86250003Sadrian } 87250003Sadrian } else { 88250003Sadrian /* if width is not given, assume whole 32 bits are meaningfull */ 89250003Sadrian bits = 32; 90250003Sadrian } 91250003Sadrian 92250003Sadrian *pwidth = bits; 93250003Sadrian pmask->s_addr = htonl(netmasks[bits]); 94250003Sadrian 95250003Sadrian return(1); 96250008Sadrian} 97250003Sadrian 98250003Sadrianstatic int 99250003SadrianParseProto(argc, argv) 100250003Sadrianint argc; 101250003Sadrianchar **argv; 102250003Sadrian{ 103250003Sadrian int proto; 104250003Sadrian 105250003Sadrian if (argc < 1) 106250003Sadrian return(P_NONE); 107250003Sadrian 108250003Sadrian if (STREQ(*argv, "tcp")) 109250003Sadrian proto = P_TCP; 110250003Sadrian else if (STREQ(*argv, "udp")) 111250003Sadrian proto = P_UDP; 112250003Sadrian else if (STREQ(*argv, "icmp")) 113250003Sadrian proto = P_ICMP; 114250003Sadrian else 115250003Sadrian proto = P_NONE; 116250003Sadrian return(proto); 117250003Sadrian} 118250003Sadrian 119250003Sadrianstatic int 120250003SadrianParsePort(service, proto) 121250003Sadrianchar *service; 122250003Sadrianint proto; 123250003Sadrian{ 124250008Sadrian char *protocol_name, *cp; 125250003Sadrian struct servent *servent; 126250003Sadrian int port; 127250003Sadrian 128250003Sadrian switch (proto) { 129250003Sadrian case P_UDP: 130250003Sadrian protocol_name = "udp"; 131250003Sadrian break; 132250003Sadrian case P_TCP: 133250003Sadrian protocol_name = "tcp"; 134250003Sadrian break; 135250003Sadrian default: 136250003Sadrian protocol_name = 0; 137250003Sadrian } 138250003Sadrian 139250003Sadrian servent = getservbyname (service, protocol_name); 140250003Sadrian if (servent != 0) 141250003Sadrian return(ntohs(servent->s_port)); 142250003Sadrian 143250003Sadrian port = strtol(service, &cp, 0); 144250003Sadrian if (cp == service) { 145250003Sadrian LogPrintf(LogWARN, "ParsePort: %s is not a port name or number.\n", 146250003Sadrian service); 147250003Sadrian return(0); 148250003Sadrian } 149250003Sadrian return(port); 150250003Sadrian} 151250003Sadrian 152250003Sadrian/* 153250003Sadrian * ICMP Syntax: src eq icmp_message_type 154250003Sadrian */ 155250003Sadrianstatic int 156250003SadrianParseIcmp(argc, argv) 157250003Sadrianint argc; 158250003Sadrianchar **argv; 159250003Sadrian{ 160250003Sadrian int type; 161250003Sadrian char *cp; 162250003Sadrian 163250003Sadrian switch (argc) { 164250003Sadrian case 0: 165250003Sadrian /* permit/deny all ICMP types */ 166250003Sadrian filterdata.opt.srcop = OP_NONE; 167250003Sadrian break; 168250003Sadrian default: 169250003Sadrian LogPrintf(LogWARN, "ParseIcmp: bad icmp syntax.\n"); 170250003Sadrian return(0); 171250003Sadrian case 3: 172250003Sadrian if (STREQ(*argv, "src") && STREQ(argv[1], "eq")) { 173250003Sadrian type = strtol(argv[2], &cp, 0); 174250003Sadrian if (cp == argv[2]) { 175250003Sadrian LogPrintf(LogWARN, "ParseIcmp: type is expected.\n"); 176250003Sadrian return(0); 177250003Sadrian } 178250003Sadrian filterdata.opt.srcop = OP_EQ; 179250003Sadrian filterdata.opt.srcport = type; 180250003Sadrian } 181250003Sadrian break; 182250003Sadrian } 183250003Sadrian return(1); 184250003Sadrian} 185250003Sadrian 186250003Sadrianstatic int 187250003SadrianParseOp(cp) 188250003Sadrianchar *cp; 189250003Sadrian{ 190250003Sadrian int op = OP_NONE; 191250003Sadrian 192250003Sadrian if (STREQ(cp, "eq")) 193250003Sadrian op = OP_EQ; 194250003Sadrian else if (STREQ(cp, "gt")) 195250008Sadrian op = OP_GT; 196250003Sadrian else if (STREQ(cp, "lt")) 197250003Sadrian op = OP_LT; 198250003Sadrian return(op); 199250003Sadrian} 200250003Sadrian 201250003Sadrian/* 202250003Sadrian * UDP Syntax: [src op port] [dst op port] 203250003Sadrian */ 204250003Sadrianstatic int 205250003SadrianParseUdpOrTcp(argc, argv, proto) 206250003Sadrianint argc; 207250003Sadrianchar **argv; 208250003Sadrianint proto; 209250003Sadrian{ 210250003Sadrian 211250003Sadrian if (argc == 0) { 212250003Sadrian /* permit/deny all tcp traffic */ 213250003Sadrian filterdata.opt.srcop = filterdata.opt.dstop = A_NONE; 214250003Sadrian return(1); 215250003Sadrian } 216250003Sadrian if (argc < 3) { 217250003Sadrian LogPrintf(LogWARN, "ParseUdpOrTcp: bad udp/tcp syntax.\n"); 218250003Sadrian return(0); 219250003Sadrian } 220250003Sadrian if (argc >= 3 && STREQ(*argv, "src")) { 221250003Sadrian filterdata.opt.srcop = ParseOp(argv[1]); 222250003Sadrian if (filterdata.opt.srcop == OP_NONE) { 223250003Sadrian LogPrintf(LogWARN, "ParseUdpOrTcp: bad operation\n"); 224250003Sadrian return(0); 225250003Sadrian } 226250003Sadrian filterdata.opt.srcport = ParsePort(argv[2], proto); 227250003Sadrian if (filterdata.opt.srcport == 0) 228250003Sadrian return(0); 229250003Sadrian argc -= 3; argv += 3; 230250003Sadrian if (argc == 0) 231250003Sadrian return(1); 232250003Sadrian } 233250003Sadrian if (argc >= 3 && STREQ(argv[0], "dst")) { 234250003Sadrian filterdata.opt.dstop = ParseOp(argv[1]); 235250003Sadrian if (filterdata.opt.dstop == OP_NONE) { 236250003Sadrian LogPrintf(LogWARN, "ParseUdpOrTcp: bad operation\n"); 237250003Sadrian return(0); 238250003Sadrian } 239250003Sadrian filterdata.opt.dstport = ParsePort(argv[2], proto); 240250003Sadrian if (filterdata.opt.dstport == 0) 241250003Sadrian return(0); 242250003Sadrian argc -= 3; argv += 3; 243250003Sadrian if (argc == 0) 244250003Sadrian return(1); 245250003Sadrian } 246250003Sadrian if (argc == 1) { 247250003Sadrian if (STREQ(*argv, "estab")) { 248250003Sadrian filterdata.opt.estab = 1; 249250003Sadrian return(1); 250250003Sadrian } 251250003Sadrian LogPrintf(LogWARN, "ParseUdpOrTcp: estab is expected: %s\n", *argv); 252250003Sadrian return(0); 253250003Sadrian } 254250003Sadrian if (argc > 0) 255250003Sadrian LogPrintf(LogWARN, "ParseUdpOrTcp: bad src/dst port syntax: %s\n", *argv); 256250003Sadrian return(0); 257250003Sadrian} 258250003Sadrian 259250003Sadrianchar *opname[] = { "none", "eq", "gt", "lt" }; 260250003Sadrian 261250003Sadrianstatic int 262250003SadrianParse(argc, argv, ofp) 263250003Sadrianint argc; 264250003Sadrianchar **argv; 265250003Sadrianstruct filterent *ofp; 266250003Sadrian{ 267250003Sadrian int action, proto; 268250003Sadrian int val; 269250003Sadrian char *wp; 270250003Sadrian struct filterent *fp = &filterdata; 271250003Sadrian 272250003Sadrian val = strtol(*argv, &wp, 0); 273250003Sadrian if (*argv == wp || val > MAXFILTERS) { 274250003Sadrian LogPrintf(LogWARN, "Parse: invalid filter number.\n"); 275250003Sadrian return(0); 276250003Sadrian } 277250003Sadrian if (val < 0) { 278250003Sadrian for (val = 0; val < MAXFILTERS; val++) { 279250003Sadrian ofp->action = A_NONE; 280250003Sadrian ofp++; 281250003Sadrian } 282250003Sadrian LogPrintf(LogWARN, "Parse: filter cleared.\n"); 283250003Sadrian return(1); 284250003Sadrian } 285250003Sadrian ofp += val; 286250003Sadrian 287250003Sadrian if (--argc == 0) { 288250003Sadrian LogPrintf(LogWARN, "Parse: missing action.\n"); 289250003Sadrian return(0); 290250003Sadrian } 291250003Sadrian argv++; 292250003Sadrian 293250003Sadrian proto = P_NONE; 294250003Sadrian bzero(&filterdata, sizeof(filterdata)); 295250003Sadrian 296250003Sadrian if (STREQ(*argv, "permit")) { 297250003Sadrian action = A_PERMIT; 298250003Sadrian } else if (STREQ(*argv, "deny")) { 299250003Sadrian action = A_DENY; 300250003Sadrian } else if (STREQ(*argv, "clear")) { 301250003Sadrian ofp->action = A_NONE; 302250003Sadrian return(1); 303250003Sadrian } else { 304250003Sadrian LogPrintf(LogWARN, "Parse: bad action: %s\n", *argv); 305250003Sadrian return(0); 306250003Sadrian } 307250003Sadrian fp->action = action; 308250003Sadrian 309250003Sadrian argc--; argv++; 310250003Sadrian 311250003Sadrian if (fp->action == A_DENY) { 312250003Sadrian if (STREQ(*argv, "host")) { 313250003Sadrian fp->action |= A_UHOST; 314250003Sadrian argc--; argv++; 315250003Sadrian } else if (STREQ(*argv, "port")) { 316250003Sadrian fp->action |= A_UPORT; 317250003Sadrian argc--; argv++; 318250003Sadrian } 319250003Sadrian } 320250003Sadrian 321250003Sadrian proto = ParseProto(argc, argv); 322250003Sadrian if (proto == P_NONE) { 323250003Sadrian if (ParseAddr(argc, argv, &fp->saddr, &fp->smask, &fp->swidth)) { 324250003Sadrian argc--; argv++; 325250003Sadrian proto = ParseProto(argc, argv); 326250003Sadrian if (proto == P_NONE) { 327250003Sadrian if (ParseAddr(argc, argv, &fp->daddr, &fp->dmask, &fp->dwidth)) { 328250003Sadrian argc--; argv++; 329250003Sadrian } 330250003Sadrian proto = ParseProto(argc, argv); 331250003Sadrian if (proto) { 332250003Sadrian argc--; argv++; 333250003Sadrian } 334250003Sadrian } else { 335250003Sadrian argc--; argv++; 336250003Sadrian } 337250003Sadrian } else { 338250003Sadrian LogPrintf(LogWARN, "Parse: Address/protocol expected.\n"); 339250003Sadrian return(0); 340250003Sadrian } 341250003Sadrian } else { 342250003Sadrian argc--; argv++; 343250003Sadrian } 344250003Sadrian 345250003Sadrian val = 1; 346250003Sadrian fp->proto = proto; 347250003Sadrian 348250003Sadrian switch (proto) { 349250003Sadrian case P_TCP: 350250003Sadrian val = ParseUdpOrTcp(argc, argv, P_TCP); 351250003Sadrian break; 352250003Sadrian case P_UDP: 353250003Sadrian val = ParseUdpOrTcp(argc, argv, P_UDP); 354250003Sadrian break; 355250003Sadrian case P_ICMP: 356250003Sadrian val = ParseIcmp(argc, argv); 357250003Sadrian break; 358250003Sadrian } 359250003Sadrian 360250003Sadrian LogPrintf(LogDEBUG, "Parse: Src: %s", inet_ntoa(fp->saddr)); 361250003Sadrian LogPrintf(LogDEBUG, "Parse: Src mask: %s ", inet_ntoa(fp->smask)); 362250003Sadrian LogPrintf(LogDEBUG, "Parse: Dst: %s", inet_ntoa(fp->daddr)); 363250003Sadrian LogPrintf(LogDEBUG, "Parse: Dst mask: %s\n", inet_ntoa(fp->dmask)); 364250003Sadrian LogPrintf(LogDEBUG, "Parse: Proto = %d\n", proto); 365250003Sadrian 366250003Sadrian LogPrintf(LogDEBUG, "Parse: src: %s (%d)\n", opname[fp->opt.srcop], 367250003Sadrian fp->opt.srcport); 368250003Sadrian LogPrintf(LogDEBUG, "Parse: dst: %s (%d)\n", opname[fp->opt.dstop], 369250003Sadrian fp->opt.dstport); 370250003Sadrian LogPrintf(LogDEBUG, "Parse: estab: %d\n", fp->opt.estab); 371250003Sadrian 372250003Sadrian if (val) 373250003Sadrian *ofp = *fp; 374250003Sadrian return(val); 375250003Sadrian} 376250003Sadrian 377250003Sadrianint 378250003SadrianSetIfilter(list, argc, argv) 379250003Sadrianstruct cmdtab *list; 380250003Sadrianint argc; 381250003Sadrianchar **argv; 382250003Sadrian{ 383250003Sadrian if (argc > 0) { 384250003Sadrian (void) Parse(argc, argv, ifilters); 385250003Sadrian return 0; 386250003Sadrian } 387250003Sadrian 388250003Sadrian return -1; 389250003Sadrian} 390250003Sadrian 391250003Sadrianint 392250003SadrianSetOfilter(list, argc, argv) 393250003Sadrianstruct cmdtab *list; 394250003Sadrianint argc; 395250003Sadrianchar **argv; 396250003Sadrian{ 397250003Sadrian if (argc > 0) { 398250003Sadrian (void) Parse(argc, argv, ofilters); 399250003Sadrian return 0; 400250003Sadrian } 401250003Sadrian 402250003Sadrian return -1; 403250003Sadrian} 404250003Sadrian 405250003Sadrianint 406250003SadrianSetDfilter(list, argc, argv) 407250008Sadrianstruct cmdtab *list; 408250008Sadrianint argc; 409250008Sadrianchar **argv; 410250008Sadrian{ 411250003Sadrian if (argc > 0) { 412250003Sadrian (void) Parse(argc, argv, dfilters); 413250003Sadrian return 0; 414250003Sadrian } 415250003Sadrian 416250003Sadrian return -1; 417250003Sadrian} 418250003Sadrian 419250003Sadrianint 420250003SadrianSetAfilter(list, argc, argv) 421250003Sadrianstruct cmdtab *list; 422250003Sadrianint argc; 423250003Sadrianchar **argv; 424250003Sadrian{ 425250003Sadrian if (argc > 0) { 426250003Sadrian (void) Parse(argc, argv, afilters); 427250003Sadrian return 0; 428250003Sadrian } 429250003Sadrian 430250003Sadrian return -1; 431250003Sadrian} 432250003Sadrian 433250003Sadrianstatic char *protoname[] = { 434250003Sadrian "none", "tcp", "udp", "icmp", 435250003Sadrian}; 436250003Sadrian 437250003Sadrianstatic char *actname[] = { 438250008Sadrian "none ", "permit ", "deny ", 439250003Sadrian}; 440250003Sadrian 441250008Sadrianstatic void 442250003SadrianShowFilter(fp) 443250003Sadrianstruct filterent *fp; 444250003Sadrian{ 445250003Sadrian int n; 446250008Sadrian 447250008Sadrian if (!VarTerm) 448250003Sadrian return; 449250003Sadrian 450250003Sadrian for (n = 0; n < MAXFILTERS; n++, fp++) { 451250003Sadrian if (fp->action != A_NONE) { 452250003Sadrian fprintf(VarTerm, "%2d %s", n, actname[fp->action]); 453250003Sadrian fprintf(VarTerm, "%s/%d ", inet_ntoa(fp->saddr), fp->swidth); 454250003Sadrian fprintf(VarTerm, "%s/%d ", inet_ntoa(fp->daddr), fp->dwidth); 455250003Sadrian if (fp->proto) { 456250003Sadrian fprintf(VarTerm, "%s", protoname[fp->proto]); 457250003Sadrian 458250003Sadrian if (fp->opt.srcop) 459250003Sadrian fprintf(VarTerm, " src %s %d", opname[fp->opt.srcop], 460250003Sadrian fp->opt.srcport); 461250003Sadrian if (fp->opt.dstop) 462250003Sadrian fprintf(VarTerm, " dst %s %d", opname[fp->opt.dstop], 463250003Sadrian fp->opt.dstport); 464250003Sadrian if (fp->opt.estab) 465250003Sadrian fprintf(VarTerm, " estab"); 466250003Sadrian 467250003Sadrian } 468250003Sadrian fprintf(VarTerm, "\n"); 469250003Sadrian } 470250008Sadrian } 471250003Sadrian} 472250003Sadrian 473250003Sadrianint 474250008SadrianShowIfilter(list, argc, argv) 475250003Sadrianstruct cmdtab *list; 476250003Sadrianint argc; 477250003Sadrianchar **argv; 478250003Sadrian{ 479250003Sadrian ShowFilter(ifilters); 480250003Sadrian return 0; 481250003Sadrian} 482250003Sadrian 483250003Sadrianint 484250003SadrianShowOfilter(list, argc, argv) 485250003Sadrianstruct cmdtab *list; 486250003Sadrianint argc; 487250003Sadrianchar **argv; 488250003Sadrian{ 489250003Sadrian ShowFilter(ofilters); 490250003Sadrian return 0; 491250003Sadrian} 492250003Sadrian 493250003Sadrianint 494250003SadrianShowDfilter(list, argc, argv) 495250003Sadrianstruct cmdtab *list; 496250003Sadrianint argc; 497250003Sadrianchar **argv; 498250003Sadrian{ 499250003Sadrian ShowFilter(dfilters); 500250003Sadrian return 0; 501250003Sadrian} 502250003Sadrian 503250003Sadrianint 504250003SadrianShowAfilter(list, argc, argv) 505250003Sadrianstruct cmdtab *list; 506250003Sadrianint argc; 507250003Sadrianchar **argv; 508250003Sadrian{ 509250003Sadrian ShowFilter(afilters); 510250003Sadrian return 0; 511250003Sadrian} 512250003Sadrian