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