11558Srgrimes/*-
298542Smckusick * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
398542Smckusick * All rights reserved.
498542Smckusick *
598542Smckusick * Redistribution and use in source and binary forms, with or without
698542Smckusick * modification, are permitted provided that the following conditions
798542Smckusick * are met:
898542Smckusick * 1. Redistributions of source code must retain the above copyright
9110884Smckusick *    notice, this list of conditions and the following disclaimer.
1098542Smckusick * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes *
141558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241558Srgrimes * SUCH DAMAGE.
251558Srgrimes *
261558Srgrimes */
271558Srgrimes
281558Srgrimes/*
291558Srgrimes | $Id: misc.c,v 2.1 2006/11/12 08:06:51 danny Exp $
301558Srgrimes */
311558Srgrimes
321558Srgrimes#include <sys/cdefs.h>
331558Srgrimes__FBSDID("$FreeBSD: releng/10.2/sbin/iscontrol/misc.c 254657 2013-08-22 14:02:34Z trasz $");
341558Srgrimes
351558Srgrimes#include <sys/param.h>
361558Srgrimes#include <sys/types.h>
371558Srgrimes#include <sys/socket.h>
381558Srgrimes#include <sys/sysctl.h>
391558Srgrimes
401558Srgrimes#include <netinet/in.h>
411558Srgrimes#include <netinet/tcp.h>
421558Srgrimes#include <arpa/inet.h>
431558Srgrimes#include <stdlib.h>
4436998Scharnier#include <stdio.h>
451558Srgrimes#include <string.h>
461558Srgrimes
471558Srgrimes#include <dev/iscsi_initiator/iscsi.h>
481558Srgrimes#include "iscontrol.h"
491558Srgrimes
5036998Scharnierstatic inline char
5123673Speterc2b(unsigned char c)
5236998Scharnier{
5336998Scharnier     switch(c) {
5450476Speter     case '0' ... '9':
551558Srgrimes	  return c - '0';
561558Srgrimes     case 'a' ... 'f':
571558Srgrimes	  return c - 'a' + 10;
581558Srgrimes     case 'A' ... 'F':
5996478Sphk	  return c - 'A' + 10;
601558Srgrimes     }
6198542Smckusick     return 0;
621558Srgrimes}
631558Srgrimes
6423673Speterstatic char 	base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
65105741Sjmallett	                   "abcdefghijklmnopqrstuvwxyz"
661558Srgrimes	                   "0123456789+/";
671558Srgrimes
6899826Sjmallettstatic __inline unsigned char
69109525Sjmallettc64tobin(unsigned char c64)
701558Srgrimes{
711558Srgrimes     int	i;
7223673Speter     for(i = 0; i < 64; i++)
731558Srgrimes	  if(base64[i] == c64)
7499826Sjmallett	       break;
75109510Sjmallett     return i;
761558Srgrimes}
7799826Sjmallett/*
781558Srgrimes | according to rfc3720, the binary string
7992839Simp | cannot be larger than 1024 - but i can't find it :-) XXX
80109519Sjmallett | not enforced yet.
81109525Sjmallett */
8292839Simpint
83109525Sjmallettstr2bin(char *str, char **rsp)
8492839Simp{
851558Srgrimes     char	*src, *dst, *tmp;
861558Srgrimes     int	i, len = 0;
8792839Simp
881558Srgrimes     src = str;
89109525Sjmallett     tmp = NULL;
90109525Sjmallett     if(strncasecmp("0x", src, 2) == 0) {
911558Srgrimes	  src += 2;
92109525Sjmallett	  len = strlen(src);
93109507Sjmallett
94109525Sjmallett	  if((tmp = malloc((len+1)/2)) == NULL) {
95109525Sjmallett	       // XXX: print some error?
96109525Sjmallett	       return 0;
97109525Sjmallett	  }
98109525Sjmallett	  dst = tmp;
99109525Sjmallett	  if(len & 1)
100109525Sjmallett	       *dst++ = c2b(*src++);
101109525Sjmallett	  while(*src) {
102109525Sjmallett	       *dst = c2b(*src++) << 4;
103109525Sjmallett	       *dst++ |= c2b(*src++);
1041558Srgrimes	  }
1051558Srgrimes	  len = dst - tmp;
1061558Srgrimes     } else
1071558Srgrimes     if(strncasecmp("0b", src , 2) == 0) {
1081558Srgrimes	  // base64
1091558Srgrimes	  unsigned char b6;
110109525Sjmallett
111109525Sjmallett	  src += 2;
112109525Sjmallett	  len = strlen(src) / 4 * 3;
113109525Sjmallett	  if((tmp = malloc(len)) == NULL) {
114109525Sjmallett	       // XXX: print some error?
115109525Sjmallett	       return 0;
116109525Sjmallett	  }
117109525Sjmallett	  dst = tmp;
118109525Sjmallett	  i = 0;
119109525Sjmallett	  while(*src && ((b6 = c64tobin(*src++)) != 64)) {
120109525Sjmallett	       switch(i % 4) {
121109525Sjmallett	       case 0:
1221558Srgrimes		    *dst = b6 << 2;
1231558Srgrimes		    break;
1241558Srgrimes	       case 1:
1251558Srgrimes		    *dst++ |= b6 >> 4;
12692839Simp		    *dst = b6 << 4;
1271558Srgrimes		    break;
128109532Sjmallett	       case 2:
12998542Smckusick		    *dst++ |= b6 >> 2;
130109767Snjl		    *dst = b6 << 6;
13199827Sjmallett		    break;
1321558Srgrimes	       case 3:
133101688Sjmallett		    *dst++ |= b6;
134101688Sjmallett		    break;
13598542Smckusick	       }
136109532Sjmallett	       i++;
13798542Smckusick	  }
138109532Sjmallett	  len = dst - tmp;
139122670Sjohan     }
140122670Sjohan     else {
141122670Sjohan	  /*
142122670Sjohan	   | assume it to be an ascii string, so just copy it
143101688Sjmallett	   */
144101688Sjmallett	  len = strlen(str);
14598542Smckusick	  if((tmp = malloc(len)) == NULL)
146109532Sjmallett	       return 0;
14798542Smckusick	  dst = tmp;
148109532Sjmallett	  src = str;
14998542Smckusick	  while(*src)
150122670Sjohan	       *dst++ = *src++;
151122670Sjohan     }
152101688Sjmallett
153101688Sjmallett     *rsp = tmp;
154109532Sjmallett     return len;
15598542Smckusick}
1561558Srgrimes
1571558Srgrimeschar *
1581558Srgrimesbin2str(char *encoding, unsigned char *md, int blen)
1591558Srgrimes{
1601558Srgrimes     int	len;
1611558Srgrimes     char	*dst, *ds;
16298542Smckusick     unsigned char *cp;
1631558Srgrimes
16498542Smckusick     if(strncasecmp(encoding, "0x", 2) == 0) {
165101688Sjmallett	  char	ofmt[5];
166101688Sjmallett
16798542Smckusick	  len = blen * 2;
16898542Smckusick	  dst = malloc(len + 3);
16998542Smckusick	  strcpy(dst, encoding);
170122670Sjohan	  ds = dst + 2;
171122670Sjohan	  cp = md;
172122670Sjohan	  sprintf(ofmt, "%%02%c", encoding[1]);
173122670Sjohan	  while(blen-- > 0) {
174122670Sjohan	       sprintf(ds, ofmt, *cp++);
17598542Smckusick	       ds += 2;
17698542Smckusick	  }
177122670Sjohan	  *ds = 0;
178122670Sjohan	  return dst;
179122670Sjohan     }
180109532Sjmallett     if(strncasecmp(encoding, "0b", 2) == 0) {
181109532Sjmallett	  int i, b6;
182109532Sjmallett
183101688Sjmallett	  len = (blen + 2) * 4 / 3;
184101688Sjmallett	  dst = malloc(len + 3);
18598542Smckusick	  strcpy(dst, encoding);
18698542Smckusick	  ds = dst + 2;
18798542Smckusick	  cp = md;
18898542Smckusick	  b6 = 0; // to keep compiler happy.
18998542Smckusick	  for(i = 0; i < blen; i++) {
19098542Smckusick	       switch(i % 3) {
19198542Smckusick	       case 0:
19298542Smckusick		    *ds++ = base64[*cp >> 2];
193122670Sjohan		    b6 = (*cp & 0x3) << 4;
19498542Smckusick		    break;
195122670Sjohan	       case 1:
19698542Smckusick		    b6 += (*cp >> 4);
19798542Smckusick		    *ds++ = base64[b6];
19898542Smckusick		    b6 = (*cp & 0xf) << 2;
19998542Smckusick		    break;
20098542Smckusick	       case 2:
20198542Smckusick		    b6 += (*cp >> 6);
20298542Smckusick		    *ds++ = base64[b6];
20398542Smckusick		    *ds++ = base64[*cp & 0x3f];
20498542Smckusick	       }
20598542Smckusick	       cp++;
206101688Sjmallett	  }
207101688Sjmallett	  switch(blen % 3) {
208109532Sjmallett	  case 0:
20998542Smckusick	       break;
2101558Srgrimes	  case 1:
2111558Srgrimes	       *ds++ = base64[b6];
2122154Sdg	       *ds++ = '=';
2132154Sdg	       *ds++ = '=';
21448875Smpp	       break;
215109767Snjl	  case 2:
216109767Snjl	       *ds++ = base64[b6];
217109767Snjl	       *ds++ = '=';
218109767Snjl	       break;
219109767Snjl	  }
22048875Smpp
221109767Snjl	  *ds = 0;
222109767Snjl	  return dst;
223109767Snjl     }
224109767Snjl
225109767Snjl     return NULL;
226109767Snjl}
227109767Snjl