diff options
Diffstat (limited to 'lib/libtle_glue/gateway.h')
-rw-r--r-- | lib/libtle_glue/gateway.h | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/lib/libtle_glue/gateway.h b/lib/libtle_glue/gateway.h new file mode 100644 index 0000000..29de6b1 --- /dev/null +++ b/lib/libtle_glue/gateway.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019 Ant Financial Services Group. + * 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. + */ + +#ifndef _TLE_GATEWAY_H_ +#define _TLE_GATEWAY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +static inline bool +is_ipv4_loopback_addr(in_addr_t addr, struct glue_ctx *ctx) +{ + if (addr == ctx->ipv4 || addr == htonl(INADDR_LOOPBACK)) + return true; + else + return false; +} + +static inline bool +is_ipv6_loopback_addr(const struct in6_addr *addr, struct glue_ctx *ctx) +{ + if (memcmp(addr, &ctx->ipv6, sizeof(struct in6_addr)) == 0 || + IN6_IS_ADDR_LOOPBACK(addr) || + (IN6_IS_ADDR_V4COMPAT(addr) && + addr->__in6_u.__u6_addr32[3] == htonl(INADDR_LOOPBACK)) || + (IN6_IS_ADDR_V4MAPPED(addr) && + addr->__in6_u.__u6_addr32[3] == htonl(INADDR_LOOPBACK))) + return true; + else + return false; +} + +static inline const struct in_addr * +ipv4_gateway_lookup(void *data, const struct in_addr *addr) +{ + uint8_t ls; + struct glue_ctx *ctx = data; + + if (is_ipv4_loopback_addr(addr->s_addr, ctx)) + return addr; + + ls = 32 - ctx->ipv4_ml; + if ((addr->s_addr << ls) == (ctx->ipv4 << ls)) + return addr; + + if (ctx->ipv4_gw.s_addr != 0) + return &ctx->ipv4_gw; + + return addr; +} + +static inline const struct in6_addr * +ipv6_gateway_lookup(void *data, const struct in6_addr *addr) +{ + uint8_t ls; + struct glue_ctx *ctx = data; + + if (is_ipv6_loopback_addr(addr, ctx)) + return addr; + + if (ctx->ipv6_ml <= 64) { + ls = 64 - ctx->ipv6_ml; + if ((*(const uint64_t*)addr << ls) == + (*(const uint64_t*)&ctx->ipv6 << ls)) + return addr; + } else if (*(const uint64_t*)addr == *(const uint64_t*)&ctx->ipv6) { + ls = 128 - ctx->ipv6_ml; + if ((*((const uint64_t*)addr + 1) << ls) == + (*((const uint64_t*)&ctx->ipv6 + 1) << ls)) + return addr; + } + + if (!IN6_IS_ADDR_UNSPECIFIED(&ctx->ipv6_gw)) + return &ctx->ipv6_gw; + + return addr; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _TLE_GATEWAY_H_ */ |