1 
2 const char *
wdns_rrclass_to_str(uint16_t rrclass)3 wdns_rrclass_to_str(uint16_t rrclass)
4 {
5 	switch (rrclass) {
6 	case WDNS_CLASS_IN: return ("IN");
7 	case WDNS_CLASS_CH: return ("CH");
8 	case WDNS_CLASS_HS: return ("HS");
9 	case WDNS_CLASS_NONE: return ("NONE");
10 	case WDNS_CLASS_ANY: return ("ANY");
11 	}
12 
13 	return (NULL);
14 }
15 
16 static struct u16str {
17     uint16_t u16;
18     const char *str;
19 } rrclasses[] = {
20 	{ WDNS_CLASS_ANY, "ANY" },
21 	{ WDNS_CLASS_CH, "CH" },
22 	{ WDNS_CLASS_HS, "HS" },
23 	{ WDNS_CLASS_IN, "IN" },
24 	{ WDNS_CLASS_NONE, "NONE" },
25 };
26 
27 #define num_rrclasses (sizeof(rrclasses) / sizeof(struct u16str))
28 
29 static int
cmp_u16str(const void * a,const void * b)30 cmp_u16str(const void *a, const void *b) {
31     struct u16str *u1 = (struct u16str *) a;
32     struct u16str *u2 = (struct u16str *) b;
33     return (strcasecmp(u1->str, u2->str));
34 }
35 
36 static bool
convert_generic_rrclass(const char * s,long int * val)37 convert_generic_rrclass(const char *s, long int *val) {
38     char *endptr = NULL;
39 
40     if (strlen(s) <= 5)
41         return (false);
42     if (strncasecmp(s, "CLASS", 5) != 0)
43         return (false);
44 
45     s += 5; /* skip leading "CLASS" */
46 
47     *val = strtol(s, &endptr, 10);
48     if (endptr != NULL && *endptr != '\0')
49         return (false);
50     if (*val < 0 || *val > 65535)
51         return (false);
52 
53     return (true);
54 }
55 
56 uint16_t
wdns_str_to_rrclass(const char * str)57 wdns_str_to_rrclass(const char *str) {
58     struct u16str key, *res;
59     key.str = str;
60     res = bsearch(&key, rrclasses, num_rrclasses, sizeof(struct u16str), cmp_u16str);
61     if (res != NULL) {
62         return (res->u16);
63     } else {
64         long int val = 0;
65         if (convert_generic_rrclass(str, &val))
66             return (val);
67     }
68     return (0);
69 }
70