pf_snmp.c revision 205280
1/*- 2 * Copyright (c) 2005 Philip Paeps <philip@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c 205280 2010-03-18 14:54:31Z syrinx $ 27 */ 28 29#include <bsnmp/snmpmod.h> 30 31#include <net/pfvar.h> 32#include <sys/ioctl.h> 33 34#include <errno.h> 35#include <fcntl.h> 36#include <stdint.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#include <syslog.h> 41#include <unistd.h> 42 43#include "pf_oid.h" 44#include "pf_tree.h" 45 46struct lmodule *module; 47 48static int dev = -1; 49static int started; 50static uint64_t pf_tick; 51 52static struct pf_status pfs; 53 54enum { IN, OUT }; 55enum { IPV4, IPV6 }; 56enum { PASS, BLOCK }; 57 58#define PFI_IFTYPE_GROUP 0 59#define PFI_IFTYPE_INSTANCE 1 60#define PFI_IFTYPE_DETACHED 2 61 62struct pfi_entry { 63 struct pfi_kif pfi; 64 u_int index; 65 TAILQ_ENTRY(pfi_entry) link; 66}; 67TAILQ_HEAD(pfi_table, pfi_entry); 68 69static struct pfi_table pfi_table; 70static time_t pfi_table_age; 71static int pfi_table_count; 72 73#define PFI_TABLE_MAXAGE 5 74 75struct pft_entry { 76 struct pfr_tstats pft; 77 u_int index; 78 TAILQ_ENTRY(pft_entry) link; 79}; 80TAILQ_HEAD(pft_table, pft_entry); 81 82static struct pft_table pft_table; 83static time_t pft_table_age; 84static int pft_table_count; 85 86#define PFT_TABLE_MAXAGE 5 87 88struct pfq_entry { 89 struct pf_altq altq; 90 u_int index; 91 TAILQ_ENTRY(pfq_entry) link; 92}; 93TAILQ_HEAD(pfq_table, pfq_entry); 94 95static struct pfq_table pfq_table; 96static time_t pfq_table_age; 97static int pfq_table_count; 98 99static int altq_enabled = 0; 100 101#define PFQ_TABLE_MAXAGE 5 102 103struct pfl_entry { 104 char name[MAXPATHLEN + PF_RULE_LABEL_SIZE]; 105 u_int64_t evals; 106 u_int64_t bytes[2]; 107 u_int64_t pkts[2]; 108 u_int index; 109 TAILQ_ENTRY(pfl_entry) link; 110}; 111TAILQ_HEAD(pfl_table, pfl_entry); 112 113static struct pfl_table pfl_table; 114static time_t pfl_table_age; 115static int pfl_table_count; 116 117#define PFL_TABLE_MAXAGE 5 118 119/* Forward declarations */ 120static int pfi_refresh(void); 121static int pfq_refresh(void); 122static int pfs_refresh(void); 123static int pft_refresh(void); 124static int pfl_refresh(void); 125static struct pfi_entry * pfi_table_find(u_int idx); 126static struct pfq_entry * pfq_table_find(u_int idx); 127static struct pft_entry * pft_table_find(u_int idx); 128static struct pfl_entry * pfl_table_find(u_int idx); 129 130static int altq_is_enabled(int pfdevice); 131 132int 133pf_status(struct snmp_context __unused *ctx, struct snmp_value *val, 134 u_int sub, u_int __unused vindex, enum snmp_op op) 135{ 136 asn_subid_t which = val->var.subs[sub - 1]; 137 time_t runtime; 138 unsigned char str[128]; 139 140 if (op == SNMP_OP_SET) 141 return (SNMP_ERR_NOT_WRITEABLE); 142 143 if (op == SNMP_OP_GET) { 144 if (pfs_refresh() == -1) 145 return (SNMP_ERR_GENERR); 146 147 switch (which) { 148 case LEAF_pfStatusRunning: 149 val->v.uint32 = pfs.running; 150 break; 151 case LEAF_pfStatusRuntime: 152 runtime = (pfs.since > 0) ? 153 time(NULL) - pfs.since : 0; 154 val->v.uint32 = runtime * 100; 155 break; 156 case LEAF_pfStatusDebug: 157 val->v.uint32 = pfs.debug; 158 break; 159 case LEAF_pfStatusHostId: 160 sprintf(str, "0x%08x", ntohl(pfs.hostid)); 161 return (string_get(val, str, strlen(str))); 162 163 default: 164 return (SNMP_ERR_NOSUCHNAME); 165 } 166 167 return (SNMP_ERR_NOERROR); 168 } 169 170 abort(); 171} 172 173int 174pf_counter(struct snmp_context __unused *ctx, struct snmp_value *val, 175 u_int sub, u_int __unused vindex, enum snmp_op op) 176{ 177 asn_subid_t which = val->var.subs[sub - 1]; 178 179 if (op == SNMP_OP_SET) 180 return (SNMP_ERR_NOT_WRITEABLE); 181 182 if (op == SNMP_OP_GET) { 183 if (pfs_refresh() == -1) 184 return (SNMP_ERR_GENERR); 185 186 switch (which) { 187 case LEAF_pfCounterMatch: 188 val->v.counter64 = pfs.counters[PFRES_MATCH]; 189 break; 190 case LEAF_pfCounterBadOffset: 191 val->v.counter64 = pfs.counters[PFRES_BADOFF]; 192 break; 193 case LEAF_pfCounterFragment: 194 val->v.counter64 = pfs.counters[PFRES_FRAG]; 195 break; 196 case LEAF_pfCounterShort: 197 val->v.counter64 = pfs.counters[PFRES_SHORT]; 198 break; 199 case LEAF_pfCounterNormalize: 200 val->v.counter64 = pfs.counters[PFRES_NORM]; 201 break; 202 case LEAF_pfCounterMemDrop: 203 val->v.counter64 = pfs.counters[PFRES_MEMORY]; 204 break; 205 206 default: 207 return (SNMP_ERR_NOSUCHNAME); 208 } 209 210 return (SNMP_ERR_NOERROR); 211 } 212 213 abort(); 214} 215 216int 217pf_statetable(struct snmp_context __unused *ctx, struct snmp_value *val, 218 u_int sub, u_int __unused vindex, enum snmp_op op) 219{ 220 asn_subid_t which = val->var.subs[sub - 1]; 221 222 if (op == SNMP_OP_SET) 223 return (SNMP_ERR_NOT_WRITEABLE); 224 225 if (op == SNMP_OP_GET) { 226 if (pfs_refresh() == -1) 227 return (SNMP_ERR_GENERR); 228 229 switch (which) { 230 case LEAF_pfStateTableCount: 231 val->v.uint32 = pfs.states; 232 break; 233 case LEAF_pfStateTableSearches: 234 val->v.counter64 = 235 pfs.fcounters[FCNT_STATE_SEARCH]; 236 break; 237 case LEAF_pfStateTableInserts: 238 val->v.counter64 = 239 pfs.fcounters[FCNT_STATE_INSERT]; 240 break; 241 case LEAF_pfStateTableRemovals: 242 val->v.counter64 = 243 pfs.fcounters[FCNT_STATE_REMOVALS]; 244 break; 245 246 default: 247 return (SNMP_ERR_NOSUCHNAME); 248 } 249 250 return (SNMP_ERR_NOERROR); 251 } 252 253 abort(); 254} 255 256int 257pf_srcnodes(struct snmp_context __unused *ctx, struct snmp_value *val, 258 u_int sub, u_int __unused vindex, enum snmp_op op) 259{ 260 asn_subid_t which = val->var.subs[sub - 1]; 261 262 if (op == SNMP_OP_SET) 263 return (SNMP_ERR_NOT_WRITEABLE); 264 265 if (op == SNMP_OP_GET) { 266 if (pfs_refresh() == -1) 267 return (SNMP_ERR_GENERR); 268 269 switch (which) { 270 case LEAF_pfSrcNodesCount: 271 val->v.uint32 = pfs.src_nodes; 272 break; 273 case LEAF_pfSrcNodesSearches: 274 val->v.counter64 = 275 pfs.scounters[SCNT_SRC_NODE_SEARCH]; 276 break; 277 case LEAF_pfSrcNodesInserts: 278 val->v.counter64 = 279 pfs.scounters[SCNT_SRC_NODE_INSERT]; 280 break; 281 case LEAF_pfSrcNodesRemovals: 282 val->v.counter64 = 283 pfs.scounters[SCNT_SRC_NODE_REMOVALS]; 284 break; 285 286 default: 287 return (SNMP_ERR_NOSUCHNAME); 288 } 289 290 return (SNMP_ERR_NOERROR); 291 } 292 293 abort(); 294} 295 296int 297pf_limits(struct snmp_context __unused *ctx, struct snmp_value *val, 298 u_int sub, u_int __unused vindex, enum snmp_op op) 299{ 300 asn_subid_t which = val->var.subs[sub - 1]; 301 struct pfioc_limit pl; 302 303 if (op == SNMP_OP_SET) 304 return (SNMP_ERR_NOT_WRITEABLE); 305 306 if (op == SNMP_OP_GET) { 307 bzero(&pl, sizeof(struct pfioc_limit)); 308 309 switch (which) { 310 case LEAF_pfLimitsStates: 311 pl.index = PF_LIMIT_STATES; 312 break; 313 case LEAF_pfLimitsSrcNodes: 314 pl.index = PF_LIMIT_SRC_NODES; 315 break; 316 case LEAF_pfLimitsFrags: 317 pl.index = PF_LIMIT_FRAGS; 318 break; 319 320 default: 321 return (SNMP_ERR_NOSUCHNAME); 322 } 323 324 if (ioctl(dev, DIOCGETLIMIT, &pl)) { 325 syslog(LOG_ERR, "pf_limits(): ioctl(): %s", 326 strerror(errno)); 327 return (SNMP_ERR_GENERR); 328 } 329 330 val->v.uint32 = pl.limit; 331 332 return (SNMP_ERR_NOERROR); 333 } 334 335 abort(); 336} 337 338int 339pf_timeouts(struct snmp_context __unused *ctx, struct snmp_value *val, 340 u_int sub, u_int __unused vindex, enum snmp_op op) 341{ 342 asn_subid_t which = val->var.subs[sub - 1]; 343 struct pfioc_tm pt; 344 345 if (op == SNMP_OP_SET) 346 return (SNMP_ERR_NOT_WRITEABLE); 347 348 if (op == SNMP_OP_GET) { 349 bzero(&pt, sizeof(struct pfioc_tm)); 350 351 switch (which) { 352 case LEAF_pfTimeoutsTcpFirst: 353 pt.timeout = PFTM_TCP_FIRST_PACKET; 354 break; 355 case LEAF_pfTimeoutsTcpOpening: 356 pt.timeout = PFTM_TCP_OPENING; 357 break; 358 case LEAF_pfTimeoutsTcpEstablished: 359 pt.timeout = PFTM_TCP_ESTABLISHED; 360 break; 361 case LEAF_pfTimeoutsTcpClosing: 362 pt.timeout = PFTM_TCP_CLOSING; 363 break; 364 case LEAF_pfTimeoutsTcpFinWait: 365 pt.timeout = PFTM_TCP_FIN_WAIT; 366 break; 367 case LEAF_pfTimeoutsTcpClosed: 368 pt.timeout = PFTM_TCP_CLOSED; 369 break; 370 case LEAF_pfTimeoutsUdpFirst: 371 pt.timeout = PFTM_UDP_FIRST_PACKET; 372 break; 373 case LEAF_pfTimeoutsUdpSingle: 374 pt.timeout = PFTM_UDP_SINGLE; 375 break; 376 case LEAF_pfTimeoutsUdpMultiple: 377 pt.timeout = PFTM_UDP_MULTIPLE; 378 break; 379 case LEAF_pfTimeoutsIcmpFirst: 380 pt.timeout = PFTM_ICMP_FIRST_PACKET; 381 break; 382 case LEAF_pfTimeoutsIcmpError: 383 pt.timeout = PFTM_ICMP_ERROR_REPLY; 384 break; 385 case LEAF_pfTimeoutsOtherFirst: 386 pt.timeout = PFTM_OTHER_FIRST_PACKET; 387 break; 388 case LEAF_pfTimeoutsOtherSingle: 389 pt.timeout = PFTM_OTHER_SINGLE; 390 break; 391 case LEAF_pfTimeoutsOtherMultiple: 392 pt.timeout = PFTM_OTHER_MULTIPLE; 393 break; 394 case LEAF_pfTimeoutsFragment: 395 pt.timeout = PFTM_FRAG; 396 break; 397 case LEAF_pfTimeoutsInterval: 398 pt.timeout = PFTM_INTERVAL; 399 break; 400 case LEAF_pfTimeoutsAdaptiveStart: 401 pt.timeout = PFTM_ADAPTIVE_START; 402 break; 403 case LEAF_pfTimeoutsAdaptiveEnd: 404 pt.timeout = PFTM_ADAPTIVE_END; 405 break; 406 case LEAF_pfTimeoutsSrcNode: 407 pt.timeout = PFTM_SRC_NODE; 408 break; 409 410 default: 411 return (SNMP_ERR_NOSUCHNAME); 412 } 413 414 if (ioctl(dev, DIOCGETTIMEOUT, &pt)) { 415 syslog(LOG_ERR, "pf_timeouts(): ioctl(): %s", 416 strerror(errno)); 417 return (SNMP_ERR_GENERR); 418 } 419 420 val->v.integer = pt.seconds; 421 422 return (SNMP_ERR_NOERROR); 423 } 424 425 abort(); 426} 427 428int 429pf_logif(struct snmp_context __unused *ctx, struct snmp_value *val, 430 u_int sub, u_int __unused vindex, enum snmp_op op) 431{ 432 asn_subid_t which = val->var.subs[sub - 1]; 433 unsigned char str[IFNAMSIZ]; 434 435 if (op == SNMP_OP_SET) 436 return (SNMP_ERR_NOT_WRITEABLE); 437 438 if (op == SNMP_OP_GET) { 439 if (pfs_refresh() == -1) 440 return (SNMP_ERR_GENERR); 441 442 switch (which) { 443 case LEAF_pfLogInterfaceName: 444 strlcpy(str, pfs.ifname, sizeof str); 445 return (string_get(val, str, strlen(str))); 446 case LEAF_pfLogInterfaceIp4BytesIn: 447 val->v.counter64 = pfs.bcounters[IPV4][IN]; 448 break; 449 case LEAF_pfLogInterfaceIp4BytesOut: 450 val->v.counter64 = pfs.bcounters[IPV4][OUT]; 451 break; 452 case LEAF_pfLogInterfaceIp4PktsInPass: 453 val->v.counter64 = 454 pfs.pcounters[IPV4][IN][PF_PASS]; 455 break; 456 case LEAF_pfLogInterfaceIp4PktsInDrop: 457 val->v.counter64 = 458 pfs.pcounters[IPV4][IN][PF_DROP]; 459 break; 460 case LEAF_pfLogInterfaceIp4PktsOutPass: 461 val->v.counter64 = 462 pfs.pcounters[IPV4][OUT][PF_PASS]; 463 break; 464 case LEAF_pfLogInterfaceIp4PktsOutDrop: 465 val->v.counter64 = 466 pfs.pcounters[IPV4][OUT][PF_DROP]; 467 break; 468 case LEAF_pfLogInterfaceIp6BytesIn: 469 val->v.counter64 = pfs.bcounters[IPV6][IN]; 470 break; 471 case LEAF_pfLogInterfaceIp6BytesOut: 472 val->v.counter64 = pfs.bcounters[IPV6][OUT]; 473 break; 474 case LEAF_pfLogInterfaceIp6PktsInPass: 475 val->v.counter64 = 476 pfs.pcounters[IPV6][IN][PF_PASS]; 477 break; 478 case LEAF_pfLogInterfaceIp6PktsInDrop: 479 val->v.counter64 = 480 pfs.pcounters[IPV6][IN][PF_DROP]; 481 break; 482 case LEAF_pfLogInterfaceIp6PktsOutPass: 483 val->v.counter64 = 484 pfs.pcounters[IPV6][OUT][PF_PASS]; 485 break; 486 case LEAF_pfLogInterfaceIp6PktsOutDrop: 487 val->v.counter64 = 488 pfs.pcounters[IPV6][OUT][PF_DROP]; 489 break; 490 491 default: 492 return (SNMP_ERR_NOSUCHNAME); 493 } 494 495 return (SNMP_ERR_NOERROR); 496 } 497 498 abort(); 499} 500 501int 502pf_interfaces(struct snmp_context __unused *ctx, struct snmp_value *val, 503 u_int sub, u_int __unused vindex, enum snmp_op op) 504{ 505 asn_subid_t which = val->var.subs[sub - 1]; 506 507 if (op == SNMP_OP_SET) 508 return (SNMP_ERR_NOT_WRITEABLE); 509 510 if (op == SNMP_OP_GET) { 511 if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE) 512 if (pfi_refresh() == -1) 513 return (SNMP_ERR_GENERR); 514 515 switch (which) { 516 case LEAF_pfInterfacesIfNumber: 517 val->v.uint32 = pfi_table_count; 518 break; 519 520 default: 521 return (SNMP_ERR_NOSUCHNAME); 522 } 523 524 return (SNMP_ERR_NOERROR); 525 } 526 527 abort(); 528} 529 530int 531pf_iftable(struct snmp_context __unused *ctx, struct snmp_value *val, 532 u_int sub, u_int __unused vindex, enum snmp_op op) 533{ 534 asn_subid_t which = val->var.subs[sub - 1]; 535 struct pfi_entry *e = NULL; 536 537 switch (op) { 538 case SNMP_OP_SET: 539 return (SNMP_ERR_NOT_WRITEABLE); 540 case SNMP_OP_GETNEXT: 541 if ((e = NEXT_OBJECT_INT(&pfi_table, 542 &val->var, sub)) == NULL) 543 return (SNMP_ERR_NOSUCHNAME); 544 val->var.len = sub + 1; 545 val->var.subs[sub] = e->index; 546 break; 547 case SNMP_OP_GET: 548 if (val->var.len - sub != 1) 549 return (SNMP_ERR_NOSUCHNAME); 550 if ((e = pfi_table_find(val->var.subs[sub])) == NULL) 551 return (SNMP_ERR_NOSUCHNAME); 552 break; 553 554 case SNMP_OP_COMMIT: 555 case SNMP_OP_ROLLBACK: 556 default: 557 abort(); 558 } 559 560 if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE) 561 pfi_refresh(); 562 563 switch (which) { 564 case LEAF_pfInterfacesIfDescr: 565 return (string_get(val, e->pfi.pfik_name, -1)); 566 case LEAF_pfInterfacesIfType: 567 val->v.integer = PFI_IFTYPE_INSTANCE; 568 break; 569 case LEAF_pfInterfacesIfTZero: 570 val->v.uint32 = 571 (time(NULL) - e->pfi.pfik_tzero) * 100; 572 break; 573 case LEAF_pfInterfacesIfRefsState: 574 val->v.uint32 = e->pfi.pfik_states; 575 break; 576 case LEAF_pfInterfacesIfRefsRule: 577 val->v.uint32 = e->pfi.pfik_rules; 578 break; 579 case LEAF_pfInterfacesIf4BytesInPass: 580 val->v.counter64 = 581 e->pfi.pfik_bytes[IPV4][IN][PASS]; 582 break; 583 case LEAF_pfInterfacesIf4BytesInBlock: 584 val->v.counter64 = 585 e->pfi.pfik_bytes[IPV4][IN][BLOCK]; 586 break; 587 case LEAF_pfInterfacesIf4BytesOutPass: 588 val->v.counter64 = 589 e->pfi.pfik_bytes[IPV4][OUT][PASS]; 590 break; 591 case LEAF_pfInterfacesIf4BytesOutBlock: 592 val->v.counter64 = 593 e->pfi.pfik_bytes[IPV4][OUT][BLOCK]; 594 break; 595 case LEAF_pfInterfacesIf4PktsInPass: 596 val->v.counter64 = 597 e->pfi.pfik_packets[IPV4][IN][PASS]; 598 break; 599 case LEAF_pfInterfacesIf4PktsInBlock: 600 val->v.counter64 = 601 e->pfi.pfik_packets[IPV4][IN][BLOCK]; 602 break; 603 case LEAF_pfInterfacesIf4PktsOutPass: 604 val->v.counter64 = 605 e->pfi.pfik_packets[IPV4][OUT][PASS]; 606 break; 607 case LEAF_pfInterfacesIf4PktsOutBlock: 608 val->v.counter64 = 609 e->pfi.pfik_packets[IPV4][OUT][BLOCK]; 610 break; 611 case LEAF_pfInterfacesIf6BytesInPass: 612 val->v.counter64 = 613 e->pfi.pfik_bytes[IPV6][IN][PASS]; 614 break; 615 case LEAF_pfInterfacesIf6BytesInBlock: 616 val->v.counter64 = 617 e->pfi.pfik_bytes[IPV6][IN][BLOCK]; 618 break; 619 case LEAF_pfInterfacesIf6BytesOutPass: 620 val->v.counter64 = 621 e->pfi.pfik_bytes[IPV6][OUT][PASS]; 622 break; 623 case LEAF_pfInterfacesIf6BytesOutBlock: 624 val->v.counter64 = 625 e->pfi.pfik_bytes[IPV6][OUT][BLOCK]; 626 break; 627 case LEAF_pfInterfacesIf6PktsInPass: 628 val->v.counter64 = 629 e->pfi.pfik_packets[IPV6][IN][PASS]; 630 break; 631 case LEAF_pfInterfacesIf6PktsInBlock: 632 val->v.counter64 = 633 e->pfi.pfik_packets[IPV6][IN][BLOCK]; 634 break; 635 case LEAF_pfInterfacesIf6PktsOutPass: 636 val->v.counter64 = 637 e->pfi.pfik_packets[IPV6][OUT][PASS]; 638 break; 639 case LEAF_pfInterfacesIf6PktsOutBlock: 640 val->v.counter64 = 641 e->pfi.pfik_packets[IPV6][OUT][BLOCK]; 642 break; 643 644 default: 645 return (SNMP_ERR_NOSUCHNAME); 646 } 647 648 return (SNMP_ERR_NOERROR); 649} 650 651int 652pf_tables(struct snmp_context __unused *ctx, struct snmp_value *val, 653 u_int sub, u_int __unused vindex, enum snmp_op op) 654{ 655 asn_subid_t which = val->var.subs[sub - 1]; 656 657 if (op == SNMP_OP_SET) 658 return (SNMP_ERR_NOT_WRITEABLE); 659 660 if (op == SNMP_OP_GET) { 661 if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE) 662 if (pft_refresh() == -1) 663 return (SNMP_ERR_GENERR); 664 665 switch (which) { 666 case LEAF_pfTablesTblNumber: 667 val->v.uint32 = pft_table_count; 668 break; 669 670 default: 671 return (SNMP_ERR_NOSUCHNAME); 672 } 673 674 return (SNMP_ERR_NOERROR); 675 } 676 677 abort(); 678} 679 680int 681pf_tbltable(struct snmp_context __unused *ctx, struct snmp_value *val, 682 u_int sub, u_int __unused vindex, enum snmp_op op) 683{ 684 asn_subid_t which = val->var.subs[sub - 1]; 685 struct pft_entry *e = NULL; 686 687 switch (op) { 688 case SNMP_OP_SET: 689 return (SNMP_ERR_NOT_WRITEABLE); 690 case SNMP_OP_GETNEXT: 691 if ((e = NEXT_OBJECT_INT(&pft_table, 692 &val->var, sub)) == NULL) 693 return (SNMP_ERR_NOSUCHNAME); 694 val->var.len = sub + 1; 695 val->var.subs[sub] = e->index; 696 break; 697 case SNMP_OP_GET: 698 if (val->var.len - sub != 1) 699 return (SNMP_ERR_NOSUCHNAME); 700 if ((e = pft_table_find(val->var.subs[sub])) == NULL) 701 return (SNMP_ERR_NOSUCHNAME); 702 break; 703 704 case SNMP_OP_COMMIT: 705 case SNMP_OP_ROLLBACK: 706 default: 707 abort(); 708 } 709 710 if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE) 711 pft_refresh(); 712 713 switch (which) { 714 case LEAF_pfTablesTblDescr: 715 return (string_get(val, e->pft.pfrts_name, -1)); 716 case LEAF_pfTablesTblCount: 717 val->v.integer = e->pft.pfrts_cnt; 718 break; 719 case LEAF_pfTablesTblTZero: 720 val->v.uint32 = 721 (time(NULL) - e->pft.pfrts_tzero) * 100; 722 break; 723 case LEAF_pfTablesTblRefsAnchor: 724 val->v.integer = 725 e->pft.pfrts_refcnt[PFR_REFCNT_ANCHOR]; 726 break; 727 case LEAF_pfTablesTblRefsRule: 728 val->v.integer = 729 e->pft.pfrts_refcnt[PFR_REFCNT_RULE]; 730 break; 731 case LEAF_pfTablesTblEvalMatch: 732 val->v.counter64 = e->pft.pfrts_match; 733 break; 734 case LEAF_pfTablesTblEvalNoMatch: 735 val->v.counter64 = e->pft.pfrts_nomatch; 736 break; 737 case LEAF_pfTablesTblBytesInPass: 738 val->v.counter64 = 739 e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_PASS]; 740 break; 741 case LEAF_pfTablesTblBytesInBlock: 742 val->v.counter64 = 743 e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_BLOCK]; 744 break; 745 case LEAF_pfTablesTblBytesInXPass: 746 val->v.counter64 = 747 e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_XPASS]; 748 break; 749 case LEAF_pfTablesTblBytesOutPass: 750 val->v.counter64 = 751 e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_PASS]; 752 break; 753 case LEAF_pfTablesTblBytesOutBlock: 754 val->v.counter64 = 755 e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_BLOCK]; 756 break; 757 case LEAF_pfTablesTblBytesOutXPass: 758 val->v.counter64 = 759 e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_XPASS]; 760 break; 761 case LEAF_pfTablesTblPktsInPass: 762 val->v.counter64 = 763 e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_PASS]; 764 break; 765 case LEAF_pfTablesTblPktsInBlock: 766 val->v.counter64 = 767 e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_BLOCK]; 768 break; 769 case LEAF_pfTablesTblPktsInXPass: 770 val->v.counter64 = 771 e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_XPASS]; 772 break; 773 case LEAF_pfTablesTblPktsOutPass: 774 val->v.counter64 = 775 e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_PASS]; 776 break; 777 case LEAF_pfTablesTblPktsOutBlock: 778 val->v.counter64 = 779 e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_BLOCK]; 780 break; 781 case LEAF_pfTablesTblPktsOutXPass: 782 val->v.counter64 = 783 e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_XPASS]; 784 break; 785 786 default: 787 return (SNMP_ERR_NOSUCHNAME); 788 } 789 790 return (SNMP_ERR_NOERROR); 791} 792 793int 794pf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val, 795 u_int __unused sub, u_int __unused vindex, enum snmp_op __unused op) 796{ 797 return (SNMP_ERR_GENERR); 798} 799 800int 801pf_altq(struct snmp_context __unused *ctx, struct snmp_value *val, 802 u_int sub, u_int __unused vindex, enum snmp_op op) 803{ 804 asn_subid_t which = val->var.subs[sub - 1]; 805 806 if (!altq_enabled) { 807 return (SNMP_ERR_NOERROR); 808 } 809 810 if (op == SNMP_OP_SET) 811 return (SNMP_ERR_NOT_WRITEABLE); 812 813 if (op == SNMP_OP_GET) { 814 if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE) 815 if (pfq_refresh() == -1) 816 return (SNMP_ERR_GENERR); 817 818 switch (which) { 819 case LEAF_pfAltqQueueNumber: 820 val->v.uint32 = pfq_table_count; 821 break; 822 823 default: 824 return (SNMP_ERR_NOSUCHNAME); 825 } 826 827 return (SNMP_ERR_NOERROR); 828 } 829 830 abort(); 831 return (SNMP_ERR_GENERR); 832} 833 834int 835pf_altqq(struct snmp_context __unused *ctx, struct snmp_value *val, 836 u_int sub, u_int __unused vindex, enum snmp_op op) 837{ 838 asn_subid_t which = val->var.subs[sub - 1]; 839 struct pfq_entry *e = NULL; 840 841 if (!altq_enabled) { 842 return (SNMP_ERR_NOERROR); 843 } 844 845 switch (op) { 846 case SNMP_OP_SET: 847 return (SNMP_ERR_NOT_WRITEABLE); 848 case SNMP_OP_GETNEXT: 849 if ((e = NEXT_OBJECT_INT(&pfq_table, 850 &val->var, sub)) == NULL) 851 return (SNMP_ERR_NOSUCHNAME); 852 val->var.len = sub + 1; 853 val->var.subs[sub] = e->index; 854 break; 855 case SNMP_OP_GET: 856 if (val->var.len - sub != 1) 857 return (SNMP_ERR_NOSUCHNAME); 858 if ((e = pfq_table_find(val->var.subs[sub])) == NULL) 859 return (SNMP_ERR_NOSUCHNAME); 860 break; 861 862 case SNMP_OP_COMMIT: 863 case SNMP_OP_ROLLBACK: 864 default: 865 abort(); 866 } 867 868 if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE) 869 pfq_refresh(); 870 871 switch (which) { 872 case LEAF_pfAltqQueueDescr: 873 return (string_get(val, e->altq.qname, -1)); 874 case LEAF_pfAltqQueueParent: 875 return (string_get(val, e->altq.parent, -1)); 876 case LEAF_pfAltqQueueScheduler: 877 val->v.integer = e->altq.scheduler; 878 break; 879 case LEAF_pfAltqQueueBandwidth: 880 val->v.uint32 = e->altq.bandwidth; 881 break; 882 case LEAF_pfAltqQueuePriority: 883 val->v.integer = e->altq.priority; 884 break; 885 case LEAF_pfAltqQueueLimit: 886 val->v.integer = e->altq.qlimit; 887 break; 888 889 default: 890 return (SNMP_ERR_NOSUCHNAME); 891 } 892 893 return (SNMP_ERR_NOERROR); 894} 895 896int 897pf_labels(struct snmp_context __unused *ctx, struct snmp_value *val, 898 u_int sub, u_int __unused vindex, enum snmp_op op) 899{ 900 asn_subid_t which = val->var.subs[sub - 1]; 901 902 if (op == SNMP_OP_SET) 903 return (SNMP_ERR_NOT_WRITEABLE); 904 905 if (op == SNMP_OP_GET) { 906 if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE) 907 if (pfl_refresh() == -1) 908 return (SNMP_ERR_GENERR); 909 910 switch (which) { 911 case LEAF_pfLabelsLblNumber: 912 val->v.uint32 = pfl_table_count; 913 break; 914 915 default: 916 return (SNMP_ERR_NOSUCHNAME); 917 } 918 919 return (SNMP_ERR_NOERROR); 920 } 921 922 abort(); 923 return (SNMP_ERR_GENERR); 924} 925 926int 927pf_lbltable(struct snmp_context __unused *ctx, struct snmp_value *val, 928 u_int sub, u_int __unused vindex, enum snmp_op op) 929{ 930 asn_subid_t which = val->var.subs[sub - 1]; 931 struct pfl_entry *e = NULL; 932 933 switch (op) { 934 case SNMP_OP_SET: 935 return (SNMP_ERR_NOT_WRITEABLE); 936 case SNMP_OP_GETNEXT: 937 if ((e = NEXT_OBJECT_INT(&pfl_table, 938 &val->var, sub)) == NULL) 939 return (SNMP_ERR_NOSUCHNAME); 940 val->var.len = sub + 1; 941 val->var.subs[sub] = e->index; 942 break; 943 case SNMP_OP_GET: 944 if (val->var.len - sub != 1) 945 return (SNMP_ERR_NOSUCHNAME); 946 if ((e = pfl_table_find(val->var.subs[sub])) == NULL) 947 return (SNMP_ERR_NOSUCHNAME); 948 break; 949 950 case SNMP_OP_COMMIT: 951 case SNMP_OP_ROLLBACK: 952 default: 953 abort(); 954 } 955 956 if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE) 957 pfl_refresh(); 958 959 switch (which) { 960 case LEAF_pfLabelsLblName: 961 return (string_get(val, e->name, -1)); 962 case LEAF_pfLabelsLblEvals: 963 val->v.counter64 = e->evals; 964 break; 965 case LEAF_pfLabelsLblBytesIn: 966 val->v.counter64 = e->bytes[IN]; 967 break; 968 case LEAF_pfLabelsLblBytesOut: 969 val->v.counter64 = e->bytes[OUT]; 970 break; 971 case LEAF_pfLabelsLblPktsIn: 972 val->v.counter64 = e->pkts[IN]; 973 break; 974 case LEAF_pfLabelsLblPktsOut: 975 val->v.counter64 = e->pkts[OUT]; 976 break; 977 default: 978 return (SNMP_ERR_NOSUCHNAME); 979 } 980 981 return (SNMP_ERR_NOERROR); 982} 983 984static struct pfi_entry * 985pfi_table_find(u_int idx) 986{ 987 struct pfi_entry *e; 988 989 TAILQ_FOREACH(e, &pfi_table, link) 990 if (e->index == idx) 991 return (e); 992 return (NULL); 993} 994 995static struct pfq_entry * 996pfq_table_find(u_int idx) 997{ 998 struct pfq_entry *e; 999 1000 TAILQ_FOREACH(e, &pfq_table, link) 1001 if (e->index == idx) 1002 return (e); 1003 return (NULL); 1004} 1005 1006static struct pft_entry * 1007pft_table_find(u_int idx) 1008{ 1009 struct pft_entry *e; 1010 1011 TAILQ_FOREACH(e, &pft_table, link) 1012 if (e->index == idx) 1013 return (e); 1014 return (NULL); 1015} 1016 1017static struct pfl_entry * 1018pfl_table_find(u_int idx) 1019{ 1020 struct pfl_entry *e; 1021 1022 TAILQ_FOREACH(e, &pfl_table, link) 1023 if (e->index == idx) 1024 return (e); 1025 1026 return (NULL); 1027} 1028 1029static int 1030pfi_refresh(void) 1031{ 1032 struct pfioc_iface io; 1033 struct pfi_kif *p = NULL; 1034 struct pfi_entry *e; 1035 int i, numifs = 1; 1036 1037 if (started && this_tick <= pf_tick) 1038 return (0); 1039 1040 while (!TAILQ_EMPTY(&pfi_table)) { 1041 e = TAILQ_FIRST(&pfi_table); 1042 TAILQ_REMOVE(&pfi_table, e, link); 1043 free(e); 1044 } 1045 1046 bzero(&io, sizeof(io)); 1047 io.pfiio_esize = sizeof(struct pfi_kif); 1048 1049 for (;;) { 1050 p = reallocf(p, numifs * sizeof(struct pfi_kif)); 1051 if (p == NULL) { 1052 syslog(LOG_ERR, "pfi_refresh(): reallocf() numifs=%d: %s", 1053 numifs, strerror(errno)); 1054 goto err2; 1055 } 1056 io.pfiio_size = numifs; 1057 io.pfiio_buffer = p; 1058 1059 if (ioctl(dev, DIOCIGETIFACES, &io)) { 1060 syslog(LOG_ERR, "pfi_refresh(): ioctl(): %s", 1061 strerror(errno)); 1062 goto err2; 1063 } 1064 1065 if (numifs >= io.pfiio_size) 1066 break; 1067 1068 numifs = io.pfiio_size; 1069 } 1070 1071 for (i = 0; i < numifs; i++) { 1072 e = malloc(sizeof(struct pfi_entry)); 1073 if (e == NULL) 1074 goto err1; 1075 e->index = i + 1; 1076 memcpy(&e->pfi, p+i, sizeof(struct pfi_kif)); 1077 TAILQ_INSERT_TAIL(&pfi_table, e, link); 1078 } 1079 1080 pfi_table_age = time(NULL); 1081 pfi_table_count = numifs; 1082 pf_tick = this_tick; 1083 1084 free(p); 1085 return (0); 1086 1087err1: 1088 while (!TAILQ_EMPTY(&pfi_table)) { 1089 e = TAILQ_FIRST(&pfi_table); 1090 TAILQ_REMOVE(&pfi_table, e, link); 1091 free(e); 1092 } 1093err2: 1094 free(p); 1095 return(-1); 1096} 1097 1098static int 1099pfq_refresh(void) 1100{ 1101 struct pfioc_altq pa; 1102 struct pfq_entry *e; 1103 int i, numqs, ticket; 1104 1105 if (started && this_tick <= pf_tick) 1106 return (0); 1107 1108 while (!TAILQ_EMPTY(&pfq_table)) { 1109 e = TAILQ_FIRST(&pfq_table); 1110 TAILQ_REMOVE(&pfq_table, e, link); 1111 free(e); 1112 } 1113 1114 bzero(&pa, sizeof(pa)); 1115 1116 if (ioctl(dev, DIOCGETALTQS, &pa)) { 1117 syslog(LOG_ERR, "pfq_refresh: ioctl(DIOCGETALTQS): %s", 1118 strerror(errno)); 1119 return (-1); 1120 } 1121 1122 numqs = pa.nr; 1123 ticket = pa.ticket; 1124 1125 for (i = 0; i < numqs; i++) { 1126 e = malloc(sizeof(struct pfq_entry)); 1127 if (e == NULL) { 1128 syslog(LOG_ERR, "pfq_refresh(): " 1129 "malloc(): %s", 1130 strerror(errno)); 1131 goto err; 1132 } 1133 pa.ticket = ticket; 1134 pa.nr = i; 1135 1136 if (ioctl(dev, DIOCGETALTQ, &pa)) { 1137 syslog(LOG_ERR, "pfq_refresh(): " 1138 "ioctl(DIOCGETALTQ): %s", 1139 strerror(errno)); 1140 goto err; 1141 } 1142 1143 if (pa.altq.qid > 0) { 1144 memcpy(&e->altq, &pa.altq, sizeof(struct pf_altq)); 1145 e->index = pa.altq.qid; 1146 pfq_table_count = i; 1147 INSERT_OBJECT_INT_LINK_INDEX(e, &pfq_table, link, index); 1148 } 1149 } 1150 1151 pfq_table_age = time(NULL); 1152 pf_tick = this_tick; 1153 1154 return (0); 1155err: 1156 free(e); 1157 while (!TAILQ_EMPTY(&pfq_table)) { 1158 e = TAILQ_FIRST(&pfq_table); 1159 TAILQ_REMOVE(&pfq_table, e, link); 1160 free(e); 1161 } 1162 return(-1); 1163} 1164 1165static int 1166pfs_refresh(void) 1167{ 1168 if (started && this_tick <= pf_tick) 1169 return (0); 1170 1171 bzero(&pfs, sizeof(struct pf_status)); 1172 1173 if (ioctl(dev, DIOCGETSTATUS, &pfs)) { 1174 syslog(LOG_ERR, "pfs_refresh(): ioctl(): %s", 1175 strerror(errno)); 1176 return (-1); 1177 } 1178 1179 pf_tick = this_tick; 1180 return (0); 1181} 1182 1183static int 1184pft_refresh(void) 1185{ 1186 struct pfioc_table io; 1187 struct pfr_tstats *t = NULL; 1188 struct pft_entry *e; 1189 int i, numtbls = 1; 1190 1191 if (started && this_tick <= pf_tick) 1192 return (0); 1193 1194 while (!TAILQ_EMPTY(&pft_table)) { 1195 e = TAILQ_FIRST(&pft_table); 1196 TAILQ_REMOVE(&pft_table, e, link); 1197 free(e); 1198 } 1199 1200 bzero(&io, sizeof(io)); 1201 io.pfrio_esize = sizeof(struct pfr_tstats); 1202 1203 for (;;) { 1204 t = reallocf(t, numtbls * sizeof(struct pfr_tstats)); 1205 if (t == NULL) { 1206 syslog(LOG_ERR, "pft_refresh(): reallocf() numtbls=%d: %s", 1207 numtbls, strerror(errno)); 1208 goto err2; 1209 } 1210 io.pfrio_size = numtbls; 1211 io.pfrio_buffer = t; 1212 1213 if (ioctl(dev, DIOCRGETTSTATS, &io)) { 1214 syslog(LOG_ERR, "pft_refresh(): ioctl(): %s", 1215 strerror(errno)); 1216 goto err2; 1217 } 1218 1219 if (numtbls >= io.pfrio_size) 1220 break; 1221 1222 numtbls = io.pfrio_size; 1223 } 1224 1225 for (i = 0; i < numtbls; i++) { 1226 e = malloc(sizeof(struct pft_entry)); 1227 if (e == NULL) 1228 goto err1; 1229 e->index = i + 1; 1230 memcpy(&e->pft, t+i, sizeof(struct pfr_tstats)); 1231 TAILQ_INSERT_TAIL(&pft_table, e, link); 1232 } 1233 1234 pft_table_age = time(NULL); 1235 pft_table_count = numtbls; 1236 pf_tick = this_tick; 1237 1238 free(t); 1239 return (0); 1240err1: 1241 while (!TAILQ_EMPTY(&pft_table)) { 1242 e = TAILQ_FIRST(&pft_table); 1243 TAILQ_REMOVE(&pft_table, e, link); 1244 free(e); 1245 } 1246err2: 1247 free(t); 1248 return(-1); 1249} 1250 1251static int 1252pfl_scan_ruleset(const char *path) 1253{ 1254 struct pfioc_rule pr; 1255 struct pfl_entry *e; 1256 u_int32_t nr, i; 1257 1258 bzero(&pr, sizeof(pr)); 1259 strlcpy(pr.anchor, path, sizeof(pr.anchor)); 1260 pr.rule.action = PF_PASS; 1261 if (ioctl(dev, DIOCGETRULES, &pr)) { 1262 syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULES): %s", 1263 strerror(errno)); 1264 goto err; 1265 } 1266 1267 for (nr = pr.nr, i = 0; i < nr; i++) { 1268 pr.nr = i; 1269 if (ioctl(dev, DIOCGETRULE, &pr)) { 1270 syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULE):" 1271 " %s", strerror(errno)); 1272 goto err; 1273 } 1274 1275 if (pr.rule.label[0]) { 1276 e = (struct pfl_entry *)malloc(sizeof(*e)); 1277 if (e == NULL) 1278 goto err; 1279 1280 strlcpy(e->name, path, sizeof(e->name)); 1281 if (path[0]) 1282 strlcat(e->name, "/", sizeof(e->name)); 1283 strlcat(e->name, pr.rule.label, sizeof(e->name)); 1284 1285 e->evals = pr.rule.evaluations; 1286 e->bytes[IN] = pr.rule.bytes[IN]; 1287 e->bytes[OUT] = pr.rule.bytes[OUT]; 1288 e->pkts[IN] = pr.rule.packets[IN]; 1289 e->pkts[OUT] = pr.rule.packets[OUT]; 1290 e->index = ++pfl_table_count; 1291 1292 TAILQ_INSERT_TAIL(&pfl_table, e, link); 1293 } 1294 } 1295 1296 return (0); 1297 1298err: 1299 return (-1); 1300} 1301 1302static int 1303pfl_walk_rulesets(const char *path) 1304{ 1305 struct pfioc_ruleset prs; 1306 char newpath[MAXPATHLEN]; 1307 u_int32_t nr, i; 1308 1309 if (pfl_scan_ruleset(path)) 1310 goto err; 1311 1312 bzero(&prs, sizeof(prs)); 1313 strlcpy(prs.path, path, sizeof(prs.path)); 1314 if (ioctl(dev, DIOCGETRULESETS, &prs)) { 1315 syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESETS): %s", 1316 strerror(errno)); 1317 goto err; 1318 } 1319 1320 for (nr = prs.nr, i = 0; i < nr; i++) { 1321 prs.nr = i; 1322 if (ioctl(dev, DIOCGETRULESET, &prs)) { 1323 syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESET):" 1324 " %s", strerror(errno)); 1325 goto err; 1326 } 1327 1328 if (strcmp(prs.name, PF_RESERVED_ANCHOR) == 0) 1329 continue; 1330 1331 strlcpy(newpath, path, sizeof(newpath)); 1332 if (path[0]) 1333 strlcat(newpath, "/", sizeof(newpath)); 1334 1335 strlcat(newpath, prs.name, sizeof(newpath)); 1336 if (pfl_walk_rulesets(newpath)) 1337 goto err; 1338 } 1339 1340 return (0); 1341 1342err: 1343 return (-1); 1344} 1345 1346static int 1347pfl_refresh(void) 1348{ 1349 struct pfl_entry *e; 1350 1351 if (started && this_tick <= pf_tick) 1352 return (0); 1353 1354 while (!TAILQ_EMPTY(&pfl_table)) { 1355 e = TAILQ_FIRST(&pfl_table); 1356 TAILQ_REMOVE(&pfl_table, e, link); 1357 free(e); 1358 } 1359 pfl_table_count = 0; 1360 1361 if (pfl_walk_rulesets("")) 1362 goto err; 1363 1364 pfl_table_age = time(NULL); 1365 pf_tick = this_tick; 1366 1367 return (0); 1368 1369err: 1370 while (!TAILQ_EMPTY(&pfl_table)) { 1371 e = TAILQ_FIRST(&pfl_table); 1372 TAILQ_REMOVE(&pfl_table, e, link); 1373 free(e); 1374 } 1375 pfl_table_count = 0; 1376 1377 return (-1); 1378} 1379 1380/* 1381 * check whether altq support is enabled in kernel 1382 */ 1383 1384static int 1385altq_is_enabled(int pfdev) 1386{ 1387 struct pfioc_altq pa; 1388 1389 errno = 0; 1390 if (ioctl(pfdev, DIOCGETALTQS, &pa)) { 1391 if (errno == ENODEV) { 1392 syslog(LOG_INFO, "No ALTQ support in kernel\n" 1393 "ALTQ related functions disabled\n"); 1394 return (0); 1395 } else 1396 syslog(LOG_ERR, "DIOCGETALTQS returned an error: %s", 1397 strerror(errno)); 1398 return (-1); 1399 } 1400 return (1); 1401} 1402 1403/* 1404 * Implement the bsnmpd module interface 1405 */ 1406static int 1407pf_init(struct lmodule *mod, int __unused argc, char __unused *argv[]) 1408{ 1409 module = mod; 1410 1411 if ((dev = open("/dev/pf", O_RDONLY)) == -1) { 1412 syslog(LOG_ERR, "pf_init(): open(): %s\n", 1413 strerror(errno)); 1414 return (-1); 1415 } 1416 1417 if ((altq_enabled = altq_is_enabled(dev)) == -1) { 1418 syslog(LOG_ERR, "pf_init(): altq test failed"); 1419 return (-1); 1420 } 1421 1422 /* Prepare internal state */ 1423 TAILQ_INIT(&pfi_table); 1424 TAILQ_INIT(&pfq_table); 1425 TAILQ_INIT(&pft_table); 1426 TAILQ_INIT(&pfl_table); 1427 1428 pfi_refresh(); 1429 if (altq_enabled) { 1430 pfq_refresh(); 1431 } 1432 1433 pfs_refresh(); 1434 pft_refresh(); 1435 pfl_refresh(); 1436 1437 started = 1; 1438 1439 return (0); 1440} 1441 1442static int 1443pf_fini(void) 1444{ 1445 struct pfi_entry *i1, *i2; 1446 struct pfq_entry *q1, *q2; 1447 struct pft_entry *t1, *t2; 1448 struct pfl_entry *l1, *l2; 1449 1450 /* Empty the list of interfaces */ 1451 i1 = TAILQ_FIRST(&pfi_table); 1452 while (i1 != NULL) { 1453 i2 = TAILQ_NEXT(i1, link); 1454 free(i1); 1455 i1 = i2; 1456 } 1457 1458 /* List of queues */ 1459 q1 = TAILQ_FIRST(&pfq_table); 1460 while (q1 != NULL) { 1461 q2 = TAILQ_NEXT(q1, link); 1462 free(q1); 1463 q1 = q2; 1464 } 1465 1466 /* List of tables */ 1467 t1 = TAILQ_FIRST(&pft_table); 1468 while (t1 != NULL) { 1469 t2 = TAILQ_NEXT(t1, link); 1470 free(t1); 1471 t1 = t2; 1472 } 1473 1474 /* And the list of labeled filter rules */ 1475 l1 = TAILQ_FIRST(&pfl_table); 1476 while (l1 != NULL) { 1477 l2 = TAILQ_NEXT(l1, link); 1478 free(l1); 1479 l1 = l2; 1480 } 1481 1482 close(dev); 1483 return (0); 1484} 1485 1486static void 1487pf_dump(void) 1488{ 1489 pfi_refresh(); 1490 if (altq_enabled) { 1491 pfq_refresh(); 1492 } 1493 pft_refresh(); 1494 pfl_refresh(); 1495 1496 syslog(LOG_ERR, "Dump: pfi_table_age = %jd", 1497 (intmax_t)pfi_table_age); 1498 syslog(LOG_ERR, "Dump: pfi_table_count = %d", 1499 pfi_table_count); 1500 1501 syslog(LOG_ERR, "Dump: pfq_table_age = %jd", 1502 (intmax_t)pfq_table_age); 1503 syslog(LOG_ERR, "Dump: pfq_table_count = %d", 1504 pfq_table_count); 1505 1506 syslog(LOG_ERR, "Dump: pft_table_age = %jd", 1507 (intmax_t)pft_table_age); 1508 syslog(LOG_ERR, "Dump: pft_table_count = %d", 1509 pft_table_count); 1510 1511 syslog(LOG_ERR, "Dump: pfl_table_age = %jd", 1512 (intmax_t)pfl_table_age); 1513 syslog(LOG_ERR, "Dump: pfl_table_count = %d", 1514 pfl_table_count); 1515} 1516 1517const struct snmp_module config = { 1518 .comment = "This module implements a MIB for the pf packet filter.", 1519 .init = pf_init, 1520 .fini = pf_fini, 1521 .tree = pf_ctree, 1522 .dump = pf_dump, 1523 .tree_size = pf_CTREE_SIZE, 1524}; 1525