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