• 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] != '-')
70                 && (name[i] != ':') && (name[i] != '.')) {
71             return false;
72         }
73     }
74 
75     return true;
76 }
77 
parsePrefix(const char * prefix,uint8_t * family,void * address,int size,uint8_t * prefixlen)78 int parsePrefix(const char *prefix, uint8_t *family, void *address, int size, uint8_t *prefixlen) {
79     if (!prefix || !family || !address || !prefixlen) {
80         return -EFAULT;
81     }
82 
83     // Find the '/' separating address from prefix length.
84     const char *slash = strchr(prefix, '/');
85     const char *prefixlenString = slash + 1;
86     if (!slash || !*prefixlenString)
87         return -EINVAL;
88 
89     // Convert the prefix length to a uint8_t.
90     char *endptr;
91     unsigned templen;
92     templen = strtoul(prefixlenString, &endptr, 10);
93     if (*endptr || templen > 255) {
94         return -EINVAL;
95     }
96     *prefixlen = templen;
97 
98     // Copy the address part of the prefix to a local buffer. We have to copy
99     // because inet_pton and getaddrinfo operate on null-terminated address
100     // strings, but prefix is const and has '/' after the address.
101     std::string addressString(prefix, slash - prefix);
102 
103     // Parse the address.
104     addrinfo *res;
105     addrinfo hints = {
106         .ai_flags = AI_NUMERICHOST,
107     };
108     int ret = getaddrinfo(addressString.c_str(), nullptr, &hints, &res);
109     if (ret || !res) {
110         return -EINVAL;  // getaddrinfo return values are not errno values.
111     }
112 
113     // Convert the address string to raw address bytes.
114     void *rawAddress;
115     int rawLength;
116     switch (res[0].ai_family) {
117         case AF_INET: {
118             if (*prefixlen > 32) {
119                 return -EINVAL;
120             }
121             sockaddr_in *sin = (sockaddr_in *) res[0].ai_addr;
122             rawAddress = &sin->sin_addr;
123             rawLength = 4;
124             break;
125         }
126         case AF_INET6: {
127             if (*prefixlen > 128) {
128                 return -EINVAL;
129             }
130             sockaddr_in6 *sin6 = (sockaddr_in6 *) res[0].ai_addr;
131             rawAddress = &sin6->sin6_addr;
132             rawLength = 16;
133             break;
134         }
135         default: {
136             freeaddrinfo(res);
137             return -EAFNOSUPPORT;
138         }
139     }
140 
141     if (rawLength > size) {
142         freeaddrinfo(res);
143         return -ENOSPC;
144     }
145 
146     *family = res[0].ai_family;
147     memcpy(address, rawAddress, rawLength);
148     freeaddrinfo(res);
149 
150     return rawLength;
151 }
152 
blockSigpipe()153 void blockSigpipe() {
154     sigset_t mask;
155 
156     sigemptyset(&mask);
157     sigaddset(&mask, SIGPIPE);
158     if (sigprocmask(SIG_BLOCK, &mask, nullptr) != 0)
159         ALOGW("WARNING: SIGPIPE not blocked\n");
160 }
161 
setCloseOnExec(const char * sock)162 void setCloseOnExec(const char *sock) {
163     int fd = android_get_control_socket(sock);
164     int flags = fcntl(fd, F_GETFD, 0);
165     if (flags == -1) {
166         ALOGE("Can't get fd flags for control socket %s", sock);
167         flags = 0;
168     }
169     flags |= FD_CLOEXEC;
170     if (fcntl(fd, F_SETFD, flags) == -1) {
171         ALOGE("Can't set control socket %s to FD_CLOEXEC", sock);
172     }
173 }
174