xref: /dragonfly/sbin/iscontrol/misc.c (revision 89a89091)
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 }
226