1 /* 2 * Copyright (C) 2017 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 <vector> 18 19 #include <string.h> 20 21 #include "log.h" 22 #include "namespace.h" 23 #include "proxy.h" 24 25 void usage(const char* program) { 26 loge("Usage: %s -n [namespace|pid] -o <outer if> -i <inner ifs>\n", 27 program); 28 loge(" -o Outer interface that connects to an existing IPv6 network.\n" 29 " -i Comma separated list of inner interfaces that would like\n" 30 " to access the IPv6 network available on the outer interface.\n" 31 " -n Optional parameter that causes the proxy to run in the given\n" 32 " network namespace. If a name is given instead of a PID the\n" 33 " namespace is expected to be set up by iproute2 or with a\n" 34 " similar approach where the namespace is linked in\n" 35 " /var/run/netns. A PID is assumed if the argument is numeric.\n" 36 " If providing a PID the same namespace that the PID is\n" 37 " running in will be used. In this scenario there is no\n" 38 " requirement for a file in /var/run/netns.\n" 39 "\n" 40 " The proxy will ensure that router solicitations from inner\n" 41 " interfaces are forwarded to the outer interface and that\n" 42 " router advertisements from the outer interface are forwarded\n" 43 " to the inner interfaces. In addition to this neighbor\n" 44 " solicitations and advertisements will also be forwarded in a\n" 45 " way that enables IPv6 connectivity and routes will be set up\n" 46 " for source addresses on the inner interfaces so that replies\n" 47 " can reach those sources as expected.\n" 48 ); 49 } 50 51 static std::vector<const char*> splitString(char* str, char delimiter) { 52 std::vector<const char*> parts; 53 char* part = nullptr; 54 do { 55 parts.push_back(str); 56 part = strchr(str, delimiter); 57 if (part != nullptr) { 58 *part = '\0'; 59 str = part + 1; 60 } 61 } while (part != nullptr); 62 return parts; 63 } 64 65 int main(int argc, char* argv[]) { 66 char* inner = nullptr; 67 const char* outer = nullptr; 68 const char* netNamespace = nullptr; 69 for (int i = 1; i < argc; ++i) { 70 if (strcmp(argv[i], "-o") == 0) { 71 outer = argv[++i]; 72 } else if (strcmp(argv[i], "-i") == 0) { 73 inner = argv[++i]; 74 } else if (strcmp(argv[i], "-h") == 0 || 75 strcmp(argv[i], "--help") == 0) { 76 usage(argv[0]); 77 return 1; 78 } else if (strcmp(argv[i], "-n") == 0) { 79 netNamespace = argv[++i]; 80 } else { 81 loge("ERROR: Unknown argument '%s'\n\n", argv[i]); 82 usage(argv[0]); 83 return 1; 84 } 85 } 86 bool error = false; 87 if (inner == nullptr) { 88 loge("ERROR: Missing inner interface\n"); 89 error = true; 90 } 91 if (outer == nullptr) { 92 loge("ERROR: Missing outer interface\n"); 93 error = true; 94 } 95 if (netNamespace) { 96 if (!setNetworkNamespace(netNamespace)) { 97 error = true; 98 } 99 } 100 if (error) { 101 usage(argv[0]); 102 return 1; 103 } 104 105 std::vector<const char*> innerInterfaces = splitString(inner, ','); 106 107 Proxy proxy(outer, innerInterfaces.begin(), innerInterfaces.end()); 108 109 return proxy.run(); 110 } 111 112