misc.c revision 225736
115714Sache/*-
215714Sache * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
315714Sache * All rights reserved.
415714Sache *
515714Sache * Redistribution and use in source and binary forms, with or without
615714Sache * modification, are permitted provided that the following conditions
715714Sache * are met:
815714Sache * 1. Redistributions of source code must retain the above copyright
915714Sache *    notice, this list of conditions and the following disclaimer.
1015714Sache * 2. Redistributions in binary form must reproduce the above copyright
1115714Sache *    notice, this list of conditions and the following disclaimer in the
1215714Sache *    documentation and/or other materials provided with the distribution.
1315714Sache *
1415714Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1515714Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1615714Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1715714Sache * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1815714Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1915714Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2015714Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2115714Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2215714Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2315714Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2415714Sache * SUCH DAMAGE.
2515714Sache *
2615714Sache */
2715737Sache
2815714Sache/*
2915714Sache | $Id: misc.c,v 2.1 2006/11/12 08:06:51 danny Exp $
3015737Sache */
3115714Sache
3215720Sache#include <sys/cdefs.h>
3315720Sache__FBSDID("$FreeBSD: stable/9/sbin/iscontrol/misc.c 211095 2010-08-09 12:36:36Z des $");
3415714Sache
3515714Sache#include <sys/param.h>
3615714Sache#include <sys/types.h>
3715714Sache#include <sys/socket.h>
3815714Sache#include <sys/sysctl.h>
3915714Sache
4015714Sache#include <netinet/in.h>
4115714Sache#include <netinet/tcp.h>
4215714Sache#include <arpa/inet.h>
4315714Sache#if __FreeBSD_version < 500000
4415714Sache#include <sys/time.h>
4515714Sache#endif
4615714Sache#include <stdlib.h>
4715720Sache#include <stdio.h>
4815714Sache#include <string.h>
4915714Sache
5015714Sache#include <dev/iscsi/initiator/iscsi.h>
5115714Sache#include "iscontrol.h"
5215714Sache
5315714Sachestatic inline char
5415723Sachec2b(unsigned char c)
5515714Sache{
5615714Sache     switch(c) {
5715714Sache     case '0' ... '9':
5815714Sache	  return c - '0';
5915714Sache     case 'a' ... 'f':
6015714Sache	  return c - 'a' + 10;
6115714Sache     case 'A' ... 'F':
6215714Sache	  return c - 'A' + 10;
6315714Sache     }
6415714Sache     return 0;
6515720Sache}
6615714Sache
6715714Sachestatic char 	base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
6815714Sache	                   "abcdefghijklmnopqrstuvwxyz"
6915720Sache	                   "0123456789+/";
7015720Sache
7115720Sachestatic __inline unsigned char
7215720Sachec64tobin(unsigned char c64)
7315714Sache{
7415714Sache     int	i;
7515714Sache     for(i = 0; i < 64; i++)
7615714Sache	  if(base64[i] == c64)
7715714Sache	       break;
7815714Sache     return i;
7915714Sache}
8015714Sache/*
8115714Sache | according to rfc3720, the binary string
8215714Sache | cannot be larger than 1024 - but i can't find it :-) XXX
8315714Sache | not enforced yet.
8415714Sache */
8515714Sacheint
8615714Sachestr2bin(char *str, char **rsp)
8715714Sache{
8815714Sache     char	*src, *dst, *tmp;
8915714Sache     int	i, len = 0;
9015714Sache
9115714Sache     src = str;
9215714Sache     tmp = NULL;
9315714Sache     if(strncasecmp("0x", src, 2) == 0) {
94	  src += 2;
95	  len = strlen(src);
96
97	  if((tmp = malloc((len+1)/2)) == NULL) {
98	       // XXX: print some error?
99	       return 0;
100	  }
101	  dst = tmp;
102	  if(len & 1)
103	       *dst++ = c2b(*src++);
104	  while(*src) {
105	       *dst = c2b(*src++) << 4;
106	       *dst++ |= c2b(*src++);
107	  }
108	  len = dst - tmp;
109     } else
110     if(strncasecmp("0b", src , 2) == 0) {
111	  // base64
112	  unsigned char b6;
113
114	  src += 2;
115	  len = strlen(src) / 4 * 3;
116	  if((tmp = malloc(len)) == NULL) {
117	       // XXX: print some error?
118	       return 0;
119	  }
120	  dst = tmp;
121	  i = 0;
122	  while(*src && ((b6 = c64tobin(*src++)) != 64)) {
123	       switch(i % 4) {
124	       case 0:
125		    *dst = b6 << 2;
126		    break;
127	       case 1:
128		    *dst++ |= b6 >> 4;
129		    *dst = b6 << 4;
130		    break;
131	       case 2:
132		    *dst++ |= b6 >> 2;
133		    *dst = b6 << 6;
134		    break;
135	       case 3:
136		    *dst++ |= b6;
137		    break;
138	       }
139	       i++;
140	  }
141	  len = dst - tmp;
142     }
143     else {
144	  /*
145	   | assume it to be an ascii string, so just copy it
146	   */
147	  len = strlen(str);
148	  if((tmp = malloc(len)) == NULL)
149	       return 0;
150	  dst = tmp;
151	  src = str;
152	  while(*src)
153	       *dst++ = *src++;
154     }
155
156     *rsp = tmp;
157     return len;
158}
159
160char *
161bin2str(char *encoding, unsigned char *md, int blen)
162{
163     int	len;
164     char	*dst, *ds;
165     unsigned char *cp;
166
167     if(strncasecmp(encoding, "0x", 2) == 0) {
168	  char	ofmt[5];
169
170	  len = blen * 2;
171	  dst = malloc(len + 3);
172	  strcpy(dst, encoding);
173	  ds = dst + 2;
174	  cp = md;
175	  sprintf(ofmt, "%%02%c", encoding[1]);
176	  while(blen-- > 0) {
177	       sprintf(ds, ofmt, *cp++);
178	       ds += 2;
179	  }
180	  *ds = 0;
181	  return dst;
182     }
183     if(strncasecmp(encoding, "0b", 2) == 0) {
184	  int i, b6;
185
186	  len = (blen + 2) * 4 / 3;
187	  dst = malloc(len + 3);
188	  strcpy(dst, encoding);
189	  ds = dst + 2;
190	  cp = md;
191	  b6 = 0; // to keep compiler happy.
192	  for(i = 0; i < blen; i++) {
193	       switch(i % 3) {
194	       case 0:
195		    *ds++ = base64[*cp >> 2];
196		    b6 = (*cp & 0x3) << 4;
197		    break;
198	       case 1:
199		    b6 += (*cp >> 4);
200		    *ds++ = base64[b6];
201		    b6 = (*cp & 0xf) << 2;
202		    break;
203	       case 2:
204		    b6 += (*cp >> 6);
205		    *ds++ = base64[b6];
206		    *ds++ = base64[*cp & 0x3f];
207	       }
208	       cp++;
209	  }
210	  switch(blen % 3) {
211	  case 0:
212	       break;
213	  case 1:
214	       *ds++ = base64[b6];
215	       *ds++ = '=';
216	       *ds++ = '=';
217	       break;
218	  case 2:
219	       *ds++ = base64[b6];
220	       *ds++ = '=';
221	       break;
222	  }
223
224	  *ds = 0;
225	  return dst;
226     }
227
228     return NULL;
229}
230