misc.c revision 171568
150476Speter/*-
234925Sdufault * Copyright (c) 2005 Daniel Braniss <danny@cs.huji.ac.il>
334925Sdufault * All rights reserved.
434925Sdufault *
534925Sdufault * Redistribution and use in source and binary forms, with or without
634925Sdufault * modification, are permitted provided that the following conditions
734925Sdufault * are met:
834925Sdufault * 1. Redistributions of source code must retain the above copyright
934925Sdufault *    notice, this list of conditions and the following disclaimer.
1034925Sdufault * 2. Redistributions in binary form must reproduce the above copyright
1134925Sdufault *    notice, this list of conditions and the following disclaimer in the
1234925Sdufault *    documentation and/or other materials provided with the distribution.
1334925Sdufault *
1434925Sdufault * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1534925Sdufault * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1634925Sdufault * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1734925Sdufault * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1834925Sdufault * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1934925Sdufault * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2034925Sdufault * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2134925Sdufault * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2234925Sdufault * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2334925Sdufault * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2434925Sdufault * SUCH DAMAGE.
2534925Sdufault *
2669857Sru */
2734925Sdufault
2879531Sru/*
2934925Sdufault | $Id: misc.c,v 2.1 2006/11/12 08:06:51 danny Exp $
3034925Sdufault */
3134925Sdufault
3234925Sdufault#include <sys/cdefs.h>
3359460Sphantom__FBSDID("$FreeBSD: head/sbin/iscontrol/misc.c 171568 2007-07-24 15:35:02Z scottl $");
3459460Sphantom
3534925Sdufault#include <sys/param.h>
3684306Sru#include <sys/types.h>
3734925Sdufault#include <sys/socket.h>
3834925Sdufault#include <sys/sysctl.h>
3934925Sdufault
4034925Sdufault#include <netinet/in.h>
4134925Sdufault#include <netinet/tcp.h>
4234925Sdufault#include <arpa/inet.h>
4334925Sdufault#if __FreeBSD_version < 500000
44108028Sru#include <sys/time.h>
4534925Sdufault#endif
4634925Sdufault#include <stdlib.h>
4734925Sdufault#include <stdio.h>
4834925Sdufault#include <string.h>
4934925Sdufault
50108087Srustatic inline char
5134925Sdufaultc2b(unsigned char c)
5234925Sdufault{
5334925Sdufault     switch(c) {
5434925Sdufault     case '0' ... '9':
5534925Sdufault	  return c - '0';
5634925Sdufault     case 'a' ... 'f':
5734925Sdufault	  return c - 'a' + 10;
5834925Sdufault     case 'A' ... 'F':
5934925Sdufault	  return c - 'A' + 10;
6034925Sdufault     }
6134925Sdufault     return 0;
6234925Sdufault}
6334925Sdufault
64108028Srustatic char 	base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
6534925Sdufault	                   "abcdefghijklmnopqrstuvwxyz"
6634925Sdufault	                   "0123456789+/";
6734925Sdufault
6834925Sdufaultstatic __inline unsigned char
6934925Sdufaultc64tobin(unsigned char c64)
7034925Sdufault{
7134925Sdufault     int	i;
7234925Sdufault     for(i = 0; i < 64; i++)
7334925Sdufault	  if(base64[i] == c64)
7434925Sdufault	       break;
7534925Sdufault     return i;
7634925Sdufault}
7734925Sdufault/*
7834925Sdufault | according to rfc3720, the binary string
7934925Sdufault | cannot be larger than 1024 - but i can't find it :-) XXX
80116023Scharnier | not enforced yet.
8134925Sdufault */
8234925Sdufaultint
8334925Sdufaultstr2bin(char *str, char **rsp)
8434925Sdufault{
8534925Sdufault     char	*src, *dst, *tmp;
8634925Sdufault     int	i, len = 0;
8734925Sdufault
8834925Sdufault     src = str;
8934925Sdufault     tmp = NULL;
9034925Sdufault     if(strncasecmp("0x", src, 2) == 0) {
9134925Sdufault	  src += 2;
9234925Sdufault	  len = strlen(src);
9334925Sdufault
9434925Sdufault	  if((tmp = malloc((len+1)/2)) == NULL) {
95108087Sru	       // XXX: print some error?
9634925Sdufault	       return 0;
9734925Sdufault	  }
9834925Sdufault	  dst = tmp;
9934925Sdufault	  if(len & 1)
10034925Sdufault	       *dst++ = c2b(*src++);
10134925Sdufault	  while(*src) {
10234925Sdufault	       *dst = c2b(*src++) << 4;
10334925Sdufault	       *dst++ |= c2b(*src++);
10434925Sdufault	  }
10534925Sdufault	  len = dst - tmp;
106108028Sru     } else
10734925Sdufault     if(strncasecmp("0b", src , 2) == 0) {
10834925Sdufault	  // base64
10934925Sdufault	  unsigned char b6;
11034925Sdufault
11134925Sdufault	  src += 2;
11234925Sdufault	  len = strlen(src) / 4 * 3;
11334925Sdufault	  if((tmp = malloc(len)) == NULL) {
11434925Sdufault	       // XXX: print some error?
11534925Sdufault	       return 0;
11634925Sdufault	  }
11734925Sdufault	  dst = tmp;
11834925Sdufault	  i = 0;
119116023Scharnier	  while(*src && ((b6 = c64tobin(*src++)) != 64)) {
12034925Sdufault	       switch(i % 4) {
12134925Sdufault	       case 0:
12234925Sdufault		    *dst = b6 << 2;
12334925Sdufault		    break;
12434925Sdufault	       case 1:
125131504Sru		    *dst++ |= b6 >> 4;
126131504Sru		    *dst = b6 << 4;
12734925Sdufault		    break;
128108028Sru	       case 2:
12934925Sdufault		    *dst++ |= b6 >> 2;
13034925Sdufault		    *dst = b6 << 6;
13168854Sru		    break;
13282642Sru	       case 3:
13334925Sdufault		    *dst++ |= b6;
13434925Sdufault		    break;
13534925Sdufault	       }
13634925Sdufault	       i++;
13759954Sphantom	  }
13834925Sdufault	  len = dst - tmp;
13934925Sdufault     }
14034925Sdufault     else {
14134925Sdufault	  /*
142116023Scharnier	   | assume it to be an ascii string, so just copy it
14334925Sdufault	   */
14434925Sdufault	  len = strlen(str);
14534925Sdufault	  if((tmp = malloc(len)) == NULL)
14634925Sdufault	       return 0;
14734925Sdufault	  dst = tmp;
14834925Sdufault	  src = str;
149108087Sru	  while(*src)
15034925Sdufault	       *dst++ = *src++;
15134925Sdufault     }
15234925Sdufault
15334925Sdufault     *rsp = tmp;
15479366Sru     return len;
15534925Sdufault}
15634925Sdufault
15734925Sdufaultchar *
15838702Swoschbin2str(char *encoding, unsigned char *md, int blen)
15934925Sdufault{
16034925Sdufault     int	len;
16134925Sdufault     char	*dst, *ds, *cp;
16279754Sdd
16334925Sdufault     if(strncasecmp(encoding, "0x", 2) == 0) {
16434925Sdufault	  char	ofmt[5];
165108028Sru
16634925Sdufault	  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