blob: 91445caf07234a6d1e0c11a047f2c87f8717c943 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <vector>
#include <string.h>
#include "log.h"
#include "namespace.h"
#include "proxy.h"
void usage(const char* program) {
loge("Usage: %s -n [namespace|pid] -o <outer if> -i <inner ifs>\n",
program);
loge(" -o Outer interface that connects to an existing IPv6 network.\n"
" -i Comma separated list of inner interfaces that would like\n"
" to access the IPv6 network available on the outer interface.\n"
" -n Optional parameter that causes the proxy to run in the given\n"
" network namespace. If a name is given instead of a PID the\n"
" namespace is expected to be set up by iproute2 or with a\n"
" similar approach where the namespace is linked in\n"
" /var/run/netns. A PID is assumed if the argument is numeric.\n"
" If providing a PID the same namespace that the PID is\n"
" running in will be used. In this scenario there is no\n"
" requirement for a file in /var/run/netns.\n"
"\n"
" The proxy will ensure that router solicitations from inner\n"
" interfaces are forwarded to the outer interface and that\n"
" router advertisements from the outer interface are forwarded\n"
" to the inner interfaces. In addition to this neighbor\n"
" solicitations and advertisements will also be forwarded in a\n"
" way that enables IPv6 connectivity and routes will be set up\n"
" for source addresses on the inner interfaces so that replies\n"
" can reach those sources as expected.\n"
);
}
static std::vector<const char*> splitString(char* str, char delimiter) {
std::vector<const char*> parts;
char* part = nullptr;
do {
parts.push_back(str);
part = strchr(str, delimiter);
if (part != nullptr) {
*part = '\0';
str = part + 1;
}
} while (part != nullptr);
return parts;
}
int main(int argc, char* argv[]) {
char* inner = nullptr;
const char* outer = nullptr;
const char* netNamespace = nullptr;
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-o") == 0) {
outer = argv[++i];
} else if (strcmp(argv[i], "-i") == 0) {
inner = argv[++i];
} else if (strcmp(argv[i], "-h") == 0 ||
strcmp(argv[i], "--help") == 0) {
usage(argv[0]);
return 1;
} else if (strcmp(argv[i], "-n") == 0) {
netNamespace = argv[++i];
} else {
loge("ERROR: Unknown argument '%s'\n\n", argv[i]);
usage(argv[0]);
return 1;
}
}
bool error = false;
if (inner == nullptr) {
loge("ERROR: Missing inner interface\n");
error = true;
}
if (outer == nullptr) {
loge("ERROR: Missing outer interface\n");
error = true;
}
if (netNamespace) {
if (!setNetworkNamespace(netNamespace)) {
error = true;
}
}
if (error) {
usage(argv[0]);
return 1;
}
std::vector<const char*> innerInterfaces = splitString(inner, ',');
Proxy proxy(outer, innerInterfaces.begin(), innerInterfaces.end());
return proxy.run();
}