1*c1e33626Sjsg /* $OpenBSD: schema.c,v 1.20 2022/10/12 11:57:40 jsg Exp $ */
2a2a43363Smartinh
3a2a43363Smartinh /*
4a2a43363Smartinh * Copyright (c) 2010 Martin Hedenfalk <martinh@openbsd.org>
5a2a43363Smartinh *
6a2a43363Smartinh * Permission to use, copy, modify, and distribute this software for any
7a2a43363Smartinh * purpose with or without fee is hereby granted, provided that the above
8a2a43363Smartinh * copyright notice and this permission notice appear in all copies.
9a2a43363Smartinh *
10a2a43363Smartinh * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11a2a43363Smartinh * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12a2a43363Smartinh * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13a2a43363Smartinh * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14a2a43363Smartinh * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15a2a43363Smartinh * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16a2a43363Smartinh * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17a2a43363Smartinh */
18a2a43363Smartinh
19a2a43363Smartinh #include <sys/types.h>
20a2a43363Smartinh
21a2a43363Smartinh #include <ctype.h>
22a2a43363Smartinh #include <stdlib.h>
23a2a43363Smartinh #include <string.h>
24a2a43363Smartinh #include <syslog.h>
25a2a43363Smartinh
26a2a43363Smartinh #include "ldapd.h"
27fdd30f56Sbenno #include "log.h"
28a2a43363Smartinh
29a2a43363Smartinh #define ERROR -1
30a2a43363Smartinh #define STRING 1
31a2a43363Smartinh
32a2a43363Smartinh static int
attr_oid_cmp(struct attr_type * a,struct attr_type * b)33a2a43363Smartinh attr_oid_cmp(struct attr_type *a, struct attr_type *b)
34a2a43363Smartinh {
35a2a43363Smartinh return strcasecmp(a->oid, b->oid);
36a2a43363Smartinh }
37a2a43363Smartinh
38a2a43363Smartinh static int
obj_oid_cmp(struct object * a,struct object * b)39a2a43363Smartinh obj_oid_cmp(struct object *a, struct object *b)
40a2a43363Smartinh {
41a2a43363Smartinh return strcasecmp(a->oid, b->oid);
42a2a43363Smartinh }
43a2a43363Smartinh
44a2a43363Smartinh static int
oidname_cmp(struct oidname * a,struct oidname * b)45a2a43363Smartinh oidname_cmp(struct oidname *a, struct oidname *b)
46a2a43363Smartinh {
47a2a43363Smartinh return strcasecmp(a->on_name, b->on_name);
48a2a43363Smartinh }
49a2a43363Smartinh
50a2a43363Smartinh static int
symoid_cmp(struct symoid * a,struct symoid * b)51a2a43363Smartinh symoid_cmp(struct symoid *a, struct symoid *b)
52a2a43363Smartinh {
53a2a43363Smartinh return strcasecmp(a->name, b->name);
54a2a43363Smartinh }
55a2a43363Smartinh
56a2a43363Smartinh RB_GENERATE(attr_type_tree, attr_type, link, attr_oid_cmp);
57a2a43363Smartinh RB_GENERATE(object_tree, object, link, obj_oid_cmp);
58a2a43363Smartinh RB_GENERATE(oidname_tree, oidname, link, oidname_cmp);
59a2a43363Smartinh RB_GENERATE(symoid_tree, symoid, link, symoid_cmp);
60a2a43363Smartinh
61a2a43363Smartinh static struct attr_list *push_attr(struct attr_list *alist, struct attr_type *a);
62a2a43363Smartinh static struct obj_list *push_obj(struct obj_list *olist, struct object *obj);
6319467dd7Smartinh static struct name_list *push_name(struct name_list *nl, char *name);
64a2a43363Smartinh int is_oidstr(const char *oidstr);
65a2a43363Smartinh
66a2a43363Smartinh struct attr_type *
lookup_attribute_by_name(struct schema * schema,char * name)67a2a43363Smartinh lookup_attribute_by_name(struct schema *schema, char *name)
68a2a43363Smartinh {
69a2a43363Smartinh struct oidname *on, find;
70a2a43363Smartinh
71a2a43363Smartinh find.on_name = name;
72a2a43363Smartinh on = RB_FIND(oidname_tree, &schema->attr_names, &find);
73a2a43363Smartinh
74a2a43363Smartinh if (on)
75a2a43363Smartinh return on->on_attr_type;
76a2a43363Smartinh return NULL;
77a2a43363Smartinh }
78a2a43363Smartinh
79a2a43363Smartinh struct attr_type *
lookup_attribute_by_oid(struct schema * schema,char * oid)80a2a43363Smartinh lookup_attribute_by_oid(struct schema *schema, char *oid)
81a2a43363Smartinh {
82a2a43363Smartinh struct attr_type find;
83a2a43363Smartinh
84a2a43363Smartinh find.oid = oid;
85a2a43363Smartinh return RB_FIND(attr_type_tree, &schema->attr_types, &find);
86a2a43363Smartinh }
87a2a43363Smartinh
88a2a43363Smartinh struct attr_type *
lookup_attribute(struct schema * schema,char * oid_or_name)89a2a43363Smartinh lookup_attribute(struct schema *schema, char *oid_or_name)
90a2a43363Smartinh {
91a2a43363Smartinh if (is_oidstr(oid_or_name))
92a2a43363Smartinh return lookup_attribute_by_oid(schema, oid_or_name);
93a2a43363Smartinh return lookup_attribute_by_name(schema, oid_or_name);
94a2a43363Smartinh }
95a2a43363Smartinh
96a2a43363Smartinh struct object *
lookup_object_by_oid(struct schema * schema,char * oid)97a2a43363Smartinh lookup_object_by_oid(struct schema *schema, char *oid)
98a2a43363Smartinh {
99a2a43363Smartinh struct object find;
100a2a43363Smartinh
101a2a43363Smartinh find.oid = oid;
102a2a43363Smartinh return RB_FIND(object_tree, &schema->objects, &find);
103a2a43363Smartinh }
104a2a43363Smartinh
105a2a43363Smartinh struct object *
lookup_object_by_name(struct schema * schema,char * name)106a2a43363Smartinh lookup_object_by_name(struct schema *schema, char *name)
107a2a43363Smartinh {
108a2a43363Smartinh struct oidname *on, find;
109a2a43363Smartinh
110a2a43363Smartinh find.on_name = name;
111a2a43363Smartinh on = RB_FIND(oidname_tree, &schema->object_names, &find);
112a2a43363Smartinh
113a2a43363Smartinh if (on)
114a2a43363Smartinh return on->on_object;
115a2a43363Smartinh return NULL;
116a2a43363Smartinh }
117a2a43363Smartinh
118a2a43363Smartinh struct object *
lookup_object(struct schema * schema,char * oid_or_name)119a2a43363Smartinh lookup_object(struct schema *schema, char *oid_or_name)
120a2a43363Smartinh {
121a2a43363Smartinh if (is_oidstr(oid_or_name))
122a2a43363Smartinh return lookup_object_by_oid(schema, oid_or_name);
123a2a43363Smartinh return lookup_object_by_name(schema, oid_or_name);
124a2a43363Smartinh }
125a2a43363Smartinh
1267c686fcdSmartinh /*
1277c686fcdSmartinh * Looks up a symbolic OID, optionally with a suffix OID, so if
128a2a43363Smartinh * SYMBOL = 1.2.3.4
129a2a43363Smartinh * then
130a2a43363Smartinh * SYMBOL:5.6 = 1.2.3.4.5.6
131a2a43363Smartinh *
132a2a43363Smartinh * Returned string must be freed by the caller.
133a2a43363Smartinh * Modifies the name argument.
134a2a43363Smartinh */
1357c686fcdSmartinh char *
lookup_symbolic_oid(struct schema * schema,char * name)136a2a43363Smartinh lookup_symbolic_oid(struct schema *schema, char *name)
137a2a43363Smartinh {
138a2a43363Smartinh struct symoid *symoid, find;
139a2a43363Smartinh char *colon, *oid;
140a2a43363Smartinh size_t sz;
141a2a43363Smartinh
142a2a43363Smartinh colon = strchr(name, ':');
143a2a43363Smartinh if (colon != NULL) {
144a2a43363Smartinh if (!is_oidstr(colon + 1)) {
145a2a43363Smartinh log_warnx("invalid OID after colon: %s", colon + 1);
146a2a43363Smartinh return NULL;
147a2a43363Smartinh }
148a2a43363Smartinh *colon = '\0';
149a2a43363Smartinh }
150a2a43363Smartinh
151a2a43363Smartinh find.name = name;
152a2a43363Smartinh symoid = RB_FIND(symoid_tree, &schema->symbolic_oids, &find);
153a2a43363Smartinh if (symoid == NULL)
154a2a43363Smartinh return NULL;
155a2a43363Smartinh
156a2a43363Smartinh if (colon == NULL)
157a2a43363Smartinh return strdup(symoid->oid);
158a2a43363Smartinh
1597c686fcdSmartinh /* Expand SYMBOL:OID. */
160a2a43363Smartinh sz = strlen(symoid->oid) + 1 + strlen(colon + 1) + 1;
161a2a43363Smartinh if ((oid = malloc(sz)) == NULL) {
162a2a43363Smartinh log_warnx("malloc");
163a2a43363Smartinh return NULL;
164a2a43363Smartinh }
165a2a43363Smartinh
166a2a43363Smartinh strlcpy(oid, symoid->oid, sz);
167a2a43363Smartinh strlcat(oid, ".", sz);
168a2a43363Smartinh strlcat(oid, colon + 1, sz);
169a2a43363Smartinh
170a2a43363Smartinh return oid;
171a2a43363Smartinh }
172a2a43363Smartinh
1737c686fcdSmartinh /*
1747c686fcdSmartinh * Push a symbol-OID pair on the tree. Name and OID must be valid pointers
175a2a43363Smartinh * during the lifetime of the tree.
176a2a43363Smartinh */
177a2a43363Smartinh static struct symoid *
push_symbolic_oid(struct schema * schema,char * name,char * oid)178a2a43363Smartinh push_symbolic_oid(struct schema *schema, char *name, char *oid)
179a2a43363Smartinh {
180a2a43363Smartinh struct symoid *symoid, find;
181a2a43363Smartinh
182a2a43363Smartinh find.name = name;
183a2a43363Smartinh symoid = RB_FIND(symoid_tree, &schema->symbolic_oids, &find);
184a2a43363Smartinh
185a2a43363Smartinh if (symoid == NULL) {
186a2a43363Smartinh symoid = calloc(1, sizeof(*symoid));
187a2a43363Smartinh if (symoid == NULL) {
188a2a43363Smartinh log_warnx("calloc");
189a2a43363Smartinh return NULL;
190a2a43363Smartinh }
191a2a43363Smartinh
192a2a43363Smartinh symoid->name = name;
193a2a43363Smartinh RB_INSERT(symoid_tree, &schema->symbolic_oids, symoid);
194a2a43363Smartinh }
195a2a43363Smartinh
196a2a43363Smartinh free(symoid->oid);
197a2a43363Smartinh symoid->oid = oid;
198a2a43363Smartinh
199a2a43363Smartinh return symoid;
200a2a43363Smartinh }
201a2a43363Smartinh
202a2a43363Smartinh static struct attr_list *
push_attr(struct attr_list * alist,struct attr_type * a)203a2a43363Smartinh push_attr(struct attr_list *alist, struct attr_type *a)
204a2a43363Smartinh {
205a2a43363Smartinh struct attr_ptr *aptr;
206a2a43363Smartinh
207a2a43363Smartinh if (alist == NULL) {
208a2a43363Smartinh if ((alist = calloc(1, sizeof(*alist))) == NULL) {
209a2a43363Smartinh log_warn("calloc");
210a2a43363Smartinh return NULL;
211a2a43363Smartinh }
212a2a43363Smartinh SLIST_INIT(alist);
213a2a43363Smartinh }
214a2a43363Smartinh
215a2a43363Smartinh if ((aptr = calloc(1, sizeof(*aptr))) == NULL) {
216a2a43363Smartinh log_warn("calloc");
217033e44abSgsoares free(alist);
218a2a43363Smartinh return NULL;
219a2a43363Smartinh }
220a2a43363Smartinh aptr->attr_type = a;
221a2a43363Smartinh SLIST_INSERT_HEAD(alist, aptr, next);
222a2a43363Smartinh
223a2a43363Smartinh return alist;
224a2a43363Smartinh }
225a2a43363Smartinh
226a2a43363Smartinh static struct obj_list *
push_obj(struct obj_list * olist,struct object * obj)227a2a43363Smartinh push_obj(struct obj_list *olist, struct object *obj)
228a2a43363Smartinh {
229a2a43363Smartinh struct obj_ptr *optr;
230a2a43363Smartinh
231a2a43363Smartinh if (olist == NULL) {
232a2a43363Smartinh if ((olist = calloc(1, sizeof(*olist))) == NULL) {
233a2a43363Smartinh log_warn("calloc");
234a2a43363Smartinh return NULL;
235a2a43363Smartinh }
236a2a43363Smartinh SLIST_INIT(olist);
237a2a43363Smartinh }
238a2a43363Smartinh
239a2a43363Smartinh if ((optr = calloc(1, sizeof(*optr))) == NULL) {
240a2a43363Smartinh log_warn("calloc");
241033e44abSgsoares free(olist);
242a2a43363Smartinh return NULL;
243a2a43363Smartinh }
244a2a43363Smartinh optr->object = obj;
245a2a43363Smartinh SLIST_INSERT_HEAD(olist, optr, next);
246a2a43363Smartinh
247a2a43363Smartinh return olist;
248a2a43363Smartinh }
249a2a43363Smartinh
250a2a43363Smartinh int
is_oidstr(const char * oidstr)251a2a43363Smartinh is_oidstr(const char *oidstr)
252a2a43363Smartinh {
253a2a43363Smartinh struct ber_oid oid;
254696b5899Stb return (ober_string2oid(oidstr, &oid) == 0);
255a2a43363Smartinh }
256a2a43363Smartinh
257a2a43363Smartinh static struct name_list *
push_name(struct name_list * nl,char * name)25819467dd7Smartinh push_name(struct name_list *nl, char *name)
259a2a43363Smartinh {
260a2a43363Smartinh struct name *n;
261a2a43363Smartinh
262a2a43363Smartinh if (nl == NULL) {
263a2a43363Smartinh if ((nl = calloc(1, sizeof(*nl))) == NULL) {
264a2a43363Smartinh log_warn("calloc");
265a2a43363Smartinh return NULL;
266a2a43363Smartinh }
267a2a43363Smartinh SLIST_INIT(nl);
268a2a43363Smartinh }
269a2a43363Smartinh if ((n = calloc(1, sizeof(*n))) == NULL) {
270a2a43363Smartinh log_warn("calloc");
271033e44abSgsoares free(nl);
272a2a43363Smartinh return NULL;
273a2a43363Smartinh }
274a2a43363Smartinh n->name = name;
275a2a43363Smartinh SLIST_INSERT_HEAD(nl, n, next);
276a2a43363Smartinh
277a2a43363Smartinh return nl;
278a2a43363Smartinh }
279a2a43363Smartinh
280a2a43363Smartinh static int
schema_getc(struct schema * schema,int quotec)281a2a43363Smartinh schema_getc(struct schema *schema, int quotec)
282a2a43363Smartinh {
283a2a43363Smartinh int c, next;
284a2a43363Smartinh
285a2a43363Smartinh if (schema->pushback_index)
286a2a43363Smartinh return (schema->pushback_buffer[--schema->pushback_index]);
287a2a43363Smartinh
288a2a43363Smartinh if (quotec) {
289a2a43363Smartinh if ((c = getc(schema->fp)) == EOF) {
290a2a43363Smartinh log_warnx("reached end of file while parsing "
291a2a43363Smartinh "quoted string");
292a2a43363Smartinh return EOF;
293a2a43363Smartinh }
294a2a43363Smartinh return (c);
295a2a43363Smartinh }
296a2a43363Smartinh
297a2a43363Smartinh while ((c = getc(schema->fp)) == '\\') {
298a2a43363Smartinh next = getc(schema->fp);
299a2a43363Smartinh if (next != '\n') {
300a2a43363Smartinh c = next;
301a2a43363Smartinh break;
302a2a43363Smartinh }
303a2a43363Smartinh schema->lineno++;
304a2a43363Smartinh }
305a2a43363Smartinh
306a2a43363Smartinh return (c);
307a2a43363Smartinh }
308a2a43363Smartinh
309a2a43363Smartinh static int
schema_ungetc(struct schema * schema,int c)310a2a43363Smartinh schema_ungetc(struct schema *schema, int c)
311a2a43363Smartinh {
312a2a43363Smartinh if (c == EOF)
313a2a43363Smartinh return EOF;
314a2a43363Smartinh
315a2a43363Smartinh if (schema->pushback_index < SCHEMA_MAXPUSHBACK-1)
316a2a43363Smartinh return (schema->pushback_buffer[schema->pushback_index++] = c);
317a2a43363Smartinh else
318a2a43363Smartinh return (EOF);
319a2a43363Smartinh }
320a2a43363Smartinh
321a2a43363Smartinh static int
findeol(struct schema * schema)322a2a43363Smartinh findeol(struct schema *schema)
323a2a43363Smartinh {
324a2a43363Smartinh int c;
325a2a43363Smartinh
326a2a43363Smartinh /* skip to either EOF or the first real EOL */
327a2a43363Smartinh while (1) {
328a2a43363Smartinh if (schema->pushback_index)
329a2a43363Smartinh c = schema->pushback_buffer[--schema->pushback_index];
330a2a43363Smartinh else
331a2a43363Smartinh c = schema_getc(schema, 0);
332a2a43363Smartinh if (c == '\n') {
333a2a43363Smartinh schema->lineno++;
334a2a43363Smartinh break;
335a2a43363Smartinh }
336a2a43363Smartinh if (c == EOF)
337a2a43363Smartinh break;
338a2a43363Smartinh }
339a2a43363Smartinh return (ERROR);
340a2a43363Smartinh }
341a2a43363Smartinh
342a2a43363Smartinh static int
schema_lex(struct schema * schema,char ** kw)343a2a43363Smartinh schema_lex(struct schema *schema, char **kw)
344a2a43363Smartinh {
345a2a43363Smartinh char buf[8096];
346a2a43363Smartinh char *p;
347a2a43363Smartinh int quotec, next, c;
348a2a43363Smartinh
349a2a43363Smartinh if (kw)
350a2a43363Smartinh *kw = NULL;
351a2a43363Smartinh
352a2a43363Smartinh top:
353a2a43363Smartinh p = buf;
354a2a43363Smartinh while ((c = schema_getc(schema, 0)) == ' ' || c == '\t')
355a2a43363Smartinh ; /* nothing */
356a2a43363Smartinh
357a2a43363Smartinh if (c == '#')
358a2a43363Smartinh while ((c = schema_getc(schema, 0)) != '\n' && c != EOF)
359a2a43363Smartinh ; /* nothing */
360a2a43363Smartinh
361a2a43363Smartinh switch (c) {
362a2a43363Smartinh case '\'':
363a2a43363Smartinh case '"':
364a2a43363Smartinh quotec = c;
365a2a43363Smartinh while (1) {
366a2a43363Smartinh if ((c = schema_getc(schema, quotec)) == EOF)
367a2a43363Smartinh return (0);
368a2a43363Smartinh if (c == '\n') {
369a2a43363Smartinh schema->lineno++;
370a2a43363Smartinh continue;
371a2a43363Smartinh } else if (c == '\\') {
372a2a43363Smartinh if ((next = schema_getc(schema, quotec)) == EOF)
373a2a43363Smartinh return (0);
374a2a43363Smartinh if (next == quotec || c == ' ' || c == '\t')
375a2a43363Smartinh c = next;
376a2a43363Smartinh else if (next == '\n')
377a2a43363Smartinh continue;
378a2a43363Smartinh else
379a2a43363Smartinh schema_ungetc(schema, next);
380a2a43363Smartinh } else if (c == quotec) {
381a2a43363Smartinh *p = '\0';
382a2a43363Smartinh break;
383a2a43363Smartinh }
384a2a43363Smartinh if (p + 1 >= buf + sizeof(buf) - 1) {
385a2a43363Smartinh log_warnx("string too long");
386a2a43363Smartinh return (findeol(schema));
387a2a43363Smartinh }
388a2a43363Smartinh *p++ = (char)c;
389a2a43363Smartinh }
390a2a43363Smartinh if (kw != NULL && (*kw = strdup(buf)) == NULL)
391a2a43363Smartinh fatal("schema_lex: strdup");
392a2a43363Smartinh return (STRING);
393a2a43363Smartinh }
394a2a43363Smartinh
395a2a43363Smartinh #define allowed_in_string(x) \
396a2a43363Smartinh (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
397a2a43363Smartinh x != '{' && x != '}' && x != '<' && x != '>' && \
398a2a43363Smartinh x != '!' && x != '=' && x != '/' && x != '#' && \
399a2a43363Smartinh x != ','))
400a2a43363Smartinh
401a2a43363Smartinh if (isalnum(c) || c == ':' || c == '_' || c == '*') {
402a2a43363Smartinh do {
403a2a43363Smartinh *p++ = c;
404915c3f33Sderaadt if ((size_t)(p-buf) >= sizeof(buf)) {
405a2a43363Smartinh log_warnx("string too long");
406a2a43363Smartinh return (findeol(schema));
407a2a43363Smartinh }
408a2a43363Smartinh } while ((c = schema_getc(schema, 0)) != EOF && (allowed_in_string(c)));
409a2a43363Smartinh schema_ungetc(schema, c);
410a2a43363Smartinh *p = '\0';
411a2a43363Smartinh if (kw != NULL && (*kw = strdup(buf)) == NULL)
412a2a43363Smartinh fatal("schema_lex: strdup");
413a2a43363Smartinh return STRING;
414a2a43363Smartinh }
415a2a43363Smartinh if (c == '\n') {
416a2a43363Smartinh schema->lineno++;
417a2a43363Smartinh goto top;
418a2a43363Smartinh }
419a2a43363Smartinh if (c == EOF)
420a2a43363Smartinh return (0);
421a2a43363Smartinh return (c);
422a2a43363Smartinh }
423a2a43363Smartinh
424a2a43363Smartinh struct schema *
schema_new(void)425a2a43363Smartinh schema_new(void)
426a2a43363Smartinh {
427a2a43363Smartinh struct schema *schema;
428a2a43363Smartinh
429a2a43363Smartinh if ((schema = calloc(1, sizeof(*schema))) == NULL)
430a2a43363Smartinh return NULL;
431a2a43363Smartinh
432a2a43363Smartinh RB_INIT(&schema->attr_types);
433a2a43363Smartinh RB_INIT(&schema->attr_names);
434a2a43363Smartinh RB_INIT(&schema->objects);
435a2a43363Smartinh RB_INIT(&schema->object_names);
436a2a43363Smartinh RB_INIT(&schema->symbolic_oids);
437a2a43363Smartinh
438a2a43363Smartinh return schema;
439a2a43363Smartinh }
440a2a43363Smartinh
441a2a43363Smartinh static void
schema_err(struct schema * schema,const char * fmt,...)442a2a43363Smartinh schema_err(struct schema *schema, const char *fmt, ...)
443a2a43363Smartinh {
444a2a43363Smartinh va_list ap;
4457576e124Sbluhm char *msg;
446a2a43363Smartinh
447a2a43363Smartinh va_start(ap, fmt);
4487576e124Sbluhm if (vasprintf(&msg, fmt, ap) == -1)
4497576e124Sbluhm fatal("vasprintf");
450a2a43363Smartinh va_end(ap);
4517576e124Sbluhm logit(LOG_CRIT, "%s:%d: %s", schema->filename, schema->lineno, msg);
4527576e124Sbluhm free(msg);
453a2a43363Smartinh
454a2a43363Smartinh schema->error++;
455a2a43363Smartinh }
456a2a43363Smartinh
457a2a43363Smartinh static int
schema_link_attr_name(struct schema * schema,const char * name,struct attr_type * attr)458a2a43363Smartinh schema_link_attr_name(struct schema *schema, const char *name, struct attr_type *attr)
459a2a43363Smartinh {
460a2a43363Smartinh struct oidname *oidname, *prev;
461a2a43363Smartinh
462a2a43363Smartinh if ((oidname = calloc(1, sizeof(*oidname))) == NULL) {
463a2a43363Smartinh log_warn("calloc");
464a2a43363Smartinh return -1;
465a2a43363Smartinh }
466a2a43363Smartinh
467a2a43363Smartinh oidname->on_name = name;
468a2a43363Smartinh oidname->on_attr_type = attr;
469a2a43363Smartinh prev = RB_INSERT(oidname_tree, &schema->attr_names, oidname);
470a2a43363Smartinh if (prev != NULL) {
471a2a43363Smartinh schema_err(schema, "attribute type name '%s'"
472a2a43363Smartinh " already defined for oid %s",
473a2a43363Smartinh name, prev->on_attr_type->oid);
474a2a43363Smartinh free(oidname);
475a2a43363Smartinh return -1;
476a2a43363Smartinh }
477a2a43363Smartinh
478a2a43363Smartinh return 0;
479a2a43363Smartinh }
480a2a43363Smartinh
481a2a43363Smartinh static int
schema_link_attr_names(struct schema * schema,struct attr_type * attr)482a2a43363Smartinh schema_link_attr_names(struct schema *schema, struct attr_type *attr)
483a2a43363Smartinh {
484a2a43363Smartinh struct name *name;
485a2a43363Smartinh
486a2a43363Smartinh SLIST_FOREACH(name, attr->names, next) {
487a2a43363Smartinh if (schema_link_attr_name(schema, name->name, attr) != 0)
488a2a43363Smartinh return -1;
489a2a43363Smartinh }
490a2a43363Smartinh return 0;
491a2a43363Smartinh }
492a2a43363Smartinh
493a2a43363Smartinh static int
schema_link_obj_name(struct schema * schema,const char * name,struct object * obj)494a2a43363Smartinh schema_link_obj_name(struct schema *schema, const char *name, struct object *obj)
495a2a43363Smartinh {
496a2a43363Smartinh struct oidname *oidname, *prev;
497a2a43363Smartinh
498a2a43363Smartinh if ((oidname = calloc(1, sizeof(*oidname))) == NULL) {
499a2a43363Smartinh log_warn("calloc");
500a2a43363Smartinh return -1;
501a2a43363Smartinh }
502a2a43363Smartinh
503a2a43363Smartinh oidname->on_name = name;
504a2a43363Smartinh oidname->on_object = obj;
505a2a43363Smartinh prev = RB_INSERT(oidname_tree, &schema->object_names, oidname);
506a2a43363Smartinh if (prev != NULL) {
507a2a43363Smartinh schema_err(schema, "object class name '%s'"
508a2a43363Smartinh " already defined for oid %s",
509a2a43363Smartinh name, prev->on_object->oid);
510a2a43363Smartinh free(oidname);
511a2a43363Smartinh return -1;
512a2a43363Smartinh }
513a2a43363Smartinh
514a2a43363Smartinh return 0;
515a2a43363Smartinh }
516a2a43363Smartinh
517a2a43363Smartinh static int
schema_link_obj_names(struct schema * schema,struct object * obj)518a2a43363Smartinh schema_link_obj_names(struct schema *schema, struct object *obj)
519a2a43363Smartinh {
520a2a43363Smartinh struct name *name;
521a2a43363Smartinh
522a2a43363Smartinh SLIST_FOREACH(name, obj->names, next) {
523a2a43363Smartinh if (schema_link_obj_name(schema, name->name, obj) != 0)
524a2a43363Smartinh return -1;
525a2a43363Smartinh }
526a2a43363Smartinh return 0;
527a2a43363Smartinh }
528a2a43363Smartinh
529a2a43363Smartinh static struct name_list *
schema_parse_names(struct schema * schema)530a2a43363Smartinh schema_parse_names(struct schema *schema)
531a2a43363Smartinh {
532a2a43363Smartinh struct name_list *nlist = NULL;
533a2a43363Smartinh char *kw;
534a2a43363Smartinh int token;
535a2a43363Smartinh
536a2a43363Smartinh token = schema_lex(schema, &kw);
537a2a43363Smartinh if (token == STRING)
538a2a43363Smartinh return push_name(NULL, kw);
539a2a43363Smartinh
540a2a43363Smartinh if (token != '(')
541a2a43363Smartinh goto fail;
542a2a43363Smartinh
543a2a43363Smartinh for (;;) {
544a2a43363Smartinh token = schema_lex(schema, &kw);
545a2a43363Smartinh if (token == ')')
546a2a43363Smartinh break;
547a2a43363Smartinh if (token != STRING)
548a2a43363Smartinh goto fail;
549a2a43363Smartinh nlist = push_name(nlist, kw);
550a2a43363Smartinh }
551a2a43363Smartinh
552a2a43363Smartinh return nlist;
553a2a43363Smartinh
554a2a43363Smartinh fail:
555a2a43363Smartinh free(kw);
556a2a43363Smartinh /* FIXME: leaks nlist here */
557a2a43363Smartinh return NULL;
558a2a43363Smartinh }
559a2a43363Smartinh
56019467dd7Smartinh static void
schema_free_name_list(struct name_list * nlist)56119467dd7Smartinh schema_free_name_list(struct name_list *nlist)
56219467dd7Smartinh {
56319467dd7Smartinh struct name *name;
56419467dd7Smartinh
56519467dd7Smartinh while ((name = SLIST_FIRST(nlist)) != NULL) {
56619467dd7Smartinh SLIST_REMOVE_HEAD(nlist, next);
56719467dd7Smartinh free(name->name);
56819467dd7Smartinh free(name);
56919467dd7Smartinh }
57019467dd7Smartinh free(nlist);
57119467dd7Smartinh }
57219467dd7Smartinh
573a2a43363Smartinh static struct attr_list *
schema_parse_attrlist(struct schema * schema)574a2a43363Smartinh schema_parse_attrlist(struct schema *schema)
575a2a43363Smartinh {
576a2a43363Smartinh struct attr_list *alist = NULL;
577a2a43363Smartinh struct attr_type *attr;
578a2a43363Smartinh char *kw;
579a2a43363Smartinh int token, want_dollar = 0;
580a2a43363Smartinh
581a2a43363Smartinh token = schema_lex(schema, &kw);
582a2a43363Smartinh if (token == STRING) {
583a2a43363Smartinh if ((attr = lookup_attribute(schema, kw)) == NULL) {
584a2a43363Smartinh schema_err(schema, "undeclared attribute type '%s'", kw);
585a2a43363Smartinh goto fail;
586a2a43363Smartinh }
587a2a43363Smartinh free(kw);
588a2a43363Smartinh return push_attr(NULL, attr);
589a2a43363Smartinh }
590a2a43363Smartinh
591a2a43363Smartinh if (token != '(')
592a2a43363Smartinh goto fail;
593a2a43363Smartinh
594a2a43363Smartinh for (;;) {
595a2a43363Smartinh token = schema_lex(schema, &kw);
596a2a43363Smartinh if (token == ')')
597a2a43363Smartinh break;
598a2a43363Smartinh if (token == '$') {
599a2a43363Smartinh if (!want_dollar)
600a2a43363Smartinh goto fail;
601a2a43363Smartinh want_dollar = 0;
602a2a43363Smartinh continue;
603a2a43363Smartinh }
604a2a43363Smartinh if (token != STRING)
605a2a43363Smartinh goto fail;
606fc0162c4Smartinh if ((attr = lookup_attribute(schema, kw)) == NULL) {
607fc0162c4Smartinh schema_err(schema, "%s: no such attribute", kw);
608a2a43363Smartinh goto fail;
609fc0162c4Smartinh }
610a2a43363Smartinh alist = push_attr(alist, attr);
611964ebf41Smartinh free(kw);
612a2a43363Smartinh want_dollar = 1;
613a2a43363Smartinh }
614a2a43363Smartinh
615a2a43363Smartinh return alist;
616a2a43363Smartinh
617a2a43363Smartinh fail:
618a2a43363Smartinh free(kw);
619a2a43363Smartinh /* FIXME: leaks alist here */
620a2a43363Smartinh return NULL;
621a2a43363Smartinh }
622a2a43363Smartinh
623a2a43363Smartinh static struct obj_list *
schema_parse_objlist(struct schema * schema)624a2a43363Smartinh schema_parse_objlist(struct schema *schema)
625a2a43363Smartinh {
626a2a43363Smartinh struct obj_list *olist = NULL;
627a2a43363Smartinh struct object *obj;
628a2a43363Smartinh char *kw;
629a2a43363Smartinh int token, want_dollar = 0;
630a2a43363Smartinh
631a2a43363Smartinh token = schema_lex(schema, &kw);
632a2a43363Smartinh if (token == STRING) {
633a2a43363Smartinh if ((obj = lookup_object(schema, kw)) == NULL) {
634a2a43363Smartinh schema_err(schema, "undeclared object class '%s'", kw);
635a2a43363Smartinh goto fail;
636a2a43363Smartinh }
637a2a43363Smartinh free(kw);
638a2a43363Smartinh return push_obj(NULL, obj);
639a2a43363Smartinh }
640a2a43363Smartinh
641a2a43363Smartinh if (token != '(')
642a2a43363Smartinh goto fail;
643a2a43363Smartinh
644a2a43363Smartinh for (;;) {
645a2a43363Smartinh token = schema_lex(schema, &kw);
646a2a43363Smartinh if (token == ')')
647a2a43363Smartinh break;
648a2a43363Smartinh if (token == '$') {
649a2a43363Smartinh if (!want_dollar)
650a2a43363Smartinh goto fail;
651a2a43363Smartinh want_dollar = 0;
652a2a43363Smartinh continue;
653a2a43363Smartinh }
654a2a43363Smartinh if (token != STRING)
655a2a43363Smartinh goto fail;
656a2a43363Smartinh if ((obj = lookup_object(schema, kw)) == NULL)
657a2a43363Smartinh goto fail;
658a2a43363Smartinh olist = push_obj(olist, obj);
659a2a43363Smartinh want_dollar = 1;
660a2a43363Smartinh }
661a2a43363Smartinh
662a2a43363Smartinh return olist;
663a2a43363Smartinh
664a2a43363Smartinh fail:
665a2a43363Smartinh free(kw);
666a2a43363Smartinh /* FIXME: leaks olist here */
667a2a43363Smartinh return NULL;
668a2a43363Smartinh }
669a2a43363Smartinh
670a2a43363Smartinh static int
schema_validate_match_rule(struct schema * schema,struct attr_type * at,const struct match_rule * mrule,enum match_rule_type type)671d6378167Smartinh schema_validate_match_rule(struct schema *schema, struct attr_type *at,
672d6378167Smartinh const struct match_rule *mrule, enum match_rule_type type)
673d6378167Smartinh {
674d6378167Smartinh int i;
675d6378167Smartinh
676d6378167Smartinh if (mrule == NULL)
677d6378167Smartinh return 0;
678d6378167Smartinh
679d6378167Smartinh if ((mrule->type & type) != type) {
680d6378167Smartinh schema_err(schema, "%s: bad matching rule '%s'",
681d6378167Smartinh ATTR_NAME(at), mrule->name);
682d6378167Smartinh return -1;
683d6378167Smartinh }
684d6378167Smartinh
685d6378167Smartinh /* Is this matching rule compatible with the attribute syntax? */
686d6378167Smartinh if (strcmp(mrule->syntax_oid, at->syntax->oid) == 0)
687d6378167Smartinh return 0;
688d6378167Smartinh
689d6378167Smartinh /* Check any alternative syntaxes for compatibility. */
690d6378167Smartinh for (i = 0; mrule->alt_syntax_oids && mrule->alt_syntax_oids[i]; i++)
691d6378167Smartinh if (strcmp(mrule->alt_syntax_oids[i], at->syntax->oid) == 0)
692d6378167Smartinh return 0;
693d6378167Smartinh
694d6378167Smartinh schema_err(schema, "%s: inappropriate matching rule '%s' for syntax [%s]",
695d6378167Smartinh ATTR_NAME(at), mrule->name, at->syntax->oid);
696d6378167Smartinh return -1;
697d6378167Smartinh }
698d6378167Smartinh
699d6378167Smartinh static int
schema_parse_attributetype(struct schema * schema)700a2a43363Smartinh schema_parse_attributetype(struct schema *schema)
701a2a43363Smartinh {
7027c686fcdSmartinh struct attr_type *attr = NULL, *prev, *sup;
70319467dd7Smartinh struct name_list *xnames;
704b59d2504Smartinh char *kw = NULL, *arg = NULL;
705a2a43363Smartinh int token, ret = 0, c;
706a2a43363Smartinh
707a2a43363Smartinh if (schema_lex(schema, NULL) != '(')
708a2a43363Smartinh goto fail;
709a2a43363Smartinh
710a2a43363Smartinh if (schema_lex(schema, &kw) != STRING)
711a2a43363Smartinh goto fail;
712a2a43363Smartinh
713a2a43363Smartinh if ((attr = calloc(1, sizeof(*attr))) == NULL) {
714a2a43363Smartinh log_warn("calloc");
715a2a43363Smartinh goto fail;
716a2a43363Smartinh }
717b27b53f1Smartinh attr->usage = USAGE_USER_APP;
718a2a43363Smartinh
719a2a43363Smartinh if (is_oidstr(kw))
720a2a43363Smartinh attr->oid = kw;
721a2a43363Smartinh else {
722a2a43363Smartinh attr->oid = lookup_symbolic_oid(schema, kw);
723a2a43363Smartinh if (attr->oid == NULL)
724a2a43363Smartinh goto fail;
725a2a43363Smartinh free(kw);
726a2a43363Smartinh }
727a2a43363Smartinh kw = NULL;
728a2a43363Smartinh
729a2a43363Smartinh prev = RB_INSERT(attr_type_tree, &schema->attr_types, attr);
730a2a43363Smartinh if (prev != NULL) {
731a2a43363Smartinh schema_err(schema, "attribute type %s already defined", attr->oid);
732a2a43363Smartinh goto fail;
733a2a43363Smartinh }
734a2a43363Smartinh
735a2a43363Smartinh while (ret == 0) {
736a2a43363Smartinh token = schema_lex(schema, &kw);
737a2a43363Smartinh if (token == ')')
738a2a43363Smartinh break;
739a2a43363Smartinh else if (token != STRING)
740a2a43363Smartinh goto fail;
741a2a43363Smartinh if (strcasecmp(kw, "NAME") == 0) {
742a2a43363Smartinh attr->names = schema_parse_names(schema);
743a2a43363Smartinh if (attr->names == NULL)
744a2a43363Smartinh goto fail;
745a2a43363Smartinh schema_link_attr_names(schema, attr);
746a2a43363Smartinh } else if (strcasecmp(kw, "DESC") == 0) {
747a2a43363Smartinh if (schema_lex(schema, &attr->desc) != STRING)
748a2a43363Smartinh goto fail;
749a2a43363Smartinh } else if (strcasecmp(kw, "OBSOLETE") == 0) {
750a2a43363Smartinh attr->obsolete = 1;
751a2a43363Smartinh } else if (strcasecmp(kw, "SUP") == 0) {
752a2a43363Smartinh if (schema_lex(schema, &arg) != STRING)
753a2a43363Smartinh goto fail;
754a2a43363Smartinh if ((attr->sup = lookup_attribute(schema, arg)) == NULL) {
755a2a43363Smartinh schema_err(schema, "%s: no such attribute", arg);
756a2a43363Smartinh goto fail;
757a2a43363Smartinh }
758964ebf41Smartinh free(arg);
759a2a43363Smartinh } else if (strcasecmp(kw, "EQUALITY") == 0) {
760d6378167Smartinh if (schema_lex(schema, &arg) != STRING)
761a2a43363Smartinh goto fail;
762d6378167Smartinh if ((attr->equality = match_rule_lookup(arg)) == NULL) {
763d6378167Smartinh schema_err(schema, "%s: unknown matching rule",
764d6378167Smartinh arg);
765d6378167Smartinh goto fail;
766d6378167Smartinh }
767d6378167Smartinh free(arg);
768a2a43363Smartinh } else if (strcasecmp(kw, "ORDERING") == 0) {
769d6378167Smartinh if (schema_lex(schema, &arg) != STRING)
770a2a43363Smartinh goto fail;
771d6378167Smartinh if ((attr->ordering = match_rule_lookup(arg)) == NULL) {
772d6378167Smartinh schema_err(schema, "%s: unknown matching rule",
773d6378167Smartinh arg);
774d6378167Smartinh goto fail;
775d6378167Smartinh }
776d6378167Smartinh free(arg);
777a2a43363Smartinh } else if (strcasecmp(kw, "SUBSTR") == 0) {
778d6378167Smartinh if (schema_lex(schema, &arg) != STRING)
779a2a43363Smartinh goto fail;
780d6378167Smartinh if ((attr->substr = match_rule_lookup(arg)) == NULL) {
781d6378167Smartinh schema_err(schema, "%s: unknown matching rule",
782d6378167Smartinh arg);
783d6378167Smartinh goto fail;
784d6378167Smartinh }
785d6378167Smartinh free(arg);
786a2a43363Smartinh } else if (strcasecmp(kw, "SYNTAX") == 0) {
7877c686fcdSmartinh if (schema_lex(schema, &arg) != STRING ||
7887c686fcdSmartinh !is_oidstr(arg))
789a2a43363Smartinh goto fail;
7907c686fcdSmartinh
7917c686fcdSmartinh if ((attr->syntax = syntax_lookup(arg)) == NULL) {
7927c686fcdSmartinh schema_err(schema, "syntax not supported: %s",
7937c686fcdSmartinh arg);
7947c686fcdSmartinh goto fail;
7957c686fcdSmartinh }
7967c686fcdSmartinh
797a2a43363Smartinh if ((c = schema_getc(schema, 0)) == '{') {
798a2a43363Smartinh if (schema_lex(schema, NULL) != STRING ||
799a2a43363Smartinh schema_lex(schema, NULL) != '}')
800a2a43363Smartinh goto fail;
801a2a43363Smartinh } else
802a2a43363Smartinh schema_ungetc(schema, c);
8037c686fcdSmartinh free(arg);
804a2a43363Smartinh } else if (strcasecmp(kw, "SINGLE-VALUE") == 0) {
805a2a43363Smartinh attr->single = 1;
806a2a43363Smartinh } else if (strcasecmp(kw, "COLLECTIVE") == 0) {
807a2a43363Smartinh attr->collective = 1;
808a2a43363Smartinh } else if (strcasecmp(kw, "NO-USER-MODIFICATION") == 0) {
809a2a43363Smartinh attr->immutable = 1;
810a2a43363Smartinh } else if (strcasecmp(kw, "USAGE") == 0) {
811a2a43363Smartinh if (schema_lex(schema, &arg) != STRING)
812a2a43363Smartinh goto fail;
813a2a43363Smartinh if (strcasecmp(arg, "dSAOperation") == 0)
814a2a43363Smartinh attr->usage = USAGE_DSA_OP;
815a2a43363Smartinh else if (strcasecmp(arg, "directoryOperation") == 0)
816a2a43363Smartinh attr->usage = USAGE_DIR_OP;
817a2a43363Smartinh else if (strcasecmp(arg, "distributedOperation") == 0)
818a2a43363Smartinh attr->usage = USAGE_DIST_OP;
819a2a43363Smartinh else if (strcasecmp(arg, "userApplications") == 0)
820a2a43363Smartinh attr->usage = USAGE_USER_APP;
821a2a43363Smartinh else {
822a2a43363Smartinh schema_err(schema, "invalid usage '%s'", arg);
823a2a43363Smartinh goto fail;
824a2a43363Smartinh }
825964ebf41Smartinh free(arg);
82619467dd7Smartinh } else if (strncmp(kw, "X-", 2) == 0) {
82719467dd7Smartinh /* unknown extension, eat argument(s) */
82819467dd7Smartinh xnames = schema_parse_names(schema);
82919467dd7Smartinh if (xnames == NULL)
83019467dd7Smartinh goto fail;
83119467dd7Smartinh schema_free_name_list(xnames);
83219467dd7Smartinh } else {
83319467dd7Smartinh schema_err(schema, "syntax error at token '%s'", kw);
83419467dd7Smartinh goto fail;
835a2a43363Smartinh }
83619467dd7Smartinh free(kw);
837*c1e33626Sjsg kw = NULL;
838a2a43363Smartinh }
839a2a43363Smartinh
8407c686fcdSmartinh /* Check that a syntax is defined, either directly or
8417c686fcdSmartinh * indirectly via a superior attribute type.
8427c686fcdSmartinh */
8437c686fcdSmartinh sup = attr->sup;
8447c686fcdSmartinh while (attr->syntax == NULL && sup != NULL) {
8457c686fcdSmartinh attr->syntax = sup->syntax;
8467c686fcdSmartinh sup = sup->sup;
8477c686fcdSmartinh }
8487c686fcdSmartinh if (attr->syntax == NULL) {
8497c686fcdSmartinh schema_err(schema, "%s: no syntax defined", ATTR_NAME(attr));
8507c686fcdSmartinh goto fail;
8517c686fcdSmartinh }
8527c686fcdSmartinh
85378a17c8cSmartinh /* If the attribute type doesn't explicitly define equality, check
85478a17c8cSmartinh * if any superior attribute type does.
85578a17c8cSmartinh */
85678a17c8cSmartinh sup = attr->sup;
85778a17c8cSmartinh while (attr->equality == NULL && sup != NULL) {
85878a17c8cSmartinh attr->equality = sup->equality;
85978a17c8cSmartinh sup = sup->sup;
86078a17c8cSmartinh }
86178a17c8cSmartinh /* Same thing with ordering matching rule. */
86278a17c8cSmartinh sup = attr->sup;
86378a17c8cSmartinh while (attr->ordering == NULL && sup != NULL) {
86478a17c8cSmartinh attr->ordering = sup->ordering;
86578a17c8cSmartinh sup = sup->sup;
86678a17c8cSmartinh }
86778a17c8cSmartinh /* ...and substring matching rule. */
86878a17c8cSmartinh sup = attr->sup;
86978a17c8cSmartinh while (attr->substr == NULL && sup != NULL) {
87078a17c8cSmartinh attr->substr = sup->substr;
87178a17c8cSmartinh sup = sup->sup;
87278a17c8cSmartinh }
87378a17c8cSmartinh
874d6378167Smartinh if (schema_validate_match_rule(schema, attr, attr->equality, MATCH_EQUALITY) != 0 ||
875d6378167Smartinh schema_validate_match_rule(schema, attr, attr->ordering, MATCH_ORDERING) != 0 ||
876d6378167Smartinh schema_validate_match_rule(schema, attr, attr->substr, MATCH_SUBSTR) != 0)
877d6378167Smartinh goto fail;
878d6378167Smartinh
879a2a43363Smartinh return 0;
880a2a43363Smartinh
881a2a43363Smartinh fail:
882a2a43363Smartinh free(kw);
883a2a43363Smartinh if (attr != NULL) {
884a2a43363Smartinh if (attr->oid != NULL) {
885a2a43363Smartinh RB_REMOVE(attr_type_tree, &schema->attr_types, attr);
886a2a43363Smartinh free(attr->oid);
887a2a43363Smartinh }
888a2a43363Smartinh free(attr->desc);
889a2a43363Smartinh free(attr);
890a2a43363Smartinh }
891a2a43363Smartinh return -1;
892a2a43363Smartinh }
893a2a43363Smartinh
894a2a43363Smartinh static int
schema_parse_objectclass(struct schema * schema)895a2a43363Smartinh schema_parse_objectclass(struct schema *schema)
896a2a43363Smartinh {
897a2a43363Smartinh struct object *obj = NULL, *prev;
8984e302eb7Smartinh struct obj_ptr *optr;
89919467dd7Smartinh struct name_list *xnames;
900b59d2504Smartinh char *kw = NULL;
901a2a43363Smartinh int token, ret = 0;
902a2a43363Smartinh
903a2a43363Smartinh if (schema_lex(schema, NULL) != '(')
904a2a43363Smartinh goto fail;
905a2a43363Smartinh
906a2a43363Smartinh if (schema_lex(schema, &kw) != STRING)
907a2a43363Smartinh goto fail;
908a2a43363Smartinh
909a2a43363Smartinh if ((obj = calloc(1, sizeof(*obj))) == NULL) {
910a2a43363Smartinh log_warn("calloc");
911a2a43363Smartinh goto fail;
912a2a43363Smartinh }
9134e302eb7Smartinh obj->kind = KIND_STRUCTURAL;
914a2a43363Smartinh
915a2a43363Smartinh if (is_oidstr(kw))
916a2a43363Smartinh obj->oid = kw;
917a2a43363Smartinh else {
918a2a43363Smartinh obj->oid = lookup_symbolic_oid(schema, kw);
919a2a43363Smartinh if (obj->oid == NULL)
920a2a43363Smartinh goto fail;
921a2a43363Smartinh free(kw);
922a2a43363Smartinh }
923a2a43363Smartinh kw = NULL;
924a2a43363Smartinh
925a2a43363Smartinh prev = RB_INSERT(object_tree, &schema->objects, obj);
926a2a43363Smartinh if (prev != NULL) {
927a2a43363Smartinh schema_err(schema, "object class %s already defined", obj->oid);
928a2a43363Smartinh goto fail;
929a2a43363Smartinh }
930a2a43363Smartinh
931a2a43363Smartinh while (ret == 0) {
932a2a43363Smartinh token = schema_lex(schema, &kw);
933a2a43363Smartinh if (token == ')')
934a2a43363Smartinh break;
935a2a43363Smartinh else if (token != STRING)
936a2a43363Smartinh goto fail;
937a2a43363Smartinh if (strcasecmp(kw, "NAME") == 0) {
938a2a43363Smartinh obj->names = schema_parse_names(schema);
939a2a43363Smartinh if (obj->names == NULL)
940a2a43363Smartinh goto fail;
941a2a43363Smartinh schema_link_obj_names(schema, obj);
942a2a43363Smartinh } else if (strcasecmp(kw, "DESC") == 0) {
943a2a43363Smartinh if (schema_lex(schema, &obj->desc) != STRING)
944a2a43363Smartinh goto fail;
945a2a43363Smartinh } else if (strcasecmp(kw, "OBSOLETE") == 0) {
946a2a43363Smartinh obj->obsolete = 1;
947a2a43363Smartinh } else if (strcasecmp(kw, "SUP") == 0) {
948a2a43363Smartinh obj->sup = schema_parse_objlist(schema);
949a2a43363Smartinh if (obj->sup == NULL)
950a2a43363Smartinh goto fail;
951a2a43363Smartinh } else if (strcasecmp(kw, "ABSTRACT") == 0) {
952a2a43363Smartinh obj->kind = KIND_ABSTRACT;
953a2a43363Smartinh } else if (strcasecmp(kw, "STRUCTURAL") == 0) {
954a2a43363Smartinh obj->kind = KIND_STRUCTURAL;
955a2a43363Smartinh } else if (strcasecmp(kw, "AUXILIARY") == 0) {
956a2a43363Smartinh obj->kind = KIND_AUXILIARY;
957a2a43363Smartinh } else if (strcasecmp(kw, "MUST") == 0) {
958a2a43363Smartinh obj->must = schema_parse_attrlist(schema);
959a2a43363Smartinh if (obj->must == NULL)
960a2a43363Smartinh goto fail;
961a2a43363Smartinh } else if (strcasecmp(kw, "MAY") == 0) {
962a2a43363Smartinh obj->may = schema_parse_attrlist(schema);
963a2a43363Smartinh if (obj->may == NULL)
964a2a43363Smartinh goto fail;
96519467dd7Smartinh } else if (strncasecmp(kw, "X-", 2) == 0) {
96619467dd7Smartinh /* unknown extension, eat argument(s) */
96719467dd7Smartinh xnames = schema_parse_names(schema);
96819467dd7Smartinh if (xnames == NULL)
96919467dd7Smartinh goto fail;
97019467dd7Smartinh schema_free_name_list(xnames);
97119467dd7Smartinh } else {
97219467dd7Smartinh schema_err(schema, "syntax error at token '%s'", kw);
97319467dd7Smartinh goto fail;
974a2a43363Smartinh }
97519467dd7Smartinh free(kw);
976*c1e33626Sjsg kw = NULL;
977a2a43363Smartinh }
978a2a43363Smartinh
9794e302eb7Smartinh /* Verify the subclassing is allowed.
9804e302eb7Smartinh *
9814e302eb7Smartinh * Structural object classes cannot subclass auxiliary object classes.
9824e302eb7Smartinh * Auxiliary object classes cannot subclass structural object classes.
9834e302eb7Smartinh * Abstract object classes cannot derive from structural or auxiliary
9844e302eb7Smartinh * object classes.
9854e302eb7Smartinh */
9864e302eb7Smartinh if (obj->sup != NULL) {
9874e302eb7Smartinh SLIST_FOREACH(optr, obj->sup, next) {
9884e302eb7Smartinh if (obj->kind == KIND_STRUCTURAL &&
9894e302eb7Smartinh optr->object->kind == KIND_AUXILIARY) {
9904e302eb7Smartinh log_warnx("structural object class '%s' cannot"
9914e302eb7Smartinh " subclass auxiliary object class '%s'",
9924e302eb7Smartinh OBJ_NAME(obj), OBJ_NAME(optr->object));
9934e302eb7Smartinh goto fail;
9944e302eb7Smartinh }
9954e302eb7Smartinh
9964e302eb7Smartinh if (obj->kind == KIND_AUXILIARY &&
9974e302eb7Smartinh optr->object->kind == KIND_STRUCTURAL) {
9984e302eb7Smartinh log_warnx("auxiliary object class '%s' cannot"
9994e302eb7Smartinh " subclass structural object class '%s'",
10004e302eb7Smartinh OBJ_NAME(obj), OBJ_NAME(optr->object));
10014e302eb7Smartinh goto fail;
10024e302eb7Smartinh }
10034e302eb7Smartinh
10044e302eb7Smartinh if (obj->kind == KIND_ABSTRACT &&
10054e302eb7Smartinh optr->object->kind != KIND_ABSTRACT) {
10064e302eb7Smartinh log_warnx("abstract object class '%s' cannot"
10074e302eb7Smartinh " subclass non-abstract object class '%s'",
10084e302eb7Smartinh OBJ_NAME(obj), OBJ_NAME(optr->object));
10094e302eb7Smartinh goto fail;
10104e302eb7Smartinh }
10114e302eb7Smartinh }
10124e302eb7Smartinh }
10134e302eb7Smartinh
1014a2a43363Smartinh return 0;
1015a2a43363Smartinh
1016a2a43363Smartinh fail:
1017a2a43363Smartinh free(kw);
1018a2a43363Smartinh if (obj != NULL) {
1019a2a43363Smartinh if (obj->oid != NULL) {
1020a2a43363Smartinh RB_REMOVE(object_tree, &schema->objects, obj);
1021a2a43363Smartinh free(obj->oid);
1022a2a43363Smartinh }
1023a2a43363Smartinh free(obj->desc);
1024a2a43363Smartinh free(obj);
1025a2a43363Smartinh }
1026a2a43363Smartinh return -1;
1027a2a43363Smartinh }
1028a2a43363Smartinh
1029a2a43363Smartinh static int
schema_parse_objectidentifier(struct schema * schema)1030a2a43363Smartinh schema_parse_objectidentifier(struct schema *schema)
1031a2a43363Smartinh {
1032a2a43363Smartinh char *symname = NULL, *symoid = NULL;
1033a2a43363Smartinh char *oid = NULL;
1034a2a43363Smartinh
1035a2a43363Smartinh if (schema_lex(schema, &symname) != STRING)
1036a2a43363Smartinh goto fail;
1037a2a43363Smartinh if (schema_lex(schema, &symoid) != STRING)
1038a2a43363Smartinh goto fail;
1039a2a43363Smartinh
1040a2a43363Smartinh if (is_oidstr(symoid)) {
1041a2a43363Smartinh oid = symoid;
1042a2a43363Smartinh symoid = NULL;
1043a2a43363Smartinh } else if ((oid = lookup_symbolic_oid(schema, symoid)) == NULL)
1044a2a43363Smartinh goto fail;
1045a2a43363Smartinh
1046a2a43363Smartinh if (push_symbolic_oid(schema, symname, oid) == NULL)
1047a2a43363Smartinh goto fail;
1048a2a43363Smartinh
1049a2a43363Smartinh free(symoid);
1050a2a43363Smartinh return 0;
1051a2a43363Smartinh
1052a2a43363Smartinh fail:
1053a2a43363Smartinh free(symname);
1054a2a43363Smartinh free(symoid);
1055a2a43363Smartinh free(oid);
1056a2a43363Smartinh return -1;
1057a2a43363Smartinh }
1058a2a43363Smartinh
1059a2a43363Smartinh int
schema_parse(struct schema * schema,const char * filename)1060a2a43363Smartinh schema_parse(struct schema *schema, const char *filename)
1061a2a43363Smartinh {
1062a2a43363Smartinh char *kw;
1063a2a43363Smartinh int token, ret = 0;
1064a2a43363Smartinh
1065a2a43363Smartinh log_debug("parsing schema file '%s'", filename);
1066a2a43363Smartinh
1067ef9fbfc9Smartinh if ((schema->fp = fopen(filename, "r")) == NULL) {
1068ef9fbfc9Smartinh log_warn("%s", filename);
1069a2a43363Smartinh return -1;
1070ef9fbfc9Smartinh }
1071a2a43363Smartinh schema->filename = filename;
1072a2a43363Smartinh schema->lineno = 1;
1073a2a43363Smartinh
1074a2a43363Smartinh while (ret == 0) {
1075a2a43363Smartinh token = schema_lex(schema, &kw);
1076a2a43363Smartinh if (token == STRING) {
1077a2a43363Smartinh if (strcasecmp(kw, "attributetype") == 0)
1078a2a43363Smartinh ret = schema_parse_attributetype(schema);
1079a2a43363Smartinh else if (strcasecmp(kw, "objectclass") == 0)
1080a2a43363Smartinh ret = schema_parse_objectclass(schema);
1081a2a43363Smartinh else if (strcasecmp(kw, "objectidentifier") == 0)
1082a2a43363Smartinh ret = schema_parse_objectidentifier(schema);
1083a2a43363Smartinh else {
1084a2a43363Smartinh schema_err(schema, "syntax error at '%s'", kw);
1085a2a43363Smartinh ret = -1;
1086a2a43363Smartinh }
1087a2a43363Smartinh if (ret == -1 && schema->error == 0)
1088a2a43363Smartinh schema_err(schema, "syntax error");
1089a2a43363Smartinh free(kw);
1090a2a43363Smartinh } else if (token == 0) { /* EOF */
1091a2a43363Smartinh break;
1092a2a43363Smartinh } else {
1093a2a43363Smartinh schema_err(schema, "syntax error");
1094a2a43363Smartinh ret = -1;
1095a2a43363Smartinh }
1096a2a43363Smartinh }
1097a2a43363Smartinh
1098a2a43363Smartinh fclose(schema->fp);
1099a2a43363Smartinh schema->fp = NULL;
1100a2a43363Smartinh schema->filename = NULL;
1101a2a43363Smartinh
1102a2a43363Smartinh return ret;
1103a2a43363Smartinh }
1104a2a43363Smartinh
1105b27b53f1Smartinh static int
schema_dump_names(const char * desc,struct name_list * nlist,char * buf,size_t size)1106b27b53f1Smartinh schema_dump_names(const char *desc, struct name_list *nlist,
1107b27b53f1Smartinh char *buf, size_t size)
1108b27b53f1Smartinh {
1109b27b53f1Smartinh struct name *name;
1110b27b53f1Smartinh
1111b27b53f1Smartinh if (nlist == NULL || SLIST_EMPTY(nlist))
1112b27b53f1Smartinh return 0;
1113b27b53f1Smartinh
1114b27b53f1Smartinh if (strlcat(buf, " ", size) >= size ||
1115b27b53f1Smartinh strlcat(buf, desc, size) >= size)
1116b27b53f1Smartinh return -1;
1117b27b53f1Smartinh
1118b27b53f1Smartinh name = SLIST_FIRST(nlist);
1119b27b53f1Smartinh if (SLIST_NEXT(name, next) == NULL) {
1120b27b53f1Smartinh /* single name, no parenthesis */
1121b27b53f1Smartinh if (strlcat(buf, " '", size) >= size ||
1122b27b53f1Smartinh strlcat(buf, name->name, size) >= size ||
1123b27b53f1Smartinh strlcat(buf, "'", size) >= size)
1124b27b53f1Smartinh return -1;
1125b27b53f1Smartinh } else {
1126b27b53f1Smartinh if (strlcat(buf, " ( ", size) >= size)
1127b27b53f1Smartinh return -1;
1128b27b53f1Smartinh SLIST_FOREACH(name, nlist, next)
1129b27b53f1Smartinh if (strlcat(buf, "'", size) >= size ||
1130b27b53f1Smartinh strlcat(buf, name->name, size) >= size ||
1131b27b53f1Smartinh strlcat(buf, "' ", size) >= size)
1132b27b53f1Smartinh return -1;
1133b27b53f1Smartinh if (strlcat(buf, ")", size) >= size)
1134b27b53f1Smartinh return -1;
1135b27b53f1Smartinh }
1136b27b53f1Smartinh
1137b27b53f1Smartinh return 0;
1138b27b53f1Smartinh }
1139b27b53f1Smartinh
1140b27b53f1Smartinh static int
schema_dump_attrlist(const char * desc,struct attr_list * alist,char * buf,size_t size)1141b27b53f1Smartinh schema_dump_attrlist(const char *desc, struct attr_list *alist,
1142b27b53f1Smartinh char *buf, size_t size)
1143b27b53f1Smartinh {
1144b27b53f1Smartinh struct attr_ptr *aptr;
1145b27b53f1Smartinh
1146b27b53f1Smartinh if (alist == NULL || SLIST_EMPTY(alist))
1147b27b53f1Smartinh return 0;
1148b27b53f1Smartinh
1149b27b53f1Smartinh if (strlcat(buf, " ", size) >= size ||
1150b27b53f1Smartinh strlcat(buf, desc, size) >= size)
1151b27b53f1Smartinh return -1;
1152b27b53f1Smartinh
1153b27b53f1Smartinh aptr = SLIST_FIRST(alist);
1154b27b53f1Smartinh if (SLIST_NEXT(aptr, next) == NULL) {
1155b27b53f1Smartinh /* single attribute, no parenthesis */
1156b27b53f1Smartinh if (strlcat(buf, " ", size) >= size ||
1157b27b53f1Smartinh strlcat(buf, ATTR_NAME(aptr->attr_type), size) >= size)
1158b27b53f1Smartinh return -1;
1159b27b53f1Smartinh } else {
1160b27b53f1Smartinh if (strlcat(buf, " ( ", size) >= size)
1161b27b53f1Smartinh return -1;
1162b27b53f1Smartinh SLIST_FOREACH(aptr, alist, next) {
1163b27b53f1Smartinh if (strlcat(buf, ATTR_NAME(aptr->attr_type),
1164b27b53f1Smartinh size) >= size ||
1165b27b53f1Smartinh strlcat(buf, " ", size) >= size)
1166b27b53f1Smartinh return -1;
1167b27b53f1Smartinh if (SLIST_NEXT(aptr, next) != NULL &&
1168b27b53f1Smartinh strlcat(buf, "$ ", size) >= size)
1169b27b53f1Smartinh return -1;
1170b27b53f1Smartinh }
1171b27b53f1Smartinh if (strlcat(buf, ")", size) >= size)
1172b27b53f1Smartinh return -1;
1173b27b53f1Smartinh }
1174b27b53f1Smartinh
1175b27b53f1Smartinh return 0;
1176b27b53f1Smartinh }
1177b27b53f1Smartinh
1178b27b53f1Smartinh static int
schema_dump_objlist(const char * desc,struct obj_list * olist,char * buf,size_t size)1179b27b53f1Smartinh schema_dump_objlist(const char *desc, struct obj_list *olist,
1180b27b53f1Smartinh char *buf, size_t size)
1181b27b53f1Smartinh {
1182b27b53f1Smartinh struct obj_ptr *optr;
1183b27b53f1Smartinh
1184b27b53f1Smartinh if (olist == NULL || SLIST_EMPTY(olist))
1185b27b53f1Smartinh return 0;
1186b27b53f1Smartinh
1187b27b53f1Smartinh if (strlcat(buf, " ", size) >= size ||
1188b27b53f1Smartinh strlcat(buf, desc, size) >= size)
1189b27b53f1Smartinh return -1;
1190b27b53f1Smartinh
1191b27b53f1Smartinh optr = SLIST_FIRST(olist);
1192b27b53f1Smartinh if (SLIST_NEXT(optr, next) == NULL) {
1193b27b53f1Smartinh /* single attribute, no parenthesis */
1194b27b53f1Smartinh if (strlcat(buf, " ", size) >= size ||
1195b27b53f1Smartinh strlcat(buf, OBJ_NAME(optr->object), size) >= size)
1196b27b53f1Smartinh return -1;
1197b27b53f1Smartinh } else {
1198b27b53f1Smartinh if (strlcat(buf, " ( ", size) >= size)
1199b27b53f1Smartinh return -1;
1200b27b53f1Smartinh SLIST_FOREACH(optr, olist, next) {
1201b27b53f1Smartinh if (strlcat(buf, OBJ_NAME(optr->object), size) >= size ||
1202b27b53f1Smartinh strlcat(buf, " ", size) >= size)
1203b27b53f1Smartinh return -1;
1204b27b53f1Smartinh if (SLIST_NEXT(optr, next) != NULL &&
1205b27b53f1Smartinh strlcat(buf, "$ ", size) >= size)
1206b27b53f1Smartinh return -1;
1207b27b53f1Smartinh }
1208b27b53f1Smartinh if (strlcat(buf, ")", size) >= size)
1209b27b53f1Smartinh return -1;
1210b27b53f1Smartinh }
1211b27b53f1Smartinh
1212b27b53f1Smartinh return 0;
1213b27b53f1Smartinh }
1214b27b53f1Smartinh
1215b27b53f1Smartinh int
schema_dump_object(struct object * obj,char * buf,size_t size)1216b27b53f1Smartinh schema_dump_object(struct object *obj, char *buf, size_t size)
1217b27b53f1Smartinh {
1218b27b53f1Smartinh if (strlcpy(buf, "( ", size) >= size ||
1219b27b53f1Smartinh strlcat(buf, obj->oid, size) >= size)
1220b27b53f1Smartinh return -1;
1221b27b53f1Smartinh
1222b27b53f1Smartinh if (schema_dump_names("NAME", obj->names, buf, size) != 0)
1223b27b53f1Smartinh return -1;
1224b27b53f1Smartinh
1225b27b53f1Smartinh if (obj->desc != NULL)
1226b27b53f1Smartinh if (strlcat(buf, " DESC '", size) >= size ||
1227b27b53f1Smartinh strlcat(buf, obj->desc, size) >= size ||
1228b27b53f1Smartinh strlcat(buf, "'", size) >= size)
1229b27b53f1Smartinh return -1;
1230b27b53f1Smartinh
1231b27b53f1Smartinh switch (obj->kind) {
1232b27b53f1Smartinh case KIND_STRUCTURAL:
1233b27b53f1Smartinh if (strlcat(buf, " STRUCTURAL", size) >= size)
1234b27b53f1Smartinh return -1;
1235b27b53f1Smartinh break;
1236b27b53f1Smartinh case KIND_ABSTRACT:
1237b27b53f1Smartinh if (strlcat(buf, " ABSTRACT", size) >= size)
1238b27b53f1Smartinh return -1;
1239b27b53f1Smartinh break;
1240b27b53f1Smartinh case KIND_AUXILIARY:
1241b27b53f1Smartinh if (strlcat(buf, " AUXILIARY", size) >= size)
1242b27b53f1Smartinh return -1;
1243b27b53f1Smartinh break;
1244b27b53f1Smartinh }
1245b27b53f1Smartinh
1246b27b53f1Smartinh if (schema_dump_objlist("SUP", obj->sup, buf, size) != 0)
1247b27b53f1Smartinh return -1;
1248b27b53f1Smartinh
1249b27b53f1Smartinh if (obj->obsolete && strlcat(buf, " OBSOLETE", size) >= size)
1250b27b53f1Smartinh return -1;
1251b27b53f1Smartinh
1252b27b53f1Smartinh if (schema_dump_attrlist("MUST", obj->must, buf, size) != 0)
1253b27b53f1Smartinh return -1;
1254b27b53f1Smartinh
1255b27b53f1Smartinh if (schema_dump_attrlist("MAY", obj->may, buf, size) != 0)
1256b27b53f1Smartinh return -1;
1257b27b53f1Smartinh
1258b27b53f1Smartinh if (strlcat(buf, " )", size) >= size)
1259b27b53f1Smartinh return -1;
1260b27b53f1Smartinh
1261b27b53f1Smartinh return 0;
1262b27b53f1Smartinh }
1263b27b53f1Smartinh
1264b27b53f1Smartinh int
schema_dump_attribute(struct attr_type * at,char * buf,size_t size)1265b27b53f1Smartinh schema_dump_attribute(struct attr_type *at, char *buf, size_t size)
1266b27b53f1Smartinh {
1267b27b53f1Smartinh if (strlcpy(buf, "( ", size) >= size ||
1268b27b53f1Smartinh strlcat(buf, at->oid, size) >= size)
1269b27b53f1Smartinh return -1;
1270b27b53f1Smartinh
1271b27b53f1Smartinh if (schema_dump_names("NAME", at->names, buf, size) != 0)
1272b27b53f1Smartinh return -1;
1273b27b53f1Smartinh
1274b27b53f1Smartinh if (at->desc != NULL)
1275d6f9690cSmartinh if (strlcat(buf, " DESC '", size) >= size ||
1276b27b53f1Smartinh strlcat(buf, at->desc, size) >= size ||
1277b27b53f1Smartinh strlcat(buf, "'", size) >= size)
1278b27b53f1Smartinh return -1;
1279b27b53f1Smartinh
1280b27b53f1Smartinh if (at->obsolete && strlcat(buf, " OBSOLETE", size) >= size)
1281b27b53f1Smartinh return -1;
1282b27b53f1Smartinh
1283b27b53f1Smartinh if (at->sup != NULL)
1284b27b53f1Smartinh if (strlcat(buf, " SUP ", size) >= size ||
1285b27b53f1Smartinh strlcat(buf, ATTR_NAME(at->sup), size) >= size)
1286b27b53f1Smartinh return -1;
1287b27b53f1Smartinh
1288b27b53f1Smartinh if (at->equality != NULL)
1289b27b53f1Smartinh if (strlcat(buf, " EQUALITY ", size) >= size ||
1290d6378167Smartinh strlcat(buf, at->equality->name, size) >= size)
1291b27b53f1Smartinh return -1;
1292b27b53f1Smartinh
1293b27b53f1Smartinh if (at->ordering != NULL)
1294b27b53f1Smartinh if (strlcat(buf, " ORDERING ", size) >= size ||
1295d6378167Smartinh strlcat(buf, at->ordering->name, size) >= size)
1296b27b53f1Smartinh return -1;
1297b27b53f1Smartinh
1298b27b53f1Smartinh if (at->substr != NULL)
1299b27b53f1Smartinh if (strlcat(buf, " SUBSTR ", size) >= size ||
1300d6378167Smartinh strlcat(buf, at->substr->name, size) >= size)
1301b27b53f1Smartinh return -1;
1302b27b53f1Smartinh
1303b27b53f1Smartinh if (at->syntax != NULL)
1304b27b53f1Smartinh if (strlcat(buf, " SYNTAX ", size) >= size ||
13057c686fcdSmartinh strlcat(buf, at->syntax->oid, size) >= size)
1306b27b53f1Smartinh return -1;
1307b27b53f1Smartinh
1308b27b53f1Smartinh if (at->single && strlcat(buf, " SINGLE-VALUE", size) >= size)
1309b27b53f1Smartinh return -1;
1310b27b53f1Smartinh
1311b27b53f1Smartinh if (at->collective && strlcat(buf, " COLLECTIVE", size) >= size)
1312b27b53f1Smartinh return -1;
1313b27b53f1Smartinh
1314b27b53f1Smartinh if (at->immutable && strlcat(buf, " NO-USER-MODIFICATION", size) >= size)
1315b27b53f1Smartinh return -1;
1316b27b53f1Smartinh
1317b27b53f1Smartinh switch (at->usage) {
1318b27b53f1Smartinh case USAGE_USER_APP:
1319b27b53f1Smartinh /* User application usage is the default. */
1320b27b53f1Smartinh break;
1321b27b53f1Smartinh case USAGE_DIR_OP:
1322b27b53f1Smartinh if (strlcat(buf, " USAGE directoryOperation", size) >= size)
1323b27b53f1Smartinh return -1;
1324b27b53f1Smartinh break;
1325b27b53f1Smartinh case USAGE_DIST_OP:
1326b27b53f1Smartinh if (strlcat(buf, " USAGE distributedOperation", size) >= size)
1327b27b53f1Smartinh return -1;
1328b27b53f1Smartinh break;
1329b27b53f1Smartinh case USAGE_DSA_OP:
1330b27b53f1Smartinh if (strlcat(buf, " USAGE dSAOperation", size) >= size)
1331b27b53f1Smartinh return -1;
1332b27b53f1Smartinh break;
1333b27b53f1Smartinh }
1334b27b53f1Smartinh
1335b27b53f1Smartinh if (strlcat(buf, " )", size) >= size)
1336b27b53f1Smartinh return -1;
1337b27b53f1Smartinh
1338b27b53f1Smartinh return 0;
1339b27b53f1Smartinh }
1340b27b53f1Smartinh
13416c195454Smartinh int
schema_dump_match_rule(struct match_rule * mr,char * buf,size_t size)13426c195454Smartinh schema_dump_match_rule(struct match_rule *mr, char *buf, size_t size)
13436c195454Smartinh {
13446c195454Smartinh if (strlcpy(buf, "( ", size) >= size ||
13456c195454Smartinh strlcat(buf, mr->oid, size) >= size ||
13466c195454Smartinh strlcat(buf, " NAME '", size) >= size ||
13476c195454Smartinh strlcat(buf, mr->name, size) >= size ||
13486c195454Smartinh strlcat(buf, "' SYNTAX ", size) >= size ||
13496c195454Smartinh strlcat(buf, mr->syntax_oid, size) >= size ||
13506c195454Smartinh strlcat(buf, " )", size) >= size)
13516c195454Smartinh return -1;
13526c195454Smartinh
13536c195454Smartinh return 0;
13546c195454Smartinh }
13556c195454Smartinh
1356