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