diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2008-09-09 13:56:40 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2008-09-09 13:56:40 +0000 |
commit | eafa0437596580a038262a0363fdd2115f6f1726 (patch) | |
tree | 508e9ede5b29e41966fa0aa869df62cbd54600a3 /sbin | |
parent | 456e9ebf40a66cc20f4da77dbd097479607938d9 (diff) |
welcome pflow(4), a netflow v5 compatible flow export interface.
flows export data gathered from pf states.
initial implementation by Joerg Goltermann <jg@osn.de>, guidance and many
changes by me. 'put it in' theo
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ifconfig/ifconfig.c | 136 | ||||
-rw-r--r-- | sbin/pfctl/parse.y | 25 | ||||
-rw-r--r-- | sbin/pfctl/pf_print_state.c | 4 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 8 |
4 files changed, 167 insertions, 6 deletions
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 03b40456482..72103b1c197 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ifconfig.c,v 1.203 2008/09/07 02:22:34 deraadt Exp $ */ +/* $OpenBSD: ifconfig.c,v 1.204 2008/09/09 13:56:38 henning Exp $ */ /* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */ /* @@ -79,6 +79,7 @@ #include <net80211/ieee80211_ioctl.h> #include <net/pfvar.h> #include <net/if_pfsync.h> +#include <net/if_pflow.h> #include <net/if_pppoe.h> #include <net/if_trunk.h> #include <net/if_sppp.h> @@ -233,6 +234,14 @@ void trunk_status(void); int main(int, char *[]); int prefix(void *val, int); +#ifndef SMALL +void pflow_status(void); +void setpflow_sender(const char *, int); +void unsetpflow_sender(const char *, int); +void setpflow_receiver(const char *, int); +void unsetpflow_receiver(const char *, int); +#endif + /* * Media stuff. Whenever a media command is first performed, the * currently select media is grabbed for this interface. If `media' @@ -395,6 +404,12 @@ const struct cmd { { "descr", NEXTARG, 0, setifdesc }, { "-description", 1, 0, unsetifdesc }, { "-descr", 1, 0, unsetifdesc }, +#ifndef SMALL + { "flowsrc", NEXTARG, 0, setpflow_sender }, + { "-flowsrc", 1, 0, unsetpflow_sender }, + { "flowdst", NEXTARG, 0, setpflow_receiver }, + { "-flowdst", 1, 0, unsetpflow_receiver }, +#endif { NULL, /*src*/ 0, 0, setifaddr }, { NULL, /*dst*/ 0, 0, setifdstaddr }, { NULL, /*illegal*/0, 0, NULL }, @@ -2592,6 +2607,7 @@ status(int link, struct sockaddr_dl *sdl) sppp_status(); trunk_status(); mpe_status(); + pflow_status(); #endif getifgroups(); @@ -3674,6 +3690,124 @@ pfsync_status(void) } } +#ifndef SMALL +void +pflow_status(void) +{ + struct pflowreq preq; + + bzero((char *)&preq, sizeof(struct pflowreq)); + ifr.ifr_data = (caddr_t)&preq; + + if (ioctl(s, SIOCGETPFLOW, (caddr_t)&ifr) == -1) + return; + + printf("\tpflow: sender: %s ", inet_ntoa(preq.sender_ip)); + printf("receiver: %s:%u\n", inet_ntoa(preq.receiver_ip), + ntohs(preq.receiver_port)); +} + +/* ARGSUSED */ +void +setpflow_sender(const char *val, int d) +{ + struct pflowreq preq; + struct addrinfo hints, *sender; + int ecode; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + + if ((ecode = getaddrinfo(val, NULL, &hints, &sender)) != 0) + errx(1, "error in parsing address string: %s", + gai_strerror(ecode)); + + if (sender->ai_addr->sa_family != AF_INET) + errx(1, "only IPv4 addresses supported for the sender"); + + bzero((char *)&preq, sizeof(struct pflowreq)); + ifr.ifr_data = (caddr_t)&preq; + preq.addrmask |= PFLOW_MASK_SRCIP; + preq.sender_ip.s_addr = ((struct sockaddr_in *) + sender->ai_addr)->sin_addr.s_addr; + + + if (ioctl(s, SIOCSETPFLOW, (caddr_t)&ifr) == -1) + err(1, "SIOCSETPFLOW"); + + freeaddrinfo(sender); +} + +void +unsetpflow_sender(const char *val, int d) +{ + struct pflowreq preq; + + bzero((char *)&preq, sizeof(struct pflowreq)); + preq.addrmask |= PFLOW_MASK_SRCIP; + ifr.ifr_data = (caddr_t)&preq; + if (ioctl(s, SIOCSETPFLOW, (caddr_t)&ifr) == -1) + err(1, "SIOCSETPFLOW"); +} + +/* ARGSUSED */ +void +setpflow_receiver(const char *val, int d) +{ + const char *errmsg = NULL; + struct pflowreq preq; + struct addrinfo hints, *receiver; + int ecode; + char *ip, *port, buf[MAXHOSTNAMELEN+sizeof (":65535")]; + + if (strchr (val, ':') == NULL) + errx(1, "%s bad value", val); + + if (strlcpy(buf, val, sizeof(buf)) >= sizeof(buf)) + errx(1, "%s bad value", val); + port = strchr(buf, ':'); + *port++ = '\0'; + ip = buf; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + + if ((ecode = getaddrinfo(ip, port, &hints, &receiver)) != 0) + errx(1, "error in parsing address string: %s", + gai_strerror(ecode)); + + if (receiver->ai_addr->sa_family != AF_INET) + errx(1, "only IPv4 addresses supported for the receiver"); + + bzero((char *)&preq, sizeof(struct pflowreq)); + ifr.ifr_data = (caddr_t)&preq; + preq.addrmask |= PFLOW_MASK_DSTIP | PFLOW_MASK_DSTPRT; + preq.receiver_ip.s_addr = ((struct sockaddr_in *) + receiver->ai_addr)->sin_addr.s_addr; + preq.receiver_port = (u_int16_t) ((struct sockaddr_in *) + receiver->ai_addr)->sin_port; + + if (ioctl(s, SIOCSETPFLOW, (caddr_t)&ifr) == -1) + err(1, "SIOCSETPFLOW"); + + freeaddrinfo(receiver); +} + +void +unsetpflow_receiver(const char *val, int d) +{ + struct pflowreq preq; + + bzero((char *)&preq, sizeof(struct pflowreq)); + ifr.ifr_data = (caddr_t)&preq; + preq.addrmask |= PFLOW_MASK_DSTIP | PFLOW_MASK_DSTPRT; + if (ioctl(s, SIOCSETPFLOW, (caddr_t)&ifr) == -1) + err(1, "SIOCSETPFLOW"); +} +#endif /* SMALL */ + void pppoe_status(void) { diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index c9ccec6f2c3..fc075f9b0ae 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.550 2008/08/07 18:29:32 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.551 2008/09/09 13:56:38 henning Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -153,7 +153,8 @@ enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK, PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN, PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES, PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK, - PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY }; + PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, + PF_STATE_OPT_PFLOW }; enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE }; @@ -442,7 +443,7 @@ int parseport(char *, struct range *r, int); %token QUEUE PRIORITY QLIMIT RTABLE %token LOAD RULESET_OPTIMIZATION %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE -%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY +%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW %token TAGGED TAG IFBOUND FLOATING STATEPOLICY ROUTE SETTOS %token DIVERTTO DIVERTREPLY %token <v.string> STRING @@ -2061,6 +2062,15 @@ pfrule : action dir logquick interface route af proto fromto } r.rule_flag |= PFRULE_STATESLOPPY; break; + case PF_STATE_OPT_PFLOW: + if (r.rule_flag & PFRULE_PFLOW) { + yyerror("state pflow " + "option: multiple " + "definitions"); + YYERROR; + } + r.rule_flag |= PFRULE_PFLOW; + break; case PF_STATE_OPT_TIMEOUT: if (o->data.timeout.number == PFTM_ADAPTIVE_START || @@ -3541,6 +3551,14 @@ state_opt_item : MAXIMUM NUMBER { $$->next = NULL; $$->tail = $$; } + | PFLOW { + $$ = calloc(1, sizeof(struct node_state_opt)); + if ($$ == NULL) + err(1, "state_opt_item: calloc"); + $$->type = PF_STATE_OPT_PFLOW; + $$->next = NULL; + $$->tail = $$; + } | STRING NUMBER { int i; @@ -5256,6 +5274,7 @@ lookup(char *s) { "out", OUT}, { "overload", OVERLOAD}, { "pass", PASS}, + { "pflow", PFLOW}, { "port", PORT}, { "priority", PRIORITY}, { "priq", PRIQ}, diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c index 73eef1199c7..b20fc941c16 100644 --- a/sbin/pfctl/pf_print_state.c +++ b/sbin/pfctl/pf_print_state.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_print_state.c,v 1.52 2008/08/12 16:40:18 david Exp $ */ +/* $OpenBSD: pf_print_state.c,v 1.53 2008/09/09 13:56:38 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -325,6 +325,8 @@ print_state(struct pfsync_state *s, int opts) printf(", rule %u", ntohl(s->rule)); if (s->state_flags & PFSTATE_SLOPPY) printf(", sloppy"); + if (s->state_flags & PFSTATE_PFLOW) + printf(", pflow"); if (s->sync_flags & PFSYNC_FLAG_SRCNODE) printf(", source-track"); if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE) diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 7368dbe7d3c..86c5f90ffeb 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.241 2008/09/09 13:56:38 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -934,6 +934,12 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose) printf("sloppy"); opts = 0; } + if (r->rule_flag & PFRULE_PFLOW) { + if (!opts) + printf(", "); + printf("pflow"); + opts = 0; + } for (i = 0; i < PFTM_MAX; ++i) if (r->timeout[i]) { int j; |