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