GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bgpctl/irr_output.c Lines: 0 109 0.0 %
Date: 2017-11-07 Branches: 0 106 0.0 %

Line Branch Exec Source
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
}