--- /dev/null
+
+
+main: y.tab.o lex.yy.o
+ cc -DYYDEBUG=stdout -o main y.tab.o lex.yy.o -ly -ll
+
+y.tab.c y.tab.h: policy_mqtt.y
+ yacc -d policy_mqtt.y
+
+y.tab.o: y.tab.c
+ cc -c y.tab.c
+
+lex.yy.o: y.tab.h lex.yy.c
+ cc -c lex.yy.c
+
+lex.yy.c: policy_mqtt.l
+ lex policy_mqtt.l
+
+clean:
+ rm -f *.o y.tab.* lex.yy.c
+
+
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+
+int main( int argc, char **argv )
+{
+ ++argv, --argc; /* skip over program name */
+ if ( argc > 0 )
+ yyin = fopen( argv[0], "r" );
+ else
+ yyin = stdin;
+
+ yyparse();
+}
+
--- /dev/null
+%{
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <net/pfkeyv2.h>
+#include <netipsec/keydb.h>
+#include <netinet/in.h>
+#include <netipsec/ipsec.h>
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "y.tab.h"
+
+%}
+
+%option noyywrap
+%option nounput
+%option noinput
+
+/* common section */
+nl \n
+ws [ \t]+
+socket [\/][a-zA-Z0-9\/]+
+topic [\"][a-zA-Z0-9/]+[\"]
+
+%%
+
+any { return(ANY); }
+drop { yylval.number=0;return (ACTION);}
+pass { yylval.number=1;return (ACTION);}
+in { yylval.number=0;return (DIR);}
+out { yylval.number=1;return (DIR);}
+{topic} { yylval.string=strdup(yytext);return WORD;}
+{socket} { yylval.string=strdup(yytext);return SOCKET;}
+"FROM" { return FROM;}
+"ANY" { return ANY;}
+
+{ws} { ; }
+{nl} { ; }
+
+%%
+
--- /dev/null
+%{
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+
+extern FILE *yyin;
+
+static size_t errors;
+enum filter_dir {
+GTW_IN,
+GTW_OUT,
+GTW_INOUT
+};
+
+#define GODROP 0
+enum filter_action {
+GTW_DROP = 0,
+GTW_PASS,
+};
+
+struct mqtt_rule {
+ char topic[128];
+ char from[128];
+ enum filter_action action;
+ enum filter_dir dir;
+ int log;
+ int quick;
+};
+
+static size_t parsed_lines;
+%}
+
+%union {
+ int64_t number;
+ char *string;
+};
+
+%token ACTION IN OUT FROM QUICK LOG SOCKET
+%token TOPIC WORD
+%token ANY FROM
+%token SLASH HYPHEN
+%token <string> WORD SOCKET
+%token <number> NUMBER
+%type <number> ACTION DIR QUICK LOG
+%type <string> from topic
+
+
+%%
+
+ruleset: /* empty */
+ |
+ ruleset mqttrule
+ ;
+
+mqttrule : ACTION DIR topic from
+ {
+ parsed_lines++;
+ struct mqtt_rule r;
+ memset(&r, 0, sizeof(r));
+ r.action = $1;
+ r.dir = $2;
+ if ($3)
+ strlcpy(r.topic, $3, sizeof r.topic);
+ if ($4)
+ strlcpy(r.from, $4, sizeof r.from);
+
+ printf("%s %s <from> %s.\n", r.action == GTW_DROP ? "Drop" : "pass", r.topic[0]!=0 ? r.topic :"*", r.from[0]!=0 ? r.from : "<all>");
+ };
+
+topic : ANY {$$=NULL;}
+ | WORD {$$=$1;}
+ ;
+
+from : /* empty */ {$$=NULL;}
+ | FROM SOCKET {$$ = $2;}
+ ;
+%%
+
+void
+yyerror(msg)
+ char *msg;
+{
+ fprintf(stderr, "while parsing \"%s\"\n",
+ msg);
+
+ return;
+}
+
+int main( int argc, char **argv )
+{
+ ++argv, --argc; /* skip over program name */
+ if ( argc > 0 )
+ yyin = fopen( argv[0], "r" );
+ else
+ yyin = stdin;
+
+ yyparse();
+ printf("\n#%zu.\n", parsed_lines);
+
+}