1 /*
2 * mod.c
3 *
4 * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
5 *
6 * $Id: mod.c,v 1.19 2002/04/07 22:55:20 dugsong Exp $
7 */
8
9 #include "config.h"
10
11 #include <ctype.h>
12 #include <err.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 #include "argv.h"
18 #include "mod.h"
19
20 #define MAX_ARGS 128 /* XXX */
21
22 struct rule {
23 struct mod *mod;
24 void *data;
25 TAILQ_ENTRY(rule) next;
26 };
27
28 /*
29 * XXX - new modules must be registered here.
30 */
31 extern struct mod mod_delay;
32 extern struct mod mod_drop;
33 extern struct mod mod_dup;
34 extern struct mod mod_echo;
35 extern struct mod mod_ip_chaff;
36 extern struct mod mod_ip_frag;
37 extern struct mod mod_ip_opt;
38 extern struct mod mod_ip_ttl;
39 extern struct mod mod_ip_tos;
40 extern struct mod mod_order;
41 extern struct mod mod_print;
42 extern struct mod mod_tcp_chaff;
43 extern struct mod mod_tcp_opt;
44 extern struct mod mod_tcp_seg;
45
46 static struct mod *mods[] = {
47 &mod_delay,
48 &mod_drop,
49 &mod_dup,
50 &mod_echo,
51 &mod_ip_chaff,
52 &mod_ip_frag,
53 &mod_ip_opt,
54 &mod_ip_ttl,
55 &mod_ip_tos,
56 &mod_order,
57 &mod_print,
58 &mod_tcp_chaff,
59 &mod_tcp_opt,
60 &mod_tcp_seg,
61 NULL
62 };
63
64 static TAILQ_HEAD(head, rule) rules;
65
66 void
mod_usage(void)67 mod_usage(void)
68 {
69 struct mod **m;
70
71 for (m = mods; *m != NULL; m++) {
72 fprintf(stderr, " %s\n", (*m)->usage);
73 }
74 }
75
76 int
mod_open(const char * script)77 mod_open(const char *script)
78 {
79 FILE *fp;
80 struct mod **m;
81 struct rule *rule;
82 char *argv[MAX_ARGS], buf[BUFSIZ];
83 int i, argc, ret = 0;
84
85 TAILQ_INIT(&rules);
86
87 if ((fp = fopen(script, "r")) == NULL) {
88 warnx("couldn't open %s", script);
89 return (-1);
90 }
91 for (i = 1; fgets(buf, sizeof(buf), fp) != NULL; i++) {
92 if (*buf == '#' || *buf == '\r' || *buf == '\n')
93 continue;
94
95 if ((argc = argv_create(buf, MAX_ARGS, argv)) < 1) {
96 warnx("couldn't parse arguments (line %d)", i);
97 ret = -1;
98 break;
99 }
100 for (m = mods; *m != NULL; m++) {
101 if (strcasecmp((*m)->name, argv[0]) == 0)
102 break;
103 }
104 if (*m == NULL) {
105 warnx("unknown directive '%s' (line %d)", argv[0], i);
106 ret = -1;
107 break;
108 }
109 if ((rule = calloc(1, sizeof(*rule))) == NULL) {
110 warn("calloc");
111 ret = -1;
112 break;
113 }
114 rule->mod = *m;
115
116 if (rule->mod->open != NULL &&
117 (rule->data = rule->mod->open(argc, argv)) == NULL) {
118 warnx("invalid argument to directive '%s' (line %d)",
119 rule->mod->name, i);
120 ret = -1;
121 break;
122 }
123 TAILQ_INSERT_TAIL(&rules, rule, next);
124 }
125 fclose(fp);
126
127 if (ret == 0) {
128 buf[0] = '\0';
129 TAILQ_FOREACH(rule, &rules, next) {
130 strlcat(buf, rule->mod->name, sizeof(buf));
131 strlcat(buf, " -> ", sizeof(buf));
132 }
133 buf[strlen(buf) - 4] = '\0';
134 warnx("%s", buf);
135 }
136 return (ret);
137 }
138
139 void
mod_apply(struct pktq * pktq)140 mod_apply(struct pktq *pktq)
141 {
142 struct rule *rule;
143
144 TAILQ_FOREACH(rule, &rules, next) {
145 rule->mod->apply(rule->data, pktq);
146 }
147 }
148
149 void
mod_close(void)150 mod_close(void)
151 {
152 struct rule *rule;
153
154 TAILQ_FOREACH_REVERSE(rule, &rules, head, next) {
155 if (rule->mod->close != NULL)
156 rule->data = rule->mod->close(rule->data);
157 TAILQ_REMOVE(&rules, rule, next);
158 free(rule);
159 }
160 }
161