1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/win32.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <winsock2.h>
14*d9f75844SAndroid Build Coastguard Worker #include <ws2tcpip.h>
15*d9f75844SAndroid Build Coastguard Worker
16*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/arraysize.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/byte_order.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_utils.h"
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker namespace rtc {
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker // Helper function declarations for inet_ntop/inet_pton.
27*d9f75844SAndroid Build Coastguard Worker static const char* inet_ntop_v4(const void* src, char* dst, socklen_t size);
28*d9f75844SAndroid Build Coastguard Worker static const char* inet_ntop_v6(const void* src, char* dst, socklen_t size);
29*d9f75844SAndroid Build Coastguard Worker static int inet_pton_v4(const char* src, void* dst);
30*d9f75844SAndroid Build Coastguard Worker static int inet_pton_v6(const char* src, void* dst);
31*d9f75844SAndroid Build Coastguard Worker
32*d9f75844SAndroid Build Coastguard Worker // Implementation of inet_ntop (create a printable representation of an
33*d9f75844SAndroid Build Coastguard Worker // ip address). XP doesn't have its own inet_ntop, and
34*d9f75844SAndroid Build Coastguard Worker // WSAAddressToString requires both IPv6 to be installed and for Winsock
35*d9f75844SAndroid Build Coastguard Worker // to be initialized.
win32_inet_ntop(int af,const void * src,char * dst,socklen_t size)36*d9f75844SAndroid Build Coastguard Worker const char* win32_inet_ntop(int af,
37*d9f75844SAndroid Build Coastguard Worker const void* src,
38*d9f75844SAndroid Build Coastguard Worker char* dst,
39*d9f75844SAndroid Build Coastguard Worker socklen_t size) {
40*d9f75844SAndroid Build Coastguard Worker if (!src || !dst) {
41*d9f75844SAndroid Build Coastguard Worker return nullptr;
42*d9f75844SAndroid Build Coastguard Worker }
43*d9f75844SAndroid Build Coastguard Worker switch (af) {
44*d9f75844SAndroid Build Coastguard Worker case AF_INET: {
45*d9f75844SAndroid Build Coastguard Worker return inet_ntop_v4(src, dst, size);
46*d9f75844SAndroid Build Coastguard Worker }
47*d9f75844SAndroid Build Coastguard Worker case AF_INET6: {
48*d9f75844SAndroid Build Coastguard Worker return inet_ntop_v6(src, dst, size);
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker }
51*d9f75844SAndroid Build Coastguard Worker return nullptr;
52*d9f75844SAndroid Build Coastguard Worker }
53*d9f75844SAndroid Build Coastguard Worker
54*d9f75844SAndroid Build Coastguard Worker // As above, but for inet_pton. Implements inet_pton for v4 and v6.
55*d9f75844SAndroid Build Coastguard Worker // Note that our inet_ntop will output normal 'dotted' v4 addresses only.
win32_inet_pton(int af,const char * src,void * dst)56*d9f75844SAndroid Build Coastguard Worker int win32_inet_pton(int af, const char* src, void* dst) {
57*d9f75844SAndroid Build Coastguard Worker if (!src || !dst) {
58*d9f75844SAndroid Build Coastguard Worker return 0;
59*d9f75844SAndroid Build Coastguard Worker }
60*d9f75844SAndroid Build Coastguard Worker if (af == AF_INET) {
61*d9f75844SAndroid Build Coastguard Worker return inet_pton_v4(src, dst);
62*d9f75844SAndroid Build Coastguard Worker } else if (af == AF_INET6) {
63*d9f75844SAndroid Build Coastguard Worker return inet_pton_v6(src, dst);
64*d9f75844SAndroid Build Coastguard Worker }
65*d9f75844SAndroid Build Coastguard Worker return -1;
66*d9f75844SAndroid Build Coastguard Worker }
67*d9f75844SAndroid Build Coastguard Worker
68*d9f75844SAndroid Build Coastguard Worker // Helper function for inet_ntop for IPv4 addresses.
69*d9f75844SAndroid Build Coastguard Worker // Outputs "dotted-quad" decimal notation.
inet_ntop_v4(const void * src,char * dst,socklen_t size)70*d9f75844SAndroid Build Coastguard Worker const char* inet_ntop_v4(const void* src, char* dst, socklen_t size) {
71*d9f75844SAndroid Build Coastguard Worker if (size < INET_ADDRSTRLEN) {
72*d9f75844SAndroid Build Coastguard Worker return nullptr;
73*d9f75844SAndroid Build Coastguard Worker }
74*d9f75844SAndroid Build Coastguard Worker const struct in_addr* as_in_addr =
75*d9f75844SAndroid Build Coastguard Worker reinterpret_cast<const struct in_addr*>(src);
76*d9f75844SAndroid Build Coastguard Worker snprintf(dst, size, "%d.%d.%d.%d", as_in_addr->S_un.S_un_b.s_b1,
77*d9f75844SAndroid Build Coastguard Worker as_in_addr->S_un.S_un_b.s_b2, as_in_addr->S_un.S_un_b.s_b3,
78*d9f75844SAndroid Build Coastguard Worker as_in_addr->S_un.S_un_b.s_b4);
79*d9f75844SAndroid Build Coastguard Worker return dst;
80*d9f75844SAndroid Build Coastguard Worker }
81*d9f75844SAndroid Build Coastguard Worker
82*d9f75844SAndroid Build Coastguard Worker // Helper function for inet_ntop for IPv6 addresses.
inet_ntop_v6(const void * src,char * dst,socklen_t size)83*d9f75844SAndroid Build Coastguard Worker const char* inet_ntop_v6(const void* src, char* dst, socklen_t size) {
84*d9f75844SAndroid Build Coastguard Worker if (size < INET6_ADDRSTRLEN) {
85*d9f75844SAndroid Build Coastguard Worker return nullptr;
86*d9f75844SAndroid Build Coastguard Worker }
87*d9f75844SAndroid Build Coastguard Worker const uint16_t* as_shorts = reinterpret_cast<const uint16_t*>(src);
88*d9f75844SAndroid Build Coastguard Worker int runpos[8];
89*d9f75844SAndroid Build Coastguard Worker int current = 1;
90*d9f75844SAndroid Build Coastguard Worker int max = 0;
91*d9f75844SAndroid Build Coastguard Worker int maxpos = -1;
92*d9f75844SAndroid Build Coastguard Worker int run_array_size = arraysize(runpos);
93*d9f75844SAndroid Build Coastguard Worker // Run over the address marking runs of 0s.
94*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < run_array_size; ++i) {
95*d9f75844SAndroid Build Coastguard Worker if (as_shorts[i] == 0) {
96*d9f75844SAndroid Build Coastguard Worker runpos[i] = current;
97*d9f75844SAndroid Build Coastguard Worker if (current > max) {
98*d9f75844SAndroid Build Coastguard Worker maxpos = i;
99*d9f75844SAndroid Build Coastguard Worker max = current;
100*d9f75844SAndroid Build Coastguard Worker }
101*d9f75844SAndroid Build Coastguard Worker ++current;
102*d9f75844SAndroid Build Coastguard Worker } else {
103*d9f75844SAndroid Build Coastguard Worker runpos[i] = -1;
104*d9f75844SAndroid Build Coastguard Worker current = 1;
105*d9f75844SAndroid Build Coastguard Worker }
106*d9f75844SAndroid Build Coastguard Worker }
107*d9f75844SAndroid Build Coastguard Worker
108*d9f75844SAndroid Build Coastguard Worker if (max > 0) {
109*d9f75844SAndroid Build Coastguard Worker int tmpmax = maxpos;
110*d9f75844SAndroid Build Coastguard Worker // Run back through, setting -1 for all but the longest run.
111*d9f75844SAndroid Build Coastguard Worker for (int i = run_array_size - 1; i >= 0; i--) {
112*d9f75844SAndroid Build Coastguard Worker if (i > tmpmax) {
113*d9f75844SAndroid Build Coastguard Worker runpos[i] = -1;
114*d9f75844SAndroid Build Coastguard Worker } else if (runpos[i] == -1) {
115*d9f75844SAndroid Build Coastguard Worker // We're less than maxpos, we hit a -1, so the 'good' run is done.
116*d9f75844SAndroid Build Coastguard Worker // Setting tmpmax -1 means all remaining positions get set to -1.
117*d9f75844SAndroid Build Coastguard Worker tmpmax = -1;
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker }
120*d9f75844SAndroid Build Coastguard Worker }
121*d9f75844SAndroid Build Coastguard Worker
122*d9f75844SAndroid Build Coastguard Worker char* cursor = dst;
123*d9f75844SAndroid Build Coastguard Worker // Print IPv4 compatible and IPv4 mapped addresses using the IPv4 helper.
124*d9f75844SAndroid Build Coastguard Worker // These addresses have an initial run of either eight zero-bytes followed
125*d9f75844SAndroid Build Coastguard Worker // by 0xFFFF, or an initial run of ten zero-bytes.
126*d9f75844SAndroid Build Coastguard Worker if (runpos[0] == 1 &&
127*d9f75844SAndroid Build Coastguard Worker (maxpos == 5 || (maxpos == 4 && as_shorts[5] == 0xFFFF))) {
128*d9f75844SAndroid Build Coastguard Worker *cursor++ = ':';
129*d9f75844SAndroid Build Coastguard Worker *cursor++ = ':';
130*d9f75844SAndroid Build Coastguard Worker if (maxpos == 4) {
131*d9f75844SAndroid Build Coastguard Worker cursor += snprintf(cursor, INET6_ADDRSTRLEN - 2, "ffff:");
132*d9f75844SAndroid Build Coastguard Worker }
133*d9f75844SAndroid Build Coastguard Worker const struct in_addr* as_v4 =
134*d9f75844SAndroid Build Coastguard Worker reinterpret_cast<const struct in_addr*>(&(as_shorts[6]));
135*d9f75844SAndroid Build Coastguard Worker inet_ntop_v4(as_v4, cursor,
136*d9f75844SAndroid Build Coastguard Worker static_cast<socklen_t>(INET6_ADDRSTRLEN - (cursor - dst)));
137*d9f75844SAndroid Build Coastguard Worker } else {
138*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < run_array_size; ++i) {
139*d9f75844SAndroid Build Coastguard Worker if (runpos[i] == -1) {
140*d9f75844SAndroid Build Coastguard Worker cursor += snprintf(cursor, INET6_ADDRSTRLEN - (cursor - dst), "%x",
141*d9f75844SAndroid Build Coastguard Worker NetworkToHost16(as_shorts[i]));
142*d9f75844SAndroid Build Coastguard Worker if (i != 7 && runpos[i + 1] != 1) {
143*d9f75844SAndroid Build Coastguard Worker *cursor++ = ':';
144*d9f75844SAndroid Build Coastguard Worker }
145*d9f75844SAndroid Build Coastguard Worker } else if (runpos[i] == 1) {
146*d9f75844SAndroid Build Coastguard Worker // Entered the run; print the colons and skip the run.
147*d9f75844SAndroid Build Coastguard Worker *cursor++ = ':';
148*d9f75844SAndroid Build Coastguard Worker *cursor++ = ':';
149*d9f75844SAndroid Build Coastguard Worker i += (max - 1);
150*d9f75844SAndroid Build Coastguard Worker }
151*d9f75844SAndroid Build Coastguard Worker }
152*d9f75844SAndroid Build Coastguard Worker }
153*d9f75844SAndroid Build Coastguard Worker return dst;
154*d9f75844SAndroid Build Coastguard Worker }
155*d9f75844SAndroid Build Coastguard Worker
156*d9f75844SAndroid Build Coastguard Worker // Helper function for inet_pton for IPv4 addresses.
157*d9f75844SAndroid Build Coastguard Worker // `src` points to a character string containing an IPv4 network address in
158*d9f75844SAndroid Build Coastguard Worker // dotted-decimal format, "ddd.ddd.ddd.ddd", where ddd is a decimal number
159*d9f75844SAndroid Build Coastguard Worker // of up to three digits in the range 0 to 255.
160*d9f75844SAndroid Build Coastguard Worker // The address is converted and copied to dst,
161*d9f75844SAndroid Build Coastguard Worker // which must be sizeof(struct in_addr) (4) bytes (32 bits) long.
inet_pton_v4(const char * src,void * dst)162*d9f75844SAndroid Build Coastguard Worker int inet_pton_v4(const char* src, void* dst) {
163*d9f75844SAndroid Build Coastguard Worker const int kIpv4AddressSize = 4;
164*d9f75844SAndroid Build Coastguard Worker int found = 0;
165*d9f75844SAndroid Build Coastguard Worker const char* src_pos = src;
166*d9f75844SAndroid Build Coastguard Worker unsigned char result[kIpv4AddressSize] = {0};
167*d9f75844SAndroid Build Coastguard Worker
168*d9f75844SAndroid Build Coastguard Worker while (*src_pos != '\0') {
169*d9f75844SAndroid Build Coastguard Worker // strtol won't treat whitespace characters in the begining as an error,
170*d9f75844SAndroid Build Coastguard Worker // so check to ensure this is started with digit before passing to strtol.
171*d9f75844SAndroid Build Coastguard Worker if (!isdigit(*src_pos)) {
172*d9f75844SAndroid Build Coastguard Worker return 0;
173*d9f75844SAndroid Build Coastguard Worker }
174*d9f75844SAndroid Build Coastguard Worker char* end_pos;
175*d9f75844SAndroid Build Coastguard Worker long value = strtol(src_pos, &end_pos, 10);
176*d9f75844SAndroid Build Coastguard Worker if (value < 0 || value > 255 || src_pos == end_pos) {
177*d9f75844SAndroid Build Coastguard Worker return 0;
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker ++found;
180*d9f75844SAndroid Build Coastguard Worker if (found > kIpv4AddressSize) {
181*d9f75844SAndroid Build Coastguard Worker return 0;
182*d9f75844SAndroid Build Coastguard Worker }
183*d9f75844SAndroid Build Coastguard Worker result[found - 1] = static_cast<unsigned char>(value);
184*d9f75844SAndroid Build Coastguard Worker src_pos = end_pos;
185*d9f75844SAndroid Build Coastguard Worker if (*src_pos == '.') {
186*d9f75844SAndroid Build Coastguard Worker // There's more.
187*d9f75844SAndroid Build Coastguard Worker ++src_pos;
188*d9f75844SAndroid Build Coastguard Worker } else if (*src_pos != '\0') {
189*d9f75844SAndroid Build Coastguard Worker // If it's neither '.' nor '\0' then return fail.
190*d9f75844SAndroid Build Coastguard Worker return 0;
191*d9f75844SAndroid Build Coastguard Worker }
192*d9f75844SAndroid Build Coastguard Worker }
193*d9f75844SAndroid Build Coastguard Worker if (found != kIpv4AddressSize) {
194*d9f75844SAndroid Build Coastguard Worker return 0;
195*d9f75844SAndroid Build Coastguard Worker }
196*d9f75844SAndroid Build Coastguard Worker memcpy(dst, result, sizeof(result));
197*d9f75844SAndroid Build Coastguard Worker return 1;
198*d9f75844SAndroid Build Coastguard Worker }
199*d9f75844SAndroid Build Coastguard Worker
200*d9f75844SAndroid Build Coastguard Worker // Helper function for inet_pton for IPv6 addresses.
inet_pton_v6(const char * src,void * dst)201*d9f75844SAndroid Build Coastguard Worker int inet_pton_v6(const char* src, void* dst) {
202*d9f75844SAndroid Build Coastguard Worker // sscanf will pick any other invalid chars up, but it parses 0xnnnn as hex.
203*d9f75844SAndroid Build Coastguard Worker // Check for literal x in the input string.
204*d9f75844SAndroid Build Coastguard Worker const char* readcursor = src;
205*d9f75844SAndroid Build Coastguard Worker char c = *readcursor++;
206*d9f75844SAndroid Build Coastguard Worker while (c) {
207*d9f75844SAndroid Build Coastguard Worker if (c == 'x') {
208*d9f75844SAndroid Build Coastguard Worker return 0;
209*d9f75844SAndroid Build Coastguard Worker }
210*d9f75844SAndroid Build Coastguard Worker c = *readcursor++;
211*d9f75844SAndroid Build Coastguard Worker }
212*d9f75844SAndroid Build Coastguard Worker readcursor = src;
213*d9f75844SAndroid Build Coastguard Worker
214*d9f75844SAndroid Build Coastguard Worker struct in6_addr an_addr;
215*d9f75844SAndroid Build Coastguard Worker memset(&an_addr, 0, sizeof(an_addr));
216*d9f75844SAndroid Build Coastguard Worker
217*d9f75844SAndroid Build Coastguard Worker uint16_t* addr_cursor = reinterpret_cast<uint16_t*>(&an_addr.s6_addr[0]);
218*d9f75844SAndroid Build Coastguard Worker uint16_t* addr_end = reinterpret_cast<uint16_t*>(&an_addr.s6_addr[16]);
219*d9f75844SAndroid Build Coastguard Worker bool seencompressed = false;
220*d9f75844SAndroid Build Coastguard Worker
221*d9f75844SAndroid Build Coastguard Worker // Addresses that start with "::" (i.e., a run of initial zeros) or
222*d9f75844SAndroid Build Coastguard Worker // "::ffff:" can potentially be IPv4 mapped or compatibility addresses.
223*d9f75844SAndroid Build Coastguard Worker // These have dotted-style IPv4 addresses on the end (e.g. "::192.168.7.1").
224*d9f75844SAndroid Build Coastguard Worker if (*readcursor == ':' && *(readcursor + 1) == ':' &&
225*d9f75844SAndroid Build Coastguard Worker *(readcursor + 2) != 0) {
226*d9f75844SAndroid Build Coastguard Worker // Check for periods, which we'll take as a sign of v4 addresses.
227*d9f75844SAndroid Build Coastguard Worker const char* addrstart = readcursor + 2;
228*d9f75844SAndroid Build Coastguard Worker if (strchr(addrstart, '.')) {
229*d9f75844SAndroid Build Coastguard Worker const char* colon = strchr(addrstart, ':');
230*d9f75844SAndroid Build Coastguard Worker if (colon) {
231*d9f75844SAndroid Build Coastguard Worker uint16_t a_short;
232*d9f75844SAndroid Build Coastguard Worker int bytesread = 0;
233*d9f75844SAndroid Build Coastguard Worker if (sscanf(addrstart, "%hx%n", &a_short, &bytesread) != 1 ||
234*d9f75844SAndroid Build Coastguard Worker a_short != 0xFFFF || bytesread != 4) {
235*d9f75844SAndroid Build Coastguard Worker // Colons + periods means has to be ::ffff:a.b.c.d. But it wasn't.
236*d9f75844SAndroid Build Coastguard Worker return 0;
237*d9f75844SAndroid Build Coastguard Worker } else {
238*d9f75844SAndroid Build Coastguard Worker an_addr.s6_addr[10] = 0xFF;
239*d9f75844SAndroid Build Coastguard Worker an_addr.s6_addr[11] = 0xFF;
240*d9f75844SAndroid Build Coastguard Worker addrstart = colon + 1;
241*d9f75844SAndroid Build Coastguard Worker }
242*d9f75844SAndroid Build Coastguard Worker }
243*d9f75844SAndroid Build Coastguard Worker struct in_addr v4;
244*d9f75844SAndroid Build Coastguard Worker if (inet_pton_v4(addrstart, &v4.s_addr)) {
245*d9f75844SAndroid Build Coastguard Worker memcpy(&an_addr.s6_addr[12], &v4, sizeof(v4));
246*d9f75844SAndroid Build Coastguard Worker memcpy(dst, &an_addr, sizeof(an_addr));
247*d9f75844SAndroid Build Coastguard Worker return 1;
248*d9f75844SAndroid Build Coastguard Worker } else {
249*d9f75844SAndroid Build Coastguard Worker // Invalid v4 address.
250*d9f75844SAndroid Build Coastguard Worker return 0;
251*d9f75844SAndroid Build Coastguard Worker }
252*d9f75844SAndroid Build Coastguard Worker }
253*d9f75844SAndroid Build Coastguard Worker }
254*d9f75844SAndroid Build Coastguard Worker
255*d9f75844SAndroid Build Coastguard Worker // For addresses without a trailing IPv4 component ('normal' IPv6 addresses).
256*d9f75844SAndroid Build Coastguard Worker while (*readcursor != 0 && addr_cursor < addr_end) {
257*d9f75844SAndroid Build Coastguard Worker if (*readcursor == ':') {
258*d9f75844SAndroid Build Coastguard Worker if (*(readcursor + 1) == ':') {
259*d9f75844SAndroid Build Coastguard Worker if (seencompressed) {
260*d9f75844SAndroid Build Coastguard Worker // Can only have one compressed run of zeroes ("::") per address.
261*d9f75844SAndroid Build Coastguard Worker return 0;
262*d9f75844SAndroid Build Coastguard Worker }
263*d9f75844SAndroid Build Coastguard Worker // Hit a compressed run. Count colons to figure out how much of the
264*d9f75844SAndroid Build Coastguard Worker // address is skipped.
265*d9f75844SAndroid Build Coastguard Worker readcursor += 2;
266*d9f75844SAndroid Build Coastguard Worker const char* coloncounter = readcursor;
267*d9f75844SAndroid Build Coastguard Worker int coloncount = 0;
268*d9f75844SAndroid Build Coastguard Worker if (*coloncounter == 0) {
269*d9f75844SAndroid Build Coastguard Worker // Special case - trailing ::.
270*d9f75844SAndroid Build Coastguard Worker addr_cursor = addr_end;
271*d9f75844SAndroid Build Coastguard Worker } else {
272*d9f75844SAndroid Build Coastguard Worker while (*coloncounter) {
273*d9f75844SAndroid Build Coastguard Worker if (*coloncounter == ':') {
274*d9f75844SAndroid Build Coastguard Worker ++coloncount;
275*d9f75844SAndroid Build Coastguard Worker }
276*d9f75844SAndroid Build Coastguard Worker ++coloncounter;
277*d9f75844SAndroid Build Coastguard Worker }
278*d9f75844SAndroid Build Coastguard Worker // (coloncount + 1) is the number of shorts left in the address.
279*d9f75844SAndroid Build Coastguard Worker // If this number is greater than the number of available shorts, the
280*d9f75844SAndroid Build Coastguard Worker // address is malformed.
281*d9f75844SAndroid Build Coastguard Worker if (coloncount + 1 > addr_end - addr_cursor) {
282*d9f75844SAndroid Build Coastguard Worker return 0;
283*d9f75844SAndroid Build Coastguard Worker }
284*d9f75844SAndroid Build Coastguard Worker addr_cursor = addr_end - (coloncount + 1);
285*d9f75844SAndroid Build Coastguard Worker seencompressed = true;
286*d9f75844SAndroid Build Coastguard Worker }
287*d9f75844SAndroid Build Coastguard Worker } else {
288*d9f75844SAndroid Build Coastguard Worker ++readcursor;
289*d9f75844SAndroid Build Coastguard Worker }
290*d9f75844SAndroid Build Coastguard Worker } else {
291*d9f75844SAndroid Build Coastguard Worker uint16_t word;
292*d9f75844SAndroid Build Coastguard Worker int bytesread = 0;
293*d9f75844SAndroid Build Coastguard Worker if (sscanf(readcursor, "%4hx%n", &word, &bytesread) != 1) {
294*d9f75844SAndroid Build Coastguard Worker return 0;
295*d9f75844SAndroid Build Coastguard Worker } else {
296*d9f75844SAndroid Build Coastguard Worker *addr_cursor = HostToNetwork16(word);
297*d9f75844SAndroid Build Coastguard Worker ++addr_cursor;
298*d9f75844SAndroid Build Coastguard Worker readcursor += bytesread;
299*d9f75844SAndroid Build Coastguard Worker if (*readcursor != ':' && *readcursor != '\0') {
300*d9f75844SAndroid Build Coastguard Worker return 0;
301*d9f75844SAndroid Build Coastguard Worker }
302*d9f75844SAndroid Build Coastguard Worker }
303*d9f75844SAndroid Build Coastguard Worker }
304*d9f75844SAndroid Build Coastguard Worker }
305*d9f75844SAndroid Build Coastguard Worker
306*d9f75844SAndroid Build Coastguard Worker if (*readcursor != '\0' || addr_cursor < addr_end) {
307*d9f75844SAndroid Build Coastguard Worker // Catches addresses too short or too long.
308*d9f75844SAndroid Build Coastguard Worker return 0;
309*d9f75844SAndroid Build Coastguard Worker }
310*d9f75844SAndroid Build Coastguard Worker memcpy(dst, &an_addr, sizeof(an_addr));
311*d9f75844SAndroid Build Coastguard Worker return 1;
312*d9f75844SAndroid Build Coastguard Worker }
313*d9f75844SAndroid Build Coastguard Worker
314*d9f75844SAndroid Build Coastguard Worker } // namespace rtc
315