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