1 /*- 2 * Copyright (c) 2005-2008 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 34 #include <sys/param.h> 35 #include <sys/types.h> 36 #include <sys/socket.h> 37 #include <sys/sysctl.h> 38 39 #include <netinet/in.h> 40 #include <netinet/tcp.h> 41 #include <arpa/inet.h> 42 #if __FreeBSD_version < 500000 43 #include <sys/time.h> 44 #endif 45 #include <stdlib.h> 46 #include <stdio.h> 47 #include <string.h> 48 49 #include "misc.h" 50 51 static inline char 52 c2b(unsigned char c) 53 { 54 switch(c) { 55 case '0' ... '9': 56 return c - '0'; 57 case 'a' ... 'f': 58 return c - 'a' + 10; 59 case 'A' ... 'F': 60 return c - 'A' + 10; 61 } 62 return 0; 63 } 64 65 static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 66 "abcdefghijklmnopqrstuvwxyz" 67 "0123456789+/"; 68 69 static __inline unsigned char 70 c64tobin(unsigned char c64) 71 { 72 int i; 73 for(i = 0; i < 64; i++) 74 if(base64[i] == c64) 75 break; 76 return i; 77 } 78 /* 79 | according to rfc3720, the binary string 80 | cannot be larger than 1024 - but i can't find it :-) XXX 81 | not enforced yet. 82 */ 83 int 84 str2bin(char *str, char **rsp) 85 { 86 char *src, *dst, *tmp; 87 int i, len = 0; 88 89 src = str; 90 tmp = NULL; 91 if(strncasecmp("0x", src, 2) == 0) { 92 src += 2; 93 len = strlen(src); 94 95 if((tmp = malloc((len+1)/2)) == NULL) { 96 // XXX: print some error? 97 return 0; 98 } 99 dst = tmp; 100 if(len & 1) 101 *dst++ = c2b(*src++); 102 while(*src) { 103 *dst = c2b(*src++) << 4; 104 *dst++ |= c2b(*src++); 105 } 106 len = dst - tmp; 107 } else 108 if(strncasecmp("0b", src , 2) == 0) { 109 // base64 110 unsigned char b6; 111 112 src += 2; 113 len = strlen(src) / 4 * 3; 114 if((tmp = malloc(len)) == NULL) { 115 // XXX: print some error? 116 return 0; 117 } 118 dst = tmp; 119 i = 0; 120 while(*src && ((b6 = c64tobin(*src++)) != 64)) { 121 switch(i % 4) { 122 case 0: 123 *dst = b6 << 2; 124 break; 125 case 1: 126 *dst++ |= b6 >> 4; 127 *dst = b6 << 4; 128 break; 129 case 2: 130 *dst++ |= b6 >> 2; 131 *dst = b6 << 6; 132 break; 133 case 3: 134 *dst++ |= b6; 135 break; 136 } 137 i++; 138 } 139 len = dst - tmp; 140 } 141 else { 142 /* 143 | assume it to be an ascii string, so just copy it 144 */ 145 len = strlen(str); 146 if((tmp = malloc(len)) == NULL) 147 return 0; 148 dst = tmp; 149 src = str; 150 while(*src) 151 *dst++ = *src++; 152 } 153 154 *rsp = tmp; 155 return len; 156 } 157 158 char * 159 bin2str(char *encoding, unsigned char *md, int blen) 160 { 161 int len; 162 char *dst, *ds; 163 unsigned char *cp; 164 165 if(strncasecmp(encoding, "0x", 2) == 0) { 166 char ofmt[5]; 167 168 len = blen * 2; 169 dst = malloc(len + 3); 170 strcpy(dst, encoding); 171 ds = dst + 2; 172 cp = md; 173 sprintf(ofmt, "%%02%c", encoding[1]); 174 while(blen-- > 0) { 175 sprintf(ds, ofmt, *cp++); 176 ds += 2; 177 } 178 *ds = 0; 179 return dst; 180 } 181 if(strncasecmp(encoding, "0b", 2) == 0) { 182 int i, b6; 183 184 len = (blen + 2) * 4 / 3; 185 dst = malloc(len + 3); 186 strcpy(dst, encoding); 187 ds = dst + 2; 188 cp = md; 189 b6 = 0; // to keep compiler happy. 190 for(i = 0; i < blen; i++) { 191 switch(i % 3) { 192 case 0: 193 *ds++ = base64[*cp >> 2]; 194 b6 = (*cp & 0x3) << 4; 195 break; 196 case 1: 197 b6 += (*cp >> 4); 198 *ds++ = base64[b6]; 199 b6 = (*cp & 0xf) << 2; 200 break; 201 case 2: 202 b6 += (*cp >> 6); 203 *ds++ = base64[b6]; 204 *ds++ = base64[*cp & 0x3f]; 205 } 206 cp++; 207 } 208 switch(blen % 3) { 209 case 0: 210 break; 211 case 1: 212 *ds++ = base64[b6]; 213 *ds++ = '='; 214 *ds++ = '='; 215 break; 216 case 2: 217 *ds++ = base64[b6]; 218 *ds++ = '='; 219 break; 220 } 221 222 *ds = 0; 223 return dst; 224 } 225 226 return NULL; 227 } 228