1 /* $OpenBSD: ber.c,v 1.9 2015/02/12 00:30:38 pelikan Exp $ */
5 * Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
6 * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org>
7 * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 #include <sys/types.h>
27 #include <err.h> /* XXX for debug output */
28 #include <stdio.h> /* XXX for debug output */
35 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
37 #define BER_TYPE_CONSTRUCTED 0x20 /* otherwise primitive */
38 #define BER_TYPE_SINGLE_MAX 30
39 #define BER_TAG_MASK 0x1f
40 #define BER_TAG_MORE 0x80 /* more subsequent octets */
41 #define BER_TAG_TYPE_MASK 0x7f
42 #define BER_CLASS_SHIFT 6
44 static int ber_dump_element(struct ber *ber, struct ber_element *root);
45 static void ber_dump_header(struct ber *ber, struct ber_element *root);
46 static void ber_putc(struct ber *ber, u_char c);
47 static void ber_write(struct ber *ber, void *buf, size_t len);
48 static ssize_t get_id(struct ber *b, unsigned long *tag, int *class,
50 static ssize_t get_len(struct ber *b, ssize_t *len);
51 static ssize_t ber_read_element(struct ber *ber, struct ber_element *elm);
52 static ssize_t ber_readbuf(struct ber *b, void *buf, size_t nbytes);
53 static ssize_t ber_getc(struct ber *b, u_char *c);
54 static ssize_t ber_read(struct ber *ber, void *buf, size_t len);
57 #define DPRINTF(...) printf(__VA_ARGS__)
59 #define DPRINTF(...) do { } while (0)
63 ber_get_element(unsigned long encoding)
65 struct ber_element *elm;
67 if ((elm = calloc(1, sizeof(*elm))) == NULL)
70 elm->be_encoding = encoding;
71 ber_set_header(elm, BER_CLASS_UNIVERSAL, BER_TYPE_DEFAULT);
77 ber_set_header(struct ber_element *elm, int class, unsigned long type)
79 elm->be_class = class & BER_CLASS_MASK;
80 if (type == BER_TYPE_DEFAULT)
81 type = elm->be_encoding;
86 ber_link_elements(struct ber_element *prev, struct ber_element *elm)
89 if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
90 prev->be_encoding == BER_TYPE_SET) &&
99 ber_unlink_elements(struct ber_element *prev)
101 struct ber_element *elm;
103 if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
104 prev->be_encoding == BER_TYPE_SET) &&
105 prev->be_sub != NULL) {
110 prev->be_next = NULL;
117 ber_replace_elements(struct ber_element *prev, struct ber_element *new)
119 struct ber_element *ber, *next;
121 ber = ber_unlink_elements(prev);
122 next = ber_unlink_elements(ber);
123 ber_link_elements(new, next);
124 ber_link_elements(prev, new);
126 /* cleanup old element */
127 ber_free_elements(ber);
131 ber_add_sequence(struct ber_element *prev)
133 struct ber_element *elm;
135 if ((elm = ber_get_element(BER_TYPE_SEQUENCE)) == NULL)
138 ber_link_elements(prev, elm);
144 ber_add_set(struct ber_element *prev)
146 struct ber_element *elm;
148 if ((elm = ber_get_element(BER_TYPE_SET)) == NULL)
151 ber_link_elements(prev, elm);
157 ber_add_enumerated(struct ber_element *prev, long long val)
159 struct ber_element *elm;
161 u_char cur, last = 0;
163 if ((elm = ber_get_element(BER_TYPE_ENUMERATED)) == NULL)
166 elm->be_numeric = val;
168 for (i = 0; i < sizeof(long long); i++) {
170 if (cur != 0 && cur != 0xff)
172 if ((cur == 0 && last & 0x80) ||
173 (cur == 0xff && (last & 0x80) == 0))
178 elm->be_len = len + 1;
180 ber_link_elements(prev, elm);
186 ber_add_integer(struct ber_element *prev, long long val)
188 struct ber_element *elm;
190 u_char cur, last = 0;
192 if ((elm = ber_get_element(BER_TYPE_INTEGER)) == NULL)
195 elm->be_numeric = val;
197 for (i = 0; i < sizeof(long long); i++) {
199 if (cur != 0 && cur != 0xff)
201 if ((cur == 0 && last & 0x80) ||
202 (cur == 0xff && (last & 0x80) == 0))
207 elm->be_len = len + 1;
209 ber_link_elements(prev, elm);
215 ber_get_integer(struct ber_element *elm, long long *n)
217 if (elm->be_encoding != BER_TYPE_INTEGER)
220 *n = elm->be_numeric;
225 ber_get_enumerated(struct ber_element *elm, long long *n)
227 if (elm->be_encoding != BER_TYPE_ENUMERATED)
230 *n = elm->be_numeric;
236 ber_add_boolean(struct ber_element *prev, int bool)
238 struct ber_element *elm;
240 if ((elm = ber_get_element(BER_TYPE_BOOLEAN)) == NULL)
243 elm->be_numeric = bool ? 0xff : 0;
246 ber_link_elements(prev, elm);
252 ber_get_boolean(struct ber_element *elm, int *b)
254 if (elm->be_encoding != BER_TYPE_BOOLEAN)
257 *b = !(elm->be_numeric == 0);
262 ber_add_string(struct ber_element *prev, const char *string)
264 return ber_add_nstring(prev, string, strlen(string));
268 ber_add_nstring(struct ber_element *prev, const char *string0, size_t len)
270 struct ber_element *elm;
273 if ((string = calloc(1, len)) == NULL)
275 if ((elm = ber_get_element(BER_TYPE_OCTETSTRING)) == NULL) {
280 bcopy(string0, string, len);
281 elm->be_val = string;
283 elm->be_free = 1; /* free string on cleanup */
285 ber_link_elements(prev, elm);
291 ber_get_string(struct ber_element *elm, char **s)
293 if (elm->be_encoding != BER_TYPE_OCTETSTRING)
301 ber_get_nstring(struct ber_element *elm, void **p, size_t *len)
303 if (elm->be_encoding != BER_TYPE_OCTETSTRING)
312 ber_add_bitstring(struct ber_element *prev, const void *v0, size_t len)
314 struct ber_element *elm;
317 if ((v = calloc(1, len)) == NULL)
319 if ((elm = ber_get_element(BER_TYPE_BITSTRING)) == NULL) {
327 elm->be_free = 1; /* free string on cleanup */
329 ber_link_elements(prev, elm);
335 ber_get_bitstring(struct ber_element *elm, void **v, size_t *len)
337 if (elm->be_encoding != BER_TYPE_BITSTRING)
346 ber_add_null(struct ber_element *prev)
348 struct ber_element *elm;
350 if ((elm = ber_get_element(BER_TYPE_NULL)) == NULL)
353 ber_link_elements(prev, elm);
359 ber_get_null(struct ber_element *elm)
361 if (elm->be_encoding != BER_TYPE_NULL)
368 ber_add_eoc(struct ber_element *prev)
370 struct ber_element *elm;
372 if ((elm = ber_get_element(BER_TYPE_EOC)) == NULL)
375 ber_link_elements(prev, elm);
381 ber_get_eoc(struct ber_element *elm)
383 if (elm->be_encoding != BER_TYPE_EOC)
390 ber_oid2ber(struct ber_oid *o, u_int8_t *buf, size_t len)
395 if (o->bo_n < BER_MIN_OID_LEN || o->bo_n > BER_MAX_OID_LEN ||
396 o->bo_id[0] > 2 || o->bo_id[1] > 40)
399 v = (o->bo_id[0] * 40) + o->bo_id[1];
400 for (i = 2, j = 0; i <= o->bo_n; v = o->bo_id[i], i++) {
401 for (k = 28; k >= 7; k -= 7) {
402 if (v >= (u_int)(1 << k)) {
404 buf[j] = v >> k | BER_TAG_MORE;
409 buf[j] = v & BER_TAG_TYPE_MASK;
417 ber_string2oid(const char *oidstr, struct ber_oid *o)
419 char *sp, *p, str[BUFSIZ];
422 if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
424 bzero(o, sizeof(*o));
426 /* Parse OID strings in the common forms n.n.n, n_n_n_n, or n-n-n */
427 for (p = sp = str; p != NULL; sp = p) {
428 if ((p = strpbrk(p, "._-")) != NULL)
430 o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
431 if (errstr || o->bo_n > BER_MAX_OID_LEN)
439 ber_add_oid(struct ber_element *prev, struct ber_oid *o)
441 struct ber_element *elm;
445 if ((elm = ber_get_element(BER_TYPE_OBJECT)) == NULL)
448 if ((len = ber_oid2ber(o, NULL, 0)) == 0)
451 if ((buf = calloc(1, len)) == NULL)
458 if (ber_oid2ber(o, buf, len) != len)
461 ber_link_elements(prev, elm);
466 ber_free_elements(elm);
471 ber_add_noid(struct ber_element *prev, struct ber_oid *o, int n)
475 if (n > BER_MAX_OID_LEN)
478 bcopy(&o->bo_id, &no.bo_id, sizeof(no.bo_id));
480 return (ber_add_oid(prev, &no));
484 ber_add_oidstring(struct ber_element *prev, const char *oidstr)
488 if (ber_string2oid(oidstr, &o) == -1)
491 return (ber_add_oid(prev, &o));
495 ber_get_oid(struct ber_element *elm, struct ber_oid *o)
498 size_t len, i = 0, j = 0;
500 if (elm->be_encoding != BER_TYPE_OBJECT)
509 bzero(o, sizeof(*o));
510 o->bo_id[j++] = buf[i] / 40;
511 o->bo_id[j++] = buf[i++] % 40;
512 for (; i < len && j < BER_MAX_OID_LEN; i++) {
513 o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
524 ber_printf_elements(struct ber_element *ber, char *fmt, ...)
534 struct ber_element *sub = ber, *e;
540 p = va_arg(ap, void *);
541 len = va_arg(ap, size_t);
542 if ((ber = ber_add_bitstring(ber, p, len)) == NULL)
547 if ((ber = ber_add_boolean(ber, d)) == NULL)
552 if ((ber = ber_add_integer(ber, d)) == NULL)
556 e = va_arg(ap, struct ber_element *);
557 ber_link_elements(ber, e);
560 i = va_arg(ap, long long);
561 if ((ber = ber_add_enumerated(ber, i)) == NULL)
565 i = va_arg(ap, long long);
566 if ((ber = ber_add_integer(ber, i)) == NULL)
570 o = va_arg(ap, struct ber_oid *);
571 if ((ber = ber_add_oid(ber, o)) == NULL)
575 s = va_arg(ap, char *);
576 if ((ber = ber_add_oidstring(ber, s)) == NULL)
580 s = va_arg(ap, char *);
581 if ((ber = ber_add_string(ber, s)) == NULL)
585 class = va_arg(ap, int);
586 type = va_arg(ap, unsigned long);
587 ber_set_header(ber, class, type);
590 s = va_arg(ap, char *);
591 len = va_arg(ap, size_t);
592 if ((ber = ber_add_nstring(ber, s, len)) == NULL)
596 if ((ber = ber_add_null(ber)) == NULL)
600 if ((ber = sub = ber_add_sequence(ber)) == NULL)
604 if ((ber = sub = ber_add_set(ber)) == NULL)
612 if ((e = ber_add_eoc(ber)) == NULL)
628 ber_scanf_elements(struct ber_element *ber, char *fmt, ...)
636 size_t *len, ret = 0, n = strlen(fmt);
639 struct ber_element *parent[_MAX_SEQ], **e;
641 bzero(parent, sizeof(struct ber_element *) * _MAX_SEQ);
647 ptr = va_arg(ap, void **);
648 len = va_arg(ap, size_t *);
649 if (ber_get_bitstring(ber, ptr, len) == -1)
654 d = va_arg(ap, int *);
655 if (ber_get_boolean(ber, d) == -1)
660 e = va_arg(ap, struct ber_element **);
665 i = va_arg(ap, long long *);
666 if (ber_get_enumerated(ber, i) == -1)
671 i = va_arg(ap, long long *);
672 if (ber_get_integer(ber, i) == -1)
677 o = va_arg(ap, struct ber_oid *);
678 if (ber_get_oid(ber, o) == -1)
686 s = va_arg(ap, char **);
687 if (ber_get_string(ber, s) == -1)
692 d = va_arg(ap, int *);
693 t = va_arg(ap, unsigned long *);
699 ptr = va_arg(ap, void **);
700 len = va_arg(ap, size_t *);
701 if (ber_get_nstring(ber, ptr, len) == -1)
706 if (ber->be_encoding != BER_TYPE_NULL)
711 if (ber->be_encoding != BER_TYPE_EOC)
717 if (ber->be_encoding != BER_TYPE_SEQUENCE &&
718 ber->be_encoding != BER_TYPE_SET)
720 if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
722 parent[++level] = ber;
728 if (level < 0 || parent[level] == NULL)
730 ber = parent[level--];
737 if (ber->be_next == NULL)
742 return (ret == n ? 0 : -1);
751 * write ber elements to the socket
754 * ber holds the socket
755 * root fully populated element tree
758 * >=0 number of bytes written
759 * -1 on failure and sets errno
762 ber_write_elements(struct ber *ber, struct ber_element *root)
766 /* calculate length because only the definite form is required */
767 len = ber_calc_len(root);
768 DPRINTF("write ber element of %zd bytes length\n", len);
770 if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
774 if (ber->br_wbuf == NULL) {
775 if ((ber->br_wbuf = malloc(len)) == NULL)
777 ber->br_wend = ber->br_wbuf + len;
780 /* reset write pointer */
781 ber->br_wptr = ber->br_wbuf;
783 if (ber_dump_element(ber, root) == -1)
786 /* XXX this should be moved to a different function */
788 return write(ber->fd, ber->br_wbuf, len);
794 * read ber elements from the socket
797 * ber holds the socket and lot more
798 * root if NULL, build up an element tree from what we receive on
799 * the wire. If not null, use the specified encoding for the
803 * !=NULL, elements read and store in the ber_element tree
804 * NULL, type mismatch or read error
807 ber_read_elements(struct ber *ber, struct ber_element *elm)
809 struct ber_element *root = elm;
812 if ((root = ber_get_element(0)) == NULL)
816 DPRINTF("read ber elements, root %p\n", root);
818 if (ber_read_element(ber, root) == -1) {
819 /* Cleanup if root was allocated by us */
821 ber_free_elements(root);
829 ber_free_elements(struct ber_element *root)
831 if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
832 root->be_encoding == BER_TYPE_SET))
833 ber_free_elements(root->be_sub);
835 ber_free_elements(root->be_next);
836 if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
837 root->be_encoding == BER_TYPE_BITSTRING ||
838 root->be_encoding == BER_TYPE_OBJECT))
844 ber_calc_len(struct ber_element *root)
848 size_t size = 2; /* minimum 1 byte head and 1 byte size */
850 /* calculate the real length of a sequence or set */
851 if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
852 root->be_encoding == BER_TYPE_SET))
853 root->be_len = ber_calc_len(root->be_sub);
855 /* fix header length for extended types */
856 if (root->be_type > BER_TYPE_SINGLE_MAX)
857 for (t = root->be_type; t > 0; t >>= 7)
859 if (root->be_len >= BER_TAG_MORE)
860 for (s = root->be_len; s > 0; s >>= 8)
863 /* calculate the length of the following elements */
865 size += ber_calc_len(root->be_next);
867 /* This is an empty element, do not use a minimal size */
868 if (root->be_type == BER_TYPE_EOC && root->be_len == 0)
871 return (root->be_len + size);
879 ber_dump_element(struct ber *ber, struct ber_element *root)
881 unsigned long long l;
885 ber_dump_header(ber, root);
887 switch (root->be_encoding) {
888 case BER_TYPE_BOOLEAN:
889 case BER_TYPE_INTEGER:
890 case BER_TYPE_ENUMERATED:
891 l = (unsigned long long)root->be_numeric;
892 for (i = root->be_len; i > 0; i--) {
893 u = (l >> ((i - 1) * 8)) & 0xff;
897 case BER_TYPE_BITSTRING:
899 case BER_TYPE_OCTETSTRING:
900 case BER_TYPE_OBJECT:
901 ber_write(ber, root->be_val, root->be_len);
903 case BER_TYPE_NULL: /* no payload */
906 case BER_TYPE_SEQUENCE:
908 if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1)
913 if (root->be_next == NULL)
915 return ber_dump_element(ber, root->be_next);
919 ber_dump_header(struct ber *ber, struct ber_element *root)
921 u_char id = 0, t, buf[8];
925 /* class universal, type encoding depending on type value */
926 /* length encoding */
927 if (root->be_type <= BER_TYPE_SINGLE_MAX) {
928 id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
929 if (root->be_encoding == BER_TYPE_SEQUENCE ||
930 root->be_encoding == BER_TYPE_SET)
931 id |= BER_TYPE_CONSTRUCTED;
935 id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
936 if (root->be_encoding == BER_TYPE_SEQUENCE ||
937 root->be_encoding == BER_TYPE_SET)
938 id |= BER_TYPE_CONSTRUCTED;
942 for (t = 0, type = root->be_type; type > 0; type >>= 7)
943 buf[t++] = type & ~BER_TAG_MORE;
947 buf[t] |= BER_TAG_MORE;
948 ber_putc(ber, buf[t]);
952 if (root->be_len < BER_TAG_MORE) {
954 ber_putc(ber, root->be_len);
956 for (t = 0, size = root->be_len; size > 0; size >>= 8)
957 buf[t++] = size & 0xff;
959 ber_putc(ber, t | BER_TAG_MORE);
962 ber_putc(ber, buf[--t]);
967 ber_putc(struct ber *ber, u_char c)
969 if (ber->br_wptr + 1 <= ber->br_wend)
975 ber_write(struct ber *ber, void *buf, size_t len)
977 if (ber->br_wptr + len <= ber->br_wend)
978 bcopy(buf, ber->br_wptr, len);
983 * extract a BER encoded tag. There are two types, a short and long form.
986 get_id(struct ber *b, unsigned long *tag, int *class, int *cstruct)
992 if (ber_getc(b, &u) == -1)
995 *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
996 *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
998 if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
999 *tag = u & BER_TAG_MASK;
1004 if (ber_getc(b, &u) == -1)
1006 t = (t << 7) | (u & ~BER_TAG_MORE);
1008 } while (u & BER_TAG_MORE);
1010 if (i > sizeof(unsigned long)) {
1020 * extract length of a ber object -- if length is unknown an error is returned.
1023 get_len(struct ber *b, ssize_t *len)
1028 if (ber_getc(b, &u) == -1)
1030 if ((u & BER_TAG_MORE) == 0) {
1036 n = u & ~BER_TAG_MORE;
1037 if (sizeof(ssize_t) < n) {
1043 for (s = 0; n > 0; n--) {
1044 if (ber_getc(b, &u) == -1)
1056 /* invalid encoding */
1066 ber_read_element(struct ber *ber, struct ber_element *elm)
1069 struct ber_element *next;
1071 int i, class, cstruct;
1072 ssize_t len, r, totlen = 0;
1075 if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1077 DPRINTF("ber read got class %d type %lu, %s\n",
1078 class, type, cstruct ? "constructive" : "primitive");
1080 if ((r = get_len(ber, &len)) == -1)
1082 DPRINTF("ber read element size %zd\n", len);
1086 * If using an external buffer and the total size of the element
1087 * is larger, then the external buffer don't bother to continue.
1089 if (ber->fd == -1 && len > ber->br_rend - ber->br_rptr) {
1094 elm->be_type = type;
1096 elm->be_class = class;
1098 if (elm->be_encoding == 0) {
1099 /* try to figure out the encoding via class, type and cstruct */
1101 elm->be_encoding = BER_TYPE_SEQUENCE;
1102 else if (class == BER_CLASS_UNIVERSAL)
1103 elm->be_encoding = type;
1104 else if (ber->br_application != NULL) {
1106 * Ask the application to map the encoding to a
1107 * universal type. For example, a SMI IpAddress
1108 * type is defined as 4 byte OCTET STRING.
1110 elm->be_encoding = (*ber->br_application)(elm);
1112 /* last resort option */
1113 elm->be_encoding = BER_TYPE_NULL;
1116 switch (elm->be_encoding) {
1117 case BER_TYPE_EOC: /* End-Of-Content */
1119 case BER_TYPE_BOOLEAN:
1120 case BER_TYPE_INTEGER:
1121 case BER_TYPE_ENUMERATED:
1122 if (len > (ssize_t)sizeof(long long))
1124 for (i = 0; i < len; i++) {
1125 if (ber_getc(ber, &c) != 1)
1131 /* sign extend if MSB is set */
1132 if (val >> ((i - 1) * 8) & 0x80)
1133 val |= ULLONG_MAX << (i * 8);
1134 elm->be_numeric = val;
1136 case BER_TYPE_BITSTRING:
1137 elm->be_val = malloc(len);
1138 if (elm->be_val == NULL)
1142 ber_read(ber, elm->be_val, len);
1144 case BER_TYPE_OCTETSTRING:
1145 case BER_TYPE_OBJECT:
1146 elm->be_val = malloc(len + 1);
1147 if (elm->be_val == NULL)
1151 ber_read(ber, elm->be_val, len);
1152 ((u_char *)elm->be_val)[len] = '\0';
1154 case BER_TYPE_NULL: /* no payload */
1158 case BER_TYPE_SEQUENCE:
1160 if (elm->be_sub == NULL) {
1161 if ((elm->be_sub = ber_get_element(0)) == NULL)
1166 r = ber_read_element(ber, next);
1170 if (len > 0 && next->be_next == NULL) {
1171 if ((next->be_next = ber_get_element(0)) ==
1175 next = next->be_next;
1183 ber_readbuf(struct ber *b, void *buf, size_t nbytes)
1188 if (b->br_rbuf == NULL)
1191 sz = b->br_rend - b->br_rptr;
1192 len = MINIMUM(nbytes, sz);
1195 return (-1); /* end of buffer and parser wants more data */
1198 bcopy(b->br_rptr, buf, len);
1205 ber_set_readbuf(struct ber *b, void *buf, size_t len)
1207 b->br_rbuf = b->br_rptr = buf;
1208 b->br_rend = (u_int8_t *)buf + len;
1212 ber_get_writebuf(struct ber *b, void **buf)
1214 if (b->br_wbuf == NULL)
1217 return (b->br_wend - b->br_wbuf);
1221 ber_set_application(struct ber *b, unsigned long (*cb)(struct ber_element *))
1223 b->br_application = cb;
1227 ber_free(struct ber *b)
1233 ber_getc(struct ber *b, u_char *c)
1237 * XXX calling read here is wrong in many ways. The most obvious one
1238 * being that we will block till data arrives.
1239 * But for now it is _good enough_ *gulp*
1242 r = ber_readbuf(b, c, 1);
1244 r = read(b->fd, c, 1);
1249 ber_read(struct ber *ber, void *buf, size_t len)
1252 ssize_t r, remain = len;
1255 * XXX calling read here is wrong in many ways. The most obvious one
1256 * being that we will block till data arrives.
1257 * But for now it is _good enough_ *gulp*
1260 while (remain > 0) {
1262 r = ber_readbuf(ber, b, remain);
1264 r = read(ber->fd, b, remain);
1266 if (errno == EINTR || errno == EAGAIN)
1271 return (b - (u_char *)buf);
1275 return (b - (u_char *)buf);