• 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 <openssl/ssl.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/wait.h>
27 
28 #define LOG_TAG "Netd"
29 
30 #include <android-base/stringprintf.h>
31 #include <cutils/log.h>
32 #include <cutils/sockets.h>
33 #include <logwrap/logwrap.h>
34 
35 #include "Controllers.h"
36 #include "NetdConstants.h"
37 #include "IptablesRestoreController.h"
38 
39 const size_t SHA256_SIZE = EVP_MD_size(EVP_sha256());
40 
41 const char * const OEM_SCRIPT_PATH = "/system/bin/oem-iptables-init.sh";
42 const char * const ADD = "add";
43 const char * const DEL = "del";
44 
execIptablesRestoreWithOutput(IptablesTarget target,const std::string & commands,std::string * output)45 int execIptablesRestoreWithOutput(IptablesTarget target, const std::string& commands,
46                                   std::string *output) {
47     return android::net::gCtls->iptablesRestoreCtrl.execute(target, commands, output);
48 }
49 
execIptablesRestore(IptablesTarget target,const std::string & commands)50 int execIptablesRestore(IptablesTarget target, const std::string& commands) {
51     return execIptablesRestoreWithOutput(target, commands, nullptr);
52 }
53 
execIptablesRestoreCommand(IptablesTarget target,const std::string & table,const std::string & command,std::string * output)54 int execIptablesRestoreCommand(IptablesTarget target, const std::string& table,
55                                const std::string& command, std::string *output) {
56     std::string fullCmd = android::base::StringPrintf("*%s\n%s\nCOMMIT\n", table.c_str(),
57                                                       command.c_str());
58     return execIptablesRestoreWithOutput(target, fullCmd, output);
59 }
60 
61 /*
62  * Check an interface name for plausibility. This should e.g. help against
63  * directory traversal.
64  */
isIfaceName(const std::string & name)65 bool isIfaceName(const std::string& name) {
66     size_t i;
67     if ((name.empty()) || (name.size() > IFNAMSIZ)) {
68         return false;
69     }
70 
71     /* First character must be alphanumeric */
72     if (!isalnum(name[0])) {
73         return false;
74     }
75 
76     for (i = 1; i < name.size(); i++) {
77         if (!isalnum(name[i]) && (name[i] != '_') && (name[i] != '-') && (name[i] != ':')) {
78             return false;
79         }
80     }
81 
82     return true;
83 }
84 
parsePrefix(const char * prefix,uint8_t * family,void * address,int size,uint8_t * prefixlen)85 int parsePrefix(const char *prefix, uint8_t *family, void *address, int size, uint8_t *prefixlen) {
86     if (!prefix || !family || !address || !prefixlen) {
87         return -EFAULT;
88     }
89 
90     // Find the '/' separating address from prefix length.
91     const char *slash = strchr(prefix, '/');
92     const char *prefixlenString = slash + 1;
93     if (!slash || !*prefixlenString)
94         return -EINVAL;
95 
96     // Convert the prefix length to a uint8_t.
97     char *endptr;
98     unsigned templen;
99     templen = strtoul(prefixlenString, &endptr, 10);
100     if (*endptr || templen > 255) {
101         return -EINVAL;
102     }
103     *prefixlen = templen;
104 
105     // Copy the address part of the prefix to a local buffer. We have to copy
106     // because inet_pton and getaddrinfo operate on null-terminated address
107     // strings, but prefix is const and has '/' after the address.
108     std::string addressString(prefix, slash - prefix);
109 
110     // Parse the address.
111     addrinfo *res;
112     addrinfo hints = {
113         .ai_flags = AI_NUMERICHOST,
114     };
115     int ret = getaddrinfo(addressString.c_str(), NULL, &hints, &res);
116     if (ret || !res) {
117         return -EINVAL;  // getaddrinfo return values are not errno values.
118     }
119 
120     // Convert the address string to raw address bytes.
121     void *rawAddress;
122     int rawLength;
123     switch (res[0].ai_family) {
124         case AF_INET: {
125             if (*prefixlen > 32) {
126                 return -EINVAL;
127             }
128             sockaddr_in *sin = (sockaddr_in *) res[0].ai_addr;
129             rawAddress = &sin->sin_addr;
130             rawLength = 4;
131             break;
132         }
133         case AF_INET6: {
134             if (*prefixlen > 128) {
135                 return -EINVAL;
136             }
137             sockaddr_in6 *sin6 = (sockaddr_in6 *) res[0].ai_addr;
138             rawAddress = &sin6->sin6_addr;
139             rawLength = 16;
140             break;
141         }
142         default: {
143             freeaddrinfo(res);
144             return -EAFNOSUPPORT;
145         }
146     }
147 
148     if (rawLength > size) {
149         freeaddrinfo(res);
150         return -ENOSPC;
151     }
152 
153     *family = res[0].ai_family;
154     memcpy(address, rawAddress, rawLength);
155     freeaddrinfo(res);
156 
157     return rawLength;
158 }
159 
blockSigpipe()160 void blockSigpipe() {
161     sigset_t mask;
162 
163     sigemptyset(&mask);
164     sigaddset(&mask, SIGPIPE);
165     if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
166         ALOGW("WARNING: SIGPIPE not blocked\n");
167 }
168 
setCloseOnExec(const char * sock)169 void setCloseOnExec(const char *sock) {
170     int fd = android_get_control_socket(sock);
171     int flags = fcntl(fd, F_GETFD, 0);
172     if (flags == -1) {
173         ALOGE("Can't get fd flags for control socket %s", sock);
174         flags = 0;
175     }
176     flags |= FD_CLOEXEC;
177     if (fcntl(fd, F_SETFD, flags) == -1) {
178         ALOGE("Can't set control socket %s to FD_CLOEXEC", sock);
179     }
180 }
181