1171568Sscottl/*-
2211095Sdes * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
3171568Sscottl * All rights reserved.
4171568Sscottl *
5171568Sscottl * Redistribution and use in source and binary forms, with or without
6171568Sscottl * modification, are permitted provided that the following conditions
7171568Sscottl * are met:
8171568Sscottl * 1. Redistributions of source code must retain the above copyright
9171568Sscottl *    notice, this list of conditions and the following disclaimer.
10171568Sscottl * 2. Redistributions in binary form must reproduce the above copyright
11171568Sscottl *    notice, this list of conditions and the following disclaimer in the
12171568Sscottl *    documentation and/or other materials provided with the distribution.
13171568Sscottl *
14171568Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15171568Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16171568Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17171568Sscottl * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18171568Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19171568Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20171568Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21171568Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22171568Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23171568Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24171568Sscottl * SUCH DAMAGE.
25171568Sscottl *
26171568Sscottl */
27171568Sscottl
28171568Sscottl/*
29171568Sscottl | $Id: misc.c,v 2.1 2006/11/12 08:06:51 danny Exp $
30171568Sscottl */
31171568Sscottl
32171568Sscottl#include <sys/cdefs.h>
33171568Sscottl__FBSDID("$FreeBSD$");
34171568Sscottl
35171568Sscottl#include <sys/param.h>
36171568Sscottl#include <sys/types.h>
37171568Sscottl#include <sys/socket.h>
38171568Sscottl#include <sys/sysctl.h>
39171568Sscottl
40171568Sscottl#include <netinet/in.h>
41171568Sscottl#include <netinet/tcp.h>
42171568Sscottl#include <arpa/inet.h>
43171568Sscottl#include <stdlib.h>
44171568Sscottl#include <stdio.h>
45171568Sscottl#include <string.h>
46171568Sscottl
47254657Strasz#include <dev/iscsi_initiator/iscsi.h>
48211095Sdes#include "iscontrol.h"
49211095Sdes
50171568Sscottlstatic inline char
51171568Sscottlc2b(unsigned char c)
52171568Sscottl{
53171568Sscottl     switch(c) {
54171568Sscottl     case '0' ... '9':
55171568Sscottl	  return c - '0';
56171568Sscottl     case 'a' ... 'f':
57171568Sscottl	  return c - 'a' + 10;
58171568Sscottl     case 'A' ... 'F':
59171568Sscottl	  return c - 'A' + 10;
60171568Sscottl     }
61171568Sscottl     return 0;
62171568Sscottl}
63171568Sscottl
64171568Sscottlstatic char 	base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
65171568Sscottl	                   "abcdefghijklmnopqrstuvwxyz"
66171568Sscottl	                   "0123456789+/";
67171568Sscottl
68171568Sscottlstatic __inline unsigned char
69171568Sscottlc64tobin(unsigned char c64)
70171568Sscottl{
71171568Sscottl     int	i;
72171568Sscottl     for(i = 0; i < 64; i++)
73171568Sscottl	  if(base64[i] == c64)
74171568Sscottl	       break;
75171568Sscottl     return i;
76171568Sscottl}
77171568Sscottl/*
78171568Sscottl | according to rfc3720, the binary string
79171568Sscottl | cannot be larger than 1024 - but i can't find it :-) XXX
80171568Sscottl | not enforced yet.
81171568Sscottl */
82171568Sscottlint
83171568Sscottlstr2bin(char *str, char **rsp)
84171568Sscottl{
85171568Sscottl     char	*src, *dst, *tmp;
86171568Sscottl     int	i, len = 0;
87171568Sscottl
88171568Sscottl     src = str;
89171568Sscottl     tmp = NULL;
90171568Sscottl     if(strncasecmp("0x", src, 2) == 0) {
91171568Sscottl	  src += 2;
92171568Sscottl	  len = strlen(src);
93171568Sscottl
94171568Sscottl	  if((tmp = malloc((len+1)/2)) == NULL) {
95171568Sscottl	       // XXX: print some error?
96171568Sscottl	       return 0;
97171568Sscottl	  }
98171568Sscottl	  dst = tmp;
99171568Sscottl	  if(len & 1)
100171568Sscottl	       *dst++ = c2b(*src++);
101171568Sscottl	  while(*src) {
102171568Sscottl	       *dst = c2b(*src++) << 4;
103171568Sscottl	       *dst++ |= c2b(*src++);
104171568Sscottl	  }
105171568Sscottl	  len = dst - tmp;
106171568Sscottl     } else
107171568Sscottl     if(strncasecmp("0b", src , 2) == 0) {
108171568Sscottl	  // base64
109171568Sscottl	  unsigned char b6;
110171568Sscottl
111171568Sscottl	  src += 2;
112171568Sscottl	  len = strlen(src) / 4 * 3;
113171568Sscottl	  if((tmp = malloc(len)) == NULL) {
114171568Sscottl	       // XXX: print some error?
115171568Sscottl	       return 0;
116171568Sscottl	  }
117171568Sscottl	  dst = tmp;
118171568Sscottl	  i = 0;
119171568Sscottl	  while(*src && ((b6 = c64tobin(*src++)) != 64)) {
120171568Sscottl	       switch(i % 4) {
121171568Sscottl	       case 0:
122171568Sscottl		    *dst = b6 << 2;
123171568Sscottl		    break;
124171568Sscottl	       case 1:
125171568Sscottl		    *dst++ |= b6 >> 4;
126171568Sscottl		    *dst = b6 << 4;
127171568Sscottl		    break;
128171568Sscottl	       case 2:
129171568Sscottl		    *dst++ |= b6 >> 2;
130171568Sscottl		    *dst = b6 << 6;
131171568Sscottl		    break;
132171568Sscottl	       case 3:
133171568Sscottl		    *dst++ |= b6;
134171568Sscottl		    break;
135171568Sscottl	       }
136171568Sscottl	       i++;
137171568Sscottl	  }
138171568Sscottl	  len = dst - tmp;
139171568Sscottl     }
140171568Sscottl     else {
141171568Sscottl	  /*
142171568Sscottl	   | assume it to be an ascii string, so just copy it
143171568Sscottl	   */
144171568Sscottl	  len = strlen(str);
145171568Sscottl	  if((tmp = malloc(len)) == NULL)
146171568Sscottl	       return 0;
147171568Sscottl	  dst = tmp;
148171568Sscottl	  src = str;
149171568Sscottl	  while(*src)
150171568Sscottl	       *dst++ = *src++;
151171568Sscottl     }
152171568Sscottl
153171568Sscottl     *rsp = tmp;
154171568Sscottl     return len;
155171568Sscottl}
156171568Sscottl
157171568Sscottlchar *
158171568Sscottlbin2str(char *encoding, unsigned char *md, int blen)
159171568Sscottl{
160171568Sscottl     int	len;
161176033Spb     char	*dst, *ds;
162176033Spb     unsigned char *cp;
163171568Sscottl
164171568Sscottl     if(strncasecmp(encoding, "0x", 2) == 0) {
165171568Sscottl	  char	ofmt[5];
166171568Sscottl
167171568Sscottl	  len = blen * 2;
168171568Sscottl	  dst = malloc(len + 3);
169171568Sscottl	  strcpy(dst, encoding);
170171568Sscottl	  ds = dst + 2;
171176033Spb	  cp = md;
172171568Sscottl	  sprintf(ofmt, "%%02%c", encoding[1]);
173171568Sscottl	  while(blen-- > 0) {
174171568Sscottl	       sprintf(ds, ofmt, *cp++);
175171568Sscottl	       ds += 2;
176171568Sscottl	  }
177171568Sscottl	  *ds = 0;
178171568Sscottl	  return dst;
179171568Sscottl     }
180171568Sscottl     if(strncasecmp(encoding, "0b", 2) == 0) {
181171568Sscottl	  int i, b6;
182171568Sscottl
183171568Sscottl	  len = (blen + 2) * 4 / 3;
184171568Sscottl	  dst = malloc(len + 3);
185171568Sscottl	  strcpy(dst, encoding);
186171568Sscottl	  ds = dst + 2;
187176033Spb	  cp = md;
188176034Spb	  b6 = 0; // to keep compiler happy.
189171568Sscottl	  for(i = 0; i < blen; i++) {
190171568Sscottl	       switch(i % 3) {
191171568Sscottl	       case 0:
192171568Sscottl		    *ds++ = base64[*cp >> 2];
193171568Sscottl		    b6 = (*cp & 0x3) << 4;
194171568Sscottl		    break;
195171568Sscottl	       case 1:
196171568Sscottl		    b6 += (*cp >> 4);
197171568Sscottl		    *ds++ = base64[b6];
198171568Sscottl		    b6 = (*cp & 0xf) << 2;
199171568Sscottl		    break;
200171568Sscottl	       case 2:
201171568Sscottl		    b6 += (*cp >> 6);
202171568Sscottl		    *ds++ = base64[b6];
203171568Sscottl		    *ds++ = base64[*cp & 0x3f];
204171568Sscottl	       }
205171568Sscottl	       cp++;
206171568Sscottl	  }
207171568Sscottl	  switch(blen % 3) {
208171568Sscottl	  case 0:
209171568Sscottl	       break;
210171568Sscottl	  case 1:
211171568Sscottl	       *ds++ = base64[b6];
212171568Sscottl	       *ds++ = '=';
213171568Sscottl	       *ds++ = '=';
214171568Sscottl	       break;
215171568Sscottl	  case 2:
216171568Sscottl	       *ds++ = base64[b6];
217171568Sscottl	       *ds++ = '=';
218171568Sscottl	       break;
219171568Sscottl	  }
220171568Sscottl
221171568Sscottl	  *ds = 0;
222171568Sscottl	  return dst;
223171568Sscottl     }
224171568Sscottl
225171568Sscottl     return NULL;
226171568Sscottl}
227