• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <ctype.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <netdb.h>
21 #include <net/if.h>
22 #include <netinet/in.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/wait.h>
26 
27 #define LOG_TAG "Netd"
28 
29 #include <android-base/stringprintf.h>
30 #include <cutils/sockets.h>
31 #include <log/log.h>
32 
33 #include "Controllers.h"
34 #include "NetdConstants.h"
35 #include "IptablesRestoreController.h"
36 
execIptablesRestoreWithOutput(IptablesTarget target,const std::string & commands,std::string * output)37 int execIptablesRestoreWithOutput(IptablesTarget target, const std::string& commands,
38                                   std::string *output) {
39     return android::net::gCtls->iptablesRestoreCtrl.execute(target, commands, output);
40 }
41 
execIptablesRestore(IptablesTarget target,const std::string & commands)42 int execIptablesRestore(IptablesTarget target, const std::string& commands) {
43     return execIptablesRestoreWithOutput(target, commands, nullptr);
44 }
45 
execIptablesRestoreCommand(IptablesTarget target,const std::string & table,const std::string & command,std::string * output)46 int execIptablesRestoreCommand(IptablesTarget target, const std::string& table,
47                                const std::string& command, std::string *output) {
48     std::string fullCmd = android::base::StringPrintf("*%s\n%s\nCOMMIT\n", table.c_str(),
49                                                       command.c_str());
50     return execIptablesRestoreWithOutput(target, fullCmd, output);
51 }
52 
53 /*
54  * Check an interface name for plausibility. This should e.g. help against
55  * directory traversal.
56  */
isIfaceName(const std::string & name)57 bool isIfaceName(const std::string& name) {
58     size_t i;
59     if ((name.empty()) || (name.size() > IFNAMSIZ)) {
60         return false;
61     }
62 
63     /* First character must be alphanumeric */
64     if (!isalnum(name[0])) {
65         return false;
66     }
67 
68     for (i = 1; i < name.size(); i++) {
69         if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-') && (name[i] != ':')) {
70             return false;
71         }
72     }
73 
74     return true;
75 }
76 
parsePrefix(const char * prefix,uint8_t * family,void * address,int size,uint8_t * prefixlen)77 int parsePrefix(const char *prefix, uint8_t *family, void *address, int size, uint8_t *prefixlen) {
78     if (!prefix || !family || !address || !prefixlen) {
79         return -EFAULT;
80     }
81 
82     // Find the '/' separating address from prefix length.
83     const char *slash = strchr(prefix, '/');
84     const char *prefixlenString = slash + 1;
85     if (!slash || !*prefixlenString)
86         return -EINVAL;
87 
88     // Convert the prefix length to a uint8_t.
89     char *endptr;
90     unsigned templen;
91     templen = strtoul(prefixlenString, &endptr, 10);
92     if (*endptr || templen > 255) {
93         return -EINVAL;
94     }
95     *prefixlen = templen;
96 
97     // Copy the address part of the prefix to a local buffer. We have to copy
98     // because inet_pton and getaddrinfo operate on null-terminated address
99     // strings, but prefix is const and has '/' after the address.
100     std::string addressString(prefix, slash - prefix);
101 
102     // Parse the address.
103     addrinfo *res;
104     addrinfo hints = {
105         .ai_flags = AI_NUMERICHOST,
106     };
107     int ret = getaddrinfo(addressString.c_str(), nullptr, &hints, &res);
108     if (ret || !res) {
109         return -EINVAL;  // getaddrinfo return values are not errno values.
110     }
111 
112     // Convert the address string to raw address bytes.
113     void *rawAddress;
114     int rawLength;
115     switch (res[0].ai_family) {
116         case AF_INET: {
117             if (*prefixlen > 32) {
118                 return -EINVAL;
119             }
120             sockaddr_in *sin = (sockaddr_in *) res[0].ai_addr;
121             rawAddress = &sin->sin_addr;
122             rawLength = 4;
123             break;
124         }
125         case AF_INET6: {
126             if (*prefixlen > 128) {
127                 return -EINVAL;
128             }
129             sockaddr_in6 *sin6 = (sockaddr_in6 *) res[0].ai_addr;
130             rawAddress = &sin6->sin6_addr;
131             rawLength = 16;
132             break;
133         }
134         default: {
135             freeaddrinfo(res);
136             return -EAFNOSUPPORT;
137         }
138     }
139 
140     if (rawLength > size) {
141         freeaddrinfo(res);
142         return -ENOSPC;
143     }
144 
145     *family = res[0].ai_family;
146     memcpy(address, rawAddress, rawLength);
147     freeaddrinfo(res);
148 
149     return rawLength;
150 }
151 
blockSigpipe()152 void blockSigpipe() {
153     sigset_t mask;
154 
155     sigemptyset(&mask);
156     sigaddset(&mask, SIGPIPE);
157     if (sigprocmask(SIG_BLOCK, &mask, nullptr) != 0)
158         ALOGW("WARNING: SIGPIPE not blocked\n");
159 }
160 
setCloseOnExec(const char * sock)161 void setCloseOnExec(const char *sock) {
162     int fd = android_get_control_socket(sock);
163     int flags = fcntl(fd, F_GETFD, 0);
164     if (flags == -1) {
165         ALOGE("Can't get fd flags for control socket %s", sock);
166         flags = 0;
167     }
168     flags |= FD_CLOEXEC;
169     if (fcntl(fd, F_SETFD, flags) == -1) {
170         ALOGE("Can't set control socket %s to FD_CLOEXEC", sock);
171     }
172 }
173