Remove unneeded inclusions of <sys/cdefs.h> throughout the tree.
[dragonfly.git] / sbin / iscontrol / misc.c
1 /*-
2  * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27
28 /*
29  | $Id: misc.c,v 2.1 2006/11/12 08:06:51 danny Exp $
30  */
31
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/sysctl.h>
36
37 #include <netinet/in.h>
38 #include <netinet/tcp.h>
39 #include <arpa/inet.h>
40 #if __FreeBSD_version < 500000
41 #include <sys/time.h>
42 #endif
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46
47 #include "misc.h"
48
49 static inline char
50 c2b(unsigned char c)
51 {
52      switch(c) {
53      case '0' ... '9':
54           return c - '0';
55      case 'a' ... 'f':
56           return c - 'a' + 10;
57      case 'A' ... 'F':
58           return c - 'A' + 10;
59      }
60      return 0;
61 }
62
63 static char     base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
64                            "abcdefghijklmnopqrstuvwxyz"
65                            "0123456789+/";
66
67 static __inline unsigned char
68 c64tobin(unsigned char c64)
69 {
70      int        i;
71      for(i = 0; i < 64; i++)
72           if(base64[i] == c64)
73                break;
74      return i;
75 }
76 /*
77  | according to rfc3720, the binary string
78  | cannot be larger than 1024 - but i can't find it :-) XXX
79  | not enforced yet.
80  */
81 int
82 str2bin(char *str, char **rsp)
83 {
84      char       *src, *dst, *tmp;
85      int        i, len = 0;
86
87      src = str;
88      tmp = NULL;
89      if(strncasecmp("0x", src, 2) == 0) {
90           src += 2;
91           len = strlen(src);
92
93           if((tmp = malloc((len+1)/2)) == NULL) {
94                // XXX: print some error?
95                return 0;
96           }
97           dst = tmp;
98           if(len & 1)
99                *dst++ = c2b(*src++);
100           while(*src) {
101                *dst = c2b(*src++) << 4;
102                *dst++ |= c2b(*src++);
103           }
104           len = dst - tmp;
105      } else
106      if(strncasecmp("0b", src , 2) == 0) {
107           // base64
108           unsigned char b6;
109
110           src += 2;
111           len = strlen(src) / 4 * 3;
112           if((tmp = malloc(len)) == NULL) {
113                // XXX: print some error?
114                return 0;
115           }
116           dst = tmp;
117           i = 0;
118           while(*src && ((b6 = c64tobin(*src++)) != 64)) {
119                switch(i % 4) {
120                case 0:
121                     *dst = b6 << 2;
122                     break;
123                case 1:
124                     *dst++ |= b6 >> 4;
125                     *dst = b6 << 4;
126                     break;
127                case 2:
128                     *dst++ |= b6 >> 2;
129                     *dst = b6 << 6;
130                     break;
131                case 3:
132                     *dst++ |= b6;
133                     break;
134                }
135                i++;
136           }
137           len = dst - tmp;
138      }
139      else {
140           /*
141            | assume it to be an ascii string, so just copy it
142            */
143           len = strlen(str);
144           if((tmp = malloc(len)) == NULL)
145                return 0;
146           dst = tmp;
147           src = str;
148           while(*src)
149                *dst++ = *src++;
150      }
151
152      *rsp = tmp;
153      return len;
154 }
155
156 char *
157 bin2str(char *encoding, unsigned char *md, int blen)
158 {
159      int        len;
160      char       *dst, *ds;
161      unsigned char *cp;
162
163      if(strncasecmp(encoding, "0x", 2) == 0) {
164           char  ofmt[5];
165
166           len = blen * 2;
167           dst = malloc(len + 3);
168           strcpy(dst, encoding);
169           ds = dst + 2;
170           cp = md;
171           sprintf(ofmt, "%%02%c", encoding[1]);
172           while(blen-- > 0) {
173                sprintf(ds, ofmt, *cp++);
174                ds += 2;
175           }
176           *ds = 0;
177           return dst;
178      }
179      if(strncasecmp(encoding, "0b", 2) == 0) {
180           int i, b6;
181
182           len = (blen + 2) * 4 / 3;
183           dst = malloc(len + 3);
184           strcpy(dst, encoding);
185           ds = dst + 2;
186           cp = md;
187           b6 = 0; // to keep compiler happy.
188           for(i = 0; i < blen; i++) {
189                switch(i % 3) {
190                case 0:
191                     *ds++ = base64[*cp >> 2];
192                     b6 = (*cp & 0x3) << 4;
193                     break;
194                case 1:
195                     b6 += (*cp >> 4);
196                     *ds++ = base64[b6];
197                     b6 = (*cp & 0xf) << 2;
198                     break;
199                case 2:
200                     b6 += (*cp >> 6);
201                     *ds++ = base64[b6];
202                     *ds++ = base64[*cp & 0x3f];
203                }
204                cp++;
205           }
206           switch(blen % 3) {
207           case 0:
208                break;
209           case 1:
210                *ds++ = base64[b6];
211                *ds++ = '=';
212                *ds++ = '=';
213                break;
214           case 2:
215                *ds++ = base64[b6];
216                *ds++ = '=';
217                break;
218           }
219
220           *ds = 0;
221           return dst;
222      }
223
224      return NULL;
225 }