• 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 #include <logwrap/logwrap.h>
33 
34 #include "Controllers.h"
35 #include "NetdConstants.h"
36 #include "IptablesRestoreController.h"
37 
execIptablesRestoreWithOutput(IptablesTarget target,const std::string & commands,std::string * output)38 int execIptablesRestoreWithOutput(IptablesTarget target, const std::string& commands,
39                                   std::string *output) {
40     return android::net::gCtls->iptablesRestoreCtrl.execute(target, commands, output);
41 }
42 
execIptablesRestore(IptablesTarget target,const std::string & commands)43 int execIptablesRestore(IptablesTarget target, const std::string& commands) {
44     return execIptablesRestoreWithOutput(target, commands, nullptr);
45 }
46 
execIptablesRestoreCommand(IptablesTarget target,const std::string & table,const std::string & command,std::string * output)47 int execIptablesRestoreCommand(IptablesTarget target, const std::string& table,
48                                const std::string& command, std::string *output) {
49     std::string fullCmd = android::base::StringPrintf("*%s\n%s\nCOMMIT\n", table.c_str(),
50                                                       command.c_str());
51     return execIptablesRestoreWithOutput(target, fullCmd, output);
52 }
53 
54 /*
55  * Check an interface name for plausibility. This should e.g. help against
56  * directory traversal.
57  */
isIfaceName(const std::string & name)58 bool isIfaceName(const std::string& name) {
59     size_t i;
60     if ((name.empty()) || (name.size() > IFNAMSIZ)) {
61         return false;
62     }
63 
64     /* First character must be alphanumeric */
65     if (!isalnum(name[0])) {
66         return false;
67     }
68 
69     for (i = 1; i < name.size(); i++) {
70         if (!isalnum(name[i]) && (name[i] != '_') && (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