1/*- 2 * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28/* 29 | $Id: misc.c,v 2.1 2006/11/12 08:06:51 danny Exp $ 30 */ 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD$"); 34 35#include <sys/param.h> 36#include <sys/types.h> 37#include <sys/socket.h> 38#include <sys/sysctl.h> 39 40#include <netinet/in.h> 41#include <netinet/tcp.h> 42#include <arpa/inet.h> 43#include <stdlib.h> 44#include <stdio.h> 45#include <string.h> 46 47#include <dev/iscsi_initiator/iscsi.h> 48#include "iscontrol.h" 49 50static inline char 51c2b(unsigned char c) 52{ 53 switch(c) { 54 case '0' ... '9': 55 return c - '0'; 56 case 'a' ... 'f': 57 return c - 'a' + 10; 58 case 'A' ... 'F': 59 return c - 'A' + 10; 60 } 61 return 0; 62} 63 64static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 65 "abcdefghijklmnopqrstuvwxyz" 66 "0123456789+/"; 67 68static __inline unsigned char 69c64tobin(unsigned char c64) 70{ 71 int i; 72 for(i = 0; i < 64; i++) 73 if(base64[i] == c64) 74 break; 75 return i; 76} 77/* 78 | according to rfc3720, the binary string 79 | cannot be larger than 1024 - but i can't find it :-) XXX 80 | not enforced yet. 81 */ 82int 83str2bin(char *str, char **rsp) 84{ 85 char *src, *dst, *tmp; 86 int i, len = 0; 87 88 src = str; 89 tmp = NULL; 90 if(strncasecmp("0x", src, 2) == 0) { 91 src += 2; 92 len = strlen(src); 93 94 if((tmp = malloc((len+1)/2)) == NULL) { 95 // XXX: print some error? 96 return 0; 97 } 98 dst = tmp; 99 if(len & 1) 100 *dst++ = c2b(*src++); 101 while(*src) { 102 *dst = c2b(*src++) << 4; 103 *dst++ |= c2b(*src++); 104 } 105 len = dst - tmp; 106 } else 107 if(strncasecmp("0b", src , 2) == 0) { 108 // base64 109 unsigned char b6; 110 111 src += 2; 112 len = strlen(src) / 4 * 3; 113 if((tmp = malloc(len)) == NULL) { 114 // XXX: print some error? 115 return 0; 116 } 117 dst = tmp; 118 i = 0; 119 while(*src && ((b6 = c64tobin(*src++)) != 64)) { 120 switch(i % 4) { 121 case 0: 122 *dst = b6 << 2; 123 break; 124 case 1: 125 *dst++ |= b6 >> 4; 126 *dst = b6 << 4; 127 break; 128 case 2: 129 *dst++ |= b6 >> 2; 130 *dst = b6 << 6; 131 break; 132 case 3: 133 *dst++ |= b6; 134 break; 135 } 136 i++; 137 } 138 len = dst - tmp; 139 } 140 else { 141 /* 142 | assume it to be an ascii string, so just copy it 143 */ 144 len = strlen(str); 145 if((tmp = malloc(len)) == NULL) 146 return 0; 147 dst = tmp; 148 src = str; 149 while(*src) 150 *dst++ = *src++; 151 } 152 153 *rsp = tmp; 154 return len; 155} 156 157char * 158bin2str(char *encoding, unsigned char *md, int blen) 159{ 160 int len; 161 char *dst, *ds; 162 unsigned char *cp; 163 164 if(strncasecmp(encoding, "0x", 2) == 0) { 165 char ofmt[5]; 166 167 len = blen * 2; 168 dst = malloc(len + 3); 169 strcpy(dst, encoding); 170 ds = dst + 2; 171 cp = md; 172 sprintf(ofmt, "%%02%c", encoding[1]); 173 while(blen-- > 0) { 174 sprintf(ds, ofmt, *cp++); 175 ds += 2; 176 } 177 *ds = 0; 178 return dst; 179 } 180 if(strncasecmp(encoding, "0b", 2) == 0) { 181 int i, b6; 182 183 len = (blen + 2) * 4 / 3; 184 dst = malloc(len + 3); 185 strcpy(dst, encoding); 186 ds = dst + 2; 187 cp = md; 188 b6 = 0; // to keep compiler happy. 189 for(i = 0; i < blen; i++) { 190 switch(i % 3) { 191 case 0: 192 *ds++ = base64[*cp >> 2]; 193 b6 = (*cp & 0x3) << 4; 194 break; 195 case 1: 196 b6 += (*cp >> 4); 197 *ds++ = base64[b6]; 198 b6 = (*cp & 0xf) << 2; 199 break; 200 case 2: 201 b6 += (*cp >> 6); 202 *ds++ = base64[b6]; 203 *ds++ = base64[*cp & 0x3f]; 204 } 205 cp++; 206 } 207 switch(blen % 3) { 208 case 0: 209 break; 210 case 1: 211 *ds++ = base64[b6]; 212 *ds++ = '='; 213 *ds++ = '='; 214 break; 215 case 2: 216 *ds++ = base64[b6]; 217 *ds++ = '='; 218 break; 219 } 220 221 *ds = 0; 222 return dst; 223 } 224 225 return NULL; 226} 227