[Flow-tools] flexible and simple flow filter for flow-tools utilites
mitrohin a.s.
swp at swp.pp.ru
Tue Jun 10 11:19:00 EDT 2008
I rewrite flow-merge.c to extend it with easy flow filter (switch -f).
Filter have flexible and simple syntax:
start : sp
| sp cond sp
;
cond : expr
| cond spaces expr
| cond sp '|' '|' sp expr
;
expr : 'p' 'r' 'o' 't' 'o' spaces protos
| 'i' 'p' spaces ipnets
| 's' 'r' 'c' '-' 'i' 'p' spaces ipnets
| 'd' 's' 't' '-' 'i' 'p' spaces ipnets
| 'p' 'o' 'r' 't' spaces ports
| 's' 'r' 'c' '-' 'p' 'o' 'r' 't' spaces ports
| 'd' 's' 't' '-' 'p' 'o' 'r' 't' spaces ports
| '!' sp expr
| '(' sp cond sp ')'
;
protos : proto
| '{' sp listprotos sp '}'
;
listprotos : proto
| listprotos sp ',' sp proto
;
proto : 'i' 'p'
| 'i' 'c' 'm' 'p'
| 't' 'c' 'p'
| 'u' 'd' 'p'
| 'i' 'p' 'e' 'n' 'c' 'a' 'p'
| 'g' 'r' 'e'
| '*'
| number
| '!' proto
;
ipnets : ipnet
| '{' sp listipnets sp '}'
;
listipnets : ipnet
| listipnets sp ',' sp ipnet
;
ipnet : ipaddr
| ipaddr '/' netbits
| ipaddr '/' netmask
| '*'
| '!' ipnet
;
ports : port
| '{' sp listports sp '}'
;
listports : port
| listports sp ',' sp port
;
port : number
| '*'
| '!' port
;
netbits : number
;
netmask : byte '.' byte '.' byte '.' byte
;
ipaddr : byte '.' byte '.' byte '.' byte
;
byte : number
;
number : DIGIT
| number DIGIT
;
sp :
| spaces
;
spaces : SP
| spaces SP
;
filter exmple:
1. src-ip 10.1.1.1 dst-ip {!10.1.1.1,10.0.0.0/8} proto {tcp,udp}
2. src-ip !10.1.1.0/24 (src-port {10,11,12} || dst-port 5)
3. ! src-ip 10.1.1.1
4. src-ip !10.1.1.1
5. src-ip !{10.1.1.1,10.1.1.2}
6. src-ip {!10.1.1.1,10.1.1.2}
7. ! src-ip ! {!10.1.1.1}
8. proto *
flow-merge2 example:
flow-merge2 -f 'src-ip 10.1.1.1 ! dst-ip { 10.0.0.0/8 }' /var/db/flows
I want to contribute this code to flow-tools. Please.
/swp
-------------- next part --------------
A non-text attachment was scrubbed...
Name: flow-merge2.c
Type: text/x-csrc
Size: 13228 bytes
Desc: not available
Url : http://mailman.splintered.net/pipermail/flow-tools/attachments/20080610/4802020b/flow-merge2-0001.bin
-------------- next part --------------
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <err.h>
#define ELOG(fmt, args...) warnx(fmt, ##args)
#define WLOG(fmt, args...) warnx(fmt, ##args)
#include "ippf.h"
enum action
{ ALLOW = 1, DENY = 0 };
enum ltype
{ LTYPE_PROTO, LTYPE_IPNET, LTYPE_PORT };
struct proto {
enum action act;
int proto;
};
struct ipnet {
enum action act;
in_addr_t addr;
in_addr_t mask;
};
struct port {
enum action act;
int port;
};
struct node {
int n;
union {
enum action act;
struct proto proto;
struct ipnet ipnet;
struct port port;
} ar[0x10];
STAILQ_ENTRY(node) ent;
};
STAILQ_HEAD(list, node);
static
int
list_add(struct list *list, enum ltype ltype, ...)
{
struct node *p;
va_list ap;
p = STAILQ_LAST(list, node, ent);
if (!p || p->n == sizeof p->ar / sizeof p->ar[0]) {
p = malloc(sizeof *p);
if (!p)
return 1;
p->n = 0;
STAILQ_INSERT_TAIL(list, p, ent);
}
va_start(ap, ltype);
if (ltype == LTYPE_PROTO)
p->ar[p->n].proto = *va_arg(ap, typeof(p->ar[0].proto) *);
else if (ltype == LTYPE_IPNET)
p->ar[p->n].ipnet = *va_arg(ap, typeof(p->ar[0].ipnet) *);
else /* if (ltype == LTYPE_PORT) */
p->ar[p->n].port = *va_arg(ap, typeof(p->ar[0].port) *);
va_end(ap);
p->n++;
return 0;
}
static
void
list_clear(struct list *list)
{
struct node *p, *q;
for (p = STAILQ_FIRST(list); p; p = q) {
q = STAILQ_NEXT(p, ent);
free(p);
}
STAILQ_INIT(list);
}
enum exprtype {
EXPR_NONE,
EXPR_PROTO,
EXPR_IP,
EXPR_SRCIP,
EXPR_DSTIP,
EXPR_PORT,
EXPR_SRCPORT,
EXPR_DSTPORT,
EXPR_NOT,
EXPR_OR,
EXPR_AND
};
struct expr_proto {
enum exprtype type;
struct list list[1];
};
struct expr_ip {
enum exprtype type;
struct list list[1];
};
struct expr_srcip {
enum exprtype type;
struct list list[1];
};
struct expr_dstip {
enum exprtype type;
struct list list[1];
};
struct expr_port {
enum exprtype type;
struct list list[1];
};
struct expr_srcport {
enum exprtype type;
struct list list[1];
};
struct expr_dstport {
enum exprtype type;
struct list list[1];
};
struct expr_not {
enum exprtype type;
union expr * op;
};
struct expr_or {
enum exprtype type;
union expr * op[2];
};
struct expr_and {
enum exprtype type;
union expr * op[2];
};
union expr {
enum exprtype type;
struct expr_proto expr_proto;
struct expr_ip expr_ip;
struct expr_srcip expr_srcip;
struct expr_dstip expr_dstip;
struct expr_port expr_port;
struct expr_srcport expr_srcport;
struct expr_dstport expr_dstport;
struct expr_not expr_not;
struct expr_or expr_or;
struct expr_and expr_and;
};
static
void
expr_clear(union expr *expr)
{
if (expr->type == EXPR_PROTO)
list_clear(expr->expr_proto.list);
else if (expr->type == EXPR_IP)
list_clear(expr->expr_ip.list);
else if (expr->type == EXPR_SRCIP)
list_clear(expr->expr_srcip.list);
else if (expr->type == EXPR_DSTIP)
list_clear(expr->expr_dstip.list);
else if (expr->type == EXPR_PORT)
list_clear(expr->expr_port.list);
else if (expr->type == EXPR_SRCPORT)
list_clear(expr->expr_srcport.list);
else if (expr->type == EXPR_DSTPORT)
list_clear(expr->expr_dstport.list);
else if (expr->type == EXPR_NOT) {
expr_clear(expr->expr_not.op);
free(expr->expr_not.op);
} else if (expr->type == EXPR_OR) {
expr_clear(expr->expr_or.op[0]);
free(expr->expr_or.op[0]);
expr_clear(expr->expr_or.op[1]);
free(expr->expr_or.op[1]);
} else if (expr->type == EXPR_AND) {
expr_clear(expr->expr_and.op[0]);
free(expr->expr_and.op[0]);
expr_clear(expr->expr_and.op[1]);
free(expr->expr_and.op[1]);
} else if (expr->type == EXPR_NONE)
WLOG("expr_clear(): EXPR_NONE: ???");
else
WLOG("expr_clear(): %d: unknown enum exprtype", expr->type);
expr->type = EXPR_NONE;
}
static
void
expr_destroy(union expr *expr)
{
if (expr) {
expr_clear(expr);
free(expr);
}
}
static
int
expr_calc(union expr *expr, int proto, in_addr_t srcip, int srcport, in_addr_t dstip, int dstport)
{
int rc;
struct node *p;
int i;
rc = DENY;
if (!expr)
rc = ALLOW;
else if (expr->type == EXPR_PROTO) {
STAILQ_FOREACH(p, expr->expr_proto.list, ent)
for (i = 0; i < p->n; i++)
if (!p->ar[i].proto.proto || p->ar[i].proto.proto == proto) {
rc = p->ar[i].act;
goto L1;
}
} else if (expr->type == EXPR_IP) {
STAILQ_FOREACH(p, expr->expr_ip.list, ent)
for (i = 0; i < p->n; i++)
if (p->ar[i].ipnet.addr == (srcip & p->ar[i].ipnet.mask) ||
p->ar[i].ipnet.addr == (dstip & p->ar[i].ipnet.mask)) {
rc = p->ar[i].act;
goto L1;
}
} else if (expr->type == EXPR_SRCIP) {
STAILQ_FOREACH(p, expr->expr_srcip.list, ent)
for (i = 0; i < p->n; i++)
if (p->ar[i].ipnet.addr == (srcip & p->ar[i].ipnet.mask)) {
rc = p->ar[i].act;
goto L1;
}
} else if (expr->type == EXPR_DSTIP) {
STAILQ_FOREACH(p, expr->expr_dstip.list, ent)
for (i = 0; i < p->n; i++)
if (p->ar[i].ipnet.addr == (dstip & p->ar[i].ipnet.mask)) {
rc = p->ar[i].act;
goto L1;
}
} else if (expr->type == EXPR_PORT) {
STAILQ_FOREACH(p, expr->expr_port.list, ent)
for (i = 0; i < p->n; i++)
if (p->ar[i].port.port == 0
|| p->ar[i].port.port == srcport
|| p->ar[i].port.port == dstport) {
rc = p->ar[i].act;
goto L1;
}
} else if (expr->type == EXPR_SRCPORT) {
STAILQ_FOREACH(p, expr->expr_srcport.list, ent)
for (i = 0; i < p->n; i++)
if (p->ar[i].port.port == 0 || p->ar[i].port.port == srcport) {
rc = p->ar[i].act;
goto L1;
}
} else if (expr->type == EXPR_DSTPORT) {
STAILQ_FOREACH(p, expr->expr_dstport.list, ent)
for (i = 0; i < p->n; i++)
if (p->ar[i].port.port == 0 || p->ar[i].port.port == dstport) {
rc = p->ar[i].act;
goto L1;
}
} else if (expr->type == EXPR_NOT)
rc = !expr_calc(expr->expr_not.op, proto, srcip, srcport, dstip, dstport);
else if (expr->type == EXPR_OR)
rc = expr_calc(expr->expr_or.op[0], proto, srcip, srcport, dstip, dstport) ||
expr_calc(expr->expr_or.op[1], proto, srcip, srcport, dstip, dstport);
else if (expr->type == EXPR_AND)
rc = expr_calc(expr->expr_and.op[0], proto, srcip, srcport, dstip, dstport) &&
expr_calc(expr->expr_and.op[1], proto, srcip, srcport, dstip, dstport);
L1:
return rc;
}
%}
%union {
union expr * expr_p;
struct list list;
struct proto proto;
struct ipnet ipnet;
struct port port;
in_addr_t ipaddr;
int d;
}
%type <expr_p> cond
%type <expr_p> expr
%type <list> protos
%type <list> listprotos
%type <list> ipnets
%type <list> listipnets
%type <list> ports
%type <list> listports
%type <proto> proto
%type <ipnet> ipnet
%type <port> port
%type <ipaddr> ipaddr
%type <d> netbits
%type <d> netmask
%type <d> byte
%type <d> number
%token <d> DIGIT
%token SP
%destructor { expr_destroy($$); } expr cond
%destructor { list_clear(&$$); } listports ports listipnets ipnets listprotos protos
%pure-parser
%locations
%parse-param { FILE *fp }
%parse-param { union expr **expr }
%lex-param { FILE *fp }
%error-verbose
%initial-action
{
}
%{
static int yyparse(FILE *fp, union expr **expr);
static int yyerror(YYLTYPE *llocp, FILE *fp, union expr **expr, char const *msg);
static int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, FILE *fp);
%}
%%
start : sp
{
*expr = 0;
}
| sp cond sp
{
*expr = $2;
$2 = 0;
}
;
cond : expr
{
$$ = $1;
$1 = 0;
}
| cond spaces expr
{
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_and",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_AND;
$$->expr_and.op[0] = $1;
$1 = 0;
$$->expr_and.op[1] = $3;
$3 = 0;
}
| cond sp '|' '|' sp expr
{
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_and",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_OR;
$$->expr_or.op[0] = $1;
$1 = 0;
$$->expr_or.op[1] = $6;
$6 = 0;
}
;
expr : 'p' 'r' 'o' 't' 'o' spaces protos
{
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_proto",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_PROTO;
STAILQ_INIT($$->expr_proto.list);
STAILQ_CONCAT($$->expr_proto.list, &$7);
STAILQ_INIT(&$7);
}
| 'i' 'p' spaces ipnets
{
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_ip",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_IP;
STAILQ_INIT($$->expr_ip.list);
STAILQ_CONCAT($$->expr_ip.list, &$4);
STAILQ_INIT(&$4);
}
| 's' 'r' 'c' '-' 'i' 'p' spaces ipnets
{
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_srcip",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_SRCIP;
STAILQ_INIT($$->expr_srcip.list);
STAILQ_CONCAT($$->expr_srcip.list, &$8);
STAILQ_INIT(&$8);
}
| 'd' 's' 't' '-' 'i' 'p' spaces ipnets
{
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_dstip",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_DSTIP;
STAILQ_INIT($$->expr_dstip.list);
STAILQ_CONCAT($$->expr_dstip.list, &$8);
STAILQ_INIT(&$8);
}
| 'p' 'o' 'r' 't' spaces ports
{
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_srcport",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_PORT;
STAILQ_INIT($$->expr_srcport.list);
STAILQ_CONCAT($$->expr_srcport.list, &$6);
STAILQ_INIT(&$6);
}
| 's' 'r' 'c' '-' 'p' 'o' 'r' 't' spaces ports
{
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_srcport",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_SRCPORT;
STAILQ_INIT($$->expr_srcport.list);
STAILQ_CONCAT($$->expr_srcport.list, &$10);
STAILQ_INIT(&$10);
}
| 'd' 's' 't' '-' 'p' 'o' 'r' 't' spaces ports
{
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_dstport",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_DSTPORT;
STAILQ_INIT($$->expr_dstport.list);
STAILQ_CONCAT($$->expr_dstport.list, &$10);
STAILQ_INIT(&$10);
}
| '!' sp expr
{
if ($3->type == EXPR_NOT) {
$$ = $3->expr_not.op;
free($3);
} else {
if (!($$ = malloc(sizeof *$$))) {
ELOG("(l%d,c%d): unable create expr_not",
@$.first_line, @$.first_column);
YYABORT;
}
$$->type = EXPR_NOT;
$$->expr_not.op = $3;
$3 = 0;
}
}
| '(' sp cond sp ')'
{
$$ = $3;
$3 = 0;
}
;
protos : proto
{
STAILQ_INIT(&$$);
if (list_add(&$$, LTYPE_PORT, &$1)) {
ELOG("(l%d,c%d): %d: unable insert proto in list",
@$.first_line, @$.first_column, $1.proto);
YYABORT;
}
}
| '{' sp listprotos sp '}'
{
STAILQ_INIT(&$$);
STAILQ_CONCAT(&$$, &$3);
STAILQ_INIT(&$3);
}
;
listprotos : proto
{
STAILQ_INIT(&$$);
if (list_add(&$$, LTYPE_PORT, &$1)) {
ELOG("(l%d,c%d): %d: unable insert proto in list",
@$.first_line, @$.first_column, $1.proto);
YYABORT;
}
}
| listprotos sp ',' sp proto
{
STAILQ_INIT(&$$);
if (list_add(&$1, LTYPE_PORT, &$5)) {
ELOG("(l%d,c%d): %d: unable insert proto in list",
@$.first_line, @$.first_column, $5.proto);
YYABORT;
}
STAILQ_CONCAT(&$$, &$1);
STAILQ_INIT(&$1);
}
;
proto : 'i' 'p'
{
struct protoent *p;
if (!(p = getprotobyname("ip"))) {
ELOG("(l%d,c%d): getprotobyname(\"ip\"): not found\n",
@$.first_line, @$.first_column);
YYABORT;
}
$$.proto = p->p_proto;
$$.act = ALLOW;
}
| 'i' 'c' 'm' 'p'
{
struct protoent *p;
if (!(p = getprotobyname("icmp"))) {
ELOG("(l%d,c%d): getprotobyname(\"icmp\"): not found\n",
@$.first_line, @$.first_column);
YYABORT;
}
$$.proto = p->p_proto;
$$.act = ALLOW;
}
| 't' 'c' 'p'
{
struct protoent *p;
if (!(p = getprotobyname("tcp"))) {
ELOG("(l%d,c%d): getprotobyname(\"tcp\"): not found\n",
@$.first_line, @$.first_column);
YYABORT;
}
$$.proto = p->p_proto;
$$.act = ALLOW;
}
| 'u' 'd' 'p'
{
struct protoent *p;
if (!(p = getprotobyname("udp"))) {
ELOG("(l%d,c%d): getprotobyname(\"udp\"): not found\n",
@$.first_line, @$.first_column);
YYABORT;
}
$$.proto = p->p_proto;
$$.act = ALLOW;
}
| 'i' 'p' 'e' 'n' 'c' 'a' 'p'
{
struct protoent *p;
if (!(p = getprotobyname("ipencap"))) {
ELOG("(l%d,c%d): getprotobyname(\"ipencap\"): not found\n",
@$.first_line, @$.first_column);
YYABORT;
}
$$.proto = p->p_proto;
$$.act = ALLOW;
}
| 'g' 'r' 'e'
{
struct protoent *p;
if (!(p = getprotobyname("gre"))) {
ELOG("(l%d,c%d): getprotobyname(\"gre\"): not found\n",
@$.first_line, @$.first_column);
YYABORT;
}
$$.proto = p->p_proto;
$$.act = ALLOW;
}
| '*'
{
struct protoent *p;
if (!(p = getprotobyname("ip"))) {
ELOG("(l%d,c%d): getprotobyname(\"ip\"): not found\n",
@$.first_line, @$.first_column);
YYABORT;
}
$$.proto = p->p_proto;
$$.act = ALLOW;
}
| number
{
$$.proto = $1;
$$.act = ALLOW;
}
| '!' proto
{
$$.proto = $2.proto;
$$.act = !$2.act;
}
;
ipnets : ipnet
{
STAILQ_INIT(&$$);
if (list_add(&$$, LTYPE_IPNET, &$1)) {
in_addr_t addr = htonl($1.addr);
in_addr_t mask = htonl($1.mask);
char addrbuf[0x10], maskbuf[0x10];
ELOG("(l%d,c%d): %s/%s: unable insert ipnetwork in list",
@$.first_line, @$.first_column,
inet_ntop(AF_INET, &addr, addrbuf, sizeof addrbuf),
inet_ntop(AF_INET, &mask, maskbuf, sizeof maskbuf));
YYABORT;
}
}
| '{' sp listipnets sp '}'
{
STAILQ_INIT(&$$);
STAILQ_CONCAT(&$$, &$3);
STAILQ_INIT(&$3);
}
;
listipnets : ipnet
{
STAILQ_INIT(&$$);
if (list_add(&$$, LTYPE_IPNET, &$1)) {
in_addr_t addr = htonl($1.addr);
in_addr_t mask = htonl($1.mask);
char addrbuf[0x10], maskbuf[0x10];
ELOG("(l%d,c%d): %s/%s: unable insert ipnetwork in list",
@$.first_line, @$.first_column,
inet_ntop(AF_INET, &addr, addrbuf, sizeof addrbuf),
inet_ntop(AF_INET, &mask, maskbuf, sizeof maskbuf));
YYABORT;
}
}
| listipnets sp ',' sp ipnet
{
STAILQ_INIT(&$$);
if (list_add(&$1, LTYPE_IPNET, &$5)) {
in_addr_t addr = htonl($5.addr);
in_addr_t mask = htonl($5.mask);
char addrbuf[0x10], maskbuf[0x10];
ELOG("(l%d,c%d): %s/%s: unable insert ipnetwork in list",
@$.first_line, @$.first_column,
inet_ntop(AF_INET, &addr, addrbuf, sizeof addrbuf),
inet_ntop(AF_INET, &mask, maskbuf, sizeof maskbuf));
YYABORT;
}
STAILQ_CONCAT(&$$, &$1);
STAILQ_INIT(&$1);
}
;
ipnet : ipaddr
{
$$.addr = $1;
$$.mask = -1;
$$.act = ALLOW;
}
| ipaddr '/' netbits
{
$$.addr = $1;
$$.mask = $3 ? -1<<(32-$3) : 0;
$$.act = ALLOW;
}
| ipaddr '/' netmask
{
$$.addr = $1;
$$.mask = $3;
$$.act = ALLOW;
}
| '*'
{
$$.addr = 0;
$$.mask = 0;
$$.act = ALLOW;
}
| '!' ipnet
{
$$.addr = $2.addr;
$$.mask = $2.mask;
$$.act = !$2.act;
}
;
ports : port
{
STAILQ_INIT(&$$);
if (list_add(&$$, LTYPE_PORT, &$1)) {
ELOG("(l%d,c%d): %d: unable insert port in list",
@$.first_line, @$.first_column, $1.port);
YYABORT;
}
}
| '{' sp listports sp '}'
{
STAILQ_INIT(&$$);
STAILQ_CONCAT(&$$, &$3);
STAILQ_INIT(&$3);
}
;
listports : port
{
STAILQ_INIT(&$$);
if (list_add(&$$, LTYPE_PORT, &$1)) {
ELOG("(l%d,c%d): %d: unable insert port in list",
@$.first_line, @$.first_column, $1.port);
YYABORT;
}
}
| listports sp ',' sp port
{
STAILQ_INIT(&$$);
if (list_add(&$1, LTYPE_PORT, &$5)) {
ELOG("(l%d,c%d): %d: unable insert port in list",
@$.first_line, @$.first_column, $5.port);
YYABORT;
}
STAILQ_CONCAT(&$$, &$1);
STAILQ_INIT(&$1);
}
;
port : number
{
if ($1 > 65535) {
ELOG("(l%d,c%d): %d: wrong port number",
@$.first_line, @$.first_column, $1);
YYABORT;
}
$$.port = $1;
$$.act = ALLOW;
}
| '*'
{
$$.port = 0;
$$.act = ALLOW;
}
| '!' port
{
$$.port = $2.port;
$$.act = !$2.act;
}
;
netbits : number
{
$$ = $1;
if ($1 > 32) {
ELOG("(l%d,c%d): %d: wrong bitmask",
@$.first_line, @$.first_column, $1);
YYABORT;
}
}
;
netmask : byte '.' byte '.' byte '.' byte
{
$$ = (($7&0377)<<24) | (($5&0377)<<16) | (($3&0377)<<8) | ($1&0377);
$$ = ntohl($$);
}
;
ipaddr : byte '.' byte '.' byte '.' byte
{
$$ = (($7&0377)<<24) | (($5&0377)<<16) | (($3&0377)<<8) | ($1&0377);
$$ = ntohl($$);
}
;
byte : number
{
$$ = $1;
if ($1 > 255) {
ELOG("(l%d,c%d): %d: expect byte",
@$.first_line, @$.first_column, $1);
YYABORT;
}
}
;
number : DIGIT
{
$$ = $1;
}
| number DIGIT
{
$$ = $1 * 10 + $2;
if ($$ < $1) {
ELOG("(l%d,c%d): big number", @$.first_line, @$.first_column);
YYABORT;
}
}
;
sp :
| spaces
;
spaces : SP
| spaces SP
;
%%
int
yyerror(YYLTYPE *llocp, FILE *fp, union expr **expr, char const *msg)
{
fprintf(stderr, "ERROR(%d:%d-%d:%d): %s\n",
llocp->first_line, llocp->first_column,
llocp->last_line, llocp->last_column,
msg);
return 0;
}
int
yylex(YYSTYPE *lvalp, YYLTYPE *llocp, FILE *fp)
{
int c;
if ((c = fgetc(fp)) >= 0) {
if (c == '\n') {
llocp->first_line = ++llocp->last_line;
llocp->first_column = llocp->last_column = 0;
} else
llocp->first_column = ++llocp->last_column;
if (isspace(c)) {
c = SP;
} else if (isdigit(c)) {
lvalp->d = c - '0';
c = DIGIT;
}
}
return c;
}
struct ippf *
ippf_create(FILE *fp)
{
union expr *expr;
if (yyparse(fp, &expr)) {
expr_destroy(expr);
expr = 0;
}
return (struct ippf *)expr;
}
void
ippf_destroy(struct ippf *filt)
{
if (filt)
expr_destroy((union expr *)filt);
}
static
int
str_readfn(void *cookie, char *buf, int n)
{
int r;
r = strlcpy(buf, *(char **)cookie, n);
*(char **)cookie += r;
return r;
}
struct ippf *
ippf_create_str(char const *s)
{
struct ippf *filt;
FILE *fp;
filt = 0;
if ((fp = fropen(&s, str_readfn)) != 0) {
filt = ippf_create(fp);
fclose(fp);
}
return filt;
}
int
ippf_calc(struct ippf *filt, int proto, in_addr_t srcip, int srcport, in_addr_t dstip, int dstport)
{
return expr_calc((union expr *)filt, proto, srcip, srcport, dstip, dstport);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ippf.h
Type: text/x-chdr
Size: 350 bytes
Desc: not available
Url : http://mailman.splintered.net/pipermail/flow-tools/attachments/20080610/4802020b/ippf-0001.bin
More information about the Flow-tools
mailing list