GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bgpctl/irr_asset.c Lines: 0 107 0.0 %
Date: 2017-11-13 Branches: 0 263 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: irr_asset.c,v 1.11 2015/01/16 06:40:15 deraadt 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 <err.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <unistd.h>
25
#include <ctype.h>
26
27
#include "irrfilter.h"
28
29
int		 as_set_compare(struct as_set *, struct as_set *);
30
struct as_set	*as_set_find(char *);
31
32
RB_HEAD(as_set_h, as_set)	as_set_h;
33
RB_PROTOTYPE(as_set_h, as_set, entry, as_set_compare)
34
RB_GENERATE(as_set_h, as_set, entry, as_set_compare)
35
36
enum obj_type {
37
	T_UNKNOWN,
38
	T_ASSET,
39
	T_AUTNUM
40
};
41
42
struct as_set	*curass;
43
44
struct as_set	*asset_get(char *);
45
enum obj_type	 asset_membertype(char *);
46
void		 asset_resolve(struct as_set *);
47
int		 asset_merge(struct as_set *, struct as_set *);
48
int		 asset_add_as(struct as_set *, char *);
49
int		 asset_add_asset(struct as_set *, char *);
50
51
struct as_set *
52
asset_expand(char *s)
53
{
54
	struct as_set	*ass;
55
	char		*name;
56
	size_t		 i;
57
58
	if ((name = calloc(1, strlen(s) + 1)) == NULL)
59
		err(1, "asset_expand calloc");
60
	for (i = 0; i < strlen(s); i++)
61
		name[i] = toupper((unsigned char)s[i]);
62
63
	ass = asset_get(name);
64
	asset_resolve(ass);
65
66
	free(name);
67
	return (ass);
68
}
69
70
struct as_set *
71
asset_get(char *name)
72
{
73
	struct as_set	*ass, *mas;
74
	u_int		 i;
75
76
	/*
77
	 * the caching prevents the endless recursion.
78
	 * MUST have the RB_INSERT before calling self again.
79
	 */
80
81
	/* cached? then things are easy */
82
	if ((ass = as_set_find(name)) != NULL)
83
		return ass;
84
85
	if ((ass = calloc(1, sizeof(*ass))) == NULL)
86
		err(1, "expand_as_set calloc");
87
	if ((ass->name = strdup(name)) == NULL)
88
		err(1, "expand_as_set strdup");
89
	RB_INSERT(as_set_h, &as_set_h, ass);
90
91
	switch (asset_membertype(name)) {
92
	case T_ASSET:
93
		/* as-set */
94
		if (irrverbose >= 3) {
95
			fprintf(stdout, "query AS-SET %s... ", name);
96
			fflush(stdout);
97
		}
98
		curass = ass;
99
		if (whois(name, QTYPE_ASSET) == -1)
100
			errx(1, "whois error, asset_get %s", name);
101
		curass = NULL;
102
		if (irrverbose >= 3)
103
			fprintf(stdout, "done\n");
104
		break;
105
	case T_AUTNUM:
106
		/*
107
		 * make a dummy as-set with the AS both as name
108
		 * and its only member
109
		 */
110
		asset_add_as(ass, name);
111
		return (ass);
112
	default:
113
		fprintf(stderr, "asset_get: %s: unknown object type\n", name);
114
		break;
115
	}
116
117
118
	for (i = 0; i < ass->n_members; i++) {
119
		mas = asset_get(ass->members[i]);
120
		if (mas->n_members == 0 && mas->n_as == 0)
121
			fprintf(stderr, "%s: can't resolve member %s\n",
122
			    name, ass->members[i]);
123
		else
124
			asset_add_asset(ass, ass->members[i]);
125
	}
126
127
	return (ass);
128
}
129
130
enum obj_type
131
asset_membertype(char *name)
132
{
133
	char	*s;
134
135
	if (!strncmp(name, "AS-", 3))
136
		return (T_ASSET);
137
138
	if ((s = strchr(name, ':')) != NULL) {
139
		/* this must be an as-set. one component has to start w/ AS- */
140
		for (s = name; s != NULL; s = strchr(s, ':'))
141
			if (!strncmp(++s, "AS-", 3))
142
				return (T_ASSET);
143
		return (T_UNKNOWN);
144
	}
145
146
	/* neither plain nor hierachical set definition, might be aut-num */
147
	if (!strncmp(name, "AS", 2) && strlen(name) > 2 &&
148
	    isdigit((unsigned char)name[2]))
149
		return (T_AUTNUM);
150
151
	return (T_UNKNOWN);
152
}
153
154
void
155
asset_resolve(struct as_set *ass)
156
{
157
	struct as_set	*mas;
158
	u_int		 i;
159
160
	/*
161
	 * traverse all as_set members and fold their
162
	 * members as into this as_set.
163
	 * ass->n_as_set is a moving target, it grows
164
	 * as member as-sets' member as-sets are beeing
165
	 * added.
166
	 * remove processed member as-sets (all!) only
167
	 * after we are done, they're needed for dupe
168
	 * detection
169
	 */
170
171
	for (i = 0; i < ass->n_as_set; i++) {
172
		if ((mas = as_set_find(ass->as_set[i])) == NULL)
173
			errx(1, "asset_get %s: %s unresolved?!?",
174
			    ass->name, ass->as_set[i]);
175
		if (asset_merge(ass, mas) == -1)
176
			errx(1, "asset_merge failed");
177
	}
178
179
	for (i = 0; i < ass->n_as_set; i++) {
180
		free(ass->as_set[i]);
181
		ass->as_set[i] = NULL;
182
	}
183
	free(ass->as_set);
184
	ass->as_set = NULL;
185
	ass->n_as_set = 0;
186
}
187
188
int
189
asset_merge(struct as_set *ass, struct as_set *mas)
190
{
191
	u_int	i, j;
192
193
	/* merge ASes from the member into the parent */
194
	for (i = 0; i < mas->n_as; i++) {
195
		for (j = 0; j < ass->n_as && strcmp(ass->as[j],
196
		    mas->as[i]); j++)
197
			; /* nothing */
198
		if (j == ass->n_as)
199
			if (asset_add_as(ass, mas->as[i]) == -1)
200
				return (-1);
201
	}
202
203
	/* merge as-set members from the member into the parent */
204
	for (i = 0; i < mas->n_as_set; i++) {
205
		if (!strcmp(ass->name, mas->as_set[i]))		/* skip self! */
206
			continue;
207
		for (j = 0; j < ass->n_as_set && strcmp(ass->as_set[j],
208
		    mas->as_set[i]); j++)
209
			; /* nothing */
210
		if (j == ass->n_as_set)
211
			if (asset_add_asset(ass, mas->as_set[i]) == -1)
212
				return (-1);
213
	}
214
215
	return (0);
216
}
217
218
int
219
asset_addmember(char *s)
220
{
221
	void	*p;
222
	char	*as;
223
	size_t	 i;
224
225
	/* convert to uppercase on the fly */
226
	if ((as = calloc(1, strlen(s) + 1)) == NULL)
227
		err(1, "asset_addmember strdup");
228
	for (i = 0; i < strlen(s); i++)
229
		as[i] = toupper((unsigned char)s[i]);
230
231
	if ((p = reallocarray(curass->members,
232
	    curass->n_members + 1, sizeof(char *))) == NULL)
233
		err(1, "asset_addmember strdup");
234
	curass->members = p;
235
	curass->n_members++;
236
	curass->members[curass->n_members - 1] = as;
237
238
	return (0);
239
}
240
241
int
242
asset_add_as(struct as_set *ass, char *s)
243
{
244
	void *p;
245
246
	if ((p = reallocarray(ass->as,
247
	    ass->n_as + 1, sizeof(char *))) == NULL)
248
		err(1, "asset_add_as strdup");
249
	ass->as = p;
250
	ass->n_as++;
251
252
	if ((ass->as[ass->n_as - 1] =
253
	    strdup(s)) == NULL)
254
		err(1, "asset_add_as strdup");
255
256
	return (0);
257
}
258
259
int
260
asset_add_asset(struct as_set *ass, char *s)
261
{
262
	void *p;
263
264
	if ((p = reallocarray(ass->as_set,
265
	    ass->n_as_set + 1, sizeof(char *))) == NULL)
266
		err(1, "asset_add_asset strdup");
267
	ass->as_set = p;
268
	ass->n_as_set++;
269
270
	if ((ass->as_set[ass->n_as_set - 1] =
271
	    strdup(s)) == NULL)
272
		err(1, "asset_add_asset strdup");
273
274
	return (0);
275
}
276
277
/* RB helpers */
278
int
279
as_set_compare(struct as_set *a, struct as_set *b)
280
{
281
	return (strcmp(a->name, b->name));
282
}
283
284
struct as_set *
285
as_set_find(char *name)
286
{
287
	struct as_set	s;
288
289
	s.name = name;
290
	return (RB_FIND(as_set_h, &as_set_h, &s));
291
}