1c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt/*
2c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt * Copyright (C) 2012 The Android Open Source Project
3c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt *
4c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
5c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt * you may not use this file except in compliance with the License.
6c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt * You may obtain a copy of the License at
7c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt *
8c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
9c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt *
10c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt * Unless required by applicable law or agreed to in writing, software
11c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
12c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt * See the License for the specific language governing permissions and
14c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt * limitations under the License.
15c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt */
16c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
17aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert#include <ctype.h>
18aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert#include <errno.h>
1970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti#include <fcntl.h>
20ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti#include <netdb.h>
21aa1be2b3d24d99f3ccb98ff4fbb2a81b63587effDan Albert#include <net/if.h>
22ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti#include <netinet/in.h>
23ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti#include <stdlib.h>
248e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey#include <string.h>
25838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand#include <sys/wait.h>
268e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
27bec6d04e1a84823b89e5581ea8ebcf9f08915216Jeff Sharkey#define LOG_TAG "Netd"
28bec6d04e1a84823b89e5581ea8ebcf9f08915216Jeff Sharkey
298e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey#include <cutils/log.h>
30838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand#include <logwrap/logwrap.h>
318e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
32c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt#include "NetdConstants.h"
33c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
34c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltconst char * const OEM_SCRIPT_PATH = "/system/bin/oem-iptables-init.sh";
35c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltconst char * const IPTABLES_PATH = "/system/bin/iptables";
360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char * const IP6TABLES_PATH = "/system/bin/ip6tables";
37c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltconst char * const TC_PATH = "/system/bin/tc";
38c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltconst char * const IP_PATH = "/system/bin/ip";
39c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltconst char * const ADD = "add";
40c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltconst char * const DEL = "del";
418e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
42838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchandstatic void logExecError(const char* argv[], int res, int status) {
438e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    const char** argp = argv;
448e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    std::string args = "";
458e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    while (*argp) {
468e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        args += *argp;
478e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        args += ' ';
488e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        argp++;
498e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    }
50838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand    ALOGE("exec() res=%d, status=%d for %s", res, status, args.c_str());
51838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand}
52838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand
53838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchandstatic int execIptablesCommand(int argc, const char *argv[], bool silent) {
54838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand    int res;
55838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand    int status;
56838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand
57838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand    res = android_fork_execvp(argc, (char **)argv, &status, false,
58838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand        !silent);
59838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand    if (res || !WIFEXITED(status) || WEXITSTATUS(status)) {
60838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand        if (!silent) {
61838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand            logExecError(argv, res, status);
62838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand        }
63838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand        if (res)
64838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand            return res;
65838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand        if (!WIFEXITED(status))
66838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand            return ECHILD;
67838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand    }
68838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand    return WEXITSTATUS(status);
698e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey}
708e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
718e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic int execIptables(IptablesTarget target, bool silent, va_list args) {
728e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    /* Read arguments from incoming va_list; we expect the list to be NULL terminated. */
738e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    std::list<const char*> argsList;
748e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    argsList.push_back(NULL);
758e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    const char* arg;
76390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani
77390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani    // Wait to avoid failure due to another process holding the lock
78390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani    argsList.push_back("-w");
79390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani
808e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    do {
818e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        arg = va_arg(args, const char *);
828e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        argsList.push_back(arg);
838e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    } while (arg);
848e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
858e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    int i = 0;
868e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    const char* argv[argsList.size()];
878e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    std::list<const char*>::iterator it;
888e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    for (it = argsList.begin(); it != argsList.end(); it++, i++) {
898e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        argv[i] = *it;
908e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    }
918e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
928e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    int res = 0;
938e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    if (target == V4 || target == V4V6) {
948e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        argv[0] = IPTABLES_PATH;
95838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand        res |= execIptablesCommand(argsList.size(), argv, silent);
968e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    }
978e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    if (target == V6 || target == V4V6) {
988e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        argv[0] = IP6TABLES_PATH;
99838ef6491794900731760aecc1d4a10bb2fdd2ecRom Lemarchand        res |= execIptablesCommand(argsList.size(), argv, silent);
1008e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    }
1018e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    return res;
1028e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey}
1038e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1048e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyint execIptables(IptablesTarget target, ...) {
1058e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    va_list args;
1068e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    va_start(args, target);
1078e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    int res = execIptables(target, false, args);
1088e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    va_end(args);
1098e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    return res;
1108e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey}
1118e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1128e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyint execIptablesSilently(IptablesTarget target, ...) {
1138e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    va_list args;
1148e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    va_start(args, target);
1158e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    int res = execIptables(target, true, args);
1168e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    va_end(args);
1178e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    return res;
1188e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey}
11970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti
12069261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall/*
12169261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall * Check an interface name for plausibility. This should e.g. help against
12269261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall * directory traversal.
12369261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall */
12469261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrallbool isIfaceName(const char *name) {
12569261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    size_t i;
12669261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    size_t name_len = strlen(name);
12769261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if ((name_len == 0) || (name_len > IFNAMSIZ)) {
12869261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall        return false;
12969261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    }
13069261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall
13169261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    /* First character must be alphanumeric */
13269261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isalnum(name[0])) {
13369261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall        return false;
13469261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    }
13569261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall
13669261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    for (i = 1; i < name_len; i++) {
13769261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall        if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-') && (name[i] != ':')) {
13869261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall            return false;
13969261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall        }
14069261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    }
14169261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall
14269261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    return true;
14369261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall}
144ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti
145ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colittiint parsePrefix(const char *prefix, uint8_t *family, void *address, int size, uint8_t *prefixlen) {
146ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    if (!prefix || !family || !address || !prefixlen) {
147ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        return -EFAULT;
148ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    }
149ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti
150ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    // Find the '/' separating address from prefix length.
151ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    const char *slash = strchr(prefix, '/');
152ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    const char *prefixlenString = slash + 1;
153ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    if (!slash || !*prefixlenString)
154ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        return -EINVAL;
155ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti
156ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    // Convert the prefix length to a uint8_t.
157ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    char *endptr;
158ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    unsigned templen;
159ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    templen = strtoul(prefixlenString, &endptr, 10);
160ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    if (*endptr || templen > 255) {
161ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        return -EINVAL;
162ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    }
163ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    *prefixlen = templen;
164ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti
165ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    // Copy the address part of the prefix to a local buffer. We have to copy
166ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    // because inet_pton and getaddrinfo operate on null-terminated address
167ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    // strings, but prefix is const and has '/' after the address.
168ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    std::string addressString(prefix, slash - prefix);
169ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti
170ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    // Parse the address.
171ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    addrinfo *res;
172ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    addrinfo hints = {
173ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        .ai_flags = AI_NUMERICHOST,
174ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    };
175ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    int ret = getaddrinfo(addressString.c_str(), NULL, &hints, &res);
176ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    if (ret || !res) {
177ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        return -EINVAL;  // getaddrinfo return values are not errno values.
178ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    }
179ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti
180ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    // Convert the address string to raw address bytes.
181ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    void *rawAddress;
182ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    int rawLength;
183ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    switch (res[0].ai_family) {
184ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        case AF_INET: {
185ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            if (*prefixlen > 32) {
186ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti                return -EINVAL;
187ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            }
188ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            sockaddr_in *sin = (sockaddr_in *) res[0].ai_addr;
189ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            rawAddress = &sin->sin_addr;
190ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            rawLength = 4;
191ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            break;
192ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        }
193ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        case AF_INET6: {
194ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            if (*prefixlen > 128) {
195ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti                return -EINVAL;
196ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            }
197ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            sockaddr_in6 *sin6 = (sockaddr_in6 *) res[0].ai_addr;
198ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            rawAddress = &sin6->sin6_addr;
199ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            rawLength = 16;
200ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            break;
201ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        }
202ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        default: {
203ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            freeaddrinfo(res);
204ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti            return -EAFNOSUPPORT;
205ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        }
206ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    }
207ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti
208ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    if (rawLength > size) {
209ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        freeaddrinfo(res);
210ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti        return -ENOSPC;
211ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    }
212ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti
213ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    *family = res[0].ai_family;
214ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    memcpy(address, rawAddress, rawLength);
215ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    freeaddrinfo(res);
216ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti
217ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti    return rawLength;
218ba25df989b48f36b784ad39307a49a4fd9c3fd66Lorenzo Colitti}
219