* limitations under the License.
*/
+#include <ctype.h>
+#include <errno.h>
#include <fcntl.h>
+#include <netdb.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
-#include <ctype.h>
-#include <net/if.h>
#define LOG_TAG "Netd"
std::list<const char*> argsList;
argsList.push_back(NULL);
const char* arg;
+
+ // Wait to avoid failure due to another process holding the lock
+ argsList.push_back("-w");
+
do {
arg = va_arg(args, const char *);
argsList.push_back(arg);
return res;
}
-int writeFile(const char *path, const char *value, int size) {
- int fd = open(path, O_WRONLY);
- if (fd < 0) {
- ALOGE("Failed to open %s: %s", path, strerror(errno));
- return -1;
- }
-
- if (write(fd, value, size) != size) {
- ALOGE("Failed to write %s: %s", path, strerror(errno));
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
-}
-
-int readFile(const char *path, char *buf, int *sizep)
-{
- int fd = open(path, O_RDONLY);
- int size;
-
- if (fd < 0) {
- ALOGE("Failed to open %s: %s", path, strerror(errno));
- return -1;
- }
-
- size = read(fd, buf, *sizep);
- if (size < 0) {
- ALOGE("Failed to write %s: %s", path, strerror(errno));
- close(fd);
- return -1;
- }
- *sizep = size;
- close(fd);
- return 0;
-}
-
/*
* Check an interface name for plausibility. This should e.g. help against
* directory traversal.
return true;
}
+
+int parsePrefix(const char *prefix, uint8_t *family, void *address, int size, uint8_t *prefixlen) {
+ if (!prefix || !family || !address || !prefixlen) {
+ return -EFAULT;
+ }
+
+ // Find the '/' separating address from prefix length.
+ const char *slash = strchr(prefix, '/');
+ const char *prefixlenString = slash + 1;
+ if (!slash || !*prefixlenString)
+ return -EINVAL;
+
+ // Convert the prefix length to a uint8_t.
+ char *endptr;
+ unsigned templen;
+ templen = strtoul(prefixlenString, &endptr, 10);
+ if (*endptr || templen > 255) {
+ return -EINVAL;
+ }
+ *prefixlen = templen;
+
+ // Copy the address part of the prefix to a local buffer. We have to copy
+ // because inet_pton and getaddrinfo operate on null-terminated address
+ // strings, but prefix is const and has '/' after the address.
+ std::string addressString(prefix, slash - prefix);
+
+ // Parse the address.
+ addrinfo *res;
+ addrinfo hints = {
+ .ai_flags = AI_NUMERICHOST,
+ };
+ int ret = getaddrinfo(addressString.c_str(), NULL, &hints, &res);
+ if (ret || !res) {
+ return -EINVAL; // getaddrinfo return values are not errno values.
+ }
+
+ // Convert the address string to raw address bytes.
+ void *rawAddress;
+ int rawLength;
+ switch (res[0].ai_family) {
+ case AF_INET: {
+ if (*prefixlen > 32) {
+ return -EINVAL;
+ }
+ sockaddr_in *sin = (sockaddr_in *) res[0].ai_addr;
+ rawAddress = &sin->sin_addr;
+ rawLength = 4;
+ break;
+ }
+ case AF_INET6: {
+ if (*prefixlen > 128) {
+ return -EINVAL;
+ }
+ sockaddr_in6 *sin6 = (sockaddr_in6 *) res[0].ai_addr;
+ rawAddress = &sin6->sin6_addr;
+ rawLength = 16;
+ break;
+ }
+ default: {
+ freeaddrinfo(res);
+ return -EAFNOSUPPORT;
+ }
+ }
+
+ if (rawLength > size) {
+ freeaddrinfo(res);
+ return -ENOSPC;
+ }
+
+ *family = res[0].ai_family;
+ memcpy(address, rawAddress, rawLength);
+ freeaddrinfo(res);
+
+ return rawLength;
+}