File Coverage

src/ldns/util.c
Criterion Covered Total %
statement 107 282 37.9
branch 44 160 27.5
condition n/a
subroutine n/a
pod n/a
total 151 442 34.1


line stmt bran cond sub pod time code
1             /*
2             * util.c
3             *
4             * some general memory functions
5             *
6             * a Net::DNS like library for C
7             *
8             * (c) NLnet Labs, 2004-2006
9             *
10             * See the file LICENSE for the license
11             */
12              
13             #include
14              
15             #include
16             #include
17             #include
18             #include
19             #include
20             #include
21             #include
22             #include
23             #include
24              
25             #ifdef HAVE_SSL
26             #include
27             #endif
28              
29             ldns_lookup_table *
30 85           ldns_lookup_by_name(ldns_lookup_table *table, const char *name)
31             {
32 225 100         while (table->name != NULL) {
33 205 100         if (strcasecmp(name, table->name) == 0)
34 65           return table;
35 140           table++;
36             }
37 20           return NULL;
38             }
39              
40             ldns_lookup_table *
41 46           ldns_lookup_by_id(ldns_lookup_table *table, int id)
42             {
43 282 50         while (table->name != NULL) {
44 282 100         if (table->id == id)
45 46           return table;
46 236           table++;
47             }
48 0           return NULL;
49             }
50              
51             int
52 320           ldns_get_bit(uint8_t bits[], size_t index)
53             {
54             /*
55             * The bits are counted from left to right, so bit #0 is the
56             * left most bit.
57             */
58 320           return (int) (bits[index / 8] & (1 << (7 - index % 8)));
59             }
60              
61             int
62 0           ldns_get_bit_r(uint8_t bits[], size_t index)
63             {
64             /*
65             * The bits are counted from right to left, so bit #0 is the
66             * right most bit.
67             */
68 0           return (int) bits[index / 8] & (1 << (index % 8));
69             }
70              
71             void
72 0           ldns_set_bit(uint8_t *byte, int bit_nr, bool value)
73             {
74             /*
75             * The bits are counted from right to left, so bit #0 is the
76             * right most bit.
77             */
78 0 0         if (bit_nr >= 0 && bit_nr < 8) {
    0          
79 0 0         if (value) {
80 0           *byte = *byte | (0x01 << bit_nr);
81             } else {
82 0           *byte = *byte & ~(0x01 << bit_nr);
83             }
84             }
85 0           }
86              
87             int
88 16           ldns_hexdigit_to_int(char ch)
89             {
90 16           switch (ch) {
91 0           case '0': return 0;
92 2           case '1': return 1;
93 2           case '2': return 2;
94 1           case '3': return 3;
95 1           case '4': return 4;
96 1           case '5': return 5;
97 1           case '6': return 6;
98 1           case '7': return 7;
99 1           case '8': return 8;
100 2           case '9': return 9;
101 1           case 'a': case 'A': return 10;
102 2           case 'b': case 'B': return 11;
103 1           case 'c': case 'C': return 12;
104 0           case 'd': case 'D': return 13;
105 0           case 'e': case 'E': return 14;
106 0           case 'f': case 'F': return 15;
107             default:
108 0           return -1;
109             }
110             }
111              
112             char
113 0           ldns_int_to_hexdigit(int i)
114             {
115 0           switch (i) {
116 0           case 0: return '0';
117 0           case 1: return '1';
118 0           case 2: return '2';
119 0           case 3: return '3';
120 0           case 4: return '4';
121 0           case 5: return '5';
122 0           case 6: return '6';
123 0           case 7: return '7';
124 0           case 8: return '8';
125 0           case 9: return '9';
126 0           case 10: return 'a';
127 0           case 11: return 'b';
128 0           case 12: return 'c';
129 0           case 13: return 'd';
130 0           case 14: return 'e';
131 0           case 15: return 'f';
132             default:
133 0           abort();
134             }
135             }
136              
137             int
138 0           ldns_hexstring_to_data(uint8_t *data, const char *str)
139             {
140             size_t i;
141              
142 0 0         if (!str || !data) {
    0          
143 0           return -1;
144             }
145              
146 0 0         if (strlen(str) % 2 != 0) {
147 0           return -2;
148             }
149              
150 0 0         for (i = 0; i < strlen(str) / 2; i++) {
151 0           data[i] =
152 0           16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) +
153 0           (uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]);
154             }
155              
156 0           return (int) i;
157             }
158              
159             const char *
160 1           ldns_version(void)
161             {
162 1           return (char*)LDNS_VERSION;
163             }
164              
165             /* Number of days per month (except for February in leap years). */
166             static const int mdays[] = {
167             31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
168             };
169              
170             #define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y)))
171             #define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y)))
172              
173             static int
174 2           is_leap_year(int year)
175             {
176 2 50         return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0
    0          
    50          
    0          
    0          
    0          
    0          
177 0 0         || LDNS_MOD(year, 400) == 0);
    0          
178             }
179              
180             static int
181 2           leap_days(int y1, int y2)
182             {
183 2           --y1;
184 2           --y2;
185 4 50         return (LDNS_DIV(y2, 4) - LDNS_DIV(y1, 4)) -
    50          
186 2 50         (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) +
    50          
187 2 50         (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400));
    50          
188             }
189              
190             /*
191             * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
192             */
193             time_t
194 2           ldns_mktime_from_utc(const struct tm *tm)
195             {
196 2           int year = 1900 + tm->tm_year;
197 2           time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year);
198             time_t hours;
199             time_t minutes;
200             time_t seconds;
201             int i;
202              
203 22 100         for (i = 0; i < tm->tm_mon; ++i) {
204 20           days += mdays[i];
205             }
206 2 50         if (tm->tm_mon > 1 && is_leap_year(year)) {
    50          
207 0           ++days;
208             }
209 2           days += tm->tm_mday - 1;
210              
211 2           hours = days * 24 + tm->tm_hour;
212 2           minutes = hours * 60 + tm->tm_min;
213 2           seconds = minutes * 60 + tm->tm_sec;
214              
215 2           return seconds;
216             }
217              
218             time_t
219 0           mktime_from_utc(const struct tm *tm)
220             {
221 0           return ldns_mktime_from_utc(tm);
222             }
223              
224             #if SIZEOF_TIME_T <= 4
225              
226             static void
227             ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result)
228             {
229             int year = 1970;
230             int new_year;
231              
232             while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) {
233             new_year = year + (int) LDNS_DIV(days, 365);
234             days -= (new_year - year) * 365;
235             days -= leap_days(year, new_year);
236             year = new_year;
237             }
238             result->tm_year = year;
239             result->tm_yday = (int) days;
240             }
241              
242             /* Number of days per month in a leap year. */
243             static const int leap_year_mdays[] = {
244             31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
245             };
246              
247             static void
248             ldns_mon_and_mday_from_year_and_yday(struct tm *result)
249             {
250             int idays = result->tm_yday;
251             const int *mon_lengths = is_leap_year(result->tm_year) ?
252             leap_year_mdays : mdays;
253              
254             result->tm_mon = 0;
255             while (idays >= mon_lengths[result->tm_mon]) {
256             idays -= mon_lengths[result->tm_mon++];
257             }
258             result->tm_mday = idays + 1;
259             }
260              
261             static void
262             ldns_wday_from_year_and_yday(struct tm *result)
263             {
264             result->tm_wday = 4 /* 1-1-1970 was a thursday */
265             + LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7)
266             + leap_days(1970, result->tm_year)
267             + result->tm_yday;
268             result->tm_wday = LDNS_MOD(result->tm_wday, 7);
269             if (result->tm_wday < 0) {
270             result->tm_wday += 7;
271             }
272             }
273              
274             static struct tm *
275             ldns_gmtime64_r(int64_t clock, struct tm *result)
276             {
277             result->tm_isdst = 0;
278             result->tm_sec = (int) LDNS_MOD(clock, 60);
279             clock = LDNS_DIV(clock, 60);
280             result->tm_min = (int) LDNS_MOD(clock, 60);
281             clock = LDNS_DIV(clock, 60);
282             result->tm_hour = (int) LDNS_MOD(clock, 24);
283             clock = LDNS_DIV(clock, 24);
284              
285             ldns_year_and_yday_from_days_since_epoch(clock, result);
286             ldns_mon_and_mday_from_year_and_yday(result);
287             ldns_wday_from_year_and_yday(result);
288             result->tm_year -= 1900;
289              
290             return result;
291             }
292              
293             #endif /* SIZEOF_TIME_T <= 4 */
294              
295             static int64_t
296 0           ldns_serial_arithmitics_time(int32_t time, time_t now)
297             {
298 0           int32_t offset = time - (int32_t) now;
299 0           return (int64_t) now + offset;
300             }
301              
302              
303             struct tm *
304 0           ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result)
305             {
306             #if SIZEOF_TIME_T <= 4
307             int64_t secs_since_epoch = ldns_serial_arithmitics_time(time, now);
308             return ldns_gmtime64_r(secs_since_epoch, result);
309             #else
310 0           time_t secs_since_epoch = ldns_serial_arithmitics_time(time, now);
311 0           return gmtime_r(&secs_since_epoch, result);
312             #endif
313             }
314              
315             /**
316             * Init the random source
317             * applications should call this if they need entropy data within ldns
318             * If openSSL is available, it is automatically seeded from /dev/urandom
319             * or /dev/random
320             *
321             * If you need more entropy, or have no openssl available, this function
322             * MUST be called at the start of the program
323             *
324             * If openssl *is* available, this function just adds more entropy
325             **/
326             int
327 0           ldns_init_random(FILE *fd, unsigned int size)
328             {
329             /* if fp is given, seed srandom with data from file
330             otherwise use /dev/urandom */
331             FILE *rand_f;
332             uint8_t *seed;
333 0           size_t read = 0;
334             unsigned int seed_i;
335             struct timeval tv;
336              
337             /* we'll need at least sizeof(unsigned int) bytes for the
338             standard prng seed */
339 0 0         if (size < (unsigned int) sizeof(seed_i)){
340 0           size = (unsigned int) sizeof(seed_i);
341             }
342              
343 0           seed = LDNS_XMALLOC(uint8_t, size);
344 0 0         if(!seed) {
345 0           return 1;
346             }
347              
348 0 0         if (!fd) {
349 0 0         if ((rand_f = fopen("/dev/urandom", "r")) == NULL) {
350             /* no readable /dev/urandom, try /dev/random */
351 0 0         if ((rand_f = fopen("/dev/random", "r")) == NULL) {
352             /* no readable /dev/random either, and no entropy
353             source given. we'll have to improvise */
354 0 0         for (read = 0; read < size; read++) {
355 0           gettimeofday(&tv, NULL);
356 0           seed[read] = (uint8_t) (tv.tv_usec % 256);
357             }
358             } else {
359 0           read = fread(seed, 1, size, rand_f);
360             }
361             } else {
362 0           read = fread(seed, 1, size, rand_f);
363             }
364             } else {
365 0           rand_f = fd;
366 0           read = fread(seed, 1, size, rand_f);
367             }
368              
369 0 0         if (read < size) {
370 0           LDNS_FREE(seed);
371 0 0         if (!fd) fclose(rand_f);
372 0           return 1;
373             } else {
374             #ifdef HAVE_SSL
375             /* Seed the OpenSSL prng (most systems have it seeded
376             automatically, in that case this call just adds entropy */
377 0           RAND_seed(seed, (int) size);
378             #else
379             /* Seed the standard prng, only uses the first
380             * unsigned sizeof(unsiged int) bytes found in the entropy pool
381             */
382             memcpy(&seed_i, seed, sizeof(seed_i));
383             srandom(seed_i);
384             #endif
385 0           LDNS_FREE(seed);
386             }
387              
388 0 0         if (!fd) {
389 0 0         if (rand_f) fclose(rand_f);
390             }
391              
392 0           return 0;
393             }
394              
395             /**
396             * Get random number.
397             *
398             */
399             uint16_t
400 51           ldns_get_random(void)
401             {
402 51           uint16_t rid = 0;
403             #ifdef HAVE_SSL
404 51 50         if (RAND_bytes((unsigned char*)&rid, 2) != 1) {
405 0           rid = (uint16_t) random();
406             }
407             #else
408             rid = (uint16_t) random();
409             #endif
410 51           return rid;
411             }
412              
413             /*
414             * BubbleBabble code taken from OpenSSH
415             * Copyright (c) 2001 Carsten Raskgaard. All rights reserved.
416             */
417             char *
418 0           ldns_bubblebabble(uint8_t *data, size_t len)
419             {
420 0           char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
421 0           char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
422             'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
423 0           size_t i, j = 0, rounds, seed = 1;
424             char *retval;
425              
426 0           rounds = (len / 2) + 1;
427 0           retval = LDNS_XMALLOC(char, rounds * 6);
428 0 0         if(!retval) return NULL;
429 0           retval[j++] = 'x';
430 0 0         for (i = 0; i < rounds; i++) {
431             size_t idx0, idx1, idx2, idx3, idx4;
432 0 0         if ((i + 1 < rounds) || (len % 2 != 0)) {
    0          
433 0           idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) +
434             seed) % 6;
435 0           idx1 = (((size_t)(data[2 * i])) >> 2) & 15;
436 0           idx2 = ((((size_t)(data[2 * i])) & 3) +
437 0           (seed / 6)) % 6;
438 0           retval[j++] = vowels[idx0];
439 0           retval[j++] = consonants[idx1];
440 0           retval[j++] = vowels[idx2];
441 0 0         if ((i + 1) < rounds) {
442 0           idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15;
443 0           idx4 = (((size_t)(data[(2 * i) + 1]))) & 15;
444 0           retval[j++] = consonants[idx3];
445 0           retval[j++] = '-';
446 0           retval[j++] = consonants[idx4];
447 0           seed = ((seed * 5) +
448 0           ((((size_t)(data[2 * i])) * 7) +
449 0           ((size_t)(data[(2 * i) + 1])))) % 36;
450             }
451             } else {
452 0           idx0 = seed % 6;
453 0           idx1 = 16;
454 0           idx2 = seed / 6;
455 0           retval[j++] = vowels[idx0];
456 0           retval[j++] = consonants[idx1];
457 0           retval[j++] = vowels[idx2];
458             }
459             }
460 0           retval[j++] = 'x';
461 0           retval[j++] = '\0';
462 0           return retval;
463             }
464              
465             /*
466             * For backwards compatibility, because we have always exported this symbol.
467             */
468             #ifdef HAVE_B64_NTOP
469             int ldns_b64_ntop(const uint8_t* src, size_t srclength,
470             char *target, size_t targsize);
471             {
472             return b64_ntop(src, srclength, target, targsize);
473             }
474             #endif
475              
476             /*
477             * For backwards compatibility, because we have always exported this symbol.
478             */
479             #ifdef HAVE_B64_PTON
480             int ldns_b64_pton(const char* src, uint8_t *target, size_t targsize)
481             {
482             return b64_pton(src, target, targsize);
483             }
484             #endif
485              
486              
487             static int
488 2           ldns_b32_ntop_base(const uint8_t* src, size_t src_sz,
489             char* dst, size_t dst_sz,
490             bool extended_hex, bool add_padding)
491             {
492             size_t ret_sz;
493 2 50         const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv"
494             : "abcdefghijklmnopqrstuvwxyz234567";
495              
496 2           size_t c = 0; /* c is used to carry partial base32 character over
497             * byte boundaries for sizes with a remainder.
498             * (i.e. src_sz % 5 != 0)
499             */
500              
501 2           ret_sz = add_padding ? ldns_b32_ntop_calculate_size(src_sz)
502 2 50         : ldns_b32_ntop_calculate_size_no_padding(src_sz);
503            
504             /* Do we have enough space? */
505 2 50         if (dst_sz < ret_sz + 1)
506 0           return -1;
507              
508             /* We know the size; terminate the string */
509 2           dst[ret_sz] = '\0';
510              
511             /* First process all chunks of five */
512 10 100         while (src_sz >= 5) {
513             /* 00000... ........ ........ ........ ........ */
514 8           dst[0] = b32[(src[0] ) >> 3];
515              
516             /* .....111 11...... ........ ........ ........ */
517 8           dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6];
518              
519             /* ........ ..22222. ........ ........ ........ */
520 8           dst[2] = b32[(src[1] & 0x3e) >> 1];
521              
522             /* ........ .......3 3333.... ........ ........ */
523 8           dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4];
524              
525             /* ........ ........ ....4444 4....... ........ */
526 8           dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7];
527              
528             /* ........ ........ ........ .55555.. ........ */
529 8           dst[5] = b32[(src[3] & 0x7c) >> 2];
530              
531             /* ........ ........ ........ ......66 666..... */
532 8           dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5];
533              
534             /* ........ ........ ........ ........ ...77777 */
535 8           dst[7] = b32[(src[4] & 0x1f) ];
536              
537 8           src_sz -= 5;
538 8           src += 5;
539 8           dst += 8;
540             }
541             /* Process what remains */
542 2           switch (src_sz) {
543             case 4: /* ........ ........ ........ ......66 666..... */
544 0           dst[6] = b32[(src[3] & 0x03) << 3];
545              
546             /* ........ ........ ........ .55555.. ........ */
547 0           dst[5] = b32[(src[3] & 0x7c) >> 2];
548              
549             /* ........ ........ ....4444 4....... ........ */
550 0           c = src[3] >> 7 ;
551 0           case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c];
552              
553             /* ........ .......3 3333.... ........ ........ */
554 0           c = src[2] >> 4 ;
555 0           case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c];
556              
557             /* ........ ..22222. ........ ........ ........ */
558 0           dst[2] = b32[(src[1] & 0x3e) >> 1];
559              
560             /* .....111 11...... ........ ........ ........ */
561 0           c = src[1] >> 6 ;
562 0           case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c];
563              
564             /* 00000... ........ ........ ........ ........ */
565 0           dst[0] = b32[ src[0] >> 3];
566             }
567             /* Add padding */
568 2 50         if (add_padding) {
569 2           switch (src_sz) {
570 0           case 1: dst[2] = '=';
571 0           dst[3] = '=';
572 0           case 2: dst[4] = '=';
573 0           case 3: dst[5] = '=';
574 0           dst[6] = '=';
575 0           case 4: dst[7] = '=';
576             }
577             }
578 2           return (int)ret_sz;
579             }
580              
581             int
582 0           ldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
583             {
584 0           return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true);
585             }
586              
587             int
588 2           ldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
589             char* dst, size_t dst_sz)
590             {
591 2           return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true);
592             }
593              
594             #ifndef HAVE_B32_NTOP
595              
596             int
597 0           b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
598             {
599 0           return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true);
600             }
601              
602             int
603 0           b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
604             char* dst, size_t dst_sz)
605             {
606 0           return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true);
607             }
608              
609             #endif /* ! HAVE_B32_NTOP */
610              
611             static int
612 2           ldns_b32_pton_base(const char* src, size_t src_sz,
613             uint8_t* dst, size_t dst_sz,
614             bool extended_hex, bool check_padding)
615             {
616 2           size_t i = 0;
617 2           char ch = '\0';
618             uint8_t buf[8];
619 2           uint8_t* start = dst;
620              
621 10 100         while (src_sz) {
622             /* Collect 8 characters in buf (if possible) */
623 72 100         for (i = 0; i < 8; i++) {
624              
625             do {
626 64           ch = *src++;
627 64           --src_sz;
628              
629 64 50         } while (isspace(ch) && src_sz > 0);
    0          
630              
631 64 50         if (ch == '=' || ch == '\0')
    50          
632             break;
633              
634 64 50         else if (extended_hex)
635              
636 64 50         if (ch >= '0' && ch <= '9')
    100          
637 21           buf[i] = (uint8_t)ch - '0';
638 43 50         else if (ch >= 'a' && ch <= 'v')
    0          
639 0           buf[i] = (uint8_t)ch - 'a' + 10;
640 43 50         else if (ch >= 'A' && ch <= 'V')
    50          
641 43           buf[i] = (uint8_t)ch - 'A' + 10;
642             else
643 64           return -1;
644              
645 0 0         else if (ch >= 'a' && ch <= 'z')
    0          
646 0           buf[i] = (uint8_t)ch - 'a';
647 0 0         else if (ch >= 'A' && ch <= 'Z')
    0          
648 0           buf[i] = (uint8_t)ch - 'A';
649 0 0         else if (ch >= '2' && ch <= '7')
    0          
650 0           buf[i] = (uint8_t)ch - '2' + 26;
651             else
652 0           return -1;
653             }
654             /* Less that 8 characters. We're done. */
655 8 50         if (i < 8)
656 0           break;
657              
658             /* Enough space available at the destination? */
659 8 50         if (dst_sz < 5)
660 0           return -1;
661              
662             /* 00000... ........ ........ ........ ........ */
663             /* .....111 11...... ........ ........ ........ */
664 8           dst[0] = buf[0] << 3 | buf[1] >> 2;
665              
666             /* .....111 11...... ........ ........ ........ */
667             /* ........ ..22222. ........ ........ ........ */
668             /* ........ .......3 3333.... ........ ........ */
669 8           dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
670              
671             /* ........ .......3 3333.... ........ ........ */
672             /* ........ ........ ....4444 4....... ........ */
673 8           dst[2] = buf[3] << 4 | buf[4] >> 1;
674              
675             /* ........ ........ ....4444 4....... ........ */
676             /* ........ ........ ........ .55555.. ........ */
677             /* ........ ........ ........ ......66 666..... */
678 8           dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
679              
680             /* ........ ........ ........ ......66 666..... */
681             /* ........ ........ ........ ........ ...77777 */
682 8           dst[4] = buf[6] << 5 | buf[7];
683              
684 8           dst += 5;
685 8           dst_sz -= 5;
686             }
687             /* Not ending on a eight byte boundary? */
688 2 50         if (i > 0 && i < 8) {
    50          
689              
690             /* Enough space available at the destination? */
691 0 0         if (dst_sz < (i + 1) / 2)
692 0           return -1;
693              
694 0           switch (i) {
695             case 7: /* ........ ........ ........ ......66 666..... */
696             /* ........ ........ ........ .55555.. ........ */
697             /* ........ ........ ....4444 4....... ........ */
698 0           dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
699              
700             case 5: /* ........ ........ ....4444 4....... ........ */
701             /* ........ .......3 3333.... ........ ........ */
702 0           dst[2] = buf[3] << 4 | buf[4] >> 1;
703              
704             case 4: /* ........ .......3 3333.... ........ ........ */
705             /* ........ ..22222. ........ ........ ........ */
706             /* .....111 11...... ........ ........ ........ */
707 0           dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
708              
709             case 2: /* .....111 11...... ........ ........ ........ */
710             /* 00000... ........ ........ ........ ........ */
711 0           dst[0] = buf[0] << 3 | buf[1] >> 2;
712              
713 0           break;
714              
715             default:
716 0           return -1;
717             }
718 0           dst += (i + 1) / 2;
719              
720 0 0         if (check_padding) {
721             /* Check remaining padding characters */
722 0 0         if (ch != '=')
723 0           return -1;
724              
725             /* One down, 8 - i - 1 more to come... */
726 0 0         for (i = 8 - i - 1; i > 0; i--) {
727              
728             do {
729 0 0         if (src_sz == 0)
730 0           return -1;
731 0           ch = *src++;
732 0           src_sz--;
733              
734 0 0         } while (isspace(ch));
735              
736 0 0         if (ch != '=')
737 0           return -1;
738             }
739             }
740             }
741 2           return dst - start;
742             }
743              
744             int
745 0           ldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
746             {
747 0           return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true);
748             }
749              
750             int
751 2           ldns_b32_pton_extended_hex(const char* src, size_t src_sz,
752             uint8_t* dst, size_t dst_sz)
753             {
754 2           return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true);
755             }
756              
757             #ifndef HAVE_B32_PTON
758              
759             int
760 0           b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
761             {
762 0           return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true);
763             }
764              
765             int
766 0           b32_pton_extended_hex(const char* src, size_t src_sz,
767             uint8_t* dst, size_t dst_sz)
768             {
769 0           return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true);
770             }
771              
772             #endif /* ! HAVE_B32_PTON */
773