2 * Copyright (C) 1993-1997 by Darren Reed.
4 * Redistribution and use in source and binary forms are permitted
5 * provided that this notice is preserved and due credit is given
6 * to the original author and the contributors.
10 #include <sys/types.h>
11 #if !defined(__SVR4) && !defined(__svr4__)
14 #include <sys/byteorder.h>
16 #include <sys/param.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <netinet/in_systm.h>
24 #include <netinet/ip.h>
25 #include <netinet/tcp.h>
28 #include <arpa/nameser.h>
29 #include <arpa/inet.h>
32 #include "ip_compat.h"
37 static const char sccsid[] ="@(#)parse.c 1.44 6/5/96 (C) 1993-1996 Darren Reed";
38 static const char rcsid[] = "@(#)$Id: parse.c,v 2.0.2.18.2.5 1998/05/23 19:20:33 darrenr Exp $";
41 extern struct ipopt_names ionames[], secclass[];
44 u_short portnum __P((char *));
45 u_char tcp_flags __P((char *, u_char *));
46 int addicmp __P((char ***, struct frentry *));
47 int extras __P((char ***, struct frentry *));
53 int hostmask __P((char ***, u_32_t *, u_32_t *, u_short *, u_char *,
55 int ports __P((char ***, u_short *, u_char *, u_short *));
56 int icmpcode __P((char *)), addkeep __P((char ***, struct frentry *));
57 int to_interface __P((frdest_t *, char *));
58 void print_toif __P((char *, frdest_t *));
59 void optprint __P((u_short, u_short, u_long, u_long));
60 int countbits __P((u_32_t));
61 char *portname __P((int, int));
65 char flagset[] = "FSRPAU";
66 u_char flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG };
68 static char thishost[64];
73 gethostname(thishost, sizeof(thishost));
74 thishost[sizeof(thishost) - 1] = '\0';
80 * parse a line read from the input filter rule file
82 struct frentry *parse(line)
85 static struct frentry fil;
86 struct protoent *p = NULL;
91 while (*line && isspace(*line))
96 bzero((char *)&fil, sizeof(fil));
97 fil.fr_mip.fi_v = 0xf;
100 * break line up into max of 20 segments
102 if (opts & OPT_DEBUG)
103 fprintf(stderr, "parse [%s]\n", line);
104 for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++)
105 cps[++i] = strtok(NULL, " \b\t\r\n");
109 (void)fprintf(stderr,"not enough segments in line\n");
115 fil.fr_hits = (U_QUAD_T)atoi(*cpp++ + 1) + 1;
118 if (!strcasecmp("block", *cpp)) {
119 fil.fr_flags |= FR_BLOCK;
120 if (!strncasecmp(*(cpp+1), "return-icmp", 11)) {
121 fil.fr_flags |= FR_RETICMP;
123 if (*(*cpp + 11) == '(') {
124 i = icmpcode(*cpp + 12);
127 "uncrecognised icmp code %s\n",
133 } else if (!strncasecmp(*(cpp+1), "return-rst", 10)) {
134 fil.fr_flags |= FR_RETRST;
137 } else if (!strcasecmp("count", *cpp)) {
138 fil.fr_flags |= FR_ACCOUNT;
139 } else if (!strcasecmp("pass", *cpp)) {
140 fil.fr_flags |= FR_PASS;
141 } else if (!strcasecmp("auth", *cpp)) {
142 fil.fr_flags |= FR_AUTH;
143 } else if (!strcasecmp("preauth", *cpp)) {
144 fil.fr_flags |= FR_PREAUTH;
145 } else if (!strcasecmp("skip", *cpp)) {
147 if (!isdigit(**cpp)) {
148 (void)fprintf(stderr, "integer must follow skip\n");
151 fil.fr_skip = atoi(*cpp);
152 } else if (!strcasecmp("log", *cpp)) {
153 fil.fr_flags |= FR_LOG;
154 if (!strcasecmp(*(cpp+1), "body")) {
155 fil.fr_flags |= FR_LOGBODY;
158 if (!strcasecmp(*(cpp+1), "first")) {
159 fil.fr_flags |= FR_LOGFIRST;
164 * Doesn't start with one of the action words
166 (void)fprintf(stderr, "unknown keyword (%s)\n", *cpp);
171 if (!strcasecmp("in", *cpp))
172 fil.fr_flags |= FR_INQUE;
173 else if (!strcasecmp("out", *cpp)) {
174 fil.fr_flags |= FR_OUTQUE;
175 if (fil.fr_flags & FR_RETICMP) {
176 (void)fprintf(stderr,
177 "Can only use return-icmp with 'in'\n");
179 } else if (fil.fr_flags & FR_RETRST) {
180 (void)fprintf(stderr,
181 "Can only use return-rst with 'in'\n");
185 (void)fprintf(stderr,
186 "missing 'in'/'out' keyword (%s)\n", *cpp);
192 if (!strcasecmp("log", *cpp)) {
194 if (fil.fr_flags & FR_PASS)
195 fil.fr_flags |= FR_LOGP;
196 else if (fil.fr_flags & FR_BLOCK)
197 fil.fr_flags |= FR_LOGB;
198 if (!strcasecmp(*cpp, "body")) {
199 fil.fr_flags |= FR_LOGBODY;
202 if (!strcasecmp(*cpp, "first")) {
203 fil.fr_flags |= FR_LOGFIRST;
206 if (!strcasecmp(*cpp, "or-block")) {
207 if (!(fil.fr_flags & FR_PASS)) {
208 (void)fprintf(stderr,
209 "or-block must be used with pass\n");
212 fil.fr_flags |= FR_LOGORBLOCK;
217 if (!strcasecmp("quick", *cpp)) {
219 fil.fr_flags |= FR_QUICK;
222 *fil.fr_ifname = '\0';
223 if (*cpp && !strcasecmp(*cpp, "on")) {
225 (void)fprintf(stderr, "interface name missing\n");
228 (void)strncpy(fil.fr_ifname, *cpp, IFNAMSIZ-1);
229 fil.fr_ifname[IFNAMSIZ-1] = '\0';
232 if (fil.fr_flags & FR_RETRST) {
233 (void)fprintf(stderr,
234 "%s can only be used with TCP\n",
242 if (!strcasecmp(*cpp, "dup-to") && *(cpp + 1)) {
244 if (to_interface(&fil.fr_dif, *cpp))
248 if (!strcasecmp(*cpp, "to") && *(cpp + 1)) {
250 if (to_interface(&fil.fr_tif, *cpp))
253 } else if (!strcasecmp(*cpp, "fastroute")) {
254 fil.fr_flags |= FR_FASTROUTE;
259 if (*cpp && !strcasecmp(*cpp, "tos")) {
261 (void)fprintf(stderr, "tos missing value\n");
264 fil.fr_tos = strtol(*cpp, NULL, 0);
265 fil.fr_mip.fi_tos = 0xff;
269 if (*cpp && !strcasecmp(*cpp, "ttl")) {
271 (void)fprintf(stderr, "ttl missing hopcount value\n");
274 fil.fr_ttl = atoi(*cpp);
275 fil.fr_mip.fi_ttl = 0xff;
280 * check for "proto <protoname>" only decode udp/tcp/icmp as protoname
283 if (*cpp && !strcasecmp(*cpp, "proto")) {
285 (void)fprintf(stderr, "protocol name missing\n");
288 if (!strcasecmp(*cpp, "tcp/udp")) {
289 fil.fr_ip.fi_fl |= FI_TCPUDP;
290 fil.fr_mip.fi_fl |= FI_TCPUDP;
292 if (!(p = getprotobyname(*cpp)) && !isdigit(**cpp)) {
293 (void)fprintf(stderr,
294 "unknown protocol (%s)\n", *cpp);
298 fil.fr_proto = p->p_proto;
299 else if (isdigit(**cpp))
300 fil.fr_proto = atoi(*cpp);
301 fil.fr_mip.fi_p = 0xff;
304 if (fil.fr_proto != IPPROTO_TCP && fil.fr_flags & FR_RETRST) {
305 (void)fprintf(stderr,
306 "%s can only be used with TCP\n",
313 if (fil.fr_proto != IPPROTO_TCP && fil.fr_flags & FR_RETRST) {
314 (void)fprintf(stderr, "%s can only be used with TCP\n",
320 * get the from host and bit mask to use against packets
324 fprintf(stderr, "missing source specification\n");
327 if (!strcasecmp(*cpp, "all")) {
332 if (strcasecmp(*cpp, "from")) {
333 (void)fprintf(stderr,
334 "unexpected keyword (%s) - from\n", *cpp);
338 (void)fprintf(stderr, "missing host after from\n");
343 fil.fr_flags |= FR_NOTSRCIP;
346 if (hostmask(&cpp, (u_32_t *)&fil.fr_src,
347 (u_32_t *)&fil.fr_smsk, &fil.fr_sport, &ch,
349 (void)fprintf(stderr, "bad host (%s)\n", *cpp);
354 (void)fprintf(stderr, "missing to fields\n");
359 * do the same for the to field (destination host)
361 if (strcasecmp(*cpp, "to")) {
362 (void)fprintf(stderr,
363 "unexpected keyword (%s) - to\n", *cpp);
367 (void)fprintf(stderr, "missing host after to\n");
372 fil.fr_flags |= FR_NOTDSTIP;
375 if (hostmask(&cpp, (u_32_t *)&fil.fr_dst,
376 (u_32_t *)&fil.fr_dmsk, &fil.fr_dport, &ch,
378 (void)fprintf(stderr, "bad host (%s)\n", *cpp);
385 * check some sanity, make sure we don't have icmp checks with tcp
386 * or udp or visa versa.
388 if (fil.fr_proto && (fil.fr_dcmp || fil.fr_scmp) &&
389 fil.fr_proto != IPPROTO_TCP && fil.fr_proto != IPPROTO_UDP) {
390 (void)fprintf(stderr, "port operation on non tcp/udp\n");
393 if (fil.fr_icmp && fil.fr_proto != IPPROTO_ICMP) {
394 (void)fprintf(stderr, "icmp comparisons on wrong protocol\n");
401 if (*cpp && !strcasecmp(*cpp, "flags")) {
403 (void)fprintf(stderr, "no flags present\n");
406 fil.fr_tcpf = tcp_flags(*cpp, &fil.fr_tcpfm);
413 if (*cpp && (!strcasecmp(*cpp, "with") || !strcasecmp(*cpp, "and")))
414 if (extras(&cpp, &fil))
418 * icmp types for use with the icmp protocol
420 if (*cpp && !strcasecmp(*cpp, "icmp-type")) {
421 if (fil.fr_proto != IPPROTO_ICMP) {
422 (void)fprintf(stderr,
423 "icmp with wrong protocol (%d)\n",
427 if (addicmp(&cpp, &fil))
429 fil.fr_icmp = htons(fil.fr_icmp);
430 fil.fr_icmpm = htons(fil.fr_icmpm);
436 while (*cpp && !strcasecmp(*cpp, "keep"))
437 if (addkeep(&cpp, &fil))
441 * head of a new group ?
443 if (*cpp && !strcasecmp(*cpp, "head")) {
445 (void)fprintf(stderr, "head without group #\n");
448 fil.fr_grhead = atoi(*cpp);
453 * head of a new group ?
455 if (*cpp && !strcasecmp(*cpp, "group")) {
457 (void)fprintf(stderr, "group without group #\n");
460 fil.fr_group = atoi(*cpp);
468 fprintf(stderr, "unknown words at end: [");
470 (void)fprintf(stderr, "%s ", *cpp);
471 (void)fprintf(stderr, "]\n");
478 if ((fil.fr_tcpf || fil.fr_tcpfm) && fil.fr_proto != IPPROTO_TCP) {
479 (void)fprintf(stderr, "TCP protocol not specified\n");
482 if (!(fil.fr_ip.fi_fl & FI_TCPUDP) && (fil.fr_proto != IPPROTO_TCP) &&
483 (fil.fr_proto != IPPROTO_UDP) && (fil.fr_dcmp || fil.fr_scmp)) {
485 fil.fr_ip.fi_fl |= FI_TCPUDP;
486 fil.fr_mip.fi_fl |= FI_TCPUDP;
488 (void)fprintf(stderr,
489 "port comparisons for non-TCP/UDP\n");
494 if ((fil.fr_flags & FR_KEEPFRAG) &&
495 (!(fil.fr_ip.fi_fl & FI_FRAG) || !(fil.fr_ip.fi_fl & FI_FRAG))) {
496 (void)fprintf(stderr,
497 "must use 'with frags' with 'keep frags'\n");
505 int to_interface(fdp, to)
516 fdp->fd_ip.s_addr = hostnum(s, &r);
520 (void) strncpy(fdp->fd_ifname, to, sizeof(fdp->fd_ifname) - 1);
521 fdp->fd_ifname[sizeof(fdp->fd_ifname) - 1] = '\0';
526 void print_toif(tag, fdp)
530 (void)printf("%s %s%s", tag, fdp->fd_ifname,
531 (fdp->fd_ifp || (long)fdp->fd_ifp == -1) ? "" : "(!)");
532 if (fdp->fd_ip.s_addr)
533 (void)printf(":%s", inet_ntoa(fdp->fd_ip));
539 * returns false if neither "hostmask/num" or "hostmask mask addr" are
540 * found in the line segments
542 int hostmask(seg, sa, msk, pp, cp, tp)
549 int bits = -1, resolved;
552 * is it possibly hostname/num ?
554 if ((s = index(**seg, '/')) || (s = index(**seg, ':'))) {
560 if (!index(s, '.') && !index(s, 'x')) {
562 * set x most significant bits
564 for (bits = atoi(s); bits; bits--) {
566 *msk |= ntohl(inet_addr("128.0.0.0"));
570 if (inet_aton(s, (struct in_addr *)msk) == -1)
573 *sa = hostnum(**seg, &resolved) & *msk;
577 return ports(seg, pp, cp, tp);
581 * look for extra segments if "mask" found in right spot
583 if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) {
584 *sa = hostnum(**seg, &resolved);
589 if (inet_aton(**seg, (struct in_addr *)msk) == -1)
593 return ports(seg, pp, cp, tp);
597 *sa = hostnum(**seg, &resolved);
601 *msk = (*sa ? inet_addr("255.255.255.255") : 0L);
603 return ports(seg, pp, cp, tp);
609 * returns an ip address as a long var as a result of either a DNS lookup or
610 * straight inet_addr() call
612 u_32_t hostnum(host, resolved)
620 if (!strcasecmp("any",host))
623 return inet_addr(host);
624 if (!strcasecmp("<thishost>", host))
627 if (!(hp = gethostbyname(host))) {
628 if (!(np = getnetbyname(host))) {
630 fprintf(stderr, "can't resolve hostname: %s\n", host);
633 return htonl(np->n_net);
635 return *(u_32_t *)hp->h_addr;
639 * check for possible presence of the port fields in the line
641 int ports(seg, pp, cp, tp)
648 if (!*seg || !**seg || !***seg)
650 if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) {
652 if (isdigit(***seg) && *(*seg + 2)) {
653 *pp = portnum(**seg);
655 if (!strcmp(**seg, "<>"))
657 else if (!strcmp(**seg, "><"))
660 *tp = portnum(**seg);
661 } else if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq"))
663 else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne"))
665 else if (!strcmp(**seg, "<") || !strcasecmp(**seg, "lt"))
667 else if (!strcmp(**seg, ">") || !strcasecmp(**seg, "gt"))
669 else if (!strcmp(**seg, "<=") || !strcasecmp(**seg, "le"))
671 else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge"))
674 (void)fprintf(stderr,"unknown comparator (%s)\n",
678 if (comp != FR_OUTRANGE && comp != FR_INRANGE) {
680 *pp = portnum(**seg);
689 * find the port number given by the name, either from getservbyname() or
692 u_short portnum(name)
695 struct servent *sp, *sp2;
699 return (u_short)atoi(name);
702 if (strcasecmp(proto, "tcp/udp")) {
703 sp = getservbyname(name, proto);
705 return ntohs(sp->s_port);
706 (void) fprintf(stderr, "unknown service \"%s\".\n", name);
709 sp = getservbyname(name, "tcp");
712 sp2 = getservbyname(name, "udp");
714 (void) fprintf(stderr, "unknown tcp/udp service \"%s\".\n",
718 if (p1 != sp2->s_port) {
719 (void) fprintf(stderr, "%s %d/tcp is a different port to ",
721 (void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port);
728 u_char tcp_flags(flgs, mask)
732 u_char tcpf = 0, tcpfm = 0, *fp = &tcpf;
735 for (s = flgs; *s; s++) {
736 if (*s == '/' && fp == &tcpf) {
740 if (!(t = index(flagset, *s))) {
741 (void)fprintf(stderr, "unknown flag (%c)\n", *s);
744 *fp |= flags[t - flagset];
754 * deal with extra bits on end of the line
772 while (**cp && (!strncasecmp(**cp, "ipopt", 5) ||
773 !strncasecmp(**cp, "not", 3) || !strncasecmp(**cp, "opt", 4) ||
774 !strncasecmp(**cp, "frag", 3) || !strncasecmp(**cp, "no", 2) ||
775 !strncasecmp(**cp, "short", 5))) {
776 if (***cp == 'n' || ***cp == 'N') {
780 } else if (***cp == 'i' || ***cp == 'I') {
782 fr->fr_ip.fi_fl |= FI_OPTIONS;
783 fr->fr_mip.fi_fl |= FI_OPTIONS;
785 } else if (***cp == 'f' || ***cp == 'F') {
787 fr->fr_ip.fi_fl |= FI_FRAG;
788 fr->fr_mip.fi_fl |= FI_FRAG;
790 } else if (***cp == 'o' || ***cp == 'O') {
792 (void)fprintf(stderr,
793 "opt missing arguements\n");
797 if (!(opts = optname(cp, &secmsk)))
800 } else if (***cp == 's' || ***cp == 'S') {
802 (void) fprintf(stderr,
803 "short cannot be used with TCP flags\n");
808 fr->fr_ip.fi_fl |= FI_SHORT;
809 fr->fr_mip.fi_fl |= FI_SHORT;
814 if (!notopt || !opts)
815 fr->fr_mip.fi_fl |= oflags;
818 fr->fr_mip.fi_optmsk |= opts;
820 fr->fr_mip.fi_optmsk |= (opts & ~0x0100);
822 fr->fr_mip.fi_optmsk |= opts;
823 fr->fr_mip.fi_secmsk |= secmsk;
826 fr->fr_ip.fi_fl &= (~oflags & 0xf);
827 fr->fr_ip.fi_optmsk &= ~opts;
828 fr->fr_ip.fi_secmsk &= ~secmsk;
830 fr->fr_ip.fi_fl |= oflags;
831 fr->fr_ip.fi_optmsk |= opts;
832 fr->fr_ip.fi_secmsk |= secmsk;
845 u_32_t optname(cp, sp)
849 struct ipopt_names *io, *so;
855 for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) {
856 for (io = ionames; io->on_name; io++)
857 if (!strcasecmp(s, io->on_name)) {
862 fprintf(stderr, "unknown IP option name %s\n", s);
865 if (!strcasecmp(s, "sec-class"))
869 if (sec && !*(*cp + 1)) {
870 fprintf(stderr, "missing security level after sec-class\n");
876 for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) {
877 for (so = secclass; so->on_name; so++)
878 if (!strcasecmp(s, so->on_name)) {
883 fprintf(stderr, "no such security level: %s\n",
896 void optprint(u_short secmsk, u_short secbits, u_long optmsk, u_long optbits)
898 void optprint(secmsk, secbits, optmsk, optbits)
899 u_short secmsk, secbits;
900 u_long optmsk, optbits;
903 struct ipopt_names *io, *so;
908 for (io = ionames; io->on_name; io++)
909 if ((io->on_bit & optmsk) &&
910 ((io->on_bit & optmsk) == (io->on_bit & optbits))) {
911 if ((io->on_value != IPOPT_SECURITY) ||
912 (!secmsk && !secbits)) {
913 printf("%s%s", s, io->on_name);
914 if (io->on_value == IPOPT_SECURITY)
922 if (secmsk & secbits) {
923 printf("%ssec-class", s);
925 for (so = secclass; so->on_name; so++)
926 if ((secmsk & so->on_bit) &&
927 ((so->on_bit & secmsk) == (so->on_bit & secbits))) {
928 printf("%s%s", s, so->on_name);
933 if ((optmsk && (optmsk != optbits)) ||
934 (secmsk && (secmsk != secbits))) {
937 if (optmsk != optbits) {
938 for (io = ionames; io->on_name; io++)
939 if ((io->on_bit & optmsk) &&
940 ((io->on_bit & optmsk) !=
941 (io->on_bit & optbits))) {
942 if ((io->on_value != IPOPT_SECURITY) ||
943 (!secmsk && !secbits)) {
944 printf("%s%s", s, io->on_name);
954 if (secmsk != secbits) {
955 printf("%ssec-class", s);
957 for (so = secclass; so->on_name; so++)
958 if ((so->on_bit & secmsk) &&
959 ((so->on_bit & secmsk) !=
960 (so->on_bit & secbits))) {
961 printf("%s%s", s, so->on_name);
968 char *icmptypes[] = {
969 "echorep", (char *)NULL, (char *)NULL, "unreach", "squench",
970 "redir", (char *)NULL, (char *)NULL, "echo", "routerad",
971 "routersol", "timex", "paramprob", "timest", "timestrep",
972 "inforeq", "inforep", "maskreq", "maskrep", "END"
976 * set the icmp field to the correct type if "icmp" word is found
988 if (!fp->fr_proto) /* to catch lusers */
989 fp->fr_proto = IPPROTO_ICMP;
990 if (isdigit(***cp)) {
993 for (t = icmptypes, i = 0; ; t++, i++) {
996 if (!strcasecmp("END", *t)) {
1000 if (!strcasecmp(*t, **cp))
1004 (void)fprintf(stderr,
1005 "Invalid icmp-type (%s) specified\n", **cp);
1009 fp->fr_icmp = (u_short)(i << 8);
1010 fp->fr_icmpm = (u_short)0xff00;
1015 if (**cp && strcasecmp("code", **cp))
1018 if (isdigit(***cp)) {
1020 fp->fr_icmp |= (u_short)i;
1021 fp->fr_icmpm = (u_short)0xffff;
1029 #define MAX_ICMPCODE 12
1031 char *icmpcodes[] = {
1032 "net-unr", "host-unr", "proto-unr", "port-unr", "needfrag", "srcfail",
1033 "net-unk", "host-unk", "isolate", "net-prohib", "host-prohib",
1034 "net-tos", "host-tos", NULL };
1036 * Return the number for the associated ICMP unreachable code.
1044 if (!(s = strrchr(str, ')')))
1050 for (i = 0; icmpcodes[i]; i++)
1051 if (!strncasecmp(str, icmpcodes[i], MIN(len,
1052 strlen(icmpcodes[i])) ))
1059 * set the icmp field to the correct type if "icmp" word is found
1065 if (fp->fr_proto != IPPROTO_TCP && fp->fr_proto != IPPROTO_UDP &&
1066 fp->fr_proto != IPPROTO_ICMP && !(fp->fr_ip.fi_fl & FI_TCPUDP)) {
1067 (void)fprintf(stderr, "Can only use keep with UDP/ICMP/TCP\n");
1072 if (**cp && strcasecmp(**cp, "state") && strcasecmp(**cp, "frags")) {
1073 (void)fprintf(stderr, "Unrecognised state keyword \"%s\"\n",
1078 if (***cp == 's' || ***cp == 'S')
1079 fp->fr_flags |= FR_KEEPSTATE;
1080 else if (***cp == 'f' || ***cp == 'F')
1081 fp->fr_flags |= FR_KEEPFRAG;
1088 * count consecutive 1's in bit mask. If the mask generated by counting
1089 * consecutive 1's is different to that passed, return -1, else return #
1098 ip = ipn = ntohl(ip);
1099 for (i = 32; i; i--, ipn *= 2)
1100 if (ipn & 0x80000000)
1105 for (i = 32, j = cnt; i; i--, j--) {
1116 char *portname(pr, port)
1119 static char buf[32];
1120 struct protoent *p = NULL;
1121 struct servent *sv = NULL, *sv1 = NULL;
1124 if ((sv = getservbyport(port, "tcp"))) {
1125 strncpy(buf, sv->s_name, sizeof(buf)-1);
1126 buf[sizeof(buf)-1] = '\0';
1127 sv1 = getservbyport(port, "udp");
1128 sv = strncasecmp(buf, sv->s_name, strlen(buf)) ?
1133 } else if (pr && (p = getprotobynumber(pr))) {
1134 if ((sv = getservbyport(port, p->p_name))) {
1135 strncpy(buf, sv->s_name, sizeof(buf)-1);
1136 buf[sizeof(buf)-1] = '\0';
1141 (void) sprintf(buf, "%d", port);
1147 * print the filter structure in a useful way
1152 static char *pcmp1[] = { "*", "=", "!=", "<", ">", "<=", ">=",
1159 if (fp->fr_flags & FR_PASS)
1160 (void)printf("pass");
1161 else if (fp->fr_flags & FR_BLOCK) {
1162 (void)printf("block");
1163 if (fp->fr_flags & FR_RETICMP) {
1164 (void)printf(" return-icmp");
1166 if (fp->fr_icode <= MAX_ICMPCODE)
1168 icmpcodes[(int)fp->fr_icode]);
1170 printf("(%d)", fp->fr_icode);
1172 if (fp->fr_flags & FR_RETRST)
1173 (void)printf(" return-rst");
1174 } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) {
1175 (void)printf("log");
1176 if (fp->fr_flags & FR_LOGBODY)
1177 (void)printf(" body");
1178 if (fp->fr_flags & FR_LOGFIRST)
1179 (void)printf(" first");
1180 } else if (fp->fr_flags & FR_ACCOUNT)
1181 (void)printf("count");
1182 else if (fp->fr_flags & FR_AUTH)
1183 (void)printf("auth");
1184 else if (fp->fr_flags & FR_PREAUTH)
1185 (void)printf("preauth");
1186 else if (fp->fr_skip)
1187 (void)printf("skip %d", fp->fr_skip);
1189 if (fp->fr_flags & FR_OUTQUE)
1190 (void)printf(" out ");
1192 (void)printf(" in ");
1194 if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
1195 ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
1196 (void)printf("log ");
1197 if (fp->fr_flags & FR_LOGBODY)
1198 (void)printf("body ");
1199 if (fp->fr_flags & FR_LOGFIRST)
1200 (void)printf("first ");
1201 if (fp->fr_flags & FR_LOGORBLOCK)
1202 (void)printf("or-block ");
1204 if (fp->fr_flags & FR_QUICK)
1205 (void)printf("quick ");
1207 if (*fp->fr_ifname) {
1208 (void)printf("on %s%s ", fp->fr_ifname,
1209 (fp->fr_ifa || (long)fp->fr_ifa == -1) ? "" : "(!)");
1210 if (*fp->fr_dif.fd_ifname)
1211 print_toif("dup-to", &fp->fr_dif);
1212 if (*fp->fr_tif.fd_ifname)
1213 print_toif("to", &fp->fr_tif);
1214 if (fp->fr_flags & FR_FASTROUTE)
1215 (void)printf("fastroute ");
1218 if (fp->fr_mip.fi_tos)
1219 (void)printf("tos %#x ", fp->fr_tos);
1220 if (fp->fr_mip.fi_ttl)
1221 (void)printf("ttl %d ", fp->fr_ttl);
1222 if (fp->fr_ip.fi_fl & FI_TCPUDP) {
1223 (void)printf("proto tcp/udp ");
1225 } else if ((pr = fp->fr_mip.fi_p)) {
1226 if ((p = getprotobynumber(fp->fr_proto)))
1227 (void)printf("proto %s ", p->p_name);
1229 (void)printf("proto %d ", fp->fr_proto);
1232 printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : "");
1233 if (!fp->fr_src.s_addr & !fp->fr_smsk.s_addr)
1234 (void)printf("any ");
1236 (void)printf("%s", inet_ntoa(fp->fr_src));
1237 if ((ones = countbits(fp->fr_smsk.s_addr)) == -1)
1238 (void)printf("/%s ", inet_ntoa(fp->fr_smsk));
1240 (void)printf("/%d ", ones);
1243 if (fp->fr_scmp == FR_INRANGE || fp->fr_scmp == FR_OUTRANGE)
1244 (void)printf("port %d %s %d ", fp->fr_sport,
1245 pcmp1[fp->fr_scmp], fp->fr_stop);
1247 (void)printf("port %s %s ", pcmp1[fp->fr_scmp],
1248 portname(pr, fp->fr_sport));
1250 printf("to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : "");
1251 if (!fp->fr_dst.s_addr & !fp->fr_dmsk.s_addr)
1252 (void)printf("any");
1254 (void)printf("%s", inet_ntoa(fp->fr_dst));
1255 if ((ones = countbits(fp->fr_dmsk.s_addr)) == -1)
1256 (void)printf("/%s", inet_ntoa(fp->fr_dmsk));
1258 (void)printf("/%d", ones);
1261 if (fp->fr_dcmp == FR_INRANGE || fp->fr_dcmp == FR_OUTRANGE)
1262 (void)printf(" port %d %s %d", fp->fr_dport,
1263 pcmp1[fp->fr_dcmp], fp->fr_dtop);
1265 (void)printf(" port %s %s", pcmp1[fp->fr_dcmp],
1266 portname(pr, fp->fr_dport));
1268 if ((fp->fr_ip.fi_fl & ~FI_TCPUDP) ||
1269 (fp->fr_mip.fi_fl & ~FI_TCPUDP) ||
1270 fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk ||
1271 fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk) {
1272 (void)printf(" with");
1273 if (fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk ||
1274 fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk)
1275 optprint(fp->fr_mip.fi_secmsk,
1276 fp->fr_ip.fi_secmsk,
1277 fp->fr_mip.fi_optmsk,
1278 fp->fr_ip.fi_optmsk);
1279 else if (fp->fr_mip.fi_fl & FI_OPTIONS) {
1280 if (!(fp->fr_ip.fi_fl & FI_OPTIONS))
1281 (void)printf(" not");
1282 (void)printf(" ipopt");
1284 if (fp->fr_mip.fi_fl & FI_SHORT) {
1285 if (!(fp->fr_ip.fi_fl & FI_SHORT))
1286 (void)printf(" not");
1287 (void)printf(" short");
1289 if (fp->fr_mip.fi_fl & FI_FRAG) {
1290 if (!(fp->fr_ip.fi_fl & FI_FRAG))
1291 (void)printf(" not");
1292 (void)printf(" frag");
1295 if (fp->fr_proto == IPPROTO_ICMP && fp->fr_icmpm) {
1296 int type = fp->fr_icmp, code;
1298 type = ntohs(fp->fr_icmp);
1301 if (type < (sizeof(icmptypes) / sizeof(char *)) &&
1303 (void)printf(" icmp-type %s", icmptypes[type]);
1305 (void)printf(" icmp-type %d", type);
1307 (void)printf(" code %d", code);
1309 if (fp->fr_proto == IPPROTO_TCP && (fp->fr_tcpf || fp->fr_tcpfm)) {
1310 (void)printf(" flags ");
1311 for (s = flagset, t = flags; *s; s++, t++)
1312 if (fp->fr_tcpf & *t)
1316 for (s = flagset, t = flags; *s; s++, t++)
1317 if (fp->fr_tcpfm & *t)
1322 if (fp->fr_flags & FR_KEEPSTATE)
1323 printf(" keep state");
1324 if (fp->fr_flags & FR_KEEPFRAG)
1325 printf(" keep frags");
1327 printf(" head %d", fp->fr_grhead);
1329 printf(" group %d", fp->fr_group);
1330 (void)putchar('\n');
1336 int i = sizeof(*fp), j = 0;
1339 for (s = (u_char *)fp; i; i--, s++) {
1341 (void)printf("%02x ",*s);
1348 (void)fflush(stdout);