GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bgpd/name2id.c Lines: 0 54 0.0 %
Date: 2017-11-13 Branches: 0 42 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: name2id.c,v 1.9 2009/06/04 04:46:42 claudio Exp $ */
2
3
/*
4
 * Copyright (c) 2004, 2005 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/socket.h>
21
22
#include <net/route.h>
23
24
#include <errno.h>
25
#include <stdlib.h>
26
#include <string.h>
27
28
#include "bgpd.h"
29
30
#define	IDVAL_MAX	50000
31
32
struct n2id_label {
33
	TAILQ_ENTRY(n2id_label)	 entry;
34
	char			*name;
35
	u_int16_t		 id;
36
	int			 ref;
37
};
38
39
TAILQ_HEAD(n2id_labels, n2id_label);
40
41
u_int16_t	 _name2id(struct n2id_labels *, const char *);
42
const char	*_id2name(struct n2id_labels *, u_int16_t);
43
void		 _unref(struct n2id_labels *, u_int16_t);
44
void		 _ref(struct n2id_labels *, u_int16_t);
45
46
struct n2id_labels	rt_labels = TAILQ_HEAD_INITIALIZER(rt_labels);
47
struct n2id_labels	pftable_labels = TAILQ_HEAD_INITIALIZER(pftable_labels);
48
49
u_int16_t
50
rtlabel_name2id(const char *name)
51
{
52
	return (_name2id(&rt_labels, name));
53
}
54
55
const char *
56
rtlabel_id2name(u_int16_t id)
57
{
58
	return (_id2name(&rt_labels, id));
59
}
60
61
void
62
rtlabel_unref(u_int16_t id)
63
{
64
	_unref(&rt_labels, id);
65
}
66
67
void
68
rtlabel_ref(u_int16_t id)
69
{
70
	_ref(&rt_labels, id);
71
}
72
73
u_int16_t
74
pftable_name2id(const char *name)
75
{
76
	return (_name2id(&pftable_labels, name));
77
}
78
79
const char *
80
pftable_id2name(u_int16_t id)
81
{
82
	return (_id2name(&pftable_labels, id));
83
}
84
85
void
86
pftable_unref(u_int16_t id)
87
{
88
	_unref(&pftable_labels, id);
89
}
90
91
void
92
pftable_ref(u_int16_t id)
93
{
94
	_ref(&pftable_labels, id);
95
}
96
97
u_int16_t
98
_name2id(struct n2id_labels *head, const char *name)
99
{
100
	struct n2id_label	*label, *p = NULL;
101
	u_int16_t		 new_id = 1;
102
103
	if (!name[0]) {
104
		errno = EINVAL;
105
		return (0);
106
	}
107
108
	TAILQ_FOREACH(label, head, entry)
109
		if (strcmp(name, label->name) == 0) {
110
			label->ref++;
111
			return (label->id);
112
		}
113
114
	/*
115
	 * to avoid fragmentation, we do a linear search from the beginning
116
	 * and take the first free slot we find. if there is none or the list
117
	 * is empty, append a new entry at the end.
118
	 */
119
120
	if (!TAILQ_EMPTY(head))
121
		for (p = TAILQ_FIRST(head); p != NULL &&
122
		    p->id == new_id; p = TAILQ_NEXT(p, entry))
123
			new_id = p->id + 1;
124
125
	if (new_id > IDVAL_MAX) {
126
		errno = ERANGE;
127
		return (0);
128
	}
129
130
	if ((label = calloc(1, sizeof(struct n2id_label))) == NULL)
131
		return (0);
132
	if ((label->name = strdup(name)) == NULL) {
133
		free(label);
134
		return (0);
135
	}
136
	label->id = new_id;
137
	label->ref++;
138
139
	if (p != NULL)	/* insert new entry before p */
140
		TAILQ_INSERT_BEFORE(p, label, entry);
141
	else		/* either list empty or no free slot in between */
142
		TAILQ_INSERT_TAIL(head, label, entry);
143
144
	return (label->id);
145
}
146
147
const char *
148
_id2name(struct n2id_labels *head, u_int16_t id)
149
{
150
	struct n2id_label	*label;
151
152
	if (id == 0)
153
		return ("");
154
155
	TAILQ_FOREACH(label, head, entry)
156
		if (label->id == id)
157
			return (label->name);
158
159
	return ("");
160
}
161
162
void
163
_unref(struct n2id_labels *head, u_int16_t id)
164
{
165
	struct n2id_label	*p, *next;
166
167
	if (id == 0)
168
		return;
169
170
	for (p = TAILQ_FIRST(head); p != NULL; p = next) {
171
		next = TAILQ_NEXT(p, entry);
172
		if (id == p->id) {
173
			if (--p->ref == 0) {
174
				TAILQ_REMOVE(head, p, entry);
175
				free(p->name);
176
				free(p);
177
			}
178
			break;
179
		}
180
	}
181
}
182
183
void
184
_ref(struct n2id_labels *head, u_int16_t id)
185
{
186
	struct n2id_label	*label;
187
188
	if (id == 0)
189
		return;
190
191
	TAILQ_FOREACH(label, head, entry)
192
		if (label->id == id) {
193
			++label->ref;
194
			break;
195
		}
196
}