RouteController.cpp
modifyIpRoute
// Adds or deletes an IPv4 or IPv6 route.
// Returns 0 on success or negative errno on failure.
int modifyIpRoute(uint16_t action, uint16_t flags, uint32_t table, const char* interface,
const char* destination, const char* nexthop, uint32_t mtu) {
// At least the destination must be non-null.
if (!destination) {
ALOGE("null destination");
return -EFAULT;
}
// Parse the prefix.
uint8_t rawAddress[sizeof(in6_addr)];
uint8_t family;
uint8_t prefixLength;
int rawLength = parsePrefix(destination, &family, rawAddress, sizeof(rawAddress),
&prefixLength);
if (rawLength < 0) {
ALOGE("parsePrefix failed for destination %s (%s)", destination, strerror(-rawLength));
return rawLength;
}
if (static_cast<size_t>(rawLength) > sizeof(rawAddress)) {
ALOGE("impossible! address too long (%d vs %zu)", rawLength, sizeof(rawAddress));
return -ENOBUFS; // Cannot happen; parsePrefix only supports IPv4 and IPv6.
}
uint8_t type = RTN_UNICAST;
uint32_t ifindex;
uint8_t rawNexthop[sizeof(in6_addr)];
if (nexthop && !strcmp(nexthop, "unreachable")) {
type = RTN_UNREACHABLE;
// 'interface' is likely non-NULL, as the caller (modifyRoute()) likely used it to lookup
// the table number. But it's an error to specify an interface ("dev ...") or a nexthop for
// unreachable routes, so nuke them. (IPv6 allows them to be specified; IPv4 doesn't.)
interface = OIF_NONE;
nexthop = nullptr;
} else if (nexthop && !strcmp(nexthop, "throw")) {
type = RTN_THROW;
interf