pf_snmp.c revision 143611
1143611Sphilip/*- 2143611Sphilip * Copyright (c) 2005 Philip Paeps <philip@FreeBSD.org> 3143611Sphilip * All rights reserved. 4143611Sphilip * 5143611Sphilip * Redistribution and use in source and binary forms, with or without 6143611Sphilip * modification, are permitted provided that the following conditions 7143611Sphilip * are met: 8143611Sphilip * 1. Redistributions of source code must retain the above copyright 9143611Sphilip * notice, this list of conditions and the following disclaimer. 10143611Sphilip * 2. Redistributions in binary form must reproduce the above copyright 11143611Sphilip * notice, this list of conditions and the following disclaimer in the 12143611Sphilip * documentation and/or other materials provided with the distribution. 13143611Sphilip * 14143611Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15143611Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16143611Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17143611Sphilip * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18143611Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19143611Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20143611Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21143611Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22143611Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23143611Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24143611Sphilip * SUCH DAMAGE. 25143611Sphilip * 26143611Sphilip * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c 143611 2005-03-14 22:16:39Z philip $ 27143611Sphilip */ 28143611Sphilip 29143611Sphilip#include <bsnmp/snmpmod.h> 30143611Sphilip 31143611Sphilip#include <net/pfvar.h> 32143611Sphilip#include <sys/ioctl.h> 33143611Sphilip 34143611Sphilip#include <errno.h> 35143611Sphilip#include <fcntl.h> 36143611Sphilip#include <stdio.h> 37143611Sphilip#include <stdlib.h> 38143611Sphilip#include <string.h> 39143611Sphilip#include <syslog.h> 40143611Sphilip#include <unistd.h> 41143611Sphilip 42143611Sphilip#include "pf_oid.h" 43143611Sphilip#include "pf_tree.h" 44143611Sphilip 45143611Sphilipstruct lmodule *module; 46143611Sphilip 47143611Sphilipstatic int dev = -1; 48143611Sphilipstatic int started; 49143611Sphilipstatic uint32_t pf_tick; 50143611Sphilip 51143611Sphilipstatic struct pf_status pfs; 52143611Sphilip 53143611Sphilipenum { IN, OUT }; 54143611Sphilipenum { IPV4, IPV6 }; 55143611Sphilipenum { PASS, BLOCK }; 56143611Sphilip 57143611Sphilip#define PFI_IFTYPE_GROUP 0 58143611Sphilip#define PFI_IFTYPE_INSTANCE 1 59143611Sphilip#define PFI_IFTYPE_DETACHED 2 60143611Sphilip 61143611Sphilipstruct pfi_entry { 62143611Sphilip struct pfi_if pfi; 63143611Sphilip u_int index; 64143611Sphilip TAILQ_ENTRY(pfi_entry) link; 65143611Sphilip}; 66143611SphilipTAILQ_HEAD(pfi_table, pfi_entry); 67143611Sphilip 68143611Sphilipstatic struct pfi_table pfi_table; 69143611Sphilipstatic time_t pfi_table_age; 70143611Sphilipstatic int pfi_table_count; 71143611Sphilip 72143611Sphilip#define PFI_TABLE_MAXAGE 5 73143611Sphilip 74143611Sphilipstruct pft_entry { 75143611Sphilip struct pfr_tstats pft; 76143611Sphilip u_int index; 77143611Sphilip TAILQ_ENTRY(pft_entry) link; 78143611Sphilip}; 79143611SphilipTAILQ_HEAD(pft_table, pft_entry); 80143611Sphilip 81143611Sphilipstatic struct pft_table pft_table; 82143611Sphilipstatic time_t pft_table_age; 83143611Sphilipstatic int pft_table_count; 84143611Sphilip 85143611Sphilip#define PFT_TABLE_MAXAGE 5 86143611Sphilip 87143611Sphilipstruct pfq_entry { 88143611Sphilip struct pf_altq altq; 89143611Sphilip u_int index; 90143611Sphilip TAILQ_ENTRY(pfq_entry) link; 91143611Sphilip}; 92143611SphilipTAILQ_HEAD(pfq_table, pfq_entry); 93143611Sphilip 94143611Sphilipstatic struct pfq_table pfq_table; 95143611Sphilipstatic time_t pfq_table_age; 96143611Sphilipstatic int pfq_table_count; 97143611Sphilip 98143611Sphilip#define PFQ_TABLE_MAXAGE 5 99143611Sphilip 100143611Sphilip/* Forward declarations */ 101143611Sphilipstatic int pfi_refresh(void); 102143611Sphilipstatic int pfq_refresh(void); 103143611Sphilipstatic int pfs_refresh(void); 104143611Sphilipstatic int pft_refresh(void); 105143611Sphilipstatic struct pfi_entry * pfi_table_find(u_int idx); 106143611Sphilipstatic struct pfq_entry * pfq_table_find(u_int idx); 107143611Sphilipstatic struct pft_entry * pft_table_find(u_int idx); 108143611Sphilip 109143611Sphilipint 110143611Sphilippf_status(struct snmp_context __unused *ctx, struct snmp_value *val, 111143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 112143611Sphilip{ 113143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 114143611Sphilip time_t runtime; 115143611Sphilip unsigned char str[128]; 116143611Sphilip 117143611Sphilip if (op == SNMP_OP_SET) 118143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 119143611Sphilip 120143611Sphilip if (op == SNMP_OP_GET) { 121143611Sphilip if (pfs_refresh() == -1) 122143611Sphilip return (SNMP_ERR_GENERR); 123143611Sphilip 124143611Sphilip switch (which) { 125143611Sphilip case LEAF_pfStatusRunning: 126143611Sphilip val->v.uint32 = pfs.running; 127143611Sphilip break; 128143611Sphilip case LEAF_pfStatusRuntime: 129143611Sphilip runtime = (pfs.since > 0) ? 130143611Sphilip time(NULL) - pfs.since : 0; 131143611Sphilip val->v.uint32 = runtime * 100; 132143611Sphilip break; 133143611Sphilip case LEAF_pfStatusDebug: 134143611Sphilip val->v.uint32 = pfs.debug; 135143611Sphilip break; 136143611Sphilip case LEAF_pfStatusHostId: 137143611Sphilip sprintf(str, "0x%08x", ntohl(pfs.hostid)); 138143611Sphilip return (string_get(val, str, strlen(str))); 139143611Sphilip 140143611Sphilip default: 141143611Sphilip return (SNMP_ERR_NOSUCHNAME); 142143611Sphilip } 143143611Sphilip 144143611Sphilip return (SNMP_ERR_NOERROR); 145143611Sphilip } 146143611Sphilip 147143611Sphilip abort(); 148143611Sphilip} 149143611Sphilip 150143611Sphilipint 151143611Sphilippf_counter(struct snmp_context __unused *ctx, struct snmp_value *val, 152143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 153143611Sphilip{ 154143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 155143611Sphilip 156143611Sphilip if (op == SNMP_OP_SET) 157143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 158143611Sphilip 159143611Sphilip if (op == SNMP_OP_GET) { 160143611Sphilip if (pfs_refresh() == -1) 161143611Sphilip return (SNMP_ERR_GENERR); 162143611Sphilip 163143611Sphilip switch (which) { 164143611Sphilip case LEAF_pfCounterMatch: 165143611Sphilip val->v.counter64 = pfs.counters[PFRES_MATCH]; 166143611Sphilip break; 167143611Sphilip case LEAF_pfCounterBadOffset: 168143611Sphilip val->v.counter64 = pfs.counters[PFRES_BADOFF]; 169143611Sphilip break; 170143611Sphilip case LEAF_pfCounterFragment: 171143611Sphilip val->v.counter64 = pfs.counters[PFRES_FRAG]; 172143611Sphilip break; 173143611Sphilip case LEAF_pfCounterShort: 174143611Sphilip val->v.counter64 = pfs.counters[PFRES_SHORT]; 175143611Sphilip break; 176143611Sphilip case LEAF_pfCounterNormalize: 177143611Sphilip val->v.counter64 = pfs.counters[PFRES_NORM]; 178143611Sphilip break; 179143611Sphilip case LEAF_pfCounterMemDrop: 180143611Sphilip val->v.counter64 = pfs.counters[PFRES_MEMORY]; 181143611Sphilip break; 182143611Sphilip 183143611Sphilip default: 184143611Sphilip return (SNMP_ERR_NOSUCHNAME); 185143611Sphilip } 186143611Sphilip 187143611Sphilip return (SNMP_ERR_NOERROR); 188143611Sphilip } 189143611Sphilip 190143611Sphilip abort(); 191143611Sphilip} 192143611Sphilip 193143611Sphilipint 194143611Sphilippf_statetable(struct snmp_context __unused *ctx, struct snmp_value *val, 195143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 196143611Sphilip{ 197143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 198143611Sphilip 199143611Sphilip if (op == SNMP_OP_SET) 200143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 201143611Sphilip 202143611Sphilip if (op == SNMP_OP_GET) { 203143611Sphilip if (pfs_refresh() == -1) 204143611Sphilip return (SNMP_ERR_GENERR); 205143611Sphilip 206143611Sphilip switch (which) { 207143611Sphilip case LEAF_pfStateTableCount: 208143611Sphilip val->v.uint32 = pfs.states; 209143611Sphilip break; 210143611Sphilip case LEAF_pfStateTableSearches: 211143611Sphilip val->v.counter64 = 212143611Sphilip pfs.fcounters[FCNT_STATE_SEARCH]; 213143611Sphilip break; 214143611Sphilip case LEAF_pfStateTableInserts: 215143611Sphilip val->v.counter64 = 216143611Sphilip pfs.fcounters[FCNT_STATE_INSERT]; 217143611Sphilip break; 218143611Sphilip case LEAF_pfStateTableRemovals: 219143611Sphilip val->v.counter64 = 220143611Sphilip pfs.fcounters[FCNT_STATE_REMOVALS]; 221143611Sphilip break; 222143611Sphilip 223143611Sphilip default: 224143611Sphilip return (SNMP_ERR_NOSUCHNAME); 225143611Sphilip } 226143611Sphilip 227143611Sphilip return (SNMP_ERR_NOERROR); 228143611Sphilip } 229143611Sphilip 230143611Sphilip abort(); 231143611Sphilip} 232143611Sphilip 233143611Sphilipint 234143611Sphilippf_srcnodes(struct snmp_context __unused *ctx, struct snmp_value *val, 235143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 236143611Sphilip{ 237143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 238143611Sphilip 239143611Sphilip if (op == SNMP_OP_SET) 240143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 241143611Sphilip 242143611Sphilip if (op == SNMP_OP_GET) { 243143611Sphilip if (pfs_refresh() == -1) 244143611Sphilip return (SNMP_ERR_GENERR); 245143611Sphilip 246143611Sphilip switch (which) { 247143611Sphilip case LEAF_pfSrcNodesCount: 248143611Sphilip val->v.uint32 = pfs.src_nodes; 249143611Sphilip break; 250143611Sphilip case LEAF_pfSrcNodesSearches: 251143611Sphilip val->v.counter64 = 252143611Sphilip pfs.scounters[SCNT_SRC_NODE_SEARCH]; 253143611Sphilip break; 254143611Sphilip case LEAF_pfSrcNodesInserts: 255143611Sphilip val->v.counter64 = 256143611Sphilip pfs.scounters[SCNT_SRC_NODE_INSERT]; 257143611Sphilip break; 258143611Sphilip case LEAF_pfSrcNodesRemovals: 259143611Sphilip val->v.counter64 = 260143611Sphilip pfs.scounters[SCNT_SRC_NODE_REMOVALS]; 261143611Sphilip break; 262143611Sphilip 263143611Sphilip default: 264143611Sphilip return (SNMP_ERR_NOSUCHNAME); 265143611Sphilip } 266143611Sphilip 267143611Sphilip return (SNMP_ERR_NOERROR); 268143611Sphilip } 269143611Sphilip 270143611Sphilip abort(); 271143611Sphilip} 272143611Sphilip 273143611Sphilipint 274143611Sphilippf_limits(struct snmp_context __unused *ctx, struct snmp_value *val, 275143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 276143611Sphilip{ 277143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 278143611Sphilip struct pfioc_limit pl; 279143611Sphilip 280143611Sphilip if (op == SNMP_OP_SET) 281143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 282143611Sphilip 283143611Sphilip if (op == SNMP_OP_GET) { 284143611Sphilip bzero(&pl, sizeof(struct pfioc_limit)); 285143611Sphilip 286143611Sphilip switch (which) { 287143611Sphilip case LEAF_pfLimitsStates: 288143611Sphilip pl.index = PF_LIMIT_STATES; 289143611Sphilip break; 290143611Sphilip case LEAF_pfLimitsSrcNodes: 291143611Sphilip pl.index = PF_LIMIT_SRC_NODES; 292143611Sphilip break; 293143611Sphilip case LEAF_pfLimitsFrags: 294143611Sphilip pl.index = PF_LIMIT_FRAGS; 295143611Sphilip break; 296143611Sphilip 297143611Sphilip default: 298143611Sphilip return (SNMP_ERR_NOSUCHNAME); 299143611Sphilip } 300143611Sphilip 301143611Sphilip if (ioctl(dev, DIOCGETLIMIT, &pl)) { 302143611Sphilip syslog(LOG_ERR, "pf_limits(): ioctl(): %s", 303143611Sphilip strerror(errno)); 304143611Sphilip return (SNMP_ERR_GENERR); 305143611Sphilip } 306143611Sphilip 307143611Sphilip val->v.uint32 = pl.limit; 308143611Sphilip 309143611Sphilip return (SNMP_ERR_NOERROR); 310143611Sphilip } 311143611Sphilip 312143611Sphilip abort(); 313143611Sphilip} 314143611Sphilip 315143611Sphilipint 316143611Sphilippf_timeouts(struct snmp_context __unused *ctx, struct snmp_value *val, 317143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 318143611Sphilip{ 319143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 320143611Sphilip struct pfioc_tm pt; 321143611Sphilip 322143611Sphilip if (op == SNMP_OP_SET) 323143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 324143611Sphilip 325143611Sphilip if (op == SNMP_OP_GET) { 326143611Sphilip bzero(&pt, sizeof(struct pfioc_tm)); 327143611Sphilip 328143611Sphilip switch (which) { 329143611Sphilip case LEAF_pfTimeoutsTcpFirst: 330143611Sphilip pt.timeout = PFTM_TCP_FIRST_PACKET; 331143611Sphilip break; 332143611Sphilip case LEAF_pfTimeoutsTcpOpening: 333143611Sphilip pt.timeout = PFTM_TCP_OPENING; 334143611Sphilip break; 335143611Sphilip case LEAF_pfTimeoutsTcpEstablished: 336143611Sphilip pt.timeout = PFTM_TCP_ESTABLISHED; 337143611Sphilip break; 338143611Sphilip case LEAF_pfTimeoutsTcpClosing: 339143611Sphilip pt.timeout = PFTM_TCP_CLOSING; 340143611Sphilip break; 341143611Sphilip case LEAF_pfTimeoutsTcpFinWait: 342143611Sphilip pt.timeout = PFTM_TCP_FIN_WAIT; 343143611Sphilip break; 344143611Sphilip case LEAF_pfTimeoutsTcpClosed: 345143611Sphilip pt.timeout = PFTM_TCP_CLOSED; 346143611Sphilip break; 347143611Sphilip case LEAF_pfTimeoutsUdpFirst: 348143611Sphilip pt.timeout = PFTM_UDP_FIRST_PACKET; 349143611Sphilip break; 350143611Sphilip case LEAF_pfTimeoutsUdpSingle: 351143611Sphilip pt.timeout = PFTM_UDP_SINGLE; 352143611Sphilip break; 353143611Sphilip case LEAF_pfTimeoutsUdpMultiple: 354143611Sphilip pt.timeout = PFTM_UDP_MULTIPLE; 355143611Sphilip break; 356143611Sphilip case LEAF_pfTimeoutsIcmpFirst: 357143611Sphilip pt.timeout = PFTM_ICMP_FIRST_PACKET; 358143611Sphilip break; 359143611Sphilip case LEAF_pfTimeoutsIcmpError: 360143611Sphilip pt.timeout = PFTM_ICMP_ERROR_REPLY; 361143611Sphilip break; 362143611Sphilip case LEAF_pfTimeoutsOtherFirst: 363143611Sphilip pt.timeout = PFTM_OTHER_FIRST_PACKET; 364143611Sphilip break; 365143611Sphilip case LEAF_pfTimeoutsOtherSingle: 366143611Sphilip pt.timeout = PFTM_OTHER_SINGLE; 367143611Sphilip break; 368143611Sphilip case LEAF_pfTimeoutsOtherMultiple: 369143611Sphilip pt.timeout = PFTM_OTHER_MULTIPLE; 370143611Sphilip break; 371143611Sphilip case LEAF_pfTimeoutsFragment: 372143611Sphilip pt.timeout = PFTM_FRAG; 373143611Sphilip break; 374143611Sphilip case LEAF_pfTimeoutsInterval: 375143611Sphilip pt.timeout = PFTM_INTERVAL; 376143611Sphilip break; 377143611Sphilip case LEAF_pfTimeoutsAdaptiveStart: 378143611Sphilip pt.timeout = PFTM_ADAPTIVE_START; 379143611Sphilip break; 380143611Sphilip case LEAF_pfTimeoutsAdaptiveEnd: 381143611Sphilip pt.timeout = PFTM_ADAPTIVE_END; 382143611Sphilip break; 383143611Sphilip case LEAF_pfTimeoutsSrcNode: 384143611Sphilip pt.timeout = PFTM_SRC_NODE; 385143611Sphilip break; 386143611Sphilip 387143611Sphilip default: 388143611Sphilip return (SNMP_ERR_NOSUCHNAME); 389143611Sphilip } 390143611Sphilip 391143611Sphilip if (ioctl(dev, DIOCGETTIMEOUT, &pt)) { 392143611Sphilip syslog(LOG_ERR, "pf_timeouts(): ioctl(): %s", 393143611Sphilip strerror(errno)); 394143611Sphilip return (SNMP_ERR_GENERR); 395143611Sphilip } 396143611Sphilip 397143611Sphilip val->v.integer = pt.seconds; 398143611Sphilip 399143611Sphilip return (SNMP_ERR_NOERROR); 400143611Sphilip } 401143611Sphilip 402143611Sphilip abort(); 403143611Sphilip} 404143611Sphilip 405143611Sphilipint 406143611Sphilippf_logif(struct snmp_context __unused *ctx, struct snmp_value *val, 407143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 408143611Sphilip{ 409143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 410143611Sphilip unsigned char str[IFNAMSIZ]; 411143611Sphilip 412143611Sphilip if (op == SNMP_OP_SET) 413143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 414143611Sphilip 415143611Sphilip if (op == SNMP_OP_GET) { 416143611Sphilip if (pfs_refresh() == -1) 417143611Sphilip return (SNMP_ERR_GENERR); 418143611Sphilip 419143611Sphilip switch (which) { 420143611Sphilip case LEAF_pfLogInterfaceName: 421143611Sphilip strlcpy(str, pfs.ifname, sizeof str); 422143611Sphilip return (string_get(val, str, strlen(str))); 423143611Sphilip case LEAF_pfLogInterfaceIp4BytesIn: 424143611Sphilip val->v.counter64 = pfs.bcounters[IPV4][IN]; 425143611Sphilip break; 426143611Sphilip case LEAF_pfLogInterfaceIp4BytesOut: 427143611Sphilip val->v.counter64 = pfs.bcounters[IPV4][OUT]; 428143611Sphilip break; 429143611Sphilip case LEAF_pfLogInterfaceIp4PktsInPass: 430143611Sphilip val->v.counter64 = 431143611Sphilip pfs.pcounters[IPV4][IN][PF_PASS]; 432143611Sphilip break; 433143611Sphilip case LEAF_pfLogInterfaceIp4PktsInDrop: 434143611Sphilip val->v.counter64 = 435143611Sphilip pfs.pcounters[IPV4][IN][PF_DROP]; 436143611Sphilip break; 437143611Sphilip case LEAF_pfLogInterfaceIp4PktsOutPass: 438143611Sphilip val->v.counter64 = 439143611Sphilip pfs.pcounters[IPV4][OUT][PF_PASS]; 440143611Sphilip break; 441143611Sphilip case LEAF_pfLogInterfaceIp4PktsOutDrop: 442143611Sphilip val->v.counter64 = 443143611Sphilip pfs.pcounters[IPV4][OUT][PF_DROP]; 444143611Sphilip break; 445143611Sphilip case LEAF_pfLogInterfaceIp6BytesIn: 446143611Sphilip val->v.counter64 = pfs.bcounters[IPV6][IN]; 447143611Sphilip break; 448143611Sphilip case LEAF_pfLogInterfaceIp6BytesOut: 449143611Sphilip val->v.counter64 = pfs.bcounters[IPV6][OUT]; 450143611Sphilip break; 451143611Sphilip case LEAF_pfLogInterfaceIp6PktsInPass: 452143611Sphilip val->v.counter64 = 453143611Sphilip pfs.pcounters[IPV6][IN][PF_PASS]; 454143611Sphilip break; 455143611Sphilip case LEAF_pfLogInterfaceIp6PktsInDrop: 456143611Sphilip val->v.counter64 = 457143611Sphilip pfs.pcounters[IPV6][IN][PF_DROP]; 458143611Sphilip break; 459143611Sphilip case LEAF_pfLogInterfaceIp6PktsOutPass: 460143611Sphilip val->v.counter64 = 461143611Sphilip pfs.pcounters[IPV6][OUT][PF_PASS]; 462143611Sphilip break; 463143611Sphilip case LEAF_pfLogInterfaceIp6PktsOutDrop: 464143611Sphilip val->v.counter64 = 465143611Sphilip pfs.pcounters[IPV6][OUT][PF_DROP]; 466143611Sphilip break; 467143611Sphilip 468143611Sphilip default: 469143611Sphilip return (SNMP_ERR_NOSUCHNAME); 470143611Sphilip } 471143611Sphilip 472143611Sphilip return (SNMP_ERR_NOERROR); 473143611Sphilip } 474143611Sphilip 475143611Sphilip abort(); 476143611Sphilip} 477143611Sphilip 478143611Sphilipint 479143611Sphilippf_interfaces(struct snmp_context __unused *ctx, struct snmp_value *val, 480143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 481143611Sphilip{ 482143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 483143611Sphilip 484143611Sphilip if (op == SNMP_OP_SET) 485143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 486143611Sphilip 487143611Sphilip if (op == SNMP_OP_GET) { 488143611Sphilip if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE) 489143611Sphilip if (pfi_refresh() == -1) 490143611Sphilip return (SNMP_ERR_GENERR); 491143611Sphilip 492143611Sphilip switch (which) { 493143611Sphilip case LEAF_pfInterfacesIfNumber: 494143611Sphilip val->v.uint32 = pfi_table_count; 495143611Sphilip break; 496143611Sphilip 497143611Sphilip default: 498143611Sphilip return (SNMP_ERR_NOSUCHNAME); 499143611Sphilip } 500143611Sphilip 501143611Sphilip return (SNMP_ERR_NOERROR); 502143611Sphilip } 503143611Sphilip 504143611Sphilip abort(); 505143611Sphilip} 506143611Sphilip 507143611Sphilipint 508143611Sphilippf_iftable(struct snmp_context __unused *ctx, struct snmp_value *val, 509143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 510143611Sphilip{ 511143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 512143611Sphilip struct pfi_entry *e = NULL; 513143611Sphilip 514143611Sphilip switch (op) { 515143611Sphilip case SNMP_OP_SET: 516143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 517143611Sphilip case SNMP_OP_GETNEXT: 518143611Sphilip if ((e = NEXT_OBJECT_INT(&pfi_table, 519143611Sphilip &val->var, sub)) == NULL) 520143611Sphilip return (SNMP_ERR_NOSUCHNAME); 521143611Sphilip val->var.len = sub + 1; 522143611Sphilip val->var.subs[sub] = e->index; 523143611Sphilip break; 524143611Sphilip case SNMP_OP_GET: 525143611Sphilip if (val->var.len - sub != 1) 526143611Sphilip return (SNMP_ERR_NOSUCHNAME); 527143611Sphilip if ((e = pfi_table_find(val->var.subs[sub])) == NULL) 528143611Sphilip return (SNMP_ERR_NOSUCHNAME); 529143611Sphilip break; 530143611Sphilip 531143611Sphilip case SNMP_OP_COMMIT: 532143611Sphilip case SNMP_OP_ROLLBACK: 533143611Sphilip default: 534143611Sphilip abort(); 535143611Sphilip } 536143611Sphilip 537143611Sphilip if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE) 538143611Sphilip pfi_refresh(); 539143611Sphilip 540143611Sphilip switch (which) { 541143611Sphilip case LEAF_pfInterfacesIfDescr: 542143611Sphilip return (string_get(val, e->pfi.pfif_name, -1)); 543143611Sphilip case LEAF_pfInterfacesIfType: 544143611Sphilip val->v.integer = PFI_IFTYPE_INSTANCE; 545143611Sphilip break; 546143611Sphilip case LEAF_pfInterfacesIfTZero: 547143611Sphilip val->v.uint32 = 548143611Sphilip (time(NULL) - e->pfi.pfif_tzero) * 100; 549143611Sphilip break; 550143611Sphilip case LEAF_pfInterfacesIfRefsState: 551143611Sphilip val->v.uint32 = e->pfi.pfif_states; 552143611Sphilip break; 553143611Sphilip case LEAF_pfInterfacesIfRefsRule: 554143611Sphilip val->v.uint32 = e->pfi.pfif_rules; 555143611Sphilip break; 556143611Sphilip case LEAF_pfInterfacesIf4BytesInPass: 557143611Sphilip val->v.counter64 = 558143611Sphilip e->pfi.pfif_bytes[IPV4][IN][PASS]; 559143611Sphilip break; 560143611Sphilip case LEAF_pfInterfacesIf4BytesInBlock: 561143611Sphilip val->v.counter64 = 562143611Sphilip e->pfi.pfif_bytes[IPV4][IN][BLOCK]; 563143611Sphilip break; 564143611Sphilip case LEAF_pfInterfacesIf4BytesOutPass: 565143611Sphilip val->v.counter64 = 566143611Sphilip e->pfi.pfif_bytes[IPV4][OUT][PASS]; 567143611Sphilip break; 568143611Sphilip case LEAF_pfInterfacesIf4BytesOutBlock: 569143611Sphilip val->v.counter64 = 570143611Sphilip e->pfi.pfif_bytes[IPV4][OUT][BLOCK]; 571143611Sphilip break; 572143611Sphilip case LEAF_pfInterfacesIf4PktsInPass: 573143611Sphilip val->v.counter64 = 574143611Sphilip e->pfi.pfif_packets[IPV4][IN][PASS]; 575143611Sphilip break; 576143611Sphilip case LEAF_pfInterfacesIf4PktsInBlock: 577143611Sphilip val->v.counter64 = 578143611Sphilip e->pfi.pfif_packets[IPV4][IN][BLOCK]; 579143611Sphilip break; 580143611Sphilip case LEAF_pfInterfacesIf4PktsOutPass: 581143611Sphilip val->v.counter64 = 582143611Sphilip e->pfi.pfif_packets[IPV4][OUT][PASS]; 583143611Sphilip break; 584143611Sphilip case LEAF_pfInterfacesIf4PktsOutBlock: 585143611Sphilip val->v.counter64 = 586143611Sphilip e->pfi.pfif_packets[IPV4][OUT][BLOCK]; 587143611Sphilip break; 588143611Sphilip case LEAF_pfInterfacesIf6BytesInPass: 589143611Sphilip val->v.counter64 = 590143611Sphilip e->pfi.pfif_bytes[IPV6][IN][PASS]; 591143611Sphilip break; 592143611Sphilip case LEAF_pfInterfacesIf6BytesInBlock: 593143611Sphilip val->v.counter64 = 594143611Sphilip e->pfi.pfif_bytes[IPV6][IN][BLOCK]; 595143611Sphilip break; 596143611Sphilip case LEAF_pfInterfacesIf6BytesOutPass: 597143611Sphilip val->v.counter64 = 598143611Sphilip e->pfi.pfif_bytes[IPV6][OUT][PASS]; 599143611Sphilip break; 600143611Sphilip case LEAF_pfInterfacesIf6BytesOutBlock: 601143611Sphilip val->v.counter64 = 602143611Sphilip e->pfi.pfif_bytes[IPV6][OUT][BLOCK]; 603143611Sphilip break; 604143611Sphilip case LEAF_pfInterfacesIf6PktsInPass: 605143611Sphilip val->v.counter64 = 606143611Sphilip e->pfi.pfif_packets[IPV6][IN][PASS]; 607143611Sphilip break; 608143611Sphilip case LEAF_pfInterfacesIf6PktsInBlock: 609143611Sphilip val->v.counter64 = 610143611Sphilip e->pfi.pfif_packets[IPV6][IN][BLOCK]; 611143611Sphilip break; 612143611Sphilip case LEAF_pfInterfacesIf6PktsOutPass: 613143611Sphilip val->v.counter64 = 614143611Sphilip e->pfi.pfif_packets[IPV6][OUT][PASS]; 615143611Sphilip break; 616143611Sphilip case LEAF_pfInterfacesIf6PktsOutBlock: 617143611Sphilip val->v.counter64 = 618143611Sphilip e->pfi.pfif_packets[IPV6][OUT][BLOCK]; 619143611Sphilip break; 620143611Sphilip 621143611Sphilip default: 622143611Sphilip return (SNMP_ERR_NOSUCHNAME); 623143611Sphilip } 624143611Sphilip 625143611Sphilip return (SNMP_ERR_NOERROR); 626143611Sphilip} 627143611Sphilip 628143611Sphilipint 629143611Sphilippf_tables(struct snmp_context __unused *ctx, struct snmp_value *val, 630143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 631143611Sphilip{ 632143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 633143611Sphilip 634143611Sphilip if (op == SNMP_OP_SET) 635143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 636143611Sphilip 637143611Sphilip if (op == SNMP_OP_GET) { 638143611Sphilip if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE) 639143611Sphilip if (pft_refresh() == -1) 640143611Sphilip return (SNMP_ERR_GENERR); 641143611Sphilip 642143611Sphilip switch (which) { 643143611Sphilip case LEAF_pfTablesTblNumber: 644143611Sphilip val->v.uint32 = pft_table_count; 645143611Sphilip break; 646143611Sphilip 647143611Sphilip default: 648143611Sphilip return (SNMP_ERR_NOSUCHNAME); 649143611Sphilip } 650143611Sphilip 651143611Sphilip return (SNMP_ERR_NOERROR); 652143611Sphilip } 653143611Sphilip 654143611Sphilip abort(); 655143611Sphilip} 656143611Sphilip 657143611Sphilipint 658143611Sphilippf_tbltable(struct snmp_context __unused *ctx, struct snmp_value *val, 659143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 660143611Sphilip{ 661143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 662143611Sphilip struct pft_entry *e = NULL; 663143611Sphilip 664143611Sphilip switch (op) { 665143611Sphilip case SNMP_OP_SET: 666143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 667143611Sphilip case SNMP_OP_GETNEXT: 668143611Sphilip if ((e = NEXT_OBJECT_INT(&pft_table, 669143611Sphilip &val->var, sub)) == NULL) 670143611Sphilip return (SNMP_ERR_NOSUCHNAME); 671143611Sphilip val->var.len = sub + 1; 672143611Sphilip val->var.subs[sub] = e->index; 673143611Sphilip break; 674143611Sphilip case SNMP_OP_GET: 675143611Sphilip if (val->var.len - sub != 1) 676143611Sphilip return (SNMP_ERR_NOSUCHNAME); 677143611Sphilip if ((e = pft_table_find(val->var.subs[sub])) == NULL) 678143611Sphilip return (SNMP_ERR_NOSUCHNAME); 679143611Sphilip break; 680143611Sphilip 681143611Sphilip case SNMP_OP_COMMIT: 682143611Sphilip case SNMP_OP_ROLLBACK: 683143611Sphilip default: 684143611Sphilip abort(); 685143611Sphilip } 686143611Sphilip 687143611Sphilip if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE) 688143611Sphilip pft_refresh(); 689143611Sphilip 690143611Sphilip switch (which) { 691143611Sphilip case LEAF_pfTablesTblDescr: 692143611Sphilip return (string_get(val, e->pft.pfrts_name, -1)); 693143611Sphilip case LEAF_pfTablesTblCount: 694143611Sphilip val->v.integer = e->pft.pfrts_cnt; 695143611Sphilip break; 696143611Sphilip case LEAF_pfTablesTblTZero: 697143611Sphilip val->v.uint32 = 698143611Sphilip (time(NULL) - e->pft.pfrts_tzero) * 100; 699143611Sphilip break; 700143611Sphilip case LEAF_pfTablesTblRefsAnchor: 701143611Sphilip val->v.integer = 702143611Sphilip e->pft.pfrts_refcnt[PFR_REFCNT_ANCHOR]; 703143611Sphilip break; 704143611Sphilip case LEAF_pfTablesTblRefsRule: 705143611Sphilip val->v.integer = 706143611Sphilip e->pft.pfrts_refcnt[PFR_REFCNT_RULE]; 707143611Sphilip break; 708143611Sphilip case LEAF_pfTablesTblEvalMatch: 709143611Sphilip val->v.counter64 = e->pft.pfrts_match; 710143611Sphilip break; 711143611Sphilip case LEAF_pfTablesTblEvalNoMatch: 712143611Sphilip val->v.counter64 = e->pft.pfrts_nomatch; 713143611Sphilip break; 714143611Sphilip case LEAF_pfTablesTblBytesInPass: 715143611Sphilip val->v.counter64 = 716143611Sphilip e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_PASS]; 717143611Sphilip break; 718143611Sphilip case LEAF_pfTablesTblBytesInBlock: 719143611Sphilip val->v.counter64 = 720143611Sphilip e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_BLOCK]; 721143611Sphilip break; 722143611Sphilip case LEAF_pfTablesTblBytesInXPass: 723143611Sphilip val->v.counter64 = 724143611Sphilip e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_XPASS]; 725143611Sphilip break; 726143611Sphilip case LEAF_pfTablesTblBytesOutPass: 727143611Sphilip val->v.counter64 = 728143611Sphilip e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_PASS]; 729143611Sphilip break; 730143611Sphilip case LEAF_pfTablesTblBytesOutBlock: 731143611Sphilip val->v.counter64 = 732143611Sphilip e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_BLOCK]; 733143611Sphilip break; 734143611Sphilip case LEAF_pfTablesTblBytesOutXPass: 735143611Sphilip val->v.counter64 = 736143611Sphilip e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_XPASS]; 737143611Sphilip break; 738143611Sphilip case LEAF_pfTablesTblPktsInPass: 739143611Sphilip val->v.counter64 = 740143611Sphilip e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_PASS]; 741143611Sphilip break; 742143611Sphilip case LEAF_pfTablesTblPktsInBlock: 743143611Sphilip val->v.counter64 = 744143611Sphilip e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_BLOCK]; 745143611Sphilip break; 746143611Sphilip case LEAF_pfTablesTblPktsInXPass: 747143611Sphilip val->v.counter64 = 748143611Sphilip e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_XPASS]; 749143611Sphilip break; 750143611Sphilip case LEAF_pfTablesTblPktsOutPass: 751143611Sphilip val->v.counter64 = 752143611Sphilip e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_PASS]; 753143611Sphilip break; 754143611Sphilip case LEAF_pfTablesTblPktsOutBlock: 755143611Sphilip val->v.counter64 = 756143611Sphilip e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_BLOCK]; 757143611Sphilip break; 758143611Sphilip case LEAF_pfTablesTblPktsOutXPass: 759143611Sphilip val->v.counter64 = 760143611Sphilip e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_XPASS]; 761143611Sphilip break; 762143611Sphilip 763143611Sphilip default: 764143611Sphilip return (SNMP_ERR_NOSUCHNAME); 765143611Sphilip } 766143611Sphilip 767143611Sphilip return (SNMP_ERR_NOERROR); 768143611Sphilip} 769143611Sphilip 770143611Sphilipint 771143611Sphilippf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val, 772143611Sphilip u_int __unused sub, u_int __unused vindex, enum snmp_op __unused op) 773143611Sphilip{ 774143611Sphilip return (SNMP_ERR_GENERR); 775143611Sphilip} 776143611Sphilip 777143611Sphilipint 778143611Sphilippf_altq(struct snmp_context __unused *ctx, struct snmp_value *val, 779143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 780143611Sphilip{ 781143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 782143611Sphilip 783143611Sphilip if (op == SNMP_OP_SET) 784143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 785143611Sphilip 786143611Sphilip if (op == SNMP_OP_GET) { 787143611Sphilip if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE) 788143611Sphilip if (pfq_refresh() == -1) 789143611Sphilip return (SNMP_ERR_GENERR); 790143611Sphilip 791143611Sphilip switch (which) { 792143611Sphilip case LEAF_pfAltqQueueNumber: 793143611Sphilip val->v.uint32 = pfq_table_count; 794143611Sphilip break; 795143611Sphilip 796143611Sphilip default: 797143611Sphilip return (SNMP_ERR_NOSUCHNAME); 798143611Sphilip } 799143611Sphilip 800143611Sphilip return (SNMP_ERR_NOERROR); 801143611Sphilip } 802143611Sphilip 803143611Sphilip abort(); 804143611Sphilip return (SNMP_ERR_GENERR); 805143611Sphilip} 806143611Sphilip 807143611Sphilipint 808143611Sphilippf_altqq(struct snmp_context __unused *ctx, struct snmp_value *val, 809143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 810143611Sphilip{ 811143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 812143611Sphilip struct pfq_entry *e = NULL; 813143611Sphilip 814143611Sphilip switch (op) { 815143611Sphilip case SNMP_OP_SET: 816143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 817143611Sphilip case SNMP_OP_GETNEXT: 818143611Sphilip if ((e = NEXT_OBJECT_INT(&pfq_table, 819143611Sphilip &val->var, sub)) == NULL) 820143611Sphilip return (SNMP_ERR_NOSUCHNAME); 821143611Sphilip val->var.len = sub + 1; 822143611Sphilip val->var.subs[sub] = e->index; 823143611Sphilip break; 824143611Sphilip case SNMP_OP_GET: 825143611Sphilip if (val->var.len - sub != 1) 826143611Sphilip return (SNMP_ERR_NOSUCHNAME); 827143611Sphilip if ((e = pfq_table_find(val->var.subs[sub])) == NULL) 828143611Sphilip return (SNMP_ERR_NOSUCHNAME); 829143611Sphilip break; 830143611Sphilip 831143611Sphilip case SNMP_OP_COMMIT: 832143611Sphilip case SNMP_OP_ROLLBACK: 833143611Sphilip default: 834143611Sphilip abort(); 835143611Sphilip } 836143611Sphilip 837143611Sphilip if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE) 838143611Sphilip pfq_refresh(); 839143611Sphilip 840143611Sphilip switch (which) { 841143611Sphilip case LEAF_pfAltqQueueDescr: 842143611Sphilip return (string_get(val, e->altq.qname, -1)); 843143611Sphilip case LEAF_pfAltqQueueParent: 844143611Sphilip return (string_get(val, e->altq.parent, -1)); 845143611Sphilip case LEAF_pfAltqQueueScheduler: 846143611Sphilip val->v.integer = e->altq.scheduler; 847143611Sphilip break; 848143611Sphilip case LEAF_pfAltqQueueBandwidth: 849143611Sphilip val->v.uint32 = e->altq.bandwidth; 850143611Sphilip break; 851143611Sphilip case LEAF_pfAltqQueuePriority: 852143611Sphilip val->v.integer = e->altq.priority; 853143611Sphilip break; 854143611Sphilip case LEAF_pfAltqQueueLimit: 855143611Sphilip val->v.integer = e->altq.qlimit; 856143611Sphilip break; 857143611Sphilip 858143611Sphilip default: 859143611Sphilip return (SNMP_ERR_NOSUCHNAME); 860143611Sphilip } 861143611Sphilip 862143611Sphilip return (SNMP_ERR_NOERROR); 863143611Sphilip} 864143611Sphilip 865143611Sphilipstatic struct pfi_entry * 866143611Sphilippfi_table_find(u_int idx) 867143611Sphilip{ 868143611Sphilip struct pfi_entry *e; 869143611Sphilip 870143611Sphilip TAILQ_FOREACH(e, &pfi_table, link) 871143611Sphilip if (e->index == idx) 872143611Sphilip return (e); 873143611Sphilip return (NULL); 874143611Sphilip} 875143611Sphilip 876143611Sphilipstatic struct pfq_entry * 877143611Sphilippfq_table_find(u_int idx) 878143611Sphilip{ 879143611Sphilip struct pfq_entry *e; 880143611Sphilip TAILQ_FOREACH(e, &pfq_table, link) 881143611Sphilip if (e->index == idx) 882143611Sphilip return (e); 883143611Sphilip return (NULL); 884143611Sphilip} 885143611Sphilip 886143611Sphilipstatic struct pft_entry * 887143611Sphilippft_table_find(u_int idx) 888143611Sphilip{ 889143611Sphilip struct pft_entry *e; 890143611Sphilip 891143611Sphilip TAILQ_FOREACH(e, &pft_table, link) 892143611Sphilip if (e->index == idx) 893143611Sphilip return (e); 894143611Sphilip return (NULL); 895143611Sphilip} 896143611Sphilip 897143611Sphilipstatic int 898143611Sphilippfi_refresh(void) 899143611Sphilip{ 900143611Sphilip struct pfioc_iface io; 901143611Sphilip struct pfi_if *p; 902143611Sphilip struct pfi_entry *e; 903143611Sphilip int i, numifs = 1; 904143611Sphilip 905143611Sphilip if (started && this_tick <= pf_tick) 906143611Sphilip return (0); 907143611Sphilip 908143611Sphilip while (!TAILQ_EMPTY(&pfi_table)) { 909143611Sphilip e = TAILQ_FIRST(&pfi_table); 910143611Sphilip TAILQ_REMOVE(&pfi_table, e, link); 911143611Sphilip free(e); 912143611Sphilip } 913143611Sphilip 914143611Sphilip bzero(&io, sizeof(io)); 915143611Sphilip p = malloc(sizeof(struct pfi_if)); 916143611Sphilip io.pfiio_flags = PFI_FLAG_INSTANCE; 917143611Sphilip io.pfiio_esize = sizeof(struct pfi_if); 918143611Sphilip 919143611Sphilip for (;;) { 920143611Sphilip p = realloc(p, numifs * sizeof(struct pfi_if)); 921143611Sphilip io.pfiio_size = numifs; 922143611Sphilip io.pfiio_buffer = p; 923143611Sphilip 924143611Sphilip if (ioctl(dev, DIOCIGETIFACES, &io)) { 925143611Sphilip syslog(LOG_ERR, "pfi_refresh(): ioctl(): %s", 926143611Sphilip strerror(errno)); 927143611Sphilip return (-1); 928143611Sphilip } 929143611Sphilip 930143611Sphilip if (numifs >= io.pfiio_size) 931143611Sphilip break; 932143611Sphilip 933143611Sphilip numifs = io.pfiio_size; 934143611Sphilip } 935143611Sphilip 936143611Sphilip for (i = 0; i < numifs; i++) { 937143611Sphilip e = malloc(sizeof(struct pfi_entry)); 938143611Sphilip e->index = i + 1; 939143611Sphilip memcpy(&e->pfi, p+i, sizeof(struct pfi_if)); 940143611Sphilip TAILQ_INSERT_TAIL(&pfi_table, e, link); 941143611Sphilip } 942143611Sphilip 943143611Sphilip pfi_table_age = time(NULL); 944143611Sphilip pfi_table_count = numifs; 945143611Sphilip pf_tick = this_tick; 946143611Sphilip 947143611Sphilip free(p); 948143611Sphilip return (0); 949143611Sphilip} 950143611Sphilip 951143611Sphilipstatic int 952143611Sphilippfq_refresh(void) 953143611Sphilip{ 954143611Sphilip struct pfioc_altq pa; 955143611Sphilip struct pfq_entry *e; 956143611Sphilip int i, numqs, ticket; 957143611Sphilip 958143611Sphilip if (started && this_tick <= pf_tick) 959143611Sphilip return (0); 960143611Sphilip 961143611Sphilip while (!TAILQ_EMPTY(&pfq_table)) { 962143611Sphilip e = TAILQ_FIRST(&pfq_table); 963143611Sphilip TAILQ_REMOVE(&pfq_table, e, link); 964143611Sphilip free(e); 965143611Sphilip } 966143611Sphilip 967143611Sphilip bzero(&pa, sizeof(pa)); 968143611Sphilip 969143611Sphilip if (ioctl(dev, DIOCGETALTQS, &pa)) { 970143611Sphilip syslog(LOG_ERR, "pfq_refresh: ioctl(DIOCGETALTQS): %s", 971143611Sphilip strerror(errno)); 972143611Sphilip return (-1); 973143611Sphilip } 974143611Sphilip 975143611Sphilip numqs = pa.nr; 976143611Sphilip ticket = pa.ticket; 977143611Sphilip 978143611Sphilip for (i = 0; i < numqs; i++) { 979143611Sphilip e = malloc(sizeof(struct pfq_entry)); 980143611Sphilip pa.ticket = ticket; 981143611Sphilip pa.nr = i; 982143611Sphilip 983143611Sphilip if (ioctl(dev, DIOCGETALTQ, &pa)) { 984143611Sphilip syslog(LOG_ERR, "pfq_refresh(): " 985143611Sphilip "ioctl(DIOCGETALTQ): %s", 986143611Sphilip strerror(errno)); 987143611Sphilip return (-1); 988143611Sphilip } 989143611Sphilip 990143611Sphilip if (pa.altq.qid > 0) { 991143611Sphilip memcpy(&e->altq, &pa.altq, sizeof(struct pf_altq)); 992143611Sphilip e->index = pa.altq.qid; 993143611Sphilip pfq_table_count = i; 994143611Sphilip TAILQ_INSERT_TAIL(&pfq_table, e, link); 995143611Sphilip } 996143611Sphilip } 997143611Sphilip 998143611Sphilip pfq_table_age = time(NULL); 999143611Sphilip pf_tick = this_tick; 1000143611Sphilip 1001143611Sphilip return (0); 1002143611Sphilip} 1003143611Sphilip 1004143611Sphilipstatic int 1005143611Sphilippfs_refresh(void) 1006143611Sphilip{ 1007143611Sphilip if (started && this_tick <= pf_tick) 1008143611Sphilip return (0); 1009143611Sphilip 1010143611Sphilip bzero(&pfs, sizeof(struct pf_status)); 1011143611Sphilip 1012143611Sphilip if (ioctl(dev, DIOCGETSTATUS, &pfs)) { 1013143611Sphilip syslog(LOG_ERR, "pfs_refresh(): ioctl(): %s", 1014143611Sphilip strerror(errno)); 1015143611Sphilip return (-1); 1016143611Sphilip } 1017143611Sphilip 1018143611Sphilip pf_tick = this_tick; 1019143611Sphilip return (0); 1020143611Sphilip} 1021143611Sphilip 1022143611Sphilipstatic int 1023143611Sphilippft_refresh(void) 1024143611Sphilip{ 1025143611Sphilip struct pfioc_table io; 1026143611Sphilip struct pfr_tstats *t; 1027143611Sphilip struct pft_entry *e; 1028143611Sphilip int i, numtbls = 1; 1029143611Sphilip 1030143611Sphilip if (started && this_tick <= pf_tick) 1031143611Sphilip return (0); 1032143611Sphilip 1033143611Sphilip while (!TAILQ_EMPTY(&pft_table)) { 1034143611Sphilip e = TAILQ_FIRST(&pft_table); 1035143611Sphilip TAILQ_REMOVE(&pft_table, e, link); 1036143611Sphilip free(e); 1037143611Sphilip } 1038143611Sphilip 1039143611Sphilip bzero(&io, sizeof(io)); 1040143611Sphilip t = malloc(sizeof(struct pfr_tstats)); 1041143611Sphilip io.pfrio_esize = sizeof(struct pfr_tstats); 1042143611Sphilip 1043143611Sphilip for (;;) { 1044143611Sphilip t = realloc(t, numtbls * sizeof(struct pfr_tstats)); 1045143611Sphilip io.pfrio_size = numtbls; 1046143611Sphilip io.pfrio_buffer = t; 1047143611Sphilip 1048143611Sphilip if (ioctl(dev, DIOCRGETTSTATS, &io)) { 1049143611Sphilip syslog(LOG_ERR, "pft_refresh(): ioctl(): %s", 1050143611Sphilip strerror(errno)); 1051143611Sphilip return (-1); 1052143611Sphilip } 1053143611Sphilip 1054143611Sphilip if (numtbls >= io.pfrio_size) 1055143611Sphilip break; 1056143611Sphilip 1057143611Sphilip numtbls = io.pfrio_size; 1058143611Sphilip } 1059143611Sphilip 1060143611Sphilip for (i = 0; i < numtbls; i++) { 1061143611Sphilip e = malloc(sizeof(struct pfr_tstats)); 1062143611Sphilip e->index = i + 1; 1063143611Sphilip memcpy(&e->pft, t+i, sizeof(struct pfr_tstats)); 1064143611Sphilip TAILQ_INSERT_TAIL(&pft_table, e, link); 1065143611Sphilip } 1066143611Sphilip 1067143611Sphilip pft_table_age = time(NULL); 1068143611Sphilip pft_table_count = numtbls; 1069143611Sphilip pf_tick = this_tick; 1070143611Sphilip 1071143611Sphilip free(t); 1072143611Sphilip return (0); 1073143611Sphilip} 1074143611Sphilip 1075143611Sphilip/* 1076143611Sphilip * Implement the bsnmpd module interface 1077143611Sphilip */ 1078143611Sphilipstatic int 1079143611Sphilippf_init(struct lmodule *mod, int __unused argc, char __unused *argv[]) 1080143611Sphilip{ 1081143611Sphilip module = mod; 1082143611Sphilip 1083143611Sphilip if ((dev = open("/dev/pf", O_RDONLY)) == -1) { 1084143611Sphilip syslog(LOG_ERR, "pf_init(): open(): %s\n", 1085143611Sphilip strerror(errno)); 1086143611Sphilip return (-1); 1087143611Sphilip } 1088143611Sphilip 1089143611Sphilip /* Prepare internal state */ 1090143611Sphilip TAILQ_INIT(&pfi_table); 1091143611Sphilip TAILQ_INIT(&pfq_table); 1092143611Sphilip TAILQ_INIT(&pft_table); 1093143611Sphilip 1094143611Sphilip pfi_refresh(); 1095143611Sphilip pfq_refresh(); 1096143611Sphilip pfs_refresh(); 1097143611Sphilip pft_refresh(); 1098143611Sphilip 1099143611Sphilip started = 1; 1100143611Sphilip 1101143611Sphilip return (0); 1102143611Sphilip} 1103143611Sphilip 1104143611Sphilipstatic int 1105143611Sphilippf_fini(void) 1106143611Sphilip{ 1107143611Sphilip struct pfi_entry *i1, *i2; 1108143611Sphilip struct pfq_entry *q1, *q2; 1109143611Sphilip struct pft_entry *t1, *t2; 1110143611Sphilip 1111143611Sphilip /* Empty the list of interfaces */ 1112143611Sphilip i1 = TAILQ_FIRST(&pfi_table); 1113143611Sphilip while (i1 != NULL) { 1114143611Sphilip i2 = TAILQ_NEXT(i1, link); 1115143611Sphilip free(i1); 1116143611Sphilip i1 = i2; 1117143611Sphilip } 1118143611Sphilip 1119143611Sphilip /* List of queues */ 1120143611Sphilip q1 = TAILQ_FIRST(&pfq_table); 1121143611Sphilip while (q1 != NULL) { 1122143611Sphilip q2 = TAILQ_NEXT(q1, link); 1123143611Sphilip free(q1); 1124143611Sphilip q1 = q2; 1125143611Sphilip } 1126143611Sphilip 1127143611Sphilip /* And the list of tables */ 1128143611Sphilip t1 = TAILQ_FIRST(&pft_table); 1129143611Sphilip while (t1 != NULL) { 1130143611Sphilip t2 = TAILQ_NEXT(t1, link); 1131143611Sphilip free(t1); 1132143611Sphilip t1 = t2; 1133143611Sphilip } 1134143611Sphilip 1135143611Sphilip close(dev); 1136143611Sphilip return (0); 1137143611Sphilip} 1138143611Sphilip 1139143611Sphilipstatic void 1140143611Sphilippf_dump(void) 1141143611Sphilip{ 1142143611Sphilip pfi_refresh(); 1143143611Sphilip pfq_refresh(); 1144143611Sphilip pft_refresh(); 1145143611Sphilip 1146143611Sphilip syslog(LOG_ERR, "Dump: pfi_table_age = %u", 1147143611Sphilip pfi_table_age); 1148143611Sphilip syslog(LOG_ERR, "Dump: pfi_table_count = %d", 1149143611Sphilip pfi_table_count); 1150143611Sphilip 1151143611Sphilip syslog(LOG_ERR, "Dump: pfq_table_age = %u", 1152143611Sphilip pfq_table_age); 1153143611Sphilip syslog(LOG_ERR, "Dump: pfq_table_count = %d", 1154143611Sphilip pfq_table_count); 1155143611Sphilip 1156143611Sphilip syslog(LOG_ERR, "Dump: pft_table_age = %u", 1157143611Sphilip pft_table_age); 1158143611Sphilip 1159143611Sphilip syslog(LOG_ERR, "Dump: pft_table_count = %d", 1160143611Sphilip pft_table_count); 1161143611Sphilip} 1162143611Sphilip 1163143611Sphilipconst struct snmp_module config = { 1164143611Sphilip .comment = "This module implements a MIB for the pf packet filter.", 1165143611Sphilip .init = pf_init, 1166143611Sphilip .fini = pf_fini, 1167143611Sphilip .tree = pf_ctree, 1168143611Sphilip .dump = pf_dump, 1169143611Sphilip .tree_size = pf_CTREE_SIZE, 1170143611Sphilip}; 1171