178189Sbrian/*-
278189Sbrian * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
378189Sbrian *          based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
478189Sbrian *                           Internet Initiative Japan, Inc (IIJ)
578189Sbrian * All rights reserved.
66059Samurai *
778189Sbrian * Redistribution and use in source and binary forms, with or without
878189Sbrian * modification, are permitted provided that the following conditions
978189Sbrian * are met:
1078189Sbrian * 1. Redistributions of source code must retain the above copyright
1178189Sbrian *    notice, this list of conditions and the following disclaimer.
1278189Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1378189Sbrian *    notice, this list of conditions and the following disclaimer in the
1478189Sbrian *    documentation and/or other materials provided with the distribution.
156059Samurai *
1678189Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1778189Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1878189Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1978189Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2078189Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2178189Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2278189Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2378189Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2478189Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2578189Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2678189Sbrian * SUCH DAMAGE.
276059Samurai *
2850479Speter * $FreeBSD$
296059Samurai */
306059Samurai
3143313Sbrian#include <sys/param.h>
326059Samurai#include <netinet/in.h>
3310858Samurai#include <netdb.h>
3436285Sbrian#include <netinet/in_systm.h>
3536285Sbrian#include <netinet/ip.h>
3681634Sbrian#include <sys/socket.h>
3736285Sbrian#include <sys/un.h>
3830715Sbrian
39102500Sbrian#include <stdarg.h>
406059Samurai#include <stdio.h>
416059Samurai#include <stdlib.h>
4296582Sbrian#include <string.h>
4336285Sbrian#include <termios.h>
4430715Sbrian
4546686Sbrian#include "layer.h"
4637009Sbrian#include "defs.h"
476059Samurai#include "command.h"
4826516Sbrian#include "mbuf.h"
4926516Sbrian#include "log.h"
5036285Sbrian#include "iplist.h"
5136285Sbrian#include "timer.h"
5236285Sbrian#include "throughput.h"
5336285Sbrian#include "lqr.h"
5436285Sbrian#include "hdlc.h"
5536285Sbrian#include "fsm.h"
5636285Sbrian#include "lcp.h"
5736285Sbrian#include "ccp.h"
5836285Sbrian#include "link.h"
5936285Sbrian#include "slcompress.h"
6081634Sbrian#include "ncpaddr.h"
6127011Sbrian#include "ipcp.h"
6230715Sbrian#include "filter.h"
6336285Sbrian#include "descriptor.h"
6436285Sbrian#include "prompt.h"
6536285Sbrian#include "mp.h"
6643313Sbrian#ifndef NORADIUS
6743313Sbrian#include "radius.h"
6843313Sbrian#endif
6981634Sbrian#include "ipv6cp.h"
7081634Sbrian#include "ncp.h"
7136285Sbrian#include "bundle.h"
726059Samurai
73134789Sbrianstatic unsigned filter_Nam2Op(const char *);
7430715Sbrian
756059Samuraistatic int
7681634SbrianParsePort(const char *service, const char *proto)
7710858Samurai{
7881634Sbrian  struct servent *servent;
7931343Sbrian  char *cp;
8010858Samurai  int port;
8110858Samurai
8281634Sbrian  servent = getservbyname(service, proto);
8310858Samurai  if (servent != 0)
8449140Sbrian    return ntohs(servent->s_port);
8510858Samurai
8610858Samurai  port = strtol(service, &cp, 0);
8710858Samurai  if (cp == service) {
8836285Sbrian    log_Printf(LogWARN, "ParsePort: %s is not a port name or number.\n",
8928679Sbrian	      service);
9049140Sbrian    return 0;
9110858Samurai  }
9249140Sbrian  return port;
9310858Samurai}
9410858Samurai
956059Samurai/*
966059Samurai *	ICMP Syntax:	src eq icmp_message_type
976059Samurai */
986059Samuraistatic int
99134789SbrianParseIcmp(int argc, char const *const *argv, struct filterent *tgt)
1006059Samurai{
1016059Samurai  int type;
1026059Samurai  char *cp;
1036059Samurai
1046059Samurai  switch (argc) {
1056059Samurai  case 0:
1066059Samurai    /* permit/deny all ICMP types */
10781634Sbrian    tgt->f_srcop = tgt->f_dstop = OP_NONE;
1086059Samurai    break;
10936285Sbrian
1106059Samurai  case 3:
11130715Sbrian    if (!strcmp(*argv, "src") && !strcmp(argv[1], "eq")) {
1126059Samurai      type = strtol(argv[2], &cp, 0);
1136059Samurai      if (cp == argv[2]) {
11436285Sbrian	log_Printf(LogWARN, "ParseIcmp: type is expected.\n");
11549140Sbrian	return 0;
1166059Samurai      }
11749140Sbrian      tgt->f_srcop = OP_EQ;
11849140Sbrian      tgt->f_srcport = type;
11981634Sbrian      tgt->f_dstop = OP_NONE;
1206059Samurai    }
1216059Samurai    break;
12236285Sbrian
12336285Sbrian  default:
12436285Sbrian    log_Printf(LogWARN, "ParseIcmp: bad icmp syntax.\n");
12549140Sbrian    return 0;
1266059Samurai  }
12749140Sbrian  return 1;
1286059Samurai}
1296059Samurai
1306059Samurai/*
1316059Samurai *	UDP Syntax: [src op port] [dst op port]
1326059Samurai */
1336059Samuraistatic int
13481634SbrianParseUdpOrTcp(int argc, char const *const *argv, const struct protoent *pe,
13536285Sbrian              struct filterent *tgt)
1366059Samurai{
13749140Sbrian  tgt->f_srcop = tgt->f_dstop = OP_NONE;
13849140Sbrian  tgt->f_estab = tgt->f_syn = tgt->f_finrst = 0;
13930669Sbrian
14030715Sbrian  if (argc >= 3 && !strcmp(*argv, "src")) {
14149140Sbrian    tgt->f_srcop = filter_Nam2Op(argv[1]);
14249140Sbrian    if (tgt->f_srcop == OP_NONE) {
14381634Sbrian      log_Printf(LogWARN, "ParseUdpOrTcp: bad operator\n");
14449140Sbrian      return 0;
1456059Samurai    }
14681634Sbrian    if (pe == NULL)
14781634Sbrian      return 0;
14881634Sbrian    tgt->f_srcport = ParsePort(argv[2], pe->p_name);
14949140Sbrian    if (tgt->f_srcport == 0)
15049140Sbrian      return 0;
15128679Sbrian    argc -= 3;
15228679Sbrian    argv += 3;
1536059Samurai  }
15436285Sbrian
15530715Sbrian  if (argc >= 3 && !strcmp(argv[0], "dst")) {
15649140Sbrian    tgt->f_dstop = filter_Nam2Op(argv[1]);
15749140Sbrian    if (tgt->f_dstop == OP_NONE) {
15881634Sbrian      log_Printf(LogWARN, "ParseUdpOrTcp: bad operator\n");
15949140Sbrian      return 0;
1606059Samurai    }
16181634Sbrian    if (pe == NULL)
16281634Sbrian      return 0;
16381634Sbrian    tgt->f_dstport = ParsePort(argv[2], pe->p_name);
16449140Sbrian    if (tgt->f_dstport == 0)
16549140Sbrian      return 0;
16628679Sbrian    argc -= 3;
16728679Sbrian    argv += 3;
16810858Samurai  }
16936285Sbrian
17081634Sbrian  if (pe && pe->p_proto == IPPROTO_TCP) {
17136285Sbrian    for (; argc > 0; argc--, argv++)
17236285Sbrian      if (!strcmp(*argv, "estab"))
17349140Sbrian        tgt->f_estab = 1;
17436285Sbrian      else if (!strcmp(*argv, "syn"))
17549140Sbrian        tgt->f_syn = 1;
17636285Sbrian      else if (!strcmp(*argv, "finrst"))
17749140Sbrian        tgt->f_finrst = 1;
17836285Sbrian      else
17936285Sbrian        break;
1806059Samurai  }
18136285Sbrian
18236285Sbrian  if (argc > 0) {
18336285Sbrian    log_Printf(LogWARN, "ParseUdpOrTcp: bad src/dst port syntax: %s\n", *argv);
18436285Sbrian    return 0;
18536285Sbrian  }
18636285Sbrian
18736285Sbrian  return 1;
1886059Samurai}
1896059Samurai
19049372Sbrianstatic int
191134789SbrianParseGeneric(int argc, struct filterent *tgt)
19249140Sbrian{
19349372Sbrian  /*
19449372Sbrian   * Filter currently is a catch-all. Requests are either permitted or
19549372Sbrian   * dropped.
19649372Sbrian   */
19748142Sbrian  if (argc != 0) {
19881634Sbrian    log_Printf(LogWARN, "ParseGeneric: Too many parameters\n");
19948142Sbrian    return 0;
20048142Sbrian  } else
20181634Sbrian    tgt->f_srcop = tgt->f_dstop = OP_NONE;
20248142Sbrian
20348142Sbrian  return 1;
20448142Sbrian}
20548142Sbrian
20647648Sbrianstatic unsigned
20747648Sbrianaddrtype(const char *addr)
20847648Sbrian{
20947648Sbrian  if (!strncasecmp(addr, "MYADDR", 6) && (addr[6] == '\0' || addr[6] == '/'))
21047648Sbrian    return T_MYADDR;
21181634Sbrian  if (!strncasecmp(addr, "MYADDR6", 7) && (addr[7] == '\0' || addr[7] == '/'))
21281634Sbrian    return T_MYADDR6;
21347648Sbrian  if (!strncasecmp(addr, "HISADDR", 7) && (addr[7] == '\0' || addr[7] == '/'))
21447648Sbrian    return T_HISADDR;
21581634Sbrian  if (!strncasecmp(addr, "HISADDR6", 8) && (addr[8] == '\0' || addr[8] == '/'))
21681634Sbrian    return T_HISADDR6;
21758044Sbrian  if (!strncasecmp(addr, "DNS0", 4) && (addr[4] == '\0' || addr[4] == '/'))
21858044Sbrian    return T_DNS0;
21958044Sbrian  if (!strncasecmp(addr, "DNS1", 4) && (addr[4] == '\0' || addr[4] == '/'))
22058044Sbrian    return T_DNS1;
22147648Sbrian
22247648Sbrian  return T_ADDR;
22347648Sbrian}
22447648Sbrian
22547648Sbrianstatic const char *
22681634Sbrianaddrstr(struct ncprange *addr, unsigned type)
22747648Sbrian{
22847648Sbrian  switch (type) {
22947648Sbrian    case T_MYADDR:
23047648Sbrian      return "MYADDR";
23147648Sbrian    case T_HISADDR:
23247648Sbrian      return "HISADDR";
23358044Sbrian    case T_DNS0:
23458044Sbrian      return "DNS0";
23558044Sbrian    case T_DNS1:
23658044Sbrian      return "DNS1";
23747648Sbrian  }
23881634Sbrian  return ncprange_ntoa(addr);
23947648Sbrian}
24047648Sbrian
2416059Samuraistatic int
24281634Sbrianfilter_Parse(struct ncp *ncp, int argc, char const *const *argv,
24381634Sbrian             struct filterent *ofp)
2446059Samurai{
24581634Sbrian  struct filterent fe;
24681634Sbrian  struct protoent *pe;
2476059Samurai  char *wp;
24881634Sbrian  int action, family, ruleno, val, width;
2496059Samurai
25049140Sbrian  ruleno = strtol(*argv, &wp, 0);
25149140Sbrian  if (*argv == wp || ruleno >= MAXFILTERS) {
25236285Sbrian    log_Printf(LogWARN, "Parse: invalid filter number.\n");
25349140Sbrian    return 0;
2546059Samurai  }
25549140Sbrian  if (ruleno < 0) {
25649140Sbrian    for (ruleno = 0; ruleno < MAXFILTERS; ruleno++) {
25749140Sbrian      ofp->f_action = A_NONE;
2586059Samurai      ofp++;
2596059Samurai    }
26036285Sbrian    log_Printf(LogWARN, "Parse: filter cleared.\n");
26149140Sbrian    return 1;
2626059Samurai  }
26349140Sbrian  ofp += ruleno;
2646059Samurai
2656059Samurai  if (--argc == 0) {
26636285Sbrian    log_Printf(LogWARN, "Parse: missing action.\n");
26749140Sbrian    return 0;
2686059Samurai  }
2696059Samurai  argv++;
2706059Samurai
27181634Sbrian  memset(&fe, '\0', sizeof fe);
2726059Samurai
27349140Sbrian  val = strtol(*argv, &wp, 0);
27449140Sbrian  if (!*wp && val >= 0 && val < MAXFILTERS) {
27549140Sbrian    if (val <= ruleno) {
27649140Sbrian      log_Printf(LogWARN, "Parse: Can only jump forward from rule %d\n",
27749140Sbrian                 ruleno);
27849140Sbrian      return 0;
27949140Sbrian    }
28049140Sbrian    action = val;
28149140Sbrian  } else if (!strcmp(*argv, "permit")) {
2826059Samurai    action = A_PERMIT;
28330715Sbrian  } else if (!strcmp(*argv, "deny")) {
2846059Samurai    action = A_DENY;
28530715Sbrian  } else if (!strcmp(*argv, "clear")) {
28649140Sbrian    ofp->f_action = A_NONE;
28749140Sbrian    return 1;
2886059Samurai  } else {
28981634Sbrian    log_Printf(LogWARN, "Parse: %s: bad action\n", *argv);
29049140Sbrian    return 0;
2916059Samurai  }
29281634Sbrian  fe.f_action = action;
2936059Samurai
29428679Sbrian  argc--;
29528679Sbrian  argv++;
2966059Samurai
29749140Sbrian  if (argc && argv[0][0] == '!' && !argv[0][1]) {
29881634Sbrian    fe.f_invert = 1;
29949140Sbrian    argc--;
30049140Sbrian    argv++;
3016059Samurai  }
30243313Sbrian
30381634Sbrian  ncprange_init(&fe.f_src);
30481634Sbrian  ncprange_init(&fe.f_dst);
30581634Sbrian
30681634Sbrian  if (argc == 0)
30781634Sbrian    pe = NULL;
30881634Sbrian  else if ((pe = getprotobyname(*argv)) == NULL && strcmp(*argv, "all") != 0) {
30981634Sbrian    if (argc < 2) {
31081634Sbrian      log_Printf(LogWARN, "Parse: Protocol or address pair expected\n");
31181634Sbrian      return 0;
31281634Sbrian    } else if (strcasecmp(*argv, "any") == 0 ||
31381634Sbrian               ncprange_aton(&fe.f_src, ncp, *argv)) {
31481634Sbrian      family = ncprange_family(&fe.f_src);
31581634Sbrian      if (!ncprange_getwidth(&fe.f_src, &width))
31681634Sbrian        width = 0;
31781634Sbrian      if (width == 0)
31881634Sbrian        ncprange_init(&fe.f_src);
31981634Sbrian      fe.f_srctype = addrtype(*argv);
32028679Sbrian      argc--;
32128679Sbrian      argv++;
32281634Sbrian
32381634Sbrian      if (strcasecmp(*argv, "any") == 0 ||
32481634Sbrian          ncprange_aton(&fe.f_dst, ncp, *argv)) {
32581634Sbrian        if (ncprange_family(&fe.f_dst) != AF_UNSPEC &&
32681634Sbrian            ncprange_family(&fe.f_src) != AF_UNSPEC &&
32781634Sbrian            family != ncprange_family(&fe.f_dst)) {
32881634Sbrian          log_Printf(LogWARN, "Parse: src and dst address families differ\n");
32981634Sbrian          return 0;
33081634Sbrian        }
33181634Sbrian        if (!ncprange_getwidth(&fe.f_dst, &width))
33281634Sbrian          width = 0;
33381634Sbrian        if (width == 0)
33481634Sbrian          ncprange_init(&fe.f_dst);
33581634Sbrian        fe.f_dsttype = addrtype(*argv);
33681634Sbrian        argc--;
33781634Sbrian        argv++;
33827723Sbrian      } else {
33981634Sbrian        log_Printf(LogWARN, "Parse: Protocol or address pair expected\n");
34081634Sbrian        return 0;
3416059Samurai      }
34281634Sbrian
34381634Sbrian      if (argc) {
34481634Sbrian        if ((pe = getprotobyname(*argv)) == NULL && strcmp(*argv, "all") != 0) {
34581634Sbrian          log_Printf(LogWARN, "Parse: %s: Protocol expected\n", *argv);
34681634Sbrian          return 0;
34781634Sbrian        } else {
34881634Sbrian          argc--;
34981634Sbrian          argv++;
35081634Sbrian        }
35181634Sbrian      }
3526059Samurai    } else {
35381634Sbrian      log_Printf(LogWARN, "Parse: Protocol or address pair expected\n");
35449140Sbrian      return 0;
3556059Samurai    }
3566059Samurai  } else {
35728679Sbrian    argc--;
35828679Sbrian    argv++;
3596059Samurai  }
3606059Samurai
36181634Sbrian  if (argc >= 2 && strcmp(*argv, "timeout") == 0) {
36281634Sbrian    fe.timeout = strtoul(argv[1], NULL, 10);
36362977Sbrian    argc -= 2;
36481634Sbrian    argv += 2;
36562977Sbrian  }
36662977Sbrian
3676059Samurai  val = 1;
36881634Sbrian  fe.f_proto = (pe == NULL) ? 0 : pe->p_proto;
3696059Samurai
37081634Sbrian  switch (fe.f_proto) {
37181634Sbrian  case IPPROTO_TCP:
37281634Sbrian  case IPPROTO_UDP:
37381634Sbrian  case IPPROTO_IPIP:
37481634Sbrian#ifndef NOINET6
37581634Sbrian  case IPPROTO_IPV6:
37681634Sbrian#endif
37781634Sbrian    val = ParseUdpOrTcp(argc, argv, pe, &fe);
3786059Samurai    break;
37981634Sbrian  case IPPROTO_ICMP:
38081634Sbrian#ifndef NOINET6
38181634Sbrian  case IPPROTO_ICMPV6:
38281634Sbrian#endif
383134789Sbrian    val = ParseIcmp(argc, argv, &fe);
3846059Samurai    break;
38581634Sbrian  default:
386134789Sbrian    val = ParseGeneric(argc, &fe);
38775894Sbrian    break;
3886059Samurai  }
3896059Samurai
39081634Sbrian  log_Printf(LogDEBUG, "Parse: Src: %s\n", ncprange_ntoa(&fe.f_src));
39181634Sbrian  log_Printf(LogDEBUG, "Parse: Dst: %s\n", ncprange_ntoa(&fe.f_dst));
39281634Sbrian  log_Printf(LogDEBUG, "Parse: Proto: %d\n", fe.f_proto);
3936059Samurai
39436285Sbrian  log_Printf(LogDEBUG, "Parse: src:  %s (%d)\n",
39581634Sbrian            filter_Op2Nam(fe.f_srcop), fe.f_srcport);
39636285Sbrian  log_Printf(LogDEBUG, "Parse: dst:  %s (%d)\n",
39781634Sbrian            filter_Op2Nam(fe.f_dstop), fe.f_dstport);
39881634Sbrian  log_Printf(LogDEBUG, "Parse: estab: %u\n", fe.f_estab);
39981634Sbrian  log_Printf(LogDEBUG, "Parse: syn: %u\n", fe.f_syn);
40081634Sbrian  log_Printf(LogDEBUG, "Parse: finrst: %u\n", fe.f_finrst);
4016059Samurai
4026059Samurai  if (val)
40381634Sbrian    *ofp = fe;
40449140Sbrian
40549140Sbrian  return val;
4066059Samurai}
4076059Samurai
4086059Samuraiint
40936285Sbrianfilter_Set(struct cmdargs const *arg)
4106059Samurai{
41136285Sbrian  struct filter *filter;
4126059Samurai
41336285Sbrian  if (arg->argc < arg->argn+2)
41436285Sbrian    return -1;
41536285Sbrian
41636285Sbrian  if (!strcmp(arg->argv[arg->argn], "in"))
41736285Sbrian    filter = &arg->bundle->filter.in;
41836285Sbrian  else if (!strcmp(arg->argv[arg->argn], "out"))
41936285Sbrian    filter = &arg->bundle->filter.out;
42036285Sbrian  else if (!strcmp(arg->argv[arg->argn], "dial"))
42136285Sbrian    filter = &arg->bundle->filter.dial;
42236285Sbrian  else if (!strcmp(arg->argv[arg->argn], "alive"))
42336285Sbrian    filter = &arg->bundle->filter.alive;
42436285Sbrian  else {
42536285Sbrian    log_Printf(LogWARN, "filter_Set: %s: Invalid filter name.\n",
42636285Sbrian              arg->argv[arg->argn]);
42736285Sbrian    return -1;
42826516Sbrian  }
4296059Samurai
43081634Sbrian  filter_Parse(&arg->bundle->ncp, arg->argc - arg->argn - 1,
43136285Sbrian        arg->argv + arg->argn + 1, filter->rule);
43236285Sbrian  return 0;
4336059Samurai}
4346059Samurai
43536285Sbrianconst char *
436134789Sbrianfilter_Action2Nam(unsigned act)
4376735Samurai{
43855146Sbrian  static const char * const actname[] = { "  none ", "permit ", "  deny " };
439134789Sbrian  static char buf[8];
44049140Sbrian
441134789Sbrian  if (act < MAXFILTERS) {
44249144Sbrian    snprintf(buf, sizeof buf, "%6d ", act);
44349140Sbrian    return buf;
44449140Sbrian  } else if (act >= A_NONE && act < A_NONE + sizeof(actname)/sizeof(char *))
44549140Sbrian    return actname[act - A_NONE];
44649140Sbrian  else
44749140Sbrian    return "?????? ";
4486735Samurai}
4496735Samurai
4506059Samuraistatic void
45136285SbriandoShowFilter(struct filterent *fp, struct prompt *prompt)
4526059Samurai{
45381634Sbrian  struct protoent *pe;
4546059Samurai  int n;
4556059Samurai
4566059Samurai  for (n = 0; n < MAXFILTERS; n++, fp++) {
45749140Sbrian    if (fp->f_action != A_NONE) {
45849140Sbrian      prompt_Printf(prompt, "  %2d %s", n, filter_Action2Nam(fp->f_action));
45949140Sbrian      prompt_Printf(prompt, "%c ", fp->f_invert ? '!' : ' ');
46081634Sbrian
46181634Sbrian      if (ncprange_isset(&fp->f_src))
46281634Sbrian        prompt_Printf(prompt, "%s ", addrstr(&fp->f_src, fp->f_srctype));
46381634Sbrian      else
46481634Sbrian        prompt_Printf(prompt, "any ");
46581634Sbrian
46681634Sbrian      if (ncprange_isset(&fp->f_dst))
46781634Sbrian        prompt_Printf(prompt, "%s ", addrstr(&fp->f_dst, fp->f_dsttype));
46881634Sbrian      else
46981634Sbrian        prompt_Printf(prompt, "any ");
47081634Sbrian
47149140Sbrian      if (fp->f_proto) {
47281634Sbrian        if ((pe = getprotobynumber(fp->f_proto)) == NULL)
47381634Sbrian	  prompt_Printf(prompt, "P:%d", fp->f_proto);
47481634Sbrian        else
47581634Sbrian	  prompt_Printf(prompt, "%s", pe->p_name);
4766059Samurai
47749140Sbrian	if (fp->f_srcop)
47849140Sbrian	  prompt_Printf(prompt, " src %s %d", filter_Op2Nam(fp->f_srcop),
47949140Sbrian		  fp->f_srcport);
48049140Sbrian	if (fp->f_dstop)
48149140Sbrian	  prompt_Printf(prompt, " dst %s %d", filter_Op2Nam(fp->f_dstop),
48249140Sbrian		  fp->f_dstport);
48349140Sbrian	if (fp->f_estab)
48436285Sbrian	  prompt_Printf(prompt, " estab");
48549140Sbrian	if (fp->f_syn)
48636285Sbrian	  prompt_Printf(prompt, " syn");
48749140Sbrian	if (fp->f_finrst)
48836285Sbrian	  prompt_Printf(prompt, " finrst");
48981634Sbrian      } else
49081634Sbrian	prompt_Printf(prompt, "all");
49162977Sbrian      if (fp->timeout != 0)
49262977Sbrian	  prompt_Printf(prompt, " timeout %u", fp->timeout);
49336285Sbrian      prompt_Printf(prompt, "\n");
4946059Samurai    }
4956059Samurai  }
4966059Samurai}
4976059Samurai
4986059Samuraiint
49936285Sbrianfilter_Show(struct cmdargs const *arg)
5006059Samurai{
50136285Sbrian  if (arg->argc > arg->argn+1)
50236285Sbrian    return -1;
50336285Sbrian
50436285Sbrian  if (arg->argc == arg->argn+1) {
50536285Sbrian    struct filter *filter;
50636285Sbrian
50736285Sbrian    if (!strcmp(arg->argv[arg->argn], "in"))
50836285Sbrian      filter = &arg->bundle->filter.in;
50936285Sbrian    else if (!strcmp(arg->argv[arg->argn], "out"))
51036285Sbrian      filter = &arg->bundle->filter.out;
51136285Sbrian    else if (!strcmp(arg->argv[arg->argn], "dial"))
51236285Sbrian      filter = &arg->bundle->filter.dial;
51336285Sbrian    else if (!strcmp(arg->argv[arg->argn], "alive"))
51436285Sbrian      filter = &arg->bundle->filter.alive;
51536285Sbrian    else
51636285Sbrian      return -1;
51736285Sbrian    doShowFilter(filter->rule, arg->prompt);
51836285Sbrian  } else {
51936285Sbrian    struct filter *filter[4];
52036285Sbrian    int f;
52136285Sbrian
52236285Sbrian    filter[0] = &arg->bundle->filter.in;
52336285Sbrian    filter[1] = &arg->bundle->filter.out;
52436285Sbrian    filter[2] = &arg->bundle->filter.dial;
52536285Sbrian    filter[3] = &arg->bundle->filter.alive;
52636285Sbrian    for (f = 0; f < 4; f++) {
52736285Sbrian      if (f)
52836285Sbrian        prompt_Printf(arg->prompt, "\n");
52936285Sbrian      prompt_Printf(arg->prompt, "%s:\n", filter[f]->name);
53036285Sbrian      doShowFilter(filter[f]->rule, arg->prompt);
53136285Sbrian    }
53236285Sbrian  }
53336285Sbrian
53426516Sbrian  return 0;
5356059Samurai}
5366059Samurai
53755146Sbrianstatic const char * const opname[] = {"none", "eq", "gt", "lt"};
53836285Sbrian
53936285Sbrianconst char *
540134789Sbrianfilter_Op2Nam(unsigned op)
5416735Samurai{
54236285Sbrian  if (op >= sizeof opname / sizeof opname[0])
54336285Sbrian    return "unknown";
54436285Sbrian  return opname[op];
54536285Sbrian
5466735Samurai}
54736285Sbrian
548134789Sbrianstatic unsigned
54936285Sbrianfilter_Nam2Op(const char *cp)
55036285Sbrian{
551134789Sbrian  unsigned op;
55236285Sbrian
55336285Sbrian  for (op = sizeof opname / sizeof opname[0] - 1; op; op--)
55436285Sbrian    if (!strcasecmp(cp, opname[op]))
55536285Sbrian      break;
55636285Sbrian
55736285Sbrian  return op;
55836285Sbrian}
55947648Sbrian
56047648Sbrianvoid
56181634Sbrianfilter_AdjustAddr(struct filter *filter, struct ncpaddr *local,
56281634Sbrian                  struct ncpaddr *remote, struct in_addr *dns)
56347648Sbrian{
56447648Sbrian  struct filterent *fp;
56547648Sbrian  int n;
56647648Sbrian
56747648Sbrian  for (fp = filter->rule, n = 0; n < MAXFILTERS; fp++, n++)
56849140Sbrian    if (fp->f_action != A_NONE) {
56981634Sbrian      if (local) {
57081634Sbrian        if (fp->f_srctype == T_MYADDR && ncpaddr_family(local) == AF_INET)
57181634Sbrian          ncprange_sethost(&fp->f_src, local);
57281634Sbrian        if (fp->f_dsttype == T_MYADDR && ncpaddr_family(local) == AF_INET)
57381634Sbrian          ncprange_sethost(&fp->f_dst, local);
57481634Sbrian#ifndef NOINET6
57581634Sbrian        if (fp->f_srctype == T_MYADDR6 && ncpaddr_family(local) == AF_INET6)
57681634Sbrian          ncprange_sethost(&fp->f_src, local);
57781634Sbrian        if (fp->f_dsttype == T_MYADDR6 && ncpaddr_family(local) == AF_INET6)
57881634Sbrian          ncprange_sethost(&fp->f_dst, local);
57981634Sbrian#endif
58047648Sbrian      }
58181634Sbrian      if (remote) {
58281634Sbrian        if (fp->f_srctype == T_HISADDR && ncpaddr_family(remote) == AF_INET)
58381634Sbrian          ncprange_sethost(&fp->f_src, remote);
58481634Sbrian        if (fp->f_dsttype == T_HISADDR && ncpaddr_family(remote) == AF_INET)
58581634Sbrian          ncprange_sethost(&fp->f_dst, remote);
58681634Sbrian#ifndef NOINET6
58781634Sbrian        if (fp->f_srctype == T_HISADDR6 && ncpaddr_family(remote) == AF_INET6)
58881634Sbrian          ncprange_sethost(&fp->f_src, remote);
58981634Sbrian        if (fp->f_dsttype == T_HISADDR6 && ncpaddr_family(remote) == AF_INET6)
59081634Sbrian          ncprange_sethost(&fp->f_dst, remote);
59181634Sbrian#endif
59247648Sbrian      }
59358044Sbrian      if (dns) {
59458044Sbrian        if (fp->f_srctype == T_DNS0)
59581634Sbrian          ncprange_setip4host(&fp->f_src, dns[0]);
59658044Sbrian        if (fp->f_dsttype == T_DNS0)
59781634Sbrian          ncprange_setip4host(&fp->f_dst, dns[0]);
59858044Sbrian        if (fp->f_srctype == T_DNS1)
59981634Sbrian          ncprange_setip4host(&fp->f_src, dns[1]);
60058044Sbrian        if (fp->f_dsttype == T_DNS1)
60181634Sbrian          ncprange_setip4host(&fp->f_dst, dns[1]);
60258044Sbrian      }
60347648Sbrian    }
60447648Sbrian}
605