misc.c revision 176012
1/*-
2 * Copyright (c) 2005 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/cdefs.h>
33__FBSDID("$FreeBSD: head/sbin/iscontrol/misc.c 176012 2008-02-05 23:42:38Z pb $");
34
35#include <sys/param.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <sys/sysctl.h>
39
40#include <netinet/in.h>
41#include <netinet/tcp.h>
42#include <arpa/inet.h>
43#if __FreeBSD_version < 500000
44#include <sys/time.h>
45#endif
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49
50static inline char
51c2b(unsigned char c)
52{
53     switch(c) {
54     case '0' ... '9':
55	  return c - '0';
56     case 'a' ... 'f':
57	  return c - 'a' + 10;
58     case 'A' ... 'F':
59	  return c - 'A' + 10;
60     }
61     return 0;
62}
63
64static char 	base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
65	                   "abcdefghijklmnopqrstuvwxyz"
66	                   "0123456789+/";
67
68static __inline unsigned char
69c64tobin(unsigned char c64)
70{
71     int	i;
72     for(i = 0; i < 64; i++)
73	  if(base64[i] == c64)
74	       break;
75     return i;
76}
77/*
78 | according to rfc3720, the binary string
79 | cannot be larger than 1024 - but i can't find it :-) XXX
80 | not enforced yet.
81 */
82int
83str2bin(char *str, char **rsp)
84{
85     char	*src, *dst, *tmp;
86     int	i, len = 0;
87
88     src = str;
89     tmp = NULL;
90     if(strncasecmp("0x", src, 2) == 0) {
91	  src += 2;
92	  len = strlen(src);
93
94	  if((tmp = malloc((len+1)/2)) == NULL) {
95	       // XXX: print some error?
96	       return 0;
97	  }
98	  dst = tmp;
99	  if(len & 1)
100	       *dst++ = c2b(*src++);
101	  while(*src) {
102	       *dst = c2b(*src++) << 4;
103	       *dst++ |= c2b(*src++);
104	  }
105	  len = dst - tmp;
106     } else
107     if(strncasecmp("0b", src , 2) == 0) {
108	  // base64
109	  unsigned char b6;
110
111	  src += 2;
112	  len = strlen(src) / 4 * 3;
113	  if((tmp = malloc(len)) == NULL) {
114	       // XXX: print some error?
115	       return 0;
116	  }
117	  dst = tmp;
118	  i = 0;
119	  while(*src && ((b6 = c64tobin(*src++)) != 64)) {
120	       switch(i % 4) {
121	       case 0:
122		    *dst = b6 << 2;
123		    break;
124	       case 1:
125		    *dst++ |= b6 >> 4;
126		    *dst = b6 << 4;
127		    break;
128	       case 2:
129		    *dst++ |= b6 >> 2;
130		    *dst = b6 << 6;
131		    break;
132	       case 3:
133		    *dst++ |= b6;
134		    break;
135	       }
136	       i++;
137	  }
138	  len = dst - tmp;
139     }
140     else {
141	  /*
142	   | assume it to be an ascii string, so just copy it
143	   */
144	  len = strlen(str);
145	  if((tmp = malloc(len)) == NULL)
146	       return 0;
147	  dst = tmp;
148	  src = str;
149	  while(*src)
150	       *dst++ = *src++;
151     }
152
153     *rsp = tmp;
154     return len;
155}
156
157char *
158bin2str(char *encoding, unsigned char *md, int blen)
159{
160     int	len;
161     unsigned char	*dst, *ds, *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 = (char *)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 = (char *)md;
187	  b6 = 0; // to keep copiler 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