pf_snmp.c revision 179476
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 179476 2008-06-01 14:09:54Z 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; 50146531Sphilipstatic uint64_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 { 63171173Smlaier struct pfi_kif 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 99152970Sphilipstatic int altq_enabled = 0; 100152970Sphilip 101143611Sphilip#define PFQ_TABLE_MAXAGE 5 102143611Sphilip 103143611Sphilip/* Forward declarations */ 104143611Sphilipstatic int pfi_refresh(void); 105143611Sphilipstatic int pfq_refresh(void); 106143611Sphilipstatic int pfs_refresh(void); 107143611Sphilipstatic int pft_refresh(void); 108143611Sphilipstatic struct pfi_entry * pfi_table_find(u_int idx); 109143611Sphilipstatic struct pfq_entry * pfq_table_find(u_int idx); 110143611Sphilipstatic struct pft_entry * pft_table_find(u_int idx); 111143611Sphilip 112152970Sphilipstatic int altq_is_enabled(int pfdevice); 113152970Sphilip 114143611Sphilipint 115143611Sphilippf_status(struct snmp_context __unused *ctx, struct snmp_value *val, 116143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 117143611Sphilip{ 118143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 119143611Sphilip time_t runtime; 120143611Sphilip unsigned char str[128]; 121143611Sphilip 122143611Sphilip if (op == SNMP_OP_SET) 123143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 124143611Sphilip 125143611Sphilip if (op == SNMP_OP_GET) { 126143611Sphilip if (pfs_refresh() == -1) 127143611Sphilip return (SNMP_ERR_GENERR); 128143611Sphilip 129143611Sphilip switch (which) { 130143611Sphilip case LEAF_pfStatusRunning: 131143611Sphilip val->v.uint32 = pfs.running; 132143611Sphilip break; 133143611Sphilip case LEAF_pfStatusRuntime: 134143611Sphilip runtime = (pfs.since > 0) ? 135143611Sphilip time(NULL) - pfs.since : 0; 136143611Sphilip val->v.uint32 = runtime * 100; 137143611Sphilip break; 138143611Sphilip case LEAF_pfStatusDebug: 139143611Sphilip val->v.uint32 = pfs.debug; 140143611Sphilip break; 141143611Sphilip case LEAF_pfStatusHostId: 142143611Sphilip sprintf(str, "0x%08x", ntohl(pfs.hostid)); 143143611Sphilip return (string_get(val, str, strlen(str))); 144143611Sphilip 145143611Sphilip default: 146143611Sphilip return (SNMP_ERR_NOSUCHNAME); 147143611Sphilip } 148143611Sphilip 149143611Sphilip return (SNMP_ERR_NOERROR); 150143611Sphilip } 151143611Sphilip 152143611Sphilip abort(); 153143611Sphilip} 154143611Sphilip 155143611Sphilipint 156143611Sphilippf_counter(struct snmp_context __unused *ctx, struct snmp_value *val, 157143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 158143611Sphilip{ 159143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 160143611Sphilip 161143611Sphilip if (op == SNMP_OP_SET) 162143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 163143611Sphilip 164143611Sphilip if (op == SNMP_OP_GET) { 165143611Sphilip if (pfs_refresh() == -1) 166143611Sphilip return (SNMP_ERR_GENERR); 167143611Sphilip 168143611Sphilip switch (which) { 169143611Sphilip case LEAF_pfCounterMatch: 170143611Sphilip val->v.counter64 = pfs.counters[PFRES_MATCH]; 171143611Sphilip break; 172143611Sphilip case LEAF_pfCounterBadOffset: 173143611Sphilip val->v.counter64 = pfs.counters[PFRES_BADOFF]; 174143611Sphilip break; 175143611Sphilip case LEAF_pfCounterFragment: 176143611Sphilip val->v.counter64 = pfs.counters[PFRES_FRAG]; 177143611Sphilip break; 178143611Sphilip case LEAF_pfCounterShort: 179143611Sphilip val->v.counter64 = pfs.counters[PFRES_SHORT]; 180143611Sphilip break; 181143611Sphilip case LEAF_pfCounterNormalize: 182143611Sphilip val->v.counter64 = pfs.counters[PFRES_NORM]; 183143611Sphilip break; 184143611Sphilip case LEAF_pfCounterMemDrop: 185143611Sphilip val->v.counter64 = pfs.counters[PFRES_MEMORY]; 186143611Sphilip break; 187143611Sphilip 188143611Sphilip default: 189143611Sphilip return (SNMP_ERR_NOSUCHNAME); 190143611Sphilip } 191143611Sphilip 192143611Sphilip return (SNMP_ERR_NOERROR); 193143611Sphilip } 194143611Sphilip 195143611Sphilip abort(); 196143611Sphilip} 197143611Sphilip 198143611Sphilipint 199143611Sphilippf_statetable(struct snmp_context __unused *ctx, struct snmp_value *val, 200143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 201143611Sphilip{ 202143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 203143611Sphilip 204143611Sphilip if (op == SNMP_OP_SET) 205143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 206143611Sphilip 207143611Sphilip if (op == SNMP_OP_GET) { 208143611Sphilip if (pfs_refresh() == -1) 209143611Sphilip return (SNMP_ERR_GENERR); 210143611Sphilip 211143611Sphilip switch (which) { 212143611Sphilip case LEAF_pfStateTableCount: 213143611Sphilip val->v.uint32 = pfs.states; 214143611Sphilip break; 215143611Sphilip case LEAF_pfStateTableSearches: 216143611Sphilip val->v.counter64 = 217143611Sphilip pfs.fcounters[FCNT_STATE_SEARCH]; 218143611Sphilip break; 219143611Sphilip case LEAF_pfStateTableInserts: 220143611Sphilip val->v.counter64 = 221143611Sphilip pfs.fcounters[FCNT_STATE_INSERT]; 222143611Sphilip break; 223143611Sphilip case LEAF_pfStateTableRemovals: 224143611Sphilip val->v.counter64 = 225143611Sphilip pfs.fcounters[FCNT_STATE_REMOVALS]; 226143611Sphilip break; 227143611Sphilip 228143611Sphilip default: 229143611Sphilip return (SNMP_ERR_NOSUCHNAME); 230143611Sphilip } 231143611Sphilip 232143611Sphilip return (SNMP_ERR_NOERROR); 233143611Sphilip } 234143611Sphilip 235143611Sphilip abort(); 236143611Sphilip} 237143611Sphilip 238143611Sphilipint 239143611Sphilippf_srcnodes(struct snmp_context __unused *ctx, struct snmp_value *val, 240143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 241143611Sphilip{ 242143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 243143611Sphilip 244143611Sphilip if (op == SNMP_OP_SET) 245143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 246143611Sphilip 247143611Sphilip if (op == SNMP_OP_GET) { 248143611Sphilip if (pfs_refresh() == -1) 249143611Sphilip return (SNMP_ERR_GENERR); 250143611Sphilip 251143611Sphilip switch (which) { 252143611Sphilip case LEAF_pfSrcNodesCount: 253143611Sphilip val->v.uint32 = pfs.src_nodes; 254143611Sphilip break; 255143611Sphilip case LEAF_pfSrcNodesSearches: 256143611Sphilip val->v.counter64 = 257143611Sphilip pfs.scounters[SCNT_SRC_NODE_SEARCH]; 258143611Sphilip break; 259143611Sphilip case LEAF_pfSrcNodesInserts: 260143611Sphilip val->v.counter64 = 261143611Sphilip pfs.scounters[SCNT_SRC_NODE_INSERT]; 262143611Sphilip break; 263143611Sphilip case LEAF_pfSrcNodesRemovals: 264143611Sphilip val->v.counter64 = 265143611Sphilip pfs.scounters[SCNT_SRC_NODE_REMOVALS]; 266143611Sphilip break; 267143611Sphilip 268143611Sphilip default: 269143611Sphilip return (SNMP_ERR_NOSUCHNAME); 270143611Sphilip } 271143611Sphilip 272143611Sphilip return (SNMP_ERR_NOERROR); 273143611Sphilip } 274143611Sphilip 275143611Sphilip abort(); 276143611Sphilip} 277143611Sphilip 278143611Sphilipint 279143611Sphilippf_limits(struct snmp_context __unused *ctx, struct snmp_value *val, 280143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 281143611Sphilip{ 282143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 283143611Sphilip struct pfioc_limit pl; 284143611Sphilip 285143611Sphilip if (op == SNMP_OP_SET) 286143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 287143611Sphilip 288143611Sphilip if (op == SNMP_OP_GET) { 289143611Sphilip bzero(&pl, sizeof(struct pfioc_limit)); 290143611Sphilip 291143611Sphilip switch (which) { 292143611Sphilip case LEAF_pfLimitsStates: 293143611Sphilip pl.index = PF_LIMIT_STATES; 294143611Sphilip break; 295143611Sphilip case LEAF_pfLimitsSrcNodes: 296143611Sphilip pl.index = PF_LIMIT_SRC_NODES; 297143611Sphilip break; 298143611Sphilip case LEAF_pfLimitsFrags: 299143611Sphilip pl.index = PF_LIMIT_FRAGS; 300143611Sphilip break; 301143611Sphilip 302143611Sphilip default: 303143611Sphilip return (SNMP_ERR_NOSUCHNAME); 304143611Sphilip } 305143611Sphilip 306143611Sphilip if (ioctl(dev, DIOCGETLIMIT, &pl)) { 307143611Sphilip syslog(LOG_ERR, "pf_limits(): ioctl(): %s", 308143611Sphilip strerror(errno)); 309143611Sphilip return (SNMP_ERR_GENERR); 310143611Sphilip } 311143611Sphilip 312143611Sphilip val->v.uint32 = pl.limit; 313143611Sphilip 314143611Sphilip return (SNMP_ERR_NOERROR); 315143611Sphilip } 316143611Sphilip 317143611Sphilip abort(); 318143611Sphilip} 319143611Sphilip 320143611Sphilipint 321143611Sphilippf_timeouts(struct snmp_context __unused *ctx, struct snmp_value *val, 322143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 323143611Sphilip{ 324143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 325143611Sphilip struct pfioc_tm pt; 326143611Sphilip 327143611Sphilip if (op == SNMP_OP_SET) 328143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 329143611Sphilip 330143611Sphilip if (op == SNMP_OP_GET) { 331143611Sphilip bzero(&pt, sizeof(struct pfioc_tm)); 332143611Sphilip 333143611Sphilip switch (which) { 334143611Sphilip case LEAF_pfTimeoutsTcpFirst: 335143611Sphilip pt.timeout = PFTM_TCP_FIRST_PACKET; 336143611Sphilip break; 337143611Sphilip case LEAF_pfTimeoutsTcpOpening: 338143611Sphilip pt.timeout = PFTM_TCP_OPENING; 339143611Sphilip break; 340143611Sphilip case LEAF_pfTimeoutsTcpEstablished: 341143611Sphilip pt.timeout = PFTM_TCP_ESTABLISHED; 342143611Sphilip break; 343143611Sphilip case LEAF_pfTimeoutsTcpClosing: 344143611Sphilip pt.timeout = PFTM_TCP_CLOSING; 345143611Sphilip break; 346143611Sphilip case LEAF_pfTimeoutsTcpFinWait: 347143611Sphilip pt.timeout = PFTM_TCP_FIN_WAIT; 348143611Sphilip break; 349143611Sphilip case LEAF_pfTimeoutsTcpClosed: 350143611Sphilip pt.timeout = PFTM_TCP_CLOSED; 351143611Sphilip break; 352143611Sphilip case LEAF_pfTimeoutsUdpFirst: 353143611Sphilip pt.timeout = PFTM_UDP_FIRST_PACKET; 354143611Sphilip break; 355143611Sphilip case LEAF_pfTimeoutsUdpSingle: 356143611Sphilip pt.timeout = PFTM_UDP_SINGLE; 357143611Sphilip break; 358143611Sphilip case LEAF_pfTimeoutsUdpMultiple: 359143611Sphilip pt.timeout = PFTM_UDP_MULTIPLE; 360143611Sphilip break; 361143611Sphilip case LEAF_pfTimeoutsIcmpFirst: 362143611Sphilip pt.timeout = PFTM_ICMP_FIRST_PACKET; 363143611Sphilip break; 364143611Sphilip case LEAF_pfTimeoutsIcmpError: 365143611Sphilip pt.timeout = PFTM_ICMP_ERROR_REPLY; 366143611Sphilip break; 367143611Sphilip case LEAF_pfTimeoutsOtherFirst: 368143611Sphilip pt.timeout = PFTM_OTHER_FIRST_PACKET; 369143611Sphilip break; 370143611Sphilip case LEAF_pfTimeoutsOtherSingle: 371143611Sphilip pt.timeout = PFTM_OTHER_SINGLE; 372143611Sphilip break; 373143611Sphilip case LEAF_pfTimeoutsOtherMultiple: 374143611Sphilip pt.timeout = PFTM_OTHER_MULTIPLE; 375143611Sphilip break; 376143611Sphilip case LEAF_pfTimeoutsFragment: 377143611Sphilip pt.timeout = PFTM_FRAG; 378143611Sphilip break; 379143611Sphilip case LEAF_pfTimeoutsInterval: 380143611Sphilip pt.timeout = PFTM_INTERVAL; 381143611Sphilip break; 382143611Sphilip case LEAF_pfTimeoutsAdaptiveStart: 383143611Sphilip pt.timeout = PFTM_ADAPTIVE_START; 384143611Sphilip break; 385143611Sphilip case LEAF_pfTimeoutsAdaptiveEnd: 386143611Sphilip pt.timeout = PFTM_ADAPTIVE_END; 387143611Sphilip break; 388143611Sphilip case LEAF_pfTimeoutsSrcNode: 389143611Sphilip pt.timeout = PFTM_SRC_NODE; 390143611Sphilip break; 391143611Sphilip 392143611Sphilip default: 393143611Sphilip return (SNMP_ERR_NOSUCHNAME); 394143611Sphilip } 395143611Sphilip 396143611Sphilip if (ioctl(dev, DIOCGETTIMEOUT, &pt)) { 397143611Sphilip syslog(LOG_ERR, "pf_timeouts(): ioctl(): %s", 398143611Sphilip strerror(errno)); 399143611Sphilip return (SNMP_ERR_GENERR); 400143611Sphilip } 401143611Sphilip 402143611Sphilip val->v.integer = pt.seconds; 403143611Sphilip 404143611Sphilip return (SNMP_ERR_NOERROR); 405143611Sphilip } 406143611Sphilip 407143611Sphilip abort(); 408143611Sphilip} 409143611Sphilip 410143611Sphilipint 411143611Sphilippf_logif(struct snmp_context __unused *ctx, struct snmp_value *val, 412143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 413143611Sphilip{ 414143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 415143611Sphilip unsigned char str[IFNAMSIZ]; 416143611Sphilip 417143611Sphilip if (op == SNMP_OP_SET) 418143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 419143611Sphilip 420143611Sphilip if (op == SNMP_OP_GET) { 421143611Sphilip if (pfs_refresh() == -1) 422143611Sphilip return (SNMP_ERR_GENERR); 423143611Sphilip 424143611Sphilip switch (which) { 425143611Sphilip case LEAF_pfLogInterfaceName: 426143611Sphilip strlcpy(str, pfs.ifname, sizeof str); 427143611Sphilip return (string_get(val, str, strlen(str))); 428143611Sphilip case LEAF_pfLogInterfaceIp4BytesIn: 429143611Sphilip val->v.counter64 = pfs.bcounters[IPV4][IN]; 430143611Sphilip break; 431143611Sphilip case LEAF_pfLogInterfaceIp4BytesOut: 432143611Sphilip val->v.counter64 = pfs.bcounters[IPV4][OUT]; 433143611Sphilip break; 434143611Sphilip case LEAF_pfLogInterfaceIp4PktsInPass: 435143611Sphilip val->v.counter64 = 436143611Sphilip pfs.pcounters[IPV4][IN][PF_PASS]; 437143611Sphilip break; 438143611Sphilip case LEAF_pfLogInterfaceIp4PktsInDrop: 439143611Sphilip val->v.counter64 = 440143611Sphilip pfs.pcounters[IPV4][IN][PF_DROP]; 441143611Sphilip break; 442143611Sphilip case LEAF_pfLogInterfaceIp4PktsOutPass: 443143611Sphilip val->v.counter64 = 444143611Sphilip pfs.pcounters[IPV4][OUT][PF_PASS]; 445143611Sphilip break; 446143611Sphilip case LEAF_pfLogInterfaceIp4PktsOutDrop: 447143611Sphilip val->v.counter64 = 448143611Sphilip pfs.pcounters[IPV4][OUT][PF_DROP]; 449143611Sphilip break; 450143611Sphilip case LEAF_pfLogInterfaceIp6BytesIn: 451143611Sphilip val->v.counter64 = pfs.bcounters[IPV6][IN]; 452143611Sphilip break; 453143611Sphilip case LEAF_pfLogInterfaceIp6BytesOut: 454143611Sphilip val->v.counter64 = pfs.bcounters[IPV6][OUT]; 455143611Sphilip break; 456143611Sphilip case LEAF_pfLogInterfaceIp6PktsInPass: 457143611Sphilip val->v.counter64 = 458143611Sphilip pfs.pcounters[IPV6][IN][PF_PASS]; 459143611Sphilip break; 460143611Sphilip case LEAF_pfLogInterfaceIp6PktsInDrop: 461143611Sphilip val->v.counter64 = 462143611Sphilip pfs.pcounters[IPV6][IN][PF_DROP]; 463143611Sphilip break; 464143611Sphilip case LEAF_pfLogInterfaceIp6PktsOutPass: 465143611Sphilip val->v.counter64 = 466143611Sphilip pfs.pcounters[IPV6][OUT][PF_PASS]; 467143611Sphilip break; 468143611Sphilip case LEAF_pfLogInterfaceIp6PktsOutDrop: 469143611Sphilip val->v.counter64 = 470143611Sphilip pfs.pcounters[IPV6][OUT][PF_DROP]; 471143611Sphilip break; 472143611Sphilip 473143611Sphilip default: 474143611Sphilip return (SNMP_ERR_NOSUCHNAME); 475143611Sphilip } 476143611Sphilip 477143611Sphilip return (SNMP_ERR_NOERROR); 478143611Sphilip } 479143611Sphilip 480143611Sphilip abort(); 481143611Sphilip} 482143611Sphilip 483143611Sphilipint 484143611Sphilippf_interfaces(struct snmp_context __unused *ctx, struct snmp_value *val, 485143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 486143611Sphilip{ 487143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 488143611Sphilip 489143611Sphilip if (op == SNMP_OP_SET) 490143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 491143611Sphilip 492143611Sphilip if (op == SNMP_OP_GET) { 493143611Sphilip if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE) 494143611Sphilip if (pfi_refresh() == -1) 495143611Sphilip return (SNMP_ERR_GENERR); 496143611Sphilip 497143611Sphilip switch (which) { 498143611Sphilip case LEAF_pfInterfacesIfNumber: 499143611Sphilip val->v.uint32 = pfi_table_count; 500143611Sphilip break; 501143611Sphilip 502143611Sphilip default: 503143611Sphilip return (SNMP_ERR_NOSUCHNAME); 504143611Sphilip } 505143611Sphilip 506143611Sphilip return (SNMP_ERR_NOERROR); 507143611Sphilip } 508143611Sphilip 509143611Sphilip abort(); 510143611Sphilip} 511143611Sphilip 512143611Sphilipint 513143611Sphilippf_iftable(struct snmp_context __unused *ctx, struct snmp_value *val, 514143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 515143611Sphilip{ 516143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 517143611Sphilip struct pfi_entry *e = NULL; 518143611Sphilip 519143611Sphilip switch (op) { 520143611Sphilip case SNMP_OP_SET: 521143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 522143611Sphilip case SNMP_OP_GETNEXT: 523143611Sphilip if ((e = NEXT_OBJECT_INT(&pfi_table, 524143611Sphilip &val->var, sub)) == NULL) 525143611Sphilip return (SNMP_ERR_NOSUCHNAME); 526143611Sphilip val->var.len = sub + 1; 527143611Sphilip val->var.subs[sub] = e->index; 528143611Sphilip break; 529143611Sphilip case SNMP_OP_GET: 530143611Sphilip if (val->var.len - sub != 1) 531143611Sphilip return (SNMP_ERR_NOSUCHNAME); 532143611Sphilip if ((e = pfi_table_find(val->var.subs[sub])) == NULL) 533143611Sphilip return (SNMP_ERR_NOSUCHNAME); 534143611Sphilip break; 535143611Sphilip 536143611Sphilip case SNMP_OP_COMMIT: 537143611Sphilip case SNMP_OP_ROLLBACK: 538143611Sphilip default: 539143611Sphilip abort(); 540143611Sphilip } 541143611Sphilip 542143611Sphilip if ((time(NULL) - pfi_table_age) > PFI_TABLE_MAXAGE) 543143611Sphilip pfi_refresh(); 544143611Sphilip 545143611Sphilip switch (which) { 546143611Sphilip case LEAF_pfInterfacesIfDescr: 547171173Smlaier return (string_get(val, e->pfi.pfik_name, -1)); 548143611Sphilip case LEAF_pfInterfacesIfType: 549143611Sphilip val->v.integer = PFI_IFTYPE_INSTANCE; 550143611Sphilip break; 551143611Sphilip case LEAF_pfInterfacesIfTZero: 552143611Sphilip val->v.uint32 = 553171173Smlaier (time(NULL) - e->pfi.pfik_tzero) * 100; 554143611Sphilip break; 555143611Sphilip case LEAF_pfInterfacesIfRefsState: 556171173Smlaier val->v.uint32 = e->pfi.pfik_states; 557143611Sphilip break; 558143611Sphilip case LEAF_pfInterfacesIfRefsRule: 559171173Smlaier val->v.uint32 = e->pfi.pfik_rules; 560143611Sphilip break; 561143611Sphilip case LEAF_pfInterfacesIf4BytesInPass: 562143611Sphilip val->v.counter64 = 563171173Smlaier e->pfi.pfik_bytes[IPV4][IN][PASS]; 564143611Sphilip break; 565143611Sphilip case LEAF_pfInterfacesIf4BytesInBlock: 566143611Sphilip val->v.counter64 = 567171173Smlaier e->pfi.pfik_bytes[IPV4][IN][BLOCK]; 568143611Sphilip break; 569143611Sphilip case LEAF_pfInterfacesIf4BytesOutPass: 570143611Sphilip val->v.counter64 = 571171173Smlaier e->pfi.pfik_bytes[IPV4][OUT][PASS]; 572143611Sphilip break; 573143611Sphilip case LEAF_pfInterfacesIf4BytesOutBlock: 574143611Sphilip val->v.counter64 = 575171173Smlaier e->pfi.pfik_bytes[IPV4][OUT][BLOCK]; 576143611Sphilip break; 577143611Sphilip case LEAF_pfInterfacesIf4PktsInPass: 578143611Sphilip val->v.counter64 = 579171173Smlaier e->pfi.pfik_packets[IPV4][IN][PASS]; 580143611Sphilip break; 581143611Sphilip case LEAF_pfInterfacesIf4PktsInBlock: 582143611Sphilip val->v.counter64 = 583171173Smlaier e->pfi.pfik_packets[IPV4][IN][BLOCK]; 584143611Sphilip break; 585143611Sphilip case LEAF_pfInterfacesIf4PktsOutPass: 586143611Sphilip val->v.counter64 = 587171173Smlaier e->pfi.pfik_packets[IPV4][OUT][PASS]; 588143611Sphilip break; 589143611Sphilip case LEAF_pfInterfacesIf4PktsOutBlock: 590143611Sphilip val->v.counter64 = 591171173Smlaier e->pfi.pfik_packets[IPV4][OUT][BLOCK]; 592143611Sphilip break; 593143611Sphilip case LEAF_pfInterfacesIf6BytesInPass: 594143611Sphilip val->v.counter64 = 595171173Smlaier e->pfi.pfik_bytes[IPV6][IN][PASS]; 596143611Sphilip break; 597143611Sphilip case LEAF_pfInterfacesIf6BytesInBlock: 598143611Sphilip val->v.counter64 = 599171173Smlaier e->pfi.pfik_bytes[IPV6][IN][BLOCK]; 600143611Sphilip break; 601143611Sphilip case LEAF_pfInterfacesIf6BytesOutPass: 602143611Sphilip val->v.counter64 = 603171173Smlaier e->pfi.pfik_bytes[IPV6][OUT][PASS]; 604143611Sphilip break; 605143611Sphilip case LEAF_pfInterfacesIf6BytesOutBlock: 606143611Sphilip val->v.counter64 = 607171173Smlaier e->pfi.pfik_bytes[IPV6][OUT][BLOCK]; 608143611Sphilip break; 609143611Sphilip case LEAF_pfInterfacesIf6PktsInPass: 610143611Sphilip val->v.counter64 = 611171173Smlaier e->pfi.pfik_packets[IPV6][IN][PASS]; 612143611Sphilip break; 613143611Sphilip case LEAF_pfInterfacesIf6PktsInBlock: 614143611Sphilip val->v.counter64 = 615171173Smlaier e->pfi.pfik_packets[IPV6][IN][BLOCK]; 616143611Sphilip break; 617143611Sphilip case LEAF_pfInterfacesIf6PktsOutPass: 618143611Sphilip val->v.counter64 = 619171173Smlaier e->pfi.pfik_packets[IPV6][OUT][PASS]; 620143611Sphilip break; 621143611Sphilip case LEAF_pfInterfacesIf6PktsOutBlock: 622143611Sphilip val->v.counter64 = 623171173Smlaier e->pfi.pfik_packets[IPV6][OUT][BLOCK]; 624143611Sphilip break; 625143611Sphilip 626143611Sphilip default: 627143611Sphilip return (SNMP_ERR_NOSUCHNAME); 628143611Sphilip } 629143611Sphilip 630143611Sphilip return (SNMP_ERR_NOERROR); 631143611Sphilip} 632143611Sphilip 633143611Sphilipint 634143611Sphilippf_tables(struct snmp_context __unused *ctx, struct snmp_value *val, 635143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 636143611Sphilip{ 637143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 638143611Sphilip 639143611Sphilip if (op == SNMP_OP_SET) 640143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 641143611Sphilip 642143611Sphilip if (op == SNMP_OP_GET) { 643143611Sphilip if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE) 644143611Sphilip if (pft_refresh() == -1) 645143611Sphilip return (SNMP_ERR_GENERR); 646143611Sphilip 647143611Sphilip switch (which) { 648143611Sphilip case LEAF_pfTablesTblNumber: 649143611Sphilip val->v.uint32 = pft_table_count; 650143611Sphilip break; 651143611Sphilip 652143611Sphilip default: 653143611Sphilip return (SNMP_ERR_NOSUCHNAME); 654143611Sphilip } 655143611Sphilip 656143611Sphilip return (SNMP_ERR_NOERROR); 657143611Sphilip } 658143611Sphilip 659143611Sphilip abort(); 660143611Sphilip} 661143611Sphilip 662143611Sphilipint 663143611Sphilippf_tbltable(struct snmp_context __unused *ctx, struct snmp_value *val, 664143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 665143611Sphilip{ 666143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 667143611Sphilip struct pft_entry *e = NULL; 668143611Sphilip 669143611Sphilip switch (op) { 670143611Sphilip case SNMP_OP_SET: 671143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 672143611Sphilip case SNMP_OP_GETNEXT: 673143611Sphilip if ((e = NEXT_OBJECT_INT(&pft_table, 674143611Sphilip &val->var, sub)) == NULL) 675143611Sphilip return (SNMP_ERR_NOSUCHNAME); 676143611Sphilip val->var.len = sub + 1; 677143611Sphilip val->var.subs[sub] = e->index; 678143611Sphilip break; 679143611Sphilip case SNMP_OP_GET: 680143611Sphilip if (val->var.len - sub != 1) 681143611Sphilip return (SNMP_ERR_NOSUCHNAME); 682143611Sphilip if ((e = pft_table_find(val->var.subs[sub])) == NULL) 683143611Sphilip return (SNMP_ERR_NOSUCHNAME); 684143611Sphilip break; 685143611Sphilip 686143611Sphilip case SNMP_OP_COMMIT: 687143611Sphilip case SNMP_OP_ROLLBACK: 688143611Sphilip default: 689143611Sphilip abort(); 690143611Sphilip } 691143611Sphilip 692143611Sphilip if ((time(NULL) - pft_table_age) > PFT_TABLE_MAXAGE) 693143611Sphilip pft_refresh(); 694143611Sphilip 695143611Sphilip switch (which) { 696143611Sphilip case LEAF_pfTablesTblDescr: 697143611Sphilip return (string_get(val, e->pft.pfrts_name, -1)); 698143611Sphilip case LEAF_pfTablesTblCount: 699143611Sphilip val->v.integer = e->pft.pfrts_cnt; 700143611Sphilip break; 701143611Sphilip case LEAF_pfTablesTblTZero: 702143611Sphilip val->v.uint32 = 703143611Sphilip (time(NULL) - e->pft.pfrts_tzero) * 100; 704143611Sphilip break; 705143611Sphilip case LEAF_pfTablesTblRefsAnchor: 706143611Sphilip val->v.integer = 707143611Sphilip e->pft.pfrts_refcnt[PFR_REFCNT_ANCHOR]; 708143611Sphilip break; 709143611Sphilip case LEAF_pfTablesTblRefsRule: 710143611Sphilip val->v.integer = 711143611Sphilip e->pft.pfrts_refcnt[PFR_REFCNT_RULE]; 712143611Sphilip break; 713143611Sphilip case LEAF_pfTablesTblEvalMatch: 714143611Sphilip val->v.counter64 = e->pft.pfrts_match; 715143611Sphilip break; 716143611Sphilip case LEAF_pfTablesTblEvalNoMatch: 717143611Sphilip val->v.counter64 = e->pft.pfrts_nomatch; 718143611Sphilip break; 719143611Sphilip case LEAF_pfTablesTblBytesInPass: 720143611Sphilip val->v.counter64 = 721143611Sphilip e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_PASS]; 722143611Sphilip break; 723143611Sphilip case LEAF_pfTablesTblBytesInBlock: 724143611Sphilip val->v.counter64 = 725143611Sphilip e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_BLOCK]; 726143611Sphilip break; 727143611Sphilip case LEAF_pfTablesTblBytesInXPass: 728143611Sphilip val->v.counter64 = 729143611Sphilip e->pft.pfrts_bytes[PFR_DIR_IN][PFR_OP_XPASS]; 730143611Sphilip break; 731143611Sphilip case LEAF_pfTablesTblBytesOutPass: 732143611Sphilip val->v.counter64 = 733143611Sphilip e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_PASS]; 734143611Sphilip break; 735143611Sphilip case LEAF_pfTablesTblBytesOutBlock: 736143611Sphilip val->v.counter64 = 737143611Sphilip e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_BLOCK]; 738143611Sphilip break; 739143611Sphilip case LEAF_pfTablesTblBytesOutXPass: 740143611Sphilip val->v.counter64 = 741143611Sphilip e->pft.pfrts_bytes[PFR_DIR_OUT][PFR_OP_XPASS]; 742143611Sphilip break; 743143611Sphilip case LEAF_pfTablesTblPktsInPass: 744143611Sphilip val->v.counter64 = 745143611Sphilip e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_PASS]; 746143611Sphilip break; 747143611Sphilip case LEAF_pfTablesTblPktsInBlock: 748143611Sphilip val->v.counter64 = 749143611Sphilip e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_BLOCK]; 750143611Sphilip break; 751143611Sphilip case LEAF_pfTablesTblPktsInXPass: 752143611Sphilip val->v.counter64 = 753143611Sphilip e->pft.pfrts_packets[PFR_DIR_IN][PFR_OP_XPASS]; 754143611Sphilip break; 755143611Sphilip case LEAF_pfTablesTblPktsOutPass: 756143611Sphilip val->v.counter64 = 757143611Sphilip e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_PASS]; 758143611Sphilip break; 759143611Sphilip case LEAF_pfTablesTblPktsOutBlock: 760143611Sphilip val->v.counter64 = 761143611Sphilip e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_BLOCK]; 762143611Sphilip break; 763143611Sphilip case LEAF_pfTablesTblPktsOutXPass: 764143611Sphilip val->v.counter64 = 765143611Sphilip e->pft.pfrts_packets[PFR_DIR_OUT][PFR_OP_XPASS]; 766143611Sphilip break; 767143611Sphilip 768143611Sphilip default: 769143611Sphilip return (SNMP_ERR_NOSUCHNAME); 770143611Sphilip } 771143611Sphilip 772143611Sphilip return (SNMP_ERR_NOERROR); 773143611Sphilip} 774143611Sphilip 775143611Sphilipint 776143611Sphilippf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val, 777143611Sphilip u_int __unused sub, u_int __unused vindex, enum snmp_op __unused op) 778143611Sphilip{ 779143611Sphilip return (SNMP_ERR_GENERR); 780143611Sphilip} 781143611Sphilip 782143611Sphilipint 783143611Sphilippf_altq(struct snmp_context __unused *ctx, struct snmp_value *val, 784143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 785143611Sphilip{ 786143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 787143611Sphilip 788152970Sphilip if (!altq_enabled) { 789152970Sphilip return (SNMP_ERR_NOERROR); 790152970Sphilip } 791152970Sphilip 792143611Sphilip if (op == SNMP_OP_SET) 793143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 794143611Sphilip 795143611Sphilip if (op == SNMP_OP_GET) { 796143611Sphilip if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE) 797143611Sphilip if (pfq_refresh() == -1) 798143611Sphilip return (SNMP_ERR_GENERR); 799143611Sphilip 800143611Sphilip switch (which) { 801143611Sphilip case LEAF_pfAltqQueueNumber: 802143611Sphilip val->v.uint32 = pfq_table_count; 803143611Sphilip break; 804143611Sphilip 805143611Sphilip default: 806143611Sphilip return (SNMP_ERR_NOSUCHNAME); 807143611Sphilip } 808143611Sphilip 809143611Sphilip return (SNMP_ERR_NOERROR); 810143611Sphilip } 811143611Sphilip 812143611Sphilip abort(); 813143611Sphilip return (SNMP_ERR_GENERR); 814143611Sphilip} 815143611Sphilip 816143611Sphilipint 817143611Sphilippf_altqq(struct snmp_context __unused *ctx, struct snmp_value *val, 818143611Sphilip u_int sub, u_int __unused vindex, enum snmp_op op) 819143611Sphilip{ 820143611Sphilip asn_subid_t which = val->var.subs[sub - 1]; 821143611Sphilip struct pfq_entry *e = NULL; 822143611Sphilip 823152970Sphilip if (!altq_enabled) { 824152970Sphilip return (SNMP_ERR_NOERROR); 825152970Sphilip } 826152970Sphilip 827143611Sphilip switch (op) { 828143611Sphilip case SNMP_OP_SET: 829143611Sphilip return (SNMP_ERR_NOT_WRITEABLE); 830143611Sphilip case SNMP_OP_GETNEXT: 831143611Sphilip if ((e = NEXT_OBJECT_INT(&pfq_table, 832143611Sphilip &val->var, sub)) == NULL) 833143611Sphilip return (SNMP_ERR_NOSUCHNAME); 834143611Sphilip val->var.len = sub + 1; 835143611Sphilip val->var.subs[sub] = e->index; 836143611Sphilip break; 837143611Sphilip case SNMP_OP_GET: 838143611Sphilip if (val->var.len - sub != 1) 839143611Sphilip return (SNMP_ERR_NOSUCHNAME); 840143611Sphilip if ((e = pfq_table_find(val->var.subs[sub])) == NULL) 841143611Sphilip return (SNMP_ERR_NOSUCHNAME); 842143611Sphilip break; 843143611Sphilip 844143611Sphilip case SNMP_OP_COMMIT: 845143611Sphilip case SNMP_OP_ROLLBACK: 846143611Sphilip default: 847143611Sphilip abort(); 848143611Sphilip } 849143611Sphilip 850143611Sphilip if ((time(NULL) - pfq_table_age) > PFQ_TABLE_MAXAGE) 851143611Sphilip pfq_refresh(); 852143611Sphilip 853143611Sphilip switch (which) { 854143611Sphilip case LEAF_pfAltqQueueDescr: 855143611Sphilip return (string_get(val, e->altq.qname, -1)); 856143611Sphilip case LEAF_pfAltqQueueParent: 857143611Sphilip return (string_get(val, e->altq.parent, -1)); 858143611Sphilip case LEAF_pfAltqQueueScheduler: 859143611Sphilip val->v.integer = e->altq.scheduler; 860143611Sphilip break; 861143611Sphilip case LEAF_pfAltqQueueBandwidth: 862143611Sphilip val->v.uint32 = e->altq.bandwidth; 863143611Sphilip break; 864143611Sphilip case LEAF_pfAltqQueuePriority: 865143611Sphilip val->v.integer = e->altq.priority; 866143611Sphilip break; 867143611Sphilip case LEAF_pfAltqQueueLimit: 868143611Sphilip val->v.integer = e->altq.qlimit; 869143611Sphilip break; 870143611Sphilip 871143611Sphilip default: 872143611Sphilip return (SNMP_ERR_NOSUCHNAME); 873143611Sphilip } 874143611Sphilip 875143611Sphilip return (SNMP_ERR_NOERROR); 876143611Sphilip} 877143611Sphilip 878143611Sphilipstatic struct pfi_entry * 879143611Sphilippfi_table_find(u_int idx) 880143611Sphilip{ 881143611Sphilip struct pfi_entry *e; 882143611Sphilip 883143611Sphilip TAILQ_FOREACH(e, &pfi_table, link) 884143611Sphilip if (e->index == idx) 885143611Sphilip return (e); 886143611Sphilip return (NULL); 887143611Sphilip} 888143611Sphilip 889143611Sphilipstatic struct pfq_entry * 890143611Sphilippfq_table_find(u_int idx) 891143611Sphilip{ 892143611Sphilip struct pfq_entry *e; 893143611Sphilip TAILQ_FOREACH(e, &pfq_table, link) 894143611Sphilip if (e->index == idx) 895143611Sphilip return (e); 896143611Sphilip return (NULL); 897143611Sphilip} 898143611Sphilip 899143611Sphilipstatic struct pft_entry * 900143611Sphilippft_table_find(u_int idx) 901143611Sphilip{ 902143611Sphilip struct pft_entry *e; 903143611Sphilip 904143611Sphilip TAILQ_FOREACH(e, &pft_table, link) 905143611Sphilip if (e->index == idx) 906143611Sphilip return (e); 907143611Sphilip return (NULL); 908143611Sphilip} 909143611Sphilip 910143611Sphilipstatic int 911143611Sphilippfi_refresh(void) 912143611Sphilip{ 913143611Sphilip struct pfioc_iface io; 914171173Smlaier struct pfi_kif *p = NULL; 915143611Sphilip struct pfi_entry *e; 916143611Sphilip int i, numifs = 1; 917143611Sphilip 918143611Sphilip if (started && this_tick <= pf_tick) 919143611Sphilip return (0); 920143611Sphilip 921143611Sphilip while (!TAILQ_EMPTY(&pfi_table)) { 922143611Sphilip e = TAILQ_FIRST(&pfi_table); 923143611Sphilip TAILQ_REMOVE(&pfi_table, e, link); 924143611Sphilip free(e); 925143611Sphilip } 926143611Sphilip 927143611Sphilip bzero(&io, sizeof(io)); 928171173Smlaier io.pfiio_esize = sizeof(struct pfi_kif); 929143611Sphilip 930143611Sphilip for (;;) { 931171173Smlaier p = reallocf(p, numifs * sizeof(struct pfi_kif)); 932149571Sphilip if (p == NULL) { 933149571Sphilip syslog(LOG_ERR, "pfi_refresh(): reallocf() numifs=%d: %s", 934149571Sphilip numifs, strerror(errno)); 935149571Sphilip goto err2; 936149571Sphilip } 937143611Sphilip io.pfiio_size = numifs; 938143611Sphilip io.pfiio_buffer = p; 939143611Sphilip 940143611Sphilip if (ioctl(dev, DIOCIGETIFACES, &io)) { 941143611Sphilip syslog(LOG_ERR, "pfi_refresh(): ioctl(): %s", 942143611Sphilip strerror(errno)); 943149571Sphilip goto err2; 944143611Sphilip } 945143611Sphilip 946143611Sphilip if (numifs >= io.pfiio_size) 947143611Sphilip break; 948143611Sphilip 949143611Sphilip numifs = io.pfiio_size; 950143611Sphilip } 951143611Sphilip 952143611Sphilip for (i = 0; i < numifs; i++) { 953143611Sphilip e = malloc(sizeof(struct pfi_entry)); 954149571Sphilip if (e == NULL) 955149571Sphilip goto err1; 956143611Sphilip e->index = i + 1; 957171173Smlaier memcpy(&e->pfi, p+i, sizeof(struct pfi_kif)); 958143611Sphilip TAILQ_INSERT_TAIL(&pfi_table, e, link); 959143611Sphilip } 960143611Sphilip 961143611Sphilip pfi_table_age = time(NULL); 962143611Sphilip pfi_table_count = numifs; 963143611Sphilip pf_tick = this_tick; 964143611Sphilip 965143611Sphilip free(p); 966143611Sphilip return (0); 967149571Sphilip 968149571Sphiliperr1: 969149571Sphilip while (!TAILQ_EMPTY(&pfi_table)) { 970149571Sphilip e = TAILQ_FIRST(&pfi_table); 971149571Sphilip TAILQ_REMOVE(&pfi_table, e, link); 972149571Sphilip free(e); 973149571Sphilip } 974149571Sphiliperr2: 975149571Sphilip free(p); 976149571Sphilip return(-1); 977143611Sphilip} 978143611Sphilip 979143611Sphilipstatic int 980143611Sphilippfq_refresh(void) 981143611Sphilip{ 982143611Sphilip struct pfioc_altq pa; 983143611Sphilip struct pfq_entry *e; 984143611Sphilip int i, numqs, ticket; 985143611Sphilip 986143611Sphilip if (started && this_tick <= pf_tick) 987143611Sphilip return (0); 988143611Sphilip 989143611Sphilip while (!TAILQ_EMPTY(&pfq_table)) { 990143611Sphilip e = TAILQ_FIRST(&pfq_table); 991143611Sphilip TAILQ_REMOVE(&pfq_table, e, link); 992143611Sphilip free(e); 993143611Sphilip } 994143611Sphilip 995143611Sphilip bzero(&pa, sizeof(pa)); 996143611Sphilip 997143611Sphilip if (ioctl(dev, DIOCGETALTQS, &pa)) { 998143611Sphilip syslog(LOG_ERR, "pfq_refresh: ioctl(DIOCGETALTQS): %s", 999143611Sphilip strerror(errno)); 1000143611Sphilip return (-1); 1001143611Sphilip } 1002143611Sphilip 1003143611Sphilip numqs = pa.nr; 1004143611Sphilip ticket = pa.ticket; 1005143611Sphilip 1006143611Sphilip for (i = 0; i < numqs; i++) { 1007143611Sphilip e = malloc(sizeof(struct pfq_entry)); 1008149571Sphilip if (e == NULL) { 1009149571Sphilip syslog(LOG_ERR, "pfq_refresh(): " 1010149571Sphilip "malloc(): %s", 1011149571Sphilip strerror(errno)); 1012149571Sphilip goto err; 1013149571Sphilip } 1014143611Sphilip pa.ticket = ticket; 1015143611Sphilip pa.nr = i; 1016143611Sphilip 1017143611Sphilip if (ioctl(dev, DIOCGETALTQ, &pa)) { 1018143611Sphilip syslog(LOG_ERR, "pfq_refresh(): " 1019143611Sphilip "ioctl(DIOCGETALTQ): %s", 1020143611Sphilip strerror(errno)); 1021149571Sphilip goto err; 1022143611Sphilip } 1023143611Sphilip 1024143611Sphilip if (pa.altq.qid > 0) { 1025143611Sphilip memcpy(&e->altq, &pa.altq, sizeof(struct pf_altq)); 1026143611Sphilip e->index = pa.altq.qid; 1027143611Sphilip pfq_table_count = i; 1028179476Sphilip INSERT_OBJECT_INT_LINK_INDEX(e, &pfq_table, link, index); 1029143611Sphilip } 1030143611Sphilip } 1031143611Sphilip 1032143611Sphilip pfq_table_age = time(NULL); 1033143611Sphilip pf_tick = this_tick; 1034143611Sphilip 1035143611Sphilip return (0); 1036149571Sphiliperr: 1037149571Sphilip free(e); 1038149571Sphilip while (!TAILQ_EMPTY(&pfq_table)) { 1039149571Sphilip e = TAILQ_FIRST(&pfq_table); 1040149571Sphilip TAILQ_REMOVE(&pfq_table, e, link); 1041149571Sphilip free(e); 1042149571Sphilip } 1043149571Sphilip return(-1); 1044143611Sphilip} 1045143611Sphilip 1046143611Sphilipstatic int 1047143611Sphilippfs_refresh(void) 1048143611Sphilip{ 1049143611Sphilip if (started && this_tick <= pf_tick) 1050143611Sphilip return (0); 1051143611Sphilip 1052143611Sphilip bzero(&pfs, sizeof(struct pf_status)); 1053143611Sphilip 1054143611Sphilip if (ioctl(dev, DIOCGETSTATUS, &pfs)) { 1055143611Sphilip syslog(LOG_ERR, "pfs_refresh(): ioctl(): %s", 1056143611Sphilip strerror(errno)); 1057143611Sphilip return (-1); 1058143611Sphilip } 1059143611Sphilip 1060143611Sphilip pf_tick = this_tick; 1061143611Sphilip return (0); 1062143611Sphilip} 1063143611Sphilip 1064143611Sphilipstatic int 1065143611Sphilippft_refresh(void) 1066143611Sphilip{ 1067143611Sphilip struct pfioc_table io; 1068149571Sphilip struct pfr_tstats *t = NULL; 1069143611Sphilip struct pft_entry *e; 1070143611Sphilip int i, numtbls = 1; 1071143611Sphilip 1072143611Sphilip if (started && this_tick <= pf_tick) 1073143611Sphilip return (0); 1074143611Sphilip 1075143611Sphilip while (!TAILQ_EMPTY(&pft_table)) { 1076143611Sphilip e = TAILQ_FIRST(&pft_table); 1077143611Sphilip TAILQ_REMOVE(&pft_table, e, link); 1078143611Sphilip free(e); 1079143611Sphilip } 1080143611Sphilip 1081143611Sphilip bzero(&io, sizeof(io)); 1082143611Sphilip io.pfrio_esize = sizeof(struct pfr_tstats); 1083143611Sphilip 1084143611Sphilip for (;;) { 1085149571Sphilip t = reallocf(t, numtbls * sizeof(struct pfr_tstats)); 1086149571Sphilip if (t == NULL) { 1087149571Sphilip syslog(LOG_ERR, "pft_refresh(): reallocf() numtbls=%d: %s", 1088149571Sphilip numtbls, strerror(errno)); 1089149571Sphilip goto err2; 1090149571Sphilip } 1091143611Sphilip io.pfrio_size = numtbls; 1092143611Sphilip io.pfrio_buffer = t; 1093143611Sphilip 1094143611Sphilip if (ioctl(dev, DIOCRGETTSTATS, &io)) { 1095143611Sphilip syslog(LOG_ERR, "pft_refresh(): ioctl(): %s", 1096143611Sphilip strerror(errno)); 1097149571Sphilip goto err2; 1098143611Sphilip } 1099143611Sphilip 1100143611Sphilip if (numtbls >= io.pfrio_size) 1101143611Sphilip break; 1102143611Sphilip 1103143611Sphilip numtbls = io.pfrio_size; 1104143611Sphilip } 1105143611Sphilip 1106143611Sphilip for (i = 0; i < numtbls; i++) { 1107143611Sphilip e = malloc(sizeof(struct pfr_tstats)); 1108149571Sphilip if (e == NULL) 1109149571Sphilip goto err1; 1110143611Sphilip e->index = i + 1; 1111143611Sphilip memcpy(&e->pft, t+i, sizeof(struct pfr_tstats)); 1112143611Sphilip TAILQ_INSERT_TAIL(&pft_table, e, link); 1113143611Sphilip } 1114143611Sphilip 1115143611Sphilip pft_table_age = time(NULL); 1116143611Sphilip pft_table_count = numtbls; 1117143611Sphilip pf_tick = this_tick; 1118143611Sphilip 1119143611Sphilip free(t); 1120143611Sphilip return (0); 1121149571Sphiliperr1: 1122149571Sphilip while (!TAILQ_EMPTY(&pft_table)) { 1123149571Sphilip e = TAILQ_FIRST(&pft_table); 1124149571Sphilip TAILQ_REMOVE(&pft_table, e, link); 1125149571Sphilip free(e); 1126149571Sphilip } 1127149571Sphiliperr2: 1128149571Sphilip free(t); 1129149571Sphilip return(-1); 1130143611Sphilip} 1131143611Sphilip 1132143611Sphilip/* 1133152970Sphilip * check whether altq support is enabled in kernel 1134152970Sphilip */ 1135152970Sphilip 1136152970Sphilipstatic int 1137152970Sphilipaltq_is_enabled(int pfdev) 1138152970Sphilip{ 1139152970Sphilip struct pfioc_altq pa; 1140152970Sphilip 1141152970Sphilip errno = 0; 1142152970Sphilip if (ioctl(pfdev, DIOCGETALTQS, &pa)) { 1143152970Sphilip if (errno == ENODEV) { 1144152970Sphilip syslog(LOG_INFO, "No ALTQ support in kernel\n" 1145152970Sphilip "ALTQ related functions disabled\n"); 1146152970Sphilip return (0); 1147152970Sphilip } else 1148152970Sphilip syslog(LOG_ERR, "DIOCGETALTQS returned an error: %s", 1149152970Sphilip strerror(errno)); 1150152970Sphilip return (-1); 1151152970Sphilip } 1152152970Sphilip return (1); 1153152970Sphilip} 1154152970Sphilip 1155152970Sphilip/* 1156143611Sphilip * Implement the bsnmpd module interface 1157143611Sphilip */ 1158143611Sphilipstatic int 1159143611Sphilippf_init(struct lmodule *mod, int __unused argc, char __unused *argv[]) 1160143611Sphilip{ 1161143611Sphilip module = mod; 1162143611Sphilip 1163143611Sphilip if ((dev = open("/dev/pf", O_RDONLY)) == -1) { 1164143611Sphilip syslog(LOG_ERR, "pf_init(): open(): %s\n", 1165143611Sphilip strerror(errno)); 1166143611Sphilip return (-1); 1167143611Sphilip } 1168143611Sphilip 1169152970Sphilip if ((altq_enabled = altq_is_enabled(dev)) == -1) { 1170152970Sphilip syslog(LOG_ERR, "pf_init(): altq test failed"); 1171152970Sphilip return (-1); 1172152970Sphilip } 1173152970Sphilip 1174143611Sphilip /* Prepare internal state */ 1175143611Sphilip TAILQ_INIT(&pfi_table); 1176143611Sphilip TAILQ_INIT(&pfq_table); 1177143611Sphilip TAILQ_INIT(&pft_table); 1178143611Sphilip 1179143611Sphilip pfi_refresh(); 1180152970Sphilip if (altq_enabled) { 1181152970Sphilip pfq_refresh(); 1182152970Sphilip } 1183152970Sphilip 1184143611Sphilip pfs_refresh(); 1185143611Sphilip pft_refresh(); 1186143611Sphilip 1187143611Sphilip started = 1; 1188143611Sphilip 1189143611Sphilip return (0); 1190143611Sphilip} 1191143611Sphilip 1192143611Sphilipstatic int 1193143611Sphilippf_fini(void) 1194143611Sphilip{ 1195143611Sphilip struct pfi_entry *i1, *i2; 1196143611Sphilip struct pfq_entry *q1, *q2; 1197143611Sphilip struct pft_entry *t1, *t2; 1198143611Sphilip 1199143611Sphilip /* Empty the list of interfaces */ 1200143611Sphilip i1 = TAILQ_FIRST(&pfi_table); 1201143611Sphilip while (i1 != NULL) { 1202143611Sphilip i2 = TAILQ_NEXT(i1, link); 1203143611Sphilip free(i1); 1204143611Sphilip i1 = i2; 1205143611Sphilip } 1206143611Sphilip 1207143611Sphilip /* List of queues */ 1208143611Sphilip q1 = TAILQ_FIRST(&pfq_table); 1209143611Sphilip while (q1 != NULL) { 1210143611Sphilip q2 = TAILQ_NEXT(q1, link); 1211143611Sphilip free(q1); 1212143611Sphilip q1 = q2; 1213143611Sphilip } 1214143611Sphilip 1215143611Sphilip /* And the list of tables */ 1216143611Sphilip t1 = TAILQ_FIRST(&pft_table); 1217143611Sphilip while (t1 != NULL) { 1218143611Sphilip t2 = TAILQ_NEXT(t1, link); 1219143611Sphilip free(t1); 1220143611Sphilip t1 = t2; 1221143611Sphilip } 1222143611Sphilip 1223143611Sphilip close(dev); 1224143611Sphilip return (0); 1225143611Sphilip} 1226143611Sphilip 1227143611Sphilipstatic void 1228143611Sphilippf_dump(void) 1229143611Sphilip{ 1230143611Sphilip pfi_refresh(); 1231152970Sphilip if (altq_enabled) { 1232152970Sphilip pfq_refresh(); 1233152970Sphilip } 1234143611Sphilip pft_refresh(); 1235143611Sphilip 1236143654Sphilip syslog(LOG_ERR, "Dump: pfi_table_age = %jd", 1237143654Sphilip (intmax_t)pfi_table_age); 1238143611Sphilip syslog(LOG_ERR, "Dump: pfi_table_count = %d", 1239143611Sphilip pfi_table_count); 1240143611Sphilip 1241143654Sphilip syslog(LOG_ERR, "Dump: pfq_table_age = %jd", 1242143654Sphilip (intmax_t)pfq_table_age); 1243143611Sphilip syslog(LOG_ERR, "Dump: pfq_table_count = %d", 1244143611Sphilip pfq_table_count); 1245143611Sphilip 1246143654Sphilip syslog(LOG_ERR, "Dump: pft_table_age = %jd", 1247143654Sphilip (intmax_t)pft_table_age); 1248143611Sphilip 1249143611Sphilip syslog(LOG_ERR, "Dump: pft_table_count = %d", 1250143611Sphilip pft_table_count); 1251143611Sphilip} 1252143611Sphilip 1253143611Sphilipconst struct snmp_module config = { 1254143611Sphilip .comment = "This module implements a MIB for the pf packet filter.", 1255143611Sphilip .init = pf_init, 1256143611Sphilip .fini = pf_fini, 1257143611Sphilip .tree = pf_ctree, 1258143611Sphilip .dump = pf_dump, 1259143611Sphilip .tree_size = pf_CTREE_SIZE, 1260143611Sphilip}; 1261