1 /* $OpenBSD: name2id.c,v 1.2 2007/06/19 16:45:15 reyk 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 "ospfd.h"
29
30 #define IDVAL_MAX 50000
31
32 u_int16_t _name2id(struct n2id_labels *, const char *);
33 const char *_id2name(struct n2id_labels *, u_int16_t);
34 u_int32_t _id2tag(struct n2id_labels *, u_int16_t);
35 u_int16_t _tag2id(struct n2id_labels *, u_int32_t);
36 void _tag(struct n2id_labels *, u_int16_t, u_int32_t);
37 void _unref(struct n2id_labels *, u_int16_t);
38 void _ref(struct n2id_labels *, u_int16_t);
39
40 struct n2id_labels rt_labels = TAILQ_HEAD_INITIALIZER(rt_labels);
41
42 u_int16_t
rtlabel_name2id(const char * name)43 rtlabel_name2id(const char *name)
44 {
45 return (_name2id(&rt_labels, name));
46 }
47
48 const char *
rtlabel_id2name(u_int16_t id)49 rtlabel_id2name(u_int16_t id)
50 {
51 return (_id2name(&rt_labels, id));
52 }
53
54 u_int32_t
rtlabel_id2tag(u_int16_t id)55 rtlabel_id2tag(u_int16_t id)
56 {
57 return (_id2tag(&rt_labels, id));
58 }
59
60 u_int16_t
rtlabel_tag2id(u_int32_t tag)61 rtlabel_tag2id(u_int32_t tag)
62 {
63 return (_tag2id(&rt_labels, tag));
64 }
65
66 void
rtlabel_tag(u_int16_t id,u_int32_t tag)67 rtlabel_tag(u_int16_t id, u_int32_t tag)
68 {
69 _tag(&rt_labels, id, tag);
70 }
71
72 void
rtlabel_unref(u_int16_t id)73 rtlabel_unref(u_int16_t id)
74 {
75 _unref(&rt_labels, id);
76 }
77
78 /*
79 void
80 rtlabel_ref(u_int16_t id)
81 {
82 _ref(&rt_labels, id);
83 }
84 */
85
86 u_int16_t
_name2id(struct n2id_labels * head,const char * name)87 _name2id(struct n2id_labels *head, const char *name)
88 {
89 struct n2id_label *label, *p = NULL;
90 u_int16_t new_id = 1;
91
92 if (!name[0]) {
93 errno = EINVAL;
94 return (0);
95 }
96
97 TAILQ_FOREACH(label, head, entry)
98 if (strcmp(name, label->name) == 0) {
99 label->ref++;
100 return (label->id);
101 }
102
103 /*
104 * to avoid fragmentation, we do a linear search from the beginning
105 * and take the first free slot we find. if there is none or the list
106 * is empty, append a new entry at the end.
107 */
108
109 if (!TAILQ_EMPTY(head))
110 for (p = TAILQ_FIRST(head); p != NULL &&
111 p->id == new_id; p = TAILQ_NEXT(p, entry))
112 new_id = p->id + 1;
113
114 if (new_id > IDVAL_MAX) {
115 errno = ERANGE;
116 return (0);
117 }
118
119 if ((label = calloc(1, sizeof(struct n2id_label))) == NULL)
120 return (0);
121 if ((label->name = strdup(name)) == NULL) {
122 free(label);
123 return (0);
124 }
125 label->id = new_id;
126 label->ref++;
127
128 if (p != NULL) /* insert new entry before p */
129 TAILQ_INSERT_BEFORE(p, label, entry);
130 else /* either list empty or no free slot in between */
131 TAILQ_INSERT_TAIL(head, label, entry);
132
133 return (label->id);
134 }
135
136 const char *
_id2name(struct n2id_labels * head,u_int16_t id)137 _id2name(struct n2id_labels *head, u_int16_t id)
138 {
139 struct n2id_label *label;
140
141 if (id == 0)
142 return ("");
143
144 TAILQ_FOREACH(label, head, entry)
145 if (label->id == id)
146 return (label->name);
147
148 return ("");
149 }
150
151 u_int32_t
_id2tag(struct n2id_labels * head,u_int16_t id)152 _id2tag(struct n2id_labels *head, u_int16_t id)
153 {
154 struct n2id_label *label;
155
156 if (id == 0)
157 return (0);
158
159 TAILQ_FOREACH(label, head, entry)
160 if (label->id == id)
161 return (label->ext_tag);
162
163 return (0);
164 }
165
166 u_int16_t
_tag2id(struct n2id_labels * head,u_int32_t tag)167 _tag2id(struct n2id_labels *head, u_int32_t tag)
168 {
169 struct n2id_label *label;
170
171 if (tag == 0)
172 return (0);
173
174 TAILQ_FOREACH(label, head, entry)
175 if (label->ext_tag == tag)
176 return (label->id);
177
178 return (0);
179 }
180
181 void
_tag(struct n2id_labels * head,u_int16_t id,u_int32_t tag)182 _tag(struct n2id_labels *head, u_int16_t id, u_int32_t tag)
183 {
184 struct n2id_label *label;
185
186 if (id == 0)
187 return;
188
189 TAILQ_FOREACH(label, head, entry)
190 if (label->id == id)
191 label->ext_tag = tag;
192 }
193
194 void
_unref(struct n2id_labels * head,u_int16_t id)195 _unref(struct n2id_labels *head, u_int16_t id)
196 {
197 struct n2id_label *p, *next;
198
199 if (id == 0)
200 return;
201
202 for (p = TAILQ_FIRST(head); p != NULL; p = next) {
203 next = TAILQ_NEXT(p, entry);
204 if (id == p->id) {
205 if (--p->ref == 0) {
206 TAILQ_REMOVE(head, p, entry);
207 free(p->name);
208 free(p);
209 }
210 break;
211 }
212 }
213 }
214
215 void
_ref(struct n2id_labels * head,u_int16_t id)216 _ref(struct n2id_labels *head, u_int16_t id)
217 {
218 struct n2id_label *label;
219
220 if (id == 0)
221 return;
222
223 TAILQ_FOREACH(label, head, entry)
224 if (label->id == id) {
225 ++label->ref;
226 break;
227 }
228 }
229