1 /* Copyright 2008,2009 Bernhard R. Fischer.
2 *
3 * This file is part of OnionCat.
4 *
5 * OnionCat is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License.
8 *
9 * OnionCat is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with OnionCat. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*! @file
19 * ocatv6conv.c
20 * These functions convert IPv6 addresses to onion URLs
21 * and vice versa.
22 *
23 * @author Bernhard R. Fischer <rahra _at_ cypherpunkt at>
24 * @version 2008/02/03-01
25 */
26
27
28 #include "ocat.h"
29 #include "ocat_netdesc.h"
30
31 static const char BASE32[] = "abcdefghijklmnopqrstuvwxyz234567";
32 //! array contains inverse mapping of base32 starting with '2'.
33 static const char deBASE32_[] = {
34 /* 2 3 4 5 6 7 8 9
35 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f */
36 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1,
37 /* A B C D E F G H I J K L M N O
38 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f */
39 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
40 /* P Q R S T U V W X Y Z
41 50 51 52 53 54 55 56 57 58 59 5a */
42 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };
43
44
has_tor_prefix(const struct in6_addr * addr)45 int has_tor_prefix(const struct in6_addr *addr)
46 {
47 return memcmp(addr, &NDESC(prefix), 6) == 0;
48 }
49
50
set_tor_prefix(struct in6_addr * addr)51 void set_tor_prefix(struct in6_addr *addr)
52 {
53 memcpy(addr, &NDESC(prefix), 6);
54 }
55
56
57 /*! Shift byte buffer of size ONION_URL_LEN (=17) 5 bits to the left.
58 * @param bin Pointer to byte buffer, must be at least ONION_URL_LEN
59 * bytes long.
60 */
shl5(char * bin)61 void shl5(char *bin)
62 {
63 int i;
64
65 for (i = 0; i < ONION_URL_LEN - 1; i++)
66 {
67 bin[i] <<= 5;
68 bin[i] |= (bin[i + 1] >> 3) & 0x1f;
69 }
70 bin[i] <<= 5;
71 }
72
73
oniontipv6(const char * onion,struct in6_addr * ip6)74 int oniontipv6(const char *onion, struct in6_addr *ip6)
75 {
76 int i, j;
77
78 memset(ip6, 0, sizeof(struct in6_addr));
79
80 for (i = 0; i < 16; i++)
81 {
82 shl5((char*) ip6);
83 j = toupper((int) onion[i]);
84 if ((j < '2') || (j > 'Z'))
85 return -1;
86 if ((j = deBASE32_[j - '2']) == -1)
87 return -1;
88 *(((char*) ip6) + 15) |= j;
89 }
90 set_tor_prefix(ip6);
91 return 0;
92 }
93
94
oniontipv4(const char * onion,struct in_addr * ip,int prefix_mask)95 int oniontipv4(const char *onion, struct in_addr *ip, int prefix_mask)
96 {
97 struct in6_addr ip6;
98 //uint32_t netmask = 0xffffffff << (32 - prefix_len);
99 uint32_t netmask = prefix_mask;
100 uint32_t ip4;
101
102 if (oniontipv6(onion, &ip6))
103 return -1;
104 memcpy(&ip4, &ip6.s6_addr[12], sizeof(ip4));
105 ip4 &= htonl(~netmask);
106 ip->s_addr |= ip4;
107 return 0;
108 }
109
110
111 /*! Convert IPv6 address to onion-URL (without ".onion").
112 * @param ip6 Pointer to IPv6 address of type struct in6_addr.
113 * @param onion Pointer to buffer to should receive onion-URL.
114 * The buffer *must* be at least ONION_URL_LEN + 1 (=17) bytes long.
115 * @return Returns always again pointer to buffer.
116 */
ipv6tonion(const struct in6_addr * ip6,char * onion)117 char *ipv6tonion(const struct in6_addr *ip6, char *onion)
118 {
119 int i;
120 char bin[ONION_URL_LEN], *r = onion;
121
122 memcpy(bin, (char*) ip6 + 6, 10);
123
124 for (i = 0; i < ONION_URL_LEN; i++, onion++)
125 {
126 *onion = BASE32[bin[0] >> 3 & 0x1f];
127 shl5(bin);
128 }
129 *onion = '\0';
130 return r;
131 }
132
133
134 /*! Generate a random onion-URL.
135 * @paran onion must be of at least ONION_URL_LEN + 1 (=17).
136 */
rand_onion(char * onion)137 void rand_onion(char *onion)
138 {
139 int i;
140
141 if (RAND_MAX < 32)
142 log_msg(LOG_WARNING, "weak randomness: RAND_MAX = %d < 32", RAND_MAX);
143
144 for (i = 0; i < ONION_URL_LEN; i++, onion++)
145 *onion = BASE32[rand() & 0x1f];
146 *onion = '\0';
147 }
148
149
150 /*! Convert struct sockaddr to stuct sockaddr_str which holds the address
151 * in string representation.
152 * @param saddr Const pointer to source of type struct sockaddr-
153 * @param sas Pointer to destination of type struct sockaddr_str.
154 * @return Pointer to string (sas->sstr_addr) or NULL on error. In the
155 * latter case errno will be set correctly.
156 */
inet_ntops(const struct sockaddr * saddr,struct sockaddr_str * sas)157 const char *inet_ntops(const struct sockaddr *saddr, struct sockaddr_str *sas)
158 {
159 char *src;
160
161 log_debug("convert sockaddr %p to sockaddr_str %p", saddr, sas);
162 switch (saddr->sa_family)
163 {
164 case AF_INET:
165 src = (char*) &((struct sockaddr_in*) saddr)->sin_addr;
166 sas->sstr_port = ((struct sockaddr_in*) saddr)->sin_port;
167 break;
168
169 case AF_INET6:
170 src = (char*) &((struct sockaddr_in6*) saddr)->sin6_addr;
171 sas->sstr_port = ((struct sockaddr_in6*) saddr)->sin6_port;
172 break;
173
174 default:
175 errno = EAFNOSUPPORT;
176 return NULL;
177 }
178
179 sas->sstr_family = saddr->sa_family;
180 return inet_ntop(saddr->sa_family, src, sas->sstr_addr, sizeof(sas->sstr_addr));
181 }
182
183