tor  0.4.1.0-alpha-dev
inaddr.c
Go to the documentation of this file.
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
11 #include "lib/net/inaddr.h"
12 
13 #include "lib/cc/torint.h"
14 #include "lib/log/util_bug.h"
15 #include "lib/net/inaddr_st.h"
18 #include "lib/string/printf.h"
19 #include "lib/string/scanf.h"
20 #include "lib/string/util_string.h"
21 
22 #ifdef HAVE_ARPA_INET_H
23 #include <arpa/inet.h>
24 #endif
25 
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #ifdef _WIN32
30 #include <winsock2.h>
31 #endif
32 
37 int
38 tor_inet_aton(const char *str, struct in_addr* addr)
39 {
40  unsigned a,b,c,d;
41  char more;
42  if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
43  return 0;
44  if (a > 255) return 0;
45  if (b > 255) return 0;
46  if (c > 255) return 0;
47  if (d > 255) return 0;
48  addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
49  return 1;
50 }
51 
57 int
58 tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
59 {
60  uint32_t a = ntohl(in->s_addr);
61  return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
62  (int)(uint8_t)((a>>24)&0xff),
63  (int)(uint8_t)((a>>16)&0xff),
64  (int)(uint8_t)((a>>8 )&0xff),
65  (int)(uint8_t)((a )&0xff));
66 }
67 
76 const char *
77 tor_inet_ntop(int af, const void *src, char *dst, size_t len)
78 {
79  if (af == AF_INET) {
80  if (tor_inet_ntoa(src, dst, len) < 0)
81  return NULL;
82  else
83  return dst;
84  } else if (af == AF_INET6) {
85  const struct in6_addr *addr = src;
86  char buf[64], *cp;
87  int longestGapLen = 0, longestGapPos = -1, i,
88  curGapPos = -1, curGapLen = 0;
89  uint16_t words[8];
90  for (i = 0; i < 8; ++i) {
91  words[i] = (((uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
92  }
93  if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
94  words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) ||
95  (words[5] == 0xffff))) {
96  /* This is an IPv4 address. */
97  if (words[5] == 0) {
98  tor_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
99  addr->s6_addr[12], addr->s6_addr[13],
100  addr->s6_addr[14], addr->s6_addr[15]);
101  } else {
102  tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
103  addr->s6_addr[12], addr->s6_addr[13],
104  addr->s6_addr[14], addr->s6_addr[15]);
105  }
106  if ((strlen(buf) + 1) > len) /* +1 for \0 */
107  return NULL;
108  strlcpy(dst, buf, len);
109  return dst;
110  }
111  i = 0;
112  while (i < 8) {
113  if (words[i] == 0) {
114  curGapPos = i++;
115  curGapLen = 1;
116  while (i<8 && words[i] == 0) {
117  ++i; ++curGapLen;
118  }
119  if (curGapLen > longestGapLen) {
120  longestGapPos = curGapPos;
121  longestGapLen = curGapLen;
122  }
123  } else {
124  ++i;
125  }
126  }
127  if (longestGapLen<=1)
128  longestGapPos = -1;
129 
130  cp = buf;
131  for (i = 0; i < 8; ++i) {
132  if (words[i] == 0 && longestGapPos == i) {
133  if (i == 0)
134  *cp++ = ':';
135  *cp++ = ':';
136  while (i < 8 && words[i] == 0)
137  ++i;
138  --i; /* to compensate for loop increment. */
139  } else {
140  tor_snprintf(cp, sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
141  cp += strlen(cp);
142  if (i != 7)
143  *cp++ = ':';
144  }
145  }
146  *cp = '\0';
147  if ((strlen(buf) + 1) > len) /* +1 for \0 */
148  return NULL;
149  strlcpy(dst, buf, len);
150  return dst;
151  } else {
152  return NULL;
153  }
154 }
155 
165 int
166 tor_inet_pton(int af, const char *src, void *dst)
167 {
168  if (af == AF_INET) {
169  return tor_inet_aton(src, dst);
170  } else if (af == AF_INET6) {
171  ssize_t len = strlen(src);
172 
173  /* Reject if src has needless trailing ':'. */
174  if (len > 2 && src[len - 1] == ':' && src[len - 2] != ':') {
175  return 0;
176  }
177 
178  struct in6_addr *out = dst;
179  uint16_t words[8];
180  int gapPos = -1, i, setWords=0;
181  const char *dot = strchr(src, '.');
182  const char *eow; /* end of words. */
183  memset(words, 0xf8, sizeof(words));
184  if (dot == src)
185  return 0;
186  else if (!dot)
187  eow = src+strlen(src);
188  else {
189  unsigned byte1,byte2,byte3,byte4;
190  char more;
191  for (eow = dot-1; eow > src && TOR_ISDIGIT(*eow); --eow)
192  ;
193  if (*eow != ':')
194  return 0;
195  ++eow;
196 
197  /* We use "scanf" because some platform inet_aton()s are too lax
198  * about IPv4 addresses of the form "1.2.3" */
199  if (tor_sscanf(eow, "%3u.%3u.%3u.%3u%c",
200  &byte1,&byte2,&byte3,&byte4,&more) != 4)
201  return 0;
202 
203  if (byte1 > 255 || byte2 > 255 || byte3 > 255 || byte4 > 255)
204  return 0;
205 
206  words[6] = (byte1<<8) | byte2;
207  words[7] = (byte3<<8) | byte4;
208  setWords += 2;
209  }
210 
211  i = 0;
212  while (src < eow) {
213  if (i > 7)
214  return 0;
215  if (TOR_ISXDIGIT(*src)) {
216  char *next;
217  long r = strtol(src, &next, 16);
218  if (next == NULL || next == src) {
219  /* The 'next == src' error case can happen on versions of openbsd
220  * which treat "0xfoo" as an error, rather than as "0" followed by
221  * "xfoo". */
222  return 0;
223  }
224 
225  len = *next == '\0' ? eow - src : next - src;
226  if (len > 4)
227  return 0;
228  if (len > 1 && !TOR_ISXDIGIT(src[1]))
229  return 0; /* 0x is not valid */
230 
231  tor_assert(r >= 0);
232  tor_assert(r < 65536);
233  words[i++] = (uint16_t)r;
234  setWords++;
235  src = next;
236  if (*src != ':' && src != eow)
237  return 0;
238  ++src;
239  } else if (*src == ':' && i > 0 && gapPos == -1) {
240  gapPos = i;
241  ++src;
242  } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' &&
243  gapPos == -1) {
244  gapPos = i;
245  src += 2;
246  } else {
247  return 0;
248  }
249  }
250 
251  if (setWords > 8 ||
252  (setWords == 8 && gapPos != -1) ||
253  (setWords < 8 && gapPos == -1))
254  return 0;
255 
256  if (gapPos >= 0) {
257  int nToMove = setWords - (dot ? 2 : 0) - gapPos;
258  int gapLen = 8 - setWords;
259  tor_assert(nToMove >= 0);
260  memmove(&words[gapPos+gapLen], &words[gapPos],
261  sizeof(uint16_t)*nToMove);
262  memset(&words[gapPos], 0, sizeof(uint16_t)*gapLen);
263  }
264  for (i = 0; i < 8; ++i) {
265  out->s6_addr[2*i ] = words[i] >> 8;
266  out->s6_addr[2*i+1] = words[i] & 0xff;
267  }
268 
269  return 1;
270  } else {
271  return -1;
272  }
273 }
int tor_sscanf(const char *buf, const char *pattern,...)
Definition: scanf.c:309
int tor_inet_pton(int af, const char *src, void *dst)
Definition: inaddr.c:166
Header for printf.c.
int tor_inet_aton(const char *str, struct in_addr *addr)
Definition: inaddr.c:38
Header for util_string.c.
Header for inaddr.c.
Integer definitions used throughout Tor.
Define in6_addr, its members, and related types on platforms that lack it.
const char * tor_inet_ntop(int af, const void *src, char *dst, size_t len)
Definition: inaddr.c:77
tor_assert(buffer)
Header for scanf.c.
int tor_snprintf(char *str, size_t size, const char *format,...)
Definition: printf.c:27
Locale-independent character-type inspection (header)
Header for compat_string.c.
int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
Definition: inaddr.c:58
Macros to manage assertions, fatal and non-fatal.