1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 5 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 6 * Internet Initiative Japan, Inc (IIJ) 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $FreeBSD$ 31 */ 32 33 #include <sys/param.h> 34 #include <netinet/in.h> 35 #include <netdb.h> 36 #include <netinet/in_systm.h> 37 #include <netinet/ip.h> 38 #include <sys/socket.h> 39 #include <sys/un.h> 40 41 #include <stdarg.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <termios.h> 46 47 #include "layer.h" 48 #include "defs.h" 49 #include "command.h" 50 #include "mbuf.h" 51 #include "log.h" 52 #include "iplist.h" 53 #include "timer.h" 54 #include "throughput.h" 55 #include "lqr.h" 56 #include "hdlc.h" 57 #include "fsm.h" 58 #include "lcp.h" 59 #include "ccp.h" 60 #include "link.h" 61 #include "slcompress.h" 62 #include "ncpaddr.h" 63 #include "ipcp.h" 64 #include "filter.h" 65 #include "descriptor.h" 66 #include "prompt.h" 67 #include "mp.h" 68 #ifndef NORADIUS 69 #include "radius.h" 70 #endif 71 #include "ipv6cp.h" 72 #include "ncp.h" 73 #include "bundle.h" 74 75 static unsigned filter_Nam2Op(const char *); 76 77 static int 78 ParsePort(const char *service, const char *proto) 79 { 80 struct servent *servent; 81 char *cp; 82 int port; 83 84 servent = getservbyname(service, proto); 85 if (servent != NULL) 86 return ntohs(servent->s_port); 87 88 port = strtol(service, &cp, 0); 89 if (cp == service) { 90 log_Printf(LogWARN, "ParsePort: %s is not a port name or number.\n", 91 service); 92 return 0; 93 } 94 return port; 95 } 96 97 /* 98 * ICMP Syntax: src eq icmp_message_type 99 */ 100 static int 101 ParseIcmp(int argc, char const *const *argv, struct filterent *tgt) 102 { 103 int type; 104 char *cp; 105 106 switch (argc) { 107 case 0: 108 /* permit/deny all ICMP types */ 109 tgt->f_srcop = tgt->f_dstop = OP_NONE; 110 break; 111 112 case 3: 113 if (!strcmp(*argv, "src") && !strcmp(argv[1], "eq")) { 114 type = strtol(argv[2], &cp, 0); 115 if (cp == argv[2]) { 116 log_Printf(LogWARN, "ParseIcmp: type is expected.\n"); 117 return 0; 118 } 119 tgt->f_srcop = OP_EQ; 120 tgt->f_srcport = type; 121 tgt->f_dstop = OP_NONE; 122 } 123 break; 124 125 default: 126 log_Printf(LogWARN, "ParseIcmp: bad icmp syntax.\n"); 127 return 0; 128 } 129 return 1; 130 } 131 132 /* 133 * UDP Syntax: [src op port] [dst op port] 134 */ 135 static int 136 ParseUdpOrTcp(int argc, char const *const *argv, const struct protoent *pe, 137 struct filterent *tgt) 138 { 139 tgt->f_srcop = tgt->f_dstop = OP_NONE; 140 tgt->f_estab = tgt->f_syn = tgt->f_finrst = 0; 141 142 if (argc >= 3 && !strcmp(*argv, "src")) { 143 tgt->f_srcop = filter_Nam2Op(argv[1]); 144 if (tgt->f_srcop == OP_NONE) { 145 log_Printf(LogWARN, "ParseUdpOrTcp: bad operator\n"); 146 return 0; 147 } 148 if (pe == NULL) 149 return 0; 150 tgt->f_srcport = ParsePort(argv[2], pe->p_name); 151 if (tgt->f_srcport == 0) 152 return 0; 153 argc -= 3; 154 argv += 3; 155 } 156 157 if (argc >= 3 && !strcmp(argv[0], "dst")) { 158 tgt->f_dstop = filter_Nam2Op(argv[1]); 159 if (tgt->f_dstop == OP_NONE) { 160 log_Printf(LogWARN, "ParseUdpOrTcp: bad operator\n"); 161 return 0; 162 } 163 if (pe == NULL) 164 return 0; 165 tgt->f_dstport = ParsePort(argv[2], pe->p_name); 166 if (tgt->f_dstport == 0) 167 return 0; 168 argc -= 3; 169 argv += 3; 170 } 171 172 if (pe && pe->p_proto == IPPROTO_TCP) { 173 for (; argc > 0; argc--, argv++) 174 if (!strcmp(*argv, "estab")) 175 tgt->f_estab = 1; 176 else if (!strcmp(*argv, "syn")) 177 tgt->f_syn = 1; 178 else if (!strcmp(*argv, "finrst")) 179 tgt->f_finrst = 1; 180 else 181 break; 182 } 183 184 if (argc > 0) { 185 log_Printf(LogWARN, "ParseUdpOrTcp: bad src/dst port syntax: %s\n", *argv); 186 return 0; 187 } 188 189 return 1; 190 } 191 192 static int 193 ParseGeneric(int argc, struct filterent *tgt) 194 { 195 /* 196 * Filter currently is a catch-all. Requests are either permitted or 197 * dropped. 198 */ 199 if (argc != 0) { 200 log_Printf(LogWARN, "ParseGeneric: Too many parameters\n"); 201 return 0; 202 } else 203 tgt->f_srcop = tgt->f_dstop = OP_NONE; 204 205 return 1; 206 } 207 208 static unsigned 209 addrtype(const char *addr) 210 { 211 if (!strncasecmp(addr, "MYADDR", 6) && (addr[6] == '\0' || addr[6] == '/')) 212 return T_MYADDR; 213 if (!strncasecmp(addr, "MYADDR6", 7) && (addr[7] == '\0' || addr[7] == '/')) 214 return T_MYADDR6; 215 if (!strncasecmp(addr, "HISADDR", 7) && (addr[7] == '\0' || addr[7] == '/')) 216 return T_HISADDR; 217 if (!strncasecmp(addr, "HISADDR6", 8) && (addr[8] == '\0' || addr[8] == '/')) 218 return T_HISADDR6; 219 if (!strncasecmp(addr, "DNS0", 4) && (addr[4] == '\0' || addr[4] == '/')) 220 return T_DNS0; 221 if (!strncasecmp(addr, "DNS1", 4) && (addr[4] == '\0' || addr[4] == '/')) 222 return T_DNS1; 223 224 return T_ADDR; 225 } 226 227 static const char * 228 addrstr(struct ncprange *addr, unsigned type) 229 { 230 switch (type) { 231 case T_MYADDR: 232 return "MYADDR"; 233 case T_HISADDR: 234 return "HISADDR"; 235 case T_DNS0: 236 return "DNS0"; 237 case T_DNS1: 238 return "DNS1"; 239 } 240 return ncprange_ntoa(addr); 241 } 242 243 static int 244 filter_Parse(struct ncp *ncp, int argc, char const *const *argv, 245 struct filterent *ofp) 246 { 247 struct filterent fe; 248 struct protoent *pe; 249 char *wp; 250 int action, family, ruleno, val, width; 251 252 ruleno = strtol(*argv, &wp, 0); 253 if (*argv == wp || ruleno >= MAXFILTERS) { 254 log_Printf(LogWARN, "Parse: invalid filter number.\n"); 255 return 0; 256 } 257 if (ruleno < 0) { 258 for (ruleno = 0; ruleno < MAXFILTERS; ruleno++) { 259 ofp->f_action = A_NONE; 260 ofp++; 261 } 262 log_Printf(LogWARN, "Parse: filter cleared.\n"); 263 return 1; 264 } 265 ofp += ruleno; 266 267 if (--argc == 0) { 268 log_Printf(LogWARN, "Parse: missing action.\n"); 269 return 0; 270 } 271 argv++; 272 273 memset(&fe, '\0', sizeof fe); 274 275 val = strtol(*argv, &wp, 0); 276 if (!*wp && val >= 0 && val < MAXFILTERS) { 277 if (val <= ruleno) { 278 log_Printf(LogWARN, "Parse: Can only jump forward from rule %d\n", 279 ruleno); 280 return 0; 281 } 282 action = val; 283 } else if (!strcmp(*argv, "permit")) { 284 action = A_PERMIT; 285 } else if (!strcmp(*argv, "deny")) { 286 action = A_DENY; 287 } else if (!strcmp(*argv, "clear")) { 288 ofp->f_action = A_NONE; 289 return 1; 290 } else { 291 log_Printf(LogWARN, "Parse: %s: bad action\n", *argv); 292 return 0; 293 } 294 fe.f_action = action; 295 296 argc--; 297 argv++; 298 299 if (argc && argv[0][0] == '!' && !argv[0][1]) { 300 fe.f_invert = 1; 301 argc--; 302 argv++; 303 } 304 305 ncprange_init(&fe.f_src); 306 ncprange_init(&fe.f_dst); 307 308 if (argc == 0) 309 pe = NULL; 310 else if ((pe = getprotobyname(*argv)) == NULL && strcmp(*argv, "all") != 0) { 311 if (argc < 2) { 312 log_Printf(LogWARN, "Parse: Protocol or address pair expected\n"); 313 return 0; 314 } else if (strcasecmp(*argv, "any") == 0 || 315 ncprange_aton(&fe.f_src, ncp, *argv)) { 316 family = ncprange_family(&fe.f_src); 317 if (!ncprange_getwidth(&fe.f_src, &width)) 318 width = 0; 319 if (width == 0) 320 ncprange_init(&fe.f_src); 321 fe.f_srctype = addrtype(*argv); 322 argc--; 323 argv++; 324 325 if (strcasecmp(*argv, "any") == 0 || 326 ncprange_aton(&fe.f_dst, ncp, *argv)) { 327 if (ncprange_family(&fe.f_dst) != AF_UNSPEC && 328 ncprange_family(&fe.f_src) != AF_UNSPEC && 329 family != ncprange_family(&fe.f_dst)) { 330 log_Printf(LogWARN, "Parse: src and dst address families differ\n"); 331 return 0; 332 } 333 if (!ncprange_getwidth(&fe.f_dst, &width)) 334 width = 0; 335 if (width == 0) 336 ncprange_init(&fe.f_dst); 337 fe.f_dsttype = addrtype(*argv); 338 argc--; 339 argv++; 340 } else { 341 log_Printf(LogWARN, "Parse: Protocol or address pair expected\n"); 342 return 0; 343 } 344 345 if (argc) { 346 if ((pe = getprotobyname(*argv)) == NULL && strcmp(*argv, "all") != 0) { 347 log_Printf(LogWARN, "Parse: %s: Protocol expected\n", *argv); 348 return 0; 349 } else { 350 argc--; 351 argv++; 352 } 353 } 354 } else { 355 log_Printf(LogWARN, "Parse: Protocol or address pair expected\n"); 356 return 0; 357 } 358 } else { 359 argc--; 360 argv++; 361 } 362 363 if (argc >= 2 && strcmp(*argv, "timeout") == 0) { 364 fe.timeout = strtoul(argv[1], NULL, 10); 365 argc -= 2; 366 argv += 2; 367 } 368 369 val = 1; 370 fe.f_proto = (pe == NULL) ? 0 : pe->p_proto; 371 372 switch (fe.f_proto) { 373 case IPPROTO_TCP: 374 case IPPROTO_UDP: 375 case IPPROTO_IPIP: 376 #ifndef NOINET6 377 case IPPROTO_IPV6: 378 #endif 379 val = ParseUdpOrTcp(argc, argv, pe, &fe); 380 break; 381 case IPPROTO_ICMP: 382 #ifndef NOINET6 383 case IPPROTO_ICMPV6: 384 #endif 385 val = ParseIcmp(argc, argv, &fe); 386 break; 387 default: 388 val = ParseGeneric(argc, &fe); 389 break; 390 } 391 392 log_Printf(LogDEBUG, "Parse: Src: %s\n", ncprange_ntoa(&fe.f_src)); 393 log_Printf(LogDEBUG, "Parse: Dst: %s\n", ncprange_ntoa(&fe.f_dst)); 394 log_Printf(LogDEBUG, "Parse: Proto: %d\n", fe.f_proto); 395 396 log_Printf(LogDEBUG, "Parse: src: %s (%d)\n", 397 filter_Op2Nam(fe.f_srcop), fe.f_srcport); 398 log_Printf(LogDEBUG, "Parse: dst: %s (%d)\n", 399 filter_Op2Nam(fe.f_dstop), fe.f_dstport); 400 log_Printf(LogDEBUG, "Parse: estab: %u\n", fe.f_estab); 401 log_Printf(LogDEBUG, "Parse: syn: %u\n", fe.f_syn); 402 log_Printf(LogDEBUG, "Parse: finrst: %u\n", fe.f_finrst); 403 404 if (val) 405 *ofp = fe; 406 407 return val; 408 } 409 410 int 411 filter_Set(struct cmdargs const *arg) 412 { 413 struct filter *filter; 414 415 if (arg->argc < arg->argn+2) 416 return -1; 417 418 if (!strcmp(arg->argv[arg->argn], "in")) 419 filter = &arg->bundle->filter.in; 420 else if (!strcmp(arg->argv[arg->argn], "out")) 421 filter = &arg->bundle->filter.out; 422 else if (!strcmp(arg->argv[arg->argn], "dial")) 423 filter = &arg->bundle->filter.dial; 424 else if (!strcmp(arg->argv[arg->argn], "alive")) 425 filter = &arg->bundle->filter.alive; 426 else { 427 log_Printf(LogWARN, "filter_Set: %s: Invalid filter name.\n", 428 arg->argv[arg->argn]); 429 return -1; 430 } 431 432 filter_Parse(&arg->bundle->ncp, arg->argc - arg->argn - 1, 433 arg->argv + arg->argn + 1, filter->rule); 434 return 0; 435 } 436 437 const char * 438 filter_Action2Nam(unsigned act) 439 { 440 static const char * const actname[] = { " none ", "permit ", " deny " }; 441 static char buf[8]; 442 443 if (act < MAXFILTERS) { 444 snprintf(buf, sizeof buf, "%6d ", act); 445 return buf; 446 } else if (act >= A_NONE && act < A_NONE + sizeof(actname)/sizeof(char *)) 447 return actname[act - A_NONE]; 448 else 449 return "?????? "; 450 } 451 452 static void 453 doShowFilter(struct filterent *fp, struct prompt *prompt) 454 { 455 struct protoent *pe; 456 int n; 457 458 for (n = 0; n < MAXFILTERS; n++, fp++) { 459 if (fp->f_action != A_NONE) { 460 prompt_Printf(prompt, " %2d %s", n, filter_Action2Nam(fp->f_action)); 461 prompt_Printf(prompt, "%c ", fp->f_invert ? '!' : ' '); 462 463 if (ncprange_isset(&fp->f_src)) 464 prompt_Printf(prompt, "%s ", addrstr(&fp->f_src, fp->f_srctype)); 465 else 466 prompt_Printf(prompt, "any "); 467 468 if (ncprange_isset(&fp->f_dst)) 469 prompt_Printf(prompt, "%s ", addrstr(&fp->f_dst, fp->f_dsttype)); 470 else 471 prompt_Printf(prompt, "any "); 472 473 if (fp->f_proto) { 474 if ((pe = getprotobynumber(fp->f_proto)) == NULL) 475 prompt_Printf(prompt, "P:%d", fp->f_proto); 476 else 477 prompt_Printf(prompt, "%s", pe->p_name); 478 479 if (fp->f_srcop) 480 prompt_Printf(prompt, " src %s %d", filter_Op2Nam(fp->f_srcop), 481 fp->f_srcport); 482 if (fp->f_dstop) 483 prompt_Printf(prompt, " dst %s %d", filter_Op2Nam(fp->f_dstop), 484 fp->f_dstport); 485 if (fp->f_estab) 486 prompt_Printf(prompt, " estab"); 487 if (fp->f_syn) 488 prompt_Printf(prompt, " syn"); 489 if (fp->f_finrst) 490 prompt_Printf(prompt, " finrst"); 491 } else 492 prompt_Printf(prompt, "all"); 493 if (fp->timeout != 0) 494 prompt_Printf(prompt, " timeout %u", fp->timeout); 495 prompt_Printf(prompt, "\n"); 496 } 497 } 498 } 499 500 int 501 filter_Show(struct cmdargs const *arg) 502 { 503 if (arg->argc > arg->argn+1) 504 return -1; 505 506 if (arg->argc == arg->argn+1) { 507 struct filter *filter; 508 509 if (!strcmp(arg->argv[arg->argn], "in")) 510 filter = &arg->bundle->filter.in; 511 else if (!strcmp(arg->argv[arg->argn], "out")) 512 filter = &arg->bundle->filter.out; 513 else if (!strcmp(arg->argv[arg->argn], "dial")) 514 filter = &arg->bundle->filter.dial; 515 else if (!strcmp(arg->argv[arg->argn], "alive")) 516 filter = &arg->bundle->filter.alive; 517 else 518 return -1; 519 doShowFilter(filter->rule, arg->prompt); 520 } else { 521 struct filter *filter[4]; 522 int f; 523 524 filter[0] = &arg->bundle->filter.in; 525 filter[1] = &arg->bundle->filter.out; 526 filter[2] = &arg->bundle->filter.dial; 527 filter[3] = &arg->bundle->filter.alive; 528 for (f = 0; f < 4; f++) { 529 if (f) 530 prompt_Printf(arg->prompt, "\n"); 531 prompt_Printf(arg->prompt, "%s:\n", filter[f]->name); 532 doShowFilter(filter[f]->rule, arg->prompt); 533 } 534 } 535 536 return 0; 537 } 538 539 static const char * const opname[] = {"none", "eq", "gt", "lt"}; 540 541 const char * 542 filter_Op2Nam(unsigned op) 543 { 544 if (op >= sizeof opname / sizeof opname[0]) 545 return "unknown"; 546 return opname[op]; 547 548 } 549 550 static unsigned 551 filter_Nam2Op(const char *cp) 552 { 553 unsigned op; 554 555 for (op = sizeof opname / sizeof opname[0] - 1; op; op--) 556 if (!strcasecmp(cp, opname[op])) 557 break; 558 559 return op; 560 } 561 562 void 563 filter_AdjustAddr(struct filter *filter, struct ncpaddr *local, 564 struct ncpaddr *remote, struct in_addr *dns) 565 { 566 struct filterent *fp; 567 int n; 568 569 for (fp = filter->rule, n = 0; n < MAXFILTERS; fp++, n++) 570 if (fp->f_action != A_NONE) { 571 if (local) { 572 if (fp->f_srctype == T_MYADDR && ncpaddr_family(local) == AF_INET) 573 ncprange_sethost(&fp->f_src, local); 574 if (fp->f_dsttype == T_MYADDR && ncpaddr_family(local) == AF_INET) 575 ncprange_sethost(&fp->f_dst, local); 576 #ifndef NOINET6 577 if (fp->f_srctype == T_MYADDR6 && ncpaddr_family(local) == AF_INET6) 578 ncprange_sethost(&fp->f_src, local); 579 if (fp->f_dsttype == T_MYADDR6 && ncpaddr_family(local) == AF_INET6) 580 ncprange_sethost(&fp->f_dst, local); 581 #endif 582 } 583 if (remote) { 584 if (fp->f_srctype == T_HISADDR && ncpaddr_family(remote) == AF_INET) 585 ncprange_sethost(&fp->f_src, remote); 586 if (fp->f_dsttype == T_HISADDR && ncpaddr_family(remote) == AF_INET) 587 ncprange_sethost(&fp->f_dst, remote); 588 #ifndef NOINET6 589 if (fp->f_srctype == T_HISADDR6 && ncpaddr_family(remote) == AF_INET6) 590 ncprange_sethost(&fp->f_src, remote); 591 if (fp->f_dsttype == T_HISADDR6 && ncpaddr_family(remote) == AF_INET6) 592 ncprange_sethost(&fp->f_dst, remote); 593 #endif 594 } 595 if (dns) { 596 if (fp->f_srctype == T_DNS0) 597 ncprange_setip4host(&fp->f_src, dns[0]); 598 if (fp->f_dsttype == T_DNS0) 599 ncprange_setip4host(&fp->f_dst, dns[0]); 600 if (fp->f_srctype == T_DNS1) 601 ncprange_setip4host(&fp->f_src, dns[1]); 602 if (fp->f_dsttype == T_DNS1) 603 ncprange_setip4host(&fp->f_dst, dns[1]); 604 } 605 } 606 } 607