source: trunk/src/ct/tlv.c @ 654

Revision 654, 4.3 KB checked in by aj, 7 years ago (diff)

Lindent for consistent style.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * TLV handling routines
3 *
4 * Copyright (C) 2003 Olaf Kirch <okir@suse.de>
5 */
6
7#ifdef HAVE_CONFIG_H
8#include <config.h>
9#endif
10#ifdef HAVE_GETOPT_H
11#include <getopt.h>
12#endif
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <unistd.h>
17#include <assert.h>
18
19#include <openct/tlv.h>
20
21/*
22 * Parse TLV data
23 */
24int ct_tlv_parse(ct_tlv_parser_t * parser, ct_buf_t * bp)
25{
26        unsigned int avail, len;
27        unsigned char *p, tag;
28
29        /* Code below relies on it */
30        assert(((ifd_tag_t) - 1) == 255);
31
32        while ((avail = ct_buf_avail(bp)) != 0) {
33                unsigned int header = 2;
34
35                if (avail < 2)
36                        return -1;
37
38                p = (unsigned char *)ct_buf_head(bp);
39                tag = p[0];
40                len = p[1];
41
42                if (tag & __CT_TAG_LARGE) {
43                        parser->use_large_tags = 1;
44                        tag &= ~__CT_TAG_LARGE;
45                        if (avail < 3)
46                                return -1;
47                        len = (len << 8) | p[header++];
48                }
49
50                if (len == 0 || header + len > avail)
51                        return -1;
52
53                parser->val[tag] = p + header;
54                parser->len[tag] = len;
55
56                ct_buf_get(bp, NULL, header + len);
57        }
58
59        return 0;
60}
61
62/*
63 * Extract TLV encoded items as strings, integers, etc.
64 */
65int ct_tlv_get_string(ct_tlv_parser_t * parser, ifd_tag_t tag, char *buf,
66                      size_t size)
67{
68        unsigned char *p;
69        unsigned int len;
70
71        if (!(p = parser->val[tag]))
72                return 0;
73
74        len = parser->len[tag];
75        if (len > size - 1)
76                len = size - 1;
77        strncpy(buf, (const char *)p, len);
78        buf[len] = '\0';
79        return 1;
80}
81
82int ct_tlv_get_int(ct_tlv_parser_t * parser, ifd_tag_t tag, unsigned int *value)
83{
84        unsigned char *p;
85        unsigned int len;
86
87        *value = 0;
88        if (!(p = parser->val[tag]))
89                return 0;
90
91        len = parser->len[tag];
92        while (len--) {
93                *value <<= 8;
94                *value |= *p++;
95        }
96
97        return 1;
98}
99
100int ct_tlv_get_opaque(ct_tlv_parser_t * parser, ifd_tag_t tag,
101                      unsigned char **data, size_t * lenp)
102{
103        unsigned char *p;
104
105        *data = NULL;
106        *lenp = 0;
107
108        if (!(p = parser->val[tag]))
109                return 0;
110        *lenp = parser->len[tag];
111        *data = p;
112        return 1;
113}
114
115int ct_tlv_get_bytes(ct_tlv_parser_t * parser, ifd_tag_t tag, void *buf,
116                     size_t size)
117{
118        unsigned char *p;
119        unsigned int len;
120
121        if (!(p = parser->val[tag]))
122                return 0;
123        len = parser->len[tag];
124        if (len > size)
125                len = size;
126        memcpy(buf, p, len);
127        return len;
128}
129
130/*
131 * Initialize a TLV data builder
132 */
133void ct_tlv_builder_init(ct_tlv_builder_t * builder, ct_buf_t * bp,
134                         int large_tags)
135{
136        memset(builder, 0, sizeof(*builder));
137        builder->use_large_tags = large_tags;
138        builder->buf = bp;
139}
140
141/*
142 * TLV encode objects
143 */
144void ct_tlv_put_int(ct_tlv_builder_t * builder, ifd_tag_t tag,
145                    unsigned int value)
146{
147        int n;
148
149        if (builder->error)
150                return;
151        ct_tlv_put_tag(builder, tag);
152        for (n = 0; (value >> (n + 8)) != 0; n += 8) ;
153        do {
154                ct_tlv_add_byte(builder, value >> n);
155                n -= 8;
156        } while (n >= 0);
157
158        builder->lenp = NULL;
159}
160
161void ct_tlv_put_string(ct_tlv_builder_t * builder, ifd_tag_t tag,
162                       const char *string)
163{
164        if (builder->error)
165                return;
166
167        ct_tlv_put_tag(builder, tag);
168        ct_tlv_add_bytes(builder, (const unsigned char *)string,
169                         strlen(string));
170
171        builder->lenp = NULL;
172}
173
174void ct_tlv_put_opaque(ct_tlv_builder_t * builder, ifd_tag_t tag,
175                       const unsigned char *data, size_t len)
176{
177        if (builder->error)
178                return;
179
180        ct_tlv_put_tag(builder, tag);
181        ct_tlv_add_bytes(builder, data, len);
182
183        builder->lenp = NULL;
184}
185
186void ct_tlv_put_tag(ct_tlv_builder_t * builder, ifd_tag_t tag)
187{
188        ct_buf_t *bp = builder->buf;
189
190        if (builder->error < 0)
191                return;
192        if (builder->use_large_tags)
193                tag |= __CT_TAG_LARGE;
194        if (ct_buf_putc(bp, tag) < 0)
195                goto err;
196        builder->len = 0;
197        builder->lenp = (unsigned char *)ct_buf_tail(bp);
198        if (ct_buf_putc(bp, 0) < 0
199            || (builder->use_large_tags && ct_buf_putc(bp, 0) < 0))
200                goto err;
201        return;
202
203      err:builder->error = -1;
204}
205
206void ct_tlv_add_byte(ct_tlv_builder_t * builder, unsigned char byte)
207{
208        ct_tlv_add_bytes(builder, &byte, 1);
209}
210
211void ct_tlv_add_bytes(ct_tlv_builder_t * builder, const unsigned char *data,
212                      size_t num)
213{
214        ct_buf_t *bp = builder->buf;
215
216        if (builder->error < 0)
217                return;
218
219        if (!builder->lenp)
220                goto error;
221
222        builder->len += num;
223        if (ct_buf_put(bp, data, num) < 0)
224                goto error;
225
226        if (builder->use_large_tags) {
227                if (builder->len > 65535)
228                        goto error;
229                builder->lenp[0] = builder->len >> 8;
230                builder->lenp[1] = builder->len;
231        } else {
232                if (builder->len > 266)
233                        goto error;
234                builder->lenp[0] = builder->len;
235        }
236        return;
237
238      error:
239        builder->error = -1;
240        return;
241}
Note: See TracBrowser for help on using the repository browser.