1 |
|
|
/* $OpenBSD: irr_output.c,v 1.20 2015/11/18 16:47:04 mmcc Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org> |
5 |
|
|
* |
6 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
7 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
8 |
|
|
* copyright notice and this permission notice appear in all copies. |
9 |
|
|
* |
10 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN |
15 |
|
|
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
16 |
|
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 |
|
|
*/ |
18 |
|
|
|
19 |
|
|
#include <sys/types.h> |
20 |
|
|
#include <sys/stat.h> |
21 |
|
|
#include <err.h> |
22 |
|
|
#include <stdio.h> |
23 |
|
|
#include <stdlib.h> |
24 |
|
|
#include <string.h> |
25 |
|
|
#include <unistd.h> |
26 |
|
|
#include <fcntl.h> |
27 |
|
|
#include <ctype.h> |
28 |
|
|
#include <netdb.h> |
29 |
|
|
#include <netinet/in.h> |
30 |
|
|
#include <arpa/inet.h> |
31 |
|
|
|
32 |
|
|
#include "bgpd.h" |
33 |
|
|
#include "irrfilter.h" |
34 |
|
|
|
35 |
|
|
int process_policies(FILE *, struct policy_head *); |
36 |
|
|
void policy_prettyprint(FILE *, struct policy_item *); |
37 |
|
|
void policy_torule(FILE *, struct policy_item *); |
38 |
|
|
char *action_torule(char *); |
39 |
|
|
void print_rule(FILE *, struct policy_item *, char *, struct irr_prefix *); |
40 |
|
|
|
41 |
|
|
#define allowed_in_address(x) \ |
42 |
|
|
(isalnum((unsigned char)x) || x == '.' || x == ':' || x == '-') |
43 |
|
|
|
44 |
|
|
int |
45 |
|
|
write_filters(char *outpath) |
46 |
|
|
{ |
47 |
|
|
struct router *r; |
48 |
|
|
char *fn; |
49 |
|
|
int fd, ret = 0; |
50 |
|
|
u_int i; |
51 |
|
|
FILE *fh; |
52 |
|
|
|
53 |
|
|
while ((r = TAILQ_FIRST(&router_head)) != NULL) { |
54 |
|
|
TAILQ_REMOVE(&router_head, r, entry); |
55 |
|
|
|
56 |
|
|
if (r->address != NULL && r->address[0] != '\0') { |
57 |
|
|
for (i = 0; i < strlen(r->address); i++) |
58 |
|
|
if (!allowed_in_address(r->address[i])) |
59 |
|
|
errx(1, "router address \"%s\" contains" |
60 |
|
|
" illegal character \"%c\"", |
61 |
|
|
r->address, r->address[i]); |
62 |
|
|
if (asprintf(&fn, "%s/bgpd-%s.filter", |
63 |
|
|
outpath, r->address) == -1) |
64 |
|
|
err(1, "write_filters asprintf"); |
65 |
|
|
} else |
66 |
|
|
if (asprintf(&fn, "%s/bgpd.filter", |
67 |
|
|
outpath) == -1) |
68 |
|
|
err(1, "write_filters asprintf"); |
69 |
|
|
|
70 |
|
|
fd = open(fn, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); |
71 |
|
|
if (fd == -1) |
72 |
|
|
err(1, "error opening %s", fn); |
73 |
|
|
if ((fh = fdopen(fd, "w")) == NULL) |
74 |
|
|
err(1, "fdopen %s", fn); |
75 |
|
|
|
76 |
|
|
if (process_policies(fh, &r->policy_h) == -1) |
77 |
|
|
ret = -1; |
78 |
|
|
|
79 |
|
|
fclose(fh); |
80 |
|
|
close(fd); |
81 |
|
|
free(fn); |
82 |
|
|
free(r->address); |
83 |
|
|
free(r); |
84 |
|
|
} |
85 |
|
|
|
86 |
|
|
return (ret); |
87 |
|
|
} |
88 |
|
|
|
89 |
|
|
int |
90 |
|
|
process_policies(FILE *fh, struct policy_head *head) |
91 |
|
|
{ |
92 |
|
|
struct policy_item *pi; |
93 |
|
|
|
94 |
|
|
while ((pi = TAILQ_FIRST(head)) != NULL) { |
95 |
|
|
TAILQ_REMOVE(head, pi, entry); |
96 |
|
|
|
97 |
|
|
policy_prettyprint(fh, pi); |
98 |
|
|
policy_torule(fh, pi); |
99 |
|
|
fflush(fh); |
100 |
|
|
|
101 |
|
|
free(pi->peer_addr); |
102 |
|
|
free(pi->action); |
103 |
|
|
free(pi->filter); |
104 |
|
|
free(pi); |
105 |
|
|
} |
106 |
|
|
|
107 |
|
|
return (0); |
108 |
|
|
} |
109 |
|
|
|
110 |
|
|
void |
111 |
|
|
policy_prettyprint(FILE *fh, struct policy_item *pi) |
112 |
|
|
{ |
113 |
|
|
if (pi->dir == IMPORT) |
114 |
|
|
fprintf(fh, "# import: from "); |
115 |
|
|
else |
116 |
|
|
fprintf(fh, "# export: to "); |
117 |
|
|
fprintf(fh, "AS%u ", pi->peer_as); |
118 |
|
|
if (pi->peer_addr) |
119 |
|
|
fprintf(fh, "%s ", pi->peer_addr); |
120 |
|
|
if (pi->action) |
121 |
|
|
fprintf(fh, "action %s ", pi->action); |
122 |
|
|
fprintf(fh, "%s %s\n", pi->dir == IMPORT ? "accept" : "announce", |
123 |
|
|
pi->filter); |
124 |
|
|
} |
125 |
|
|
|
126 |
|
|
void |
127 |
|
|
policy_torule(FILE *fh, struct policy_item *pi) |
128 |
|
|
{ |
129 |
|
|
struct as_set *ass; |
130 |
|
|
struct prefix_set *pfxs; |
131 |
|
|
char *srcas; |
132 |
|
|
u_int i, j; |
133 |
|
|
|
134 |
|
|
if (pi->filter == NULL || !strcasecmp(pi->filter, "any")) |
135 |
|
|
print_rule(fh, pi, NULL, NULL); |
136 |
|
|
else { |
137 |
|
|
ass = asset_expand(pi->filter); |
138 |
|
|
|
139 |
|
|
for (i = 0; i < ass->n_as; i++) { |
140 |
|
|
pfxs = prefixset_get(ass->as[i]); |
141 |
|
|
|
142 |
|
|
/* ass->as[i] format and len have been checked before */ |
143 |
|
|
if (strlen(ass->as[i]) < 3) |
144 |
|
|
errx(1, "%s not AS...", ass->as[i]); |
145 |
|
|
srcas = ass->as[i] + 2; |
146 |
|
|
for (j = 0; j < pfxs->prefixcnt; j++) |
147 |
|
|
print_rule(fh, pi, srcas, pfxs->prefix[j]); |
148 |
|
|
} |
149 |
|
|
} |
150 |
|
|
} |
151 |
|
|
|
152 |
|
|
/* XXX should really be parsed earlier! */ |
153 |
|
|
char * |
154 |
|
|
action_torule(char *s) |
155 |
|
|
{ |
156 |
|
|
int cnt = 0; |
157 |
|
|
char *key, *val, *pre, *tmp; |
158 |
|
|
static char abuf[8192]; |
159 |
|
|
char ebuf[2048]; |
160 |
|
|
|
161 |
|
|
if ((tmp = strdup(s)) == NULL) |
162 |
|
|
err(1, NULL); |
163 |
|
|
abuf[0] = '\0'; |
164 |
|
|
while ((val = strsep(&tmp, ";")) != NULL && *val) { |
165 |
|
|
key = strsep(&val, "="); |
166 |
|
|
if (key == NULL || val == NULL) |
167 |
|
|
err(1, "format error in action spec\n"); |
168 |
|
|
|
169 |
|
|
EATWS(key); |
170 |
|
|
EATWS(val); |
171 |
|
|
|
172 |
|
|
if (cnt++ == 0) |
173 |
|
|
pre = " set {"; |
174 |
|
|
else |
175 |
|
|
pre = ","; |
176 |
|
|
|
177 |
|
|
if (!strcmp(key, "pref")) |
178 |
|
|
snprintf(ebuf, sizeof(ebuf), |
179 |
|
|
"%s localpref %s", pre, val); |
180 |
|
|
else if (!strcmp(key, "med")) |
181 |
|
|
snprintf(ebuf, sizeof(ebuf), |
182 |
|
|
"%s med %s", pre, val); |
183 |
|
|
else |
184 |
|
|
warnx("unknown action key \"%s\"", key); |
185 |
|
|
|
186 |
|
|
strlcat(abuf, ebuf, sizeof(abuf)); |
187 |
|
|
} |
188 |
|
|
if (cnt > 0) |
189 |
|
|
strlcat(abuf, " }", sizeof(abuf)); |
190 |
|
|
|
191 |
|
|
free(tmp); |
192 |
|
|
return (abuf); |
193 |
|
|
} |
194 |
|
|
|
195 |
|
|
void |
196 |
|
|
print_rule(FILE *fh, struct policy_item *pi, char *sourceas, |
197 |
|
|
struct irr_prefix *prefix) |
198 |
|
|
{ |
199 |
|
|
char peer[PEER_DESCR_LEN]; |
200 |
|
|
char *action = ""; |
201 |
|
|
char *dir; |
202 |
|
|
char *srcas[2] = { "", "" }; |
203 |
|
|
char pbuf[8 + NI_MAXHOST + 4 + 14 + 3]; |
204 |
|
|
size_t offset; |
205 |
|
|
|
206 |
|
|
if (pi->dir == IMPORT) |
207 |
|
|
dir = "from"; |
208 |
|
|
else |
209 |
|
|
dir = "to"; |
210 |
|
|
|
211 |
|
|
if (pi->peer_addr) |
212 |
|
|
snprintf(peer, PEER_DESCR_LEN, "%s", pi->peer_addr); |
213 |
|
|
else |
214 |
|
|
snprintf(peer, PEER_DESCR_LEN, "AS %s", log_as(pi->peer_as)); |
215 |
|
|
|
216 |
|
|
if (pi->action) |
217 |
|
|
action = action_torule(pi->action); |
218 |
|
|
|
219 |
|
|
pbuf[0] = '\0'; |
220 |
|
|
if (prefix != NULL) { |
221 |
|
|
strlcpy(pbuf, " prefix ", sizeof(pbuf)); |
222 |
|
|
offset = strlen(pbuf); |
223 |
|
|
if (inet_ntop(prefix->af, &prefix->addr, pbuf + offset, |
224 |
|
|
sizeof(pbuf) - offset) == NULL) |
225 |
|
|
err(1, "print_rule inet_ntop"); |
226 |
|
|
offset = strlen(pbuf); |
227 |
|
|
if (snprintf(pbuf + offset, sizeof(pbuf) - offset, |
228 |
|
|
"/%u", prefix->len) == -1) |
229 |
|
|
err(1, "print_rule snprintf"); |
230 |
|
|
|
231 |
|
|
if (prefix->maxlen > prefix->len) { |
232 |
|
|
offset = strlen(pbuf); |
233 |
|
|
if (snprintf(pbuf + offset, sizeof(pbuf) - offset, |
234 |
|
|
" prefixlen <= %u", prefix->maxlen) == -1) |
235 |
|
|
err(1, "print_rule snprintf"); |
236 |
|
|
} |
237 |
|
|
|
238 |
|
|
if (pi->dir == IMPORT) { |
239 |
|
|
srcas[0] = " source-as "; |
240 |
|
|
srcas[1] = sourceas; |
241 |
|
|
} |
242 |
|
|
} |
243 |
|
|
|
244 |
|
|
fprintf(fh, "allow quick %s %s%s%s%s%s\n", dir, peer, |
245 |
|
|
srcas[0], srcas[1], pbuf, action); |
246 |
|
|
} |