1 /*
   2  * Copyright (C) 2000-2005 by Darren Reed.
   3  *
   4  * See the IPFILTER.LICENCE file for details on licencing.
   5  *
   6  * $Id: printfr.c,v 1.43.2.12 2005/06/12 07:18:42 darrenr Exp $
   7  *
   8  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   9  * Use is subject to license terms.
  10  * Copyright 2019 Joyent, Inc.
  11  */
  12 
  13 #include <uuid/uuid.h>
  14 
  15 #include "ipf.h"
  16 
  17 /*
  18  * print the filter structure in a useful way
  19  */
  20 void    printfr(fp, iocfunc)
  21 struct  frentry *fp;
  22 ioctlfunc_t     iocfunc;
  23 {
  24         struct protoent *p;
  25         u_short sec[2];
  26         u_32_t type;
  27         u_char *t;
  28         char *s;
  29         int pr;
  30 
  31         pr = -2;
  32         type = fp->fr_type & ~FR_T_BUILTIN;
  33 
  34         if ((fp->fr_type & FR_T_BUILTIN) != 0)
  35                 printf("# Builtin: ");
  36 
  37         if (fp->fr_collect != 0)
  38                 printf("%u ", fp->fr_collect);
  39 
  40         if (fp->fr_type == FR_T_CALLFUNC) {
  41                 ;
  42         } else if (fp->fr_func != NULL) {
  43                 printf("call");
  44                 if ((fp->fr_flags & FR_CALLNOW) != 0)
  45                         printf(" now");
  46                 s = kvatoname(fp->fr_func, iocfunc);
  47                 printf(" %s/%u", s ? s : "?", fp->fr_arg);
  48         } else if (FR_ISPASS(fp->fr_flags))
  49                 printf("pass");
  50         else if (FR_ISBLOCK(fp->fr_flags)) {
  51                 printf("block");
  52                 if (fp->fr_flags & FR_RETICMP) {
  53                         if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP)
  54                                 printf(" return-icmp-as-dest");
  55                         else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP)
  56                                 printf(" return-icmp");
  57                         if (fp->fr_icode) {
  58                                 if (fp->fr_icode <= MAX_ICMPCODE)
  59                                         printf("(%s)",
  60                                                 icmpcodes[(int)fp->fr_icode]);
  61                                 else
  62                                         printf("(%d)", fp->fr_icode);
  63                         }
  64                 } else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST)
  65                         printf(" return-rst");
  66         } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) {
  67                 printlog(fp);
  68         } else if (FR_ISACCOUNT(fp->fr_flags))
  69                 printf("count");
  70         else if (FR_ISAUTH(fp->fr_flags))
  71                 printf("auth");
  72         else if (FR_ISPREAUTH(fp->fr_flags))
  73                 printf("preauth");
  74         else if (FR_ISNOMATCH(fp->fr_flags))
  75                 printf("nomatch");
  76         else if (FR_ISSKIP(fp->fr_flags))
  77                 printf("skip %u", fp->fr_arg);
  78         else {
  79                 printf("%x", fp->fr_flags);
  80         }
  81 
  82         if (fp->fr_flags & FR_OUTQUE)
  83                 printf(" out ");
  84         else
  85                 printf(" in ");
  86 
  87         if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
  88             ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
  89                 printlog(fp);
  90                 putchar(' ');
  91         }
  92 
  93         if (fp->fr_flags & FR_QUICK)
  94                 printf("quick ");
  95 
  96         if (*fp->fr_ifname) {
  97                 printifname("on ", fp->fr_ifname, fp->fr_ifa);
  98                 if (*fp->fr_ifnames[1] && strcmp(fp->fr_ifnames[1], "*"))
  99                         printifname(",", fp->fr_ifnames[1], fp->fr_ifas[1]);
 100                 putchar(' ');
 101         }
 102 
 103         if (*fp->fr_dif.fd_ifname || (fp->fr_flags & FR_DUP))
 104                 print_toif("dup-to", &fp->fr_dif);
 105         if (*fp->fr_tif.fd_ifname)
 106                 print_toif("to", &fp->fr_tif);
 107         if (*fp->fr_rif.fd_ifname)
 108                 print_toif("reply-to", &fp->fr_rif);
 109         if (fp->fr_flags & FR_FASTROUTE)
 110                 printf("fastroute ");
 111 
 112         if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) ||
 113             (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) {
 114                 if (fp->fr_flags & FR_OUTQUE)
 115                         printf("in-via ");
 116                 else
 117                         printf("out-via ");
 118 
 119                 if (*fp->fr_ifnames[2]) {
 120                         printifname("", fp->fr_ifnames[2],
 121                                     fp->fr_ifas[2]);
 122                         putchar(' ');
 123 
 124                         if (*fp->fr_ifnames[3]) {
 125                                 printifname(",", fp->fr_ifnames[3],
 126                                             fp->fr_ifas[3]);
 127                         }
 128                 }
 129         }
 130 
 131         if (type == FR_T_IPF) {
 132                 if (fp->fr_mip.fi_tos)
 133                         printf("tos %#x ", fp->fr_tos);
 134                 if (fp->fr_mip.fi_ttl)
 135                         printf("ttl %d ", fp->fr_ttl);
 136                 if (fp->fr_flx & FI_TCPUDP) {
 137                         printf("proto tcp/udp ");
 138                         pr = -1;
 139                 } else if (fp->fr_mip.fi_p) {
 140                         pr = fp->fr_ip.fi_p;
 141                         p = getprotobynumber(pr);
 142                         printf("proto ");
 143                         printproto(p, pr, NULL);
 144                         putchar(' ');
 145                 }
 146         }
 147 
 148         if (type == FR_T_NONE) {
 149                 printf("all");
 150         } else if (type == FR_T_IPF) {
 151                 printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : "");
 152                 printaddr(fp->fr_v, fp->fr_satype, fp->fr_ifname,
 153                           &fp->fr_src.s_addr, &fp->fr_smsk.s_addr);
 154                 if (fp->fr_scmp)
 155                         printportcmp(pr, &fp->fr_tuc.ftu_src);
 156 
 157                 printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : "");
 158                 printaddr(fp->fr_v, fp->fr_datype, fp->fr_ifname,
 159                           &fp->fr_dst.s_addr, &fp->fr_dmsk.s_addr);
 160                 if (fp->fr_dcmp)
 161                         printportcmp(pr, &fp->fr_tuc.ftu_dst);
 162 
 163                 if ((fp->fr_proto == IPPROTO_ICMP
 164 #ifdef  USE_INET6
 165                     || fp->fr_proto == IPPROTO_ICMPV6
 166 #endif
 167                     ) && fp->fr_icmpm) {
 168                         int     type = fp->fr_icmp, code;
 169 
 170                         type = ntohs(fp->fr_icmp);
 171                         code = type & 0xff;
 172                         type /= 256;
 173                         if (type < (sizeof(icmptypes) / sizeof(char *) - 1) &&
 174                             icmptypes[type] && fp->fr_proto == IPPROTO_ICMP)
 175                                 printf(" icmp-type %s", icmptypes[type]);
 176                         else
 177                                 printf(" icmp-type %d", type);
 178                         if (ntohs(fp->fr_icmpm) & 0xff)
 179                                 printf(" code %d", code);
 180                 }
 181                 if ((fp->fr_proto == IPPROTO_TCP) &&
 182                     (fp->fr_tcpf || fp->fr_tcpfm)) {
 183                         printf(" flags ");
 184                         if (fp->fr_tcpf & ~TCPF_ALL)
 185                                 printf("0x%x", fp->fr_tcpf);
 186                         else
 187                                 for (s = flagset, t = flags; *s; s++, t++)
 188                                         if (fp->fr_tcpf & *t)
 189                                                 (void)putchar(*s);
 190                         if (fp->fr_tcpfm) {
 191                                 (void)putchar('/');
 192                                 if (fp->fr_tcpfm & ~TCPF_ALL)
 193                                         printf("0x%x", fp->fr_tcpfm);
 194                                 else
 195                                         for (s = flagset, t = flags; *s;
 196                                              s++, t++)
 197                                                 if (fp->fr_tcpfm & *t)
 198                                                         (void)putchar(*s);
 199                         }
 200                 }
 201         } else if (type == FR_T_BPFOPC) {
 202                 fakebpf_t *fb;
 203                 int i;
 204 
 205                 printf("bpf-v%d { \"", fp->fr_v);
 206                 i = fp->fr_dsize / sizeof(*fb);
 207 
 208                 for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ")
 209                         printf("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t,
 210                                fb->fb_f, fb->fb_k);
 211 
 212                 printf("\" }");
 213         } else if (type == FR_T_COMPIPF) {
 214                 ;
 215         } else if (type == FR_T_CALLFUNC) {
 216                 printf("call function at %p", fp->fr_data);
 217         } else {
 218                 printf("[unknown filter type %#x]", fp->fr_type);
 219         }
 220 
 221         if ((type == FR_T_IPF) &&
 222             ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) ||
 223              fp->fr_optbits || fp->fr_optmask ||
 224              fp->fr_secbits || fp->fr_secmask)) {
 225                 char *comma = " ";
 226 
 227                 printf(" with");
 228                 if (fp->fr_optbits || fp->fr_optmask ||
 229                     fp->fr_secbits || fp->fr_secmask) {
 230                         sec[0] = fp->fr_secmask;
 231                         sec[1] = fp->fr_secbits;
 232                         if (fp->fr_v == 4)
 233                                 optprint(sec, fp->fr_optmask, fp->fr_optbits);
 234 #ifdef  USE_INET6
 235                         else
 236                                 optprintv6(sec, fp->fr_optmask,
 237                                            fp->fr_optbits);
 238 #endif
 239                 } else if (fp->fr_mflx & FI_OPTIONS) {
 240                         fputs(comma, stdout);
 241                         if (!(fp->fr_flx & FI_OPTIONS))
 242                                 printf("not ");
 243                         printf("ipopts");
 244                         comma = ",";
 245                 }
 246                 if (fp->fr_mflx & FI_SHORT) {
 247                         fputs(comma, stdout);
 248                         if (!(fp->fr_flx & FI_SHORT))
 249                                 printf("not ");
 250                         printf("short");
 251                         comma = ",";
 252                 }
 253                 if (fp->fr_mflx & FI_FRAG) {
 254                         fputs(comma, stdout);
 255                         if (!(fp->fr_flx & FI_FRAG))
 256                                 printf("not ");
 257                         printf("frag");
 258                         comma = ",";
 259                 }
 260                 if (fp->fr_mflx & FI_FRAGBODY) {
 261                         fputs(comma, stdout);
 262                         if (!(fp->fr_flx & FI_FRAGBODY))
 263                                 printf("not ");
 264                         printf("frag-body");
 265                         comma = ",";
 266                 }
 267                 if (fp->fr_mflx & FI_NATED) {
 268                         fputs(comma, stdout);
 269                         if (!(fp->fr_flx & FI_NATED))
 270                                 printf("not ");
 271                         printf("nat");
 272                         comma = ",";
 273                 }
 274                 if (fp->fr_mflx & FI_LOWTTL) {
 275                         fputs(comma, stdout);
 276                         if (!(fp->fr_flx & FI_LOWTTL))
 277                                 printf("not ");
 278                         printf("lowttl");
 279                         comma = ",";
 280                 }
 281                 if (fp->fr_mflx & FI_BAD) {
 282                         fputs(comma, stdout);
 283                         if (!(fp->fr_flx & FI_BAD))
 284                                 printf("not ");
 285                         printf("bad");
 286                         comma = ",";
 287                 }
 288                 if (fp->fr_mflx & FI_BADSRC) {
 289                         fputs(comma, stdout);
 290                         if (!(fp->fr_flx & FI_BADSRC))
 291                                 printf("not ");
 292                         printf("bad-src");
 293                         comma = ",";
 294                 }
 295                 if (fp->fr_mflx & FI_BADNAT) {
 296                         fputs(comma, stdout);
 297                         if (!(fp->fr_flx & FI_BADNAT))
 298                                 printf("not ");
 299                         printf("bad-nat");
 300                         comma = ",";
 301                 }
 302                 if (fp->fr_mflx & FI_OOW) {
 303                         fputs(comma, stdout);
 304                         if (!(fp->fr_flx & FI_OOW))
 305                                 printf("not ");
 306                         printf("oow");
 307                 }
 308                 if (fp->fr_mflx & FI_MULTICAST) {
 309                         fputs(comma, stdout);
 310                         if (!(fp->fr_flx & FI_MULTICAST))
 311                                 printf("not ");
 312                         printf("mcast");
 313                         comma = ",";
 314                 }
 315                 if (fp->fr_mflx & FI_BROADCAST) {
 316                         fputs(comma, stdout);
 317                         if (!(fp->fr_flx & FI_BROADCAST))
 318                                 printf("not ");
 319                         printf("bcast");
 320                         comma = ",";
 321                 }
 322                 if (fp->fr_mflx & FI_MBCAST) {
 323                         fputs(comma, stdout);
 324                         if (!(fp->fr_flx & FI_MBCAST))
 325                                 printf("not ");
 326                         printf("mbcast");
 327                         comma = ",";
 328                 }
 329                 if (fp->fr_mflx & FI_STATE) {
 330                         fputs(comma, stdout);
 331                         if (!(fp->fr_flx & FI_STATE))
 332                                 printf("not ");
 333                         printf("state");
 334                         comma = ",";
 335                 }
 336         }
 337 
 338         if (fp->fr_flags & FR_KEEPSTATE) {
 339                 printf(" keep state");
 340                 if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN|FR_NOICMPERR|FR_STATESYNC)) ||
 341                     (fp->fr_statemax != 0) || (fp->fr_age[0] != 0)) {
 342                         char *comma = "";
 343                         printf(" (");
 344                         if (fp->fr_statemax != 0) {
 345                                 printf("limit %u", fp->fr_statemax);
 346                                 comma = ",";
 347                         }
 348                         if (fp->fr_flags & FR_STSTRICT) {
 349                                 printf("%sstrict", comma);
 350                                 comma = ",";
 351                         }
 352                         if (fp->fr_flags & FR_NEWISN) {
 353                                 printf("%snewisn", comma);
 354                                 comma = ",";
 355                         }
 356                         if (fp->fr_flags & FR_NOICMPERR) {
 357                                 printf("%sno-icmp-err", comma);
 358                                 comma = ",";
 359                         }
 360                         if (fp->fr_flags & FR_STATESYNC) {
 361                                 printf("%ssync", comma);
 362                                 comma = ",";
 363                         }
 364                         if (fp->fr_age[0] || fp->fr_age[1])
 365                                 printf("%sage %d/%d", comma, fp->fr_age[0],
 366                                        fp->fr_age[1]);
 367                         printf(")");
 368                 }
 369         }
 370         if (fp->fr_flags & FR_KEEPFRAG) {
 371                 printf(" keep frags");
 372                 if (fp->fr_flags & (FR_FRSTRICT)) {
 373                         printf(" (");
 374                         if (fp->fr_flags & FR_FRSTRICT)
 375                                 printf(" strict");
 376                         printf(" )");
 377                                 
 378                 }
 379         }
 380         if (fp->fr_isc != (struct ipscan *)-1) {
 381                 if (fp->fr_isctag[0])
 382                         printf(" scan %s", fp->fr_isctag);
 383                 else
 384                         printf(" scan *");
 385         }
 386         if (*fp->fr_grhead != '\0')
 387                 printf(" head %s", fp->fr_grhead);
 388         if (*fp->fr_group != '\0')
 389                 printf(" group %s", fp->fr_group);
 390         if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag ||
 391             (fp->fr_flags & FR_CFWLOG) || !uuid_is_null(fp->fr_uuid)) {
 392                 char *s = "";
 393 
 394                 printf(" set-tag(");
 395                 if (fp->fr_logtag != FR_NOLOGTAG) {
 396                         printf("log=%u", fp->fr_logtag);
 397                         s = ", ";
 398                 }
 399                 if (*fp->fr_nattag.ipt_tag) {
 400                         printf("%snat=%-.*s", s, IPFTAG_LEN,
 401                                 fp->fr_nattag.ipt_tag);
 402                         s = ", ";
 403                 }
 404                 if (fp->fr_flags & FR_CFWLOG) {
 405                         printf("cfwlog");
 406                         s = ", ";
 407                 }
 408 
 409                 if (!uuid_is_null(fp->fr_uuid)) {
 410                         char uuid[UUID_PRINTABLE_STRING_LENGTH];
 411 
 412                         uuid_unparse(fp->fr_uuid, uuid);
 413                         printf("%suuid=%s", s, uuid);
 414                 }
 415                 printf(")");
 416         }
 417         if (fp->fr_pps)
 418                 printf(" pps %d", fp->fr_pps);
 419         (void)putchar('\n');
 420 }