123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738 |
- /* vim: set expandtab ts=4 sw=4: */
- /*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- #include "benc/String.h"
- #include "benc/Dict.h"
- #include "util/platform/Sockaddr.h"
- #include "exception/Err.h"
- #include "benc/List.h"
- #include "tunnel/RouteGen.h"
- #include "util/log/Log.h"
- #include "util/Identity.h"
- #include "util/Bits.h"
- #include "util/platform/netdev/NetDev.h"
- struct Prefix6
- {
- uint64_t highBits;
- uint64_t lowBits;
- int prefix;
- struct Allocator* alloc;
- };
- static int comparePrefixes6(struct Prefix6* a, struct Prefix6* b)
- {
- if (a->prefix != b->prefix) {
- return (a->prefix < b->prefix) ? -1 : 1;
- }
- if (a->highBits != b->highBits) {
- return (a->highBits < b->highBits) ? 1 : -1;
- }
- if (a->lowBits != b->lowBits) {
- return (a->lowBits < b->lowBits) ? 1 : -1;
- }
- return 0;
- }
- #define ArrayList_COMPARE comparePrefixes6
- #define ArrayList_TYPE struct Prefix6
- #define ArrayList_NAME OfPrefix6
- #include "util/ArrayList.h"
- struct Prefix4
- {
- uint32_t bits;
- int prefix;
- struct Allocator* alloc;
- };
- static int comparePrefixes4(struct Prefix4* a, struct Prefix4* b)
- {
- if (a->prefix != b->prefix) {
- return (a->prefix < b->prefix) ? -1 : 1;
- }
- if (a->bits != b->bits) {
- return (a->bits < b->bits) ? 1 : -1;
- }
- return 0;
- }
- #define ArrayList_COMPARE comparePrefixes4
- #define ArrayList_TYPE struct Prefix4
- #define ArrayList_NAME OfPrefix4
- #include "util/ArrayList.h"
- struct Prefix46 {
- struct ArrayList_OfPrefix4* prefix4;
- struct ArrayList_OfPrefix6* prefix6;
- };
- struct RouteGen_pvt
- {
- struct RouteGen pub;
- struct ArrayList_OfPrefix6* prefixes6;
- struct ArrayList_OfPrefix6* localPrefixes6;
- struct ArrayList_OfPrefix6* exceptions6;
- struct ArrayList_OfPrefix4* prefixes4;
- struct ArrayList_OfPrefix4* localPrefixes4;
- struct ArrayList_OfPrefix4* exceptions4;
- struct Allocator* alloc;
- struct Log* log;
- Identity
- };
- static struct Sockaddr* sockaddrForPrefix4(struct Allocator* alloc, struct Prefix4* pfx4)
- {
- union {
- uint32_t addr_be;
- uint8_t bytes[4];
- } un;
- un.addr_be = Endian_hostToBigEndian32(pfx4->bits);
- struct Sockaddr* out = Sockaddr_fromBytes(un.bytes, Sockaddr_AF_INET, alloc);
- out->flags |= Sockaddr_flags_PREFIX;
- out->prefix = pfx4->prefix;
- return out;
- }
- static String* printPrefix4(struct Allocator* alloc, struct Prefix4* pfx4)
- {
- return String_new(Sockaddr_print(sockaddrForPrefix4(alloc, pfx4), alloc), alloc);
- }
- static struct Sockaddr* sockaddrForPrefix6(struct Allocator* alloc, struct Prefix6* pfx6)
- {
- union {
- struct {
- uint64_t highBits_be;
- uint64_t lowBits_be;
- } longs;
- uint8_t bytes[16];
- } un;
- un.longs.highBits_be = Endian_hostToBigEndian64(pfx6->highBits);
- un.longs.lowBits_be = Endian_hostToBigEndian64(pfx6->lowBits);
- struct Sockaddr* out = Sockaddr_fromBytes(un.bytes, Sockaddr_AF_INET6, alloc);
- out->flags |= Sockaddr_flags_PREFIX;
- out->prefix = pfx6->prefix;
- return out;
- }
- static String* printPrefix6(struct Allocator* alloc, struct Prefix6* pfx6)
- {
- return String_new(Sockaddr_print(sockaddrForPrefix6(alloc, pfx6), alloc), alloc);
- }
- static struct Prefix4* sockaddrToPrefix4(struct Sockaddr* sa, struct Allocator* allocator)
- {
- uint32_t addrNum;
- uint8_t* addr;
- Assert_true(Sockaddr_getAddress(sa, &addr) == 4);
- Bits_memcpy(&addrNum, addr, 4);
- struct Allocator* alloc = Allocator_child(allocator);
- struct Prefix4* out = Allocator_calloc(alloc, sizeof(struct Prefix4), 1);
- out->bits = Endian_bigEndianToHost32(addrNum);
- int pfx = Sockaddr_getPrefix(sa);
- Assert_true(pfx > -1);
- out->prefix = pfx;
- out->alloc = alloc;
- return out;
- }
- static struct Prefix6* sockaddrToPrefix6(struct Sockaddr* sa, struct Allocator* allocator)
- {
- struct {
- uint64_t highBits_be;
- uint64_t lowBits_be;
- } longs;
- uint8_t* addr;
- Assert_true(Sockaddr_getAddress(sa, &addr) == 16);
- Bits_memcpy(&longs, addr, 16);
- struct Allocator* alloc = Allocator_child(allocator);
- struct Prefix6* out = Allocator_calloc(alloc, sizeof(struct Prefix6), 1);
- out->highBits = Endian_bigEndianToHost64(longs.highBits_be);
- out->lowBits = Endian_bigEndianToHost64(longs.lowBits_be);
- int pfx = Sockaddr_getPrefix(sa);
- Assert_true(pfx > -1);
- out->prefix = pfx;
- out->alloc = alloc;
- return out;
- }
- static void addSomething(struct RouteGen_pvt* rp,
- struct Sockaddr* exempt,
- struct ArrayList_OfPrefix6* list6,
- struct ArrayList_OfPrefix4* list4)
- {
- if (Sockaddr_getFamily(exempt) == Sockaddr_AF_INET) {
- struct Prefix4* p4 = sockaddrToPrefix4(exempt, rp->alloc);
- ArrayList_OfPrefix4_add(list4, p4);
- } else if (Sockaddr_getFamily(exempt) == Sockaddr_AF_INET6) {
- struct Prefix6* p6 = sockaddrToPrefix6(exempt, rp->alloc);
- ArrayList_OfPrefix6_add(list6, p6);
- } else {
- Assert_failure("unexpected addr type");
- }
- rp->pub.hasUncommittedChanges = true;
- }
- void RouteGen_addException(struct RouteGen* rg, struct Sockaddr* destination)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- addSomething(rp, destination, rp->exceptions6, rp->exceptions4);
- }
- void RouteGen_addPrefix(struct RouteGen* rg, struct Sockaddr* destination)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- addSomething(rp, destination, rp->prefixes6, rp->prefixes4);
- }
- void RouteGen_addLocalPrefix(struct RouteGen* rg, struct Sockaddr* destination)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- addSomething(rp, destination, rp->localPrefixes6, rp->localPrefixes4);
- }
- static Dict* getSomething(struct RouteGen_pvt* rp,
- struct Allocator* alloc,
- struct ArrayList_OfPrefix6* list6,
- struct ArrayList_OfPrefix4* list4)
- {
- ArrayList_OfPrefix6_sort(list6);
- ArrayList_OfPrefix4_sort(list4);
- List* prefixes4 = List_new(alloc);
- for (int i = 0; i < list4->length; i++) {
- struct Prefix4* pfx4 = ArrayList_OfPrefix4_get(list4, i);
- List_addString(prefixes4, printPrefix4(alloc, pfx4), alloc);
- }
- List* prefixes6 = List_new(alloc);
- for (int i = 0; i < list6->length; i++) {
- struct Prefix6* pfx6 = ArrayList_OfPrefix6_get(list6, i);
- List_addString(prefixes6, printPrefix6(alloc, pfx6), alloc);
- }
- Dict* out = Dict_new(alloc);
- Dict_putList(out, String_new("ipv4", alloc), prefixes4, alloc);
- Dict_putList(out, String_new("ipv6", alloc), prefixes6, alloc);
- return out;
- }
- Dict* RouteGen_getPrefixes(struct RouteGen* rg, struct Allocator* alloc)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- return getSomething(rp, alloc, rp->prefixes6, rp->prefixes4);
- }
- Dict* RouteGen_getLocalPrefixes(struct RouteGen* rg, struct Allocator* alloc)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- return getSomething(rp, alloc, rp->localPrefixes6, rp->localPrefixes4);
- }
- Dict* RouteGen_getExceptions(struct RouteGen* rg, struct Allocator* alloc)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- return getSomething(rp, alloc, rp->exceptions6, rp->exceptions4);
- }
- static bool removeSomething(struct RouteGen_pvt* rp,
- struct Sockaddr* toRemove,
- struct ArrayList_OfPrefix6* list6,
- struct ArrayList_OfPrefix4* list4)
- {
- struct Allocator* tempAlloc = Allocator_child(rp->alloc);
- bool ret = false;
- if (Sockaddr_getFamily(toRemove) == Sockaddr_AF_INET) {
- struct Prefix4* p4 = sockaddrToPrefix4(toRemove, tempAlloc);
- for (int i = list4->length - 1; i >= 0; i--) {
- struct Prefix4* p42 = ArrayList_OfPrefix4_get(list4, i);
- if (!comparePrefixes4(p4, p42)) {
- ArrayList_OfPrefix4_remove(list4, i);
- ret = true;
- }
- }
- } else if (Sockaddr_getFamily(toRemove) == Sockaddr_AF_INET6) {
- struct Prefix6* p6 = sockaddrToPrefix6(toRemove, tempAlloc);
- for (int i = list6->length - 1; i >= 0; i--) {
- struct Prefix6* p62 = ArrayList_OfPrefix6_get(list6, i);
- if (!comparePrefixes6(p6, p62)) {
- ArrayList_OfPrefix6_remove(list6, i);
- ret = true;
- }
- }
- } else {
- Assert_failure("unexpected addr type");
- }
- Allocator_free(tempAlloc);
- return ret;
- }
- bool RouteGen_removePrefix(struct RouteGen* rg, struct Sockaddr* toRemove)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- return removeSomething(rp, toRemove, rp->prefixes6, rp->prefixes4);
- }
- bool RouteGen_removeLocalPrefix(struct RouteGen* rg, struct Sockaddr* toRemove)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- return removeSomething(rp, toRemove, rp->localPrefixes6, rp->localPrefixes4);
- }
- bool RouteGen_removeException(struct RouteGen* rg, struct Sockaddr* toRemove)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- return removeSomething(rp, toRemove, rp->exceptions6, rp->exceptions4);
- }
- static struct ArrayList_OfPrefix4* invertPrefix4(struct Prefix4* toInvert, struct Allocator* alloc)
- {
- struct ArrayList_OfPrefix4* result = ArrayList_OfPrefix4_new(alloc);
- for (int i = 32 - toInvert->prefix; i < 32; i++) {
- struct Prefix4* pfx = Allocator_calloc(alloc, sizeof(struct Prefix4), 1);
- pfx->bits = ( toInvert->bits & ((uint32_t)~0 << i) ) ^ ((uint32_t)1 << i);
- pfx->prefix = 32 - i;
- ArrayList_OfPrefix4_add(result, pfx);
- }
- return result;
- }
- static struct ArrayList_OfPrefix6* invertPrefix6(struct Prefix6* toInvert, struct Allocator* alloc)
- {
- struct ArrayList_OfPrefix6* result = ArrayList_OfPrefix6_new(alloc);
- for (int i = 128 - toInvert->prefix; i < 128; i++) {
- struct Prefix6* pfx = Allocator_calloc(alloc, sizeof(struct Prefix6), 1);
- if (i >= 64) {
- pfx->highBits = ( toInvert->highBits & (~((uint64_t)0) << (i-64)) ) ^
- (((uint64_t)1) << (i-64));
- pfx->lowBits = 0;
- } else {
- pfx->highBits = toInvert->highBits;
- pfx->lowBits = ( toInvert->lowBits & (~((uint64_t)0) << i) ) ^ (((uint64_t)1) << i);
- }
- pfx->prefix = 128 - i;
- ArrayList_OfPrefix6_add(result, pfx);
- }
- return result;
- }
- static bool isSubsetOf4(struct Prefix4* isSubset, struct Prefix4* isSuperset)
- {
- if (isSuperset->prefix > isSubset->prefix) { return false; }
- if (isSuperset->prefix >= 32) {
- return isSuperset->bits == isSubset->bits;
- }
- if (!isSuperset->prefix) { return true; }
- uint32_t shift = 32 - isSuperset->prefix;
- return (isSuperset->bits >> shift) == (isSubset->bits >> shift);
- }
- static bool isSubsetOf6(struct Prefix6* isSubset, struct Prefix6* isSuperset)
- {
- if (isSuperset->prefix > isSubset->prefix) { return false; }
- if (isSuperset->prefix > 64) {
- uint64_t shift = 128 - isSuperset->prefix;
- return isSuperset->highBits == isSubset->highBits &&
- (isSuperset->lowBits >> shift) == (isSubset->lowBits >> shift);
- } else if (isSuperset->prefix) {
- uint64_t shift = 64 - isSuperset->prefix;
- return (isSuperset->highBits >> shift) == (isSubset->highBits >> shift);
- } else {
- return true;
- }
- }
- static void mergePrefixSets4(struct ArrayList_OfPrefix4* mergeInto,
- struct ArrayList_OfPrefix4* prefixes)
- {
- struct Prefix4* highestPrefix = NULL;
- for (int j = 0; j < prefixes->length; j++) {
- struct Prefix4* result = ArrayList_OfPrefix4_get(prefixes, j);
- Assert_true(result);
- if (!highestPrefix || highestPrefix->prefix < result->prefix) {
- highestPrefix = result;
- }
- }
- struct Prefix4 target;
- Bits_memcpy(&target, highestPrefix, sizeof(struct Prefix4));
- target.bits ^= (target.prefix) ? ((uint32_t)1 << (32 - target.prefix)) : 0;
- for (int i = mergeInto->length - 1; i >= 0; i--) {
- struct Prefix4* result = ArrayList_OfPrefix4_get(mergeInto, i);
- Assert_true(result);
- if (isSubsetOf4(&target, result)) {
- ArrayList_OfPrefix4_remove(mergeInto, i);
- }
- }
- for (int i = 0; i < prefixes->length; i++) {
- bool include = true;
- struct Prefix4* toInclude = ArrayList_OfPrefix4_get(prefixes, i);
- for (int j = 0; j < mergeInto->length; j++) {
- struct Prefix4* test = ArrayList_OfPrefix4_get(mergeInto, j);
- if (isSubsetOf4(test, toInclude)) {
- include = false;
- break;
- }
- }
- if (include) {
- ArrayList_OfPrefix4_add(mergeInto, toInclude);
- }
- }
- }
- static void mergePrefixSets6(struct ArrayList_OfPrefix6* mergeInto,
- struct ArrayList_OfPrefix6* prefixes, struct Allocator* alloc)
- {
- struct Prefix6* highestPrefix = NULL;
- for (int j = 0; j < prefixes->length; j++) {
- struct Prefix6* result = ArrayList_OfPrefix6_get(prefixes, j);
- Assert_true(result);
- if (!highestPrefix || highestPrefix->prefix < result->prefix) {
- highestPrefix = result;
- }
- }
- struct Prefix6 target;
- Bits_memcpy(&target, highestPrefix, sizeof(struct Prefix6));
- if (target.prefix > 64) {
- target.lowBits ^= (((uint64_t)1) << (128 - target.prefix));
- } else if (target.prefix) {
- target.highBits ^= (((uint64_t)1) << (64 - target.prefix));
- target.lowBits = 0;
- }
- for (int i = mergeInto->length - 1; i >= 0; i--) {
- struct Prefix6* result = ArrayList_OfPrefix6_get(mergeInto, i);
- Assert_true(result);
- if (isSubsetOf6(&target, result)) {
- ArrayList_OfPrefix6_remove(mergeInto, i);
- }
- }
- for (int i = 0; i < prefixes->length; i++) {
- bool include = true;
- struct Prefix6* toInclude = ArrayList_OfPrefix6_get(prefixes, i);
- for (int j = 0; j < mergeInto->length; j++) {
- struct Prefix6* test = ArrayList_OfPrefix6_get(mergeInto, j);
- if (isSubsetOf6(test, toInclude)) {
- include = false;
- break;
- }
- }
- if (include) {
- ArrayList_OfPrefix6_add(mergeInto, toInclude);
- }
- }
- }
- static struct Prefix4* clonePrefix4(struct Prefix4* original, struct Allocator* alloc)
- {
- struct Prefix4* clone = Allocator_clone(alloc, original);
- clone->alloc = alloc;
- return clone;
- }
- static struct Prefix6* clonePrefix6(struct Prefix6* original, struct Allocator* alloc)
- {
- struct Prefix6* clone = Allocator_clone(alloc, original);
- clone->alloc = alloc;
- return clone;
- }
- static struct ArrayList_OfPrefix4* mkPseudoDefault4(struct Allocator* alloc)
- {
- struct Prefix4* pfxs = Allocator_calloc(alloc, sizeof(struct Prefix4), 2);
- pfxs[0].prefix = 1;
- pfxs[1].prefix = 1;
- pfxs[1].bits = 0x80000000;
- struct ArrayList_OfPrefix4* out = ArrayList_OfPrefix4_new(alloc);
- ArrayList_OfPrefix4_add(out, &pfxs[0]);
- ArrayList_OfPrefix4_add(out, &pfxs[1]);
- return out;
- }
- static struct ArrayList_OfPrefix6* mkPseudoDefault6(struct Allocator* alloc)
- {
- struct Prefix6* pfxs = Allocator_calloc(alloc, sizeof(struct Prefix6), 2);
- pfxs[0].prefix = 1;
- pfxs[1].prefix = 1;
- pfxs[1].highBits = 0x8000000000000000ull;
- struct ArrayList_OfPrefix6* out = ArrayList_OfPrefix6_new(alloc);
- ArrayList_OfPrefix6_add(out, &pfxs[0]);
- ArrayList_OfPrefix6_add(out, &pfxs[1]);
- return out;
- }
- static bool isDefaultRoute4(struct ArrayList_OfPrefix4* prefixes)
- {
- if (prefixes->length != 1) { return false; }
- struct Prefix4* pfx = ArrayList_OfPrefix4_get(prefixes, 0);
- return pfx->prefix == 0;
- }
- static bool isDefaultRoute6(struct ArrayList_OfPrefix6* prefixes)
- {
- if (prefixes->length != 1) { return false; }
- struct Prefix6* pfx = ArrayList_OfPrefix6_get(prefixes, 0);
- return pfx->prefix == 0;
- }
- static struct ArrayList_OfPrefix4* genPrefixes4(struct ArrayList_OfPrefix4* prefixes,
- struct ArrayList_OfPrefix4* exceptions,
- struct ArrayList_OfPrefix4* localPrefixes,
- struct Allocator* alloc)
- {
- struct Allocator* tempAlloc = Allocator_child(alloc);
- struct ArrayList_OfPrefix4* effectiveLocalPrefixes = ArrayList_OfPrefix4_new(tempAlloc);
- for (int i = 0; i < localPrefixes->length; i++) {
- bool add = true;
- struct Prefix4* localPfx = ArrayList_OfPrefix4_get(localPrefixes, i);
- for (int j = 0; j < prefixes->length; j++) {
- struct Prefix4* pfx = ArrayList_OfPrefix4_get(prefixes, j);
- if (isSubsetOf4(pfx, localPfx)) {
- add = false;
- break;
- }
- }
- if (add) {
- ArrayList_OfPrefix4_add(effectiveLocalPrefixes, localPfx);
- }
- }
- struct ArrayList_OfPrefix4* allPrefixes = ArrayList_OfPrefix4_new(tempAlloc);
- for (int i = 0; i < exceptions->length; i++) {
- struct Prefix4* pfxToInvert = ArrayList_OfPrefix4_get(exceptions, i);
- bool add = true;
- for (int j = 0; j < effectiveLocalPrefixes->length; j++) {
- struct Prefix4* localPfx = ArrayList_OfPrefix4_get(effectiveLocalPrefixes, j);
- if (isSubsetOf4(pfxToInvert, localPfx)) {
- add = false;
- break;
- }
- }
- if (add) {
- struct ArrayList_OfPrefix4* prefixes4 = invertPrefix4(pfxToInvert, tempAlloc);
- mergePrefixSets4(allPrefixes, prefixes4);
- }
- }
- for (int i = allPrefixes->length - 2; i >= 0; i--) {
- struct Prefix4* pfx = ArrayList_OfPrefix4_get(allPrefixes, i);
- struct Prefix4* pfx2 = ArrayList_OfPrefix4_get(allPrefixes, i+1);
- if (isSubsetOf4(pfx2, pfx)) {
- ArrayList_OfPrefix4_remove(allPrefixes, i+1);
- if (i < (allPrefixes->length - 2)) { i++; }
- }
- }
- for (int i = 0; i < prefixes->length; i++) {
- struct Prefix4* pfx = ArrayList_OfPrefix4_get(prefixes, i);
- int addPrefix = true;
- for (int j = allPrefixes->length - 1; j >= 0; j--) {
- struct Prefix4* pfx2 = ArrayList_OfPrefix4_get(allPrefixes, j);
- if (isSubsetOf4(pfx2, pfx)) {
- addPrefix = false;
- }
- }
- if (addPrefix) {
- ArrayList_OfPrefix4_add(allPrefixes, pfx);
- }
- }
- ArrayList_OfPrefix4_sort(allPrefixes);
- struct ArrayList_OfPrefix4* out = ArrayList_OfPrefix4_new(alloc);
- for (int i = 0; i < allPrefixes->length; i++) {
- struct Prefix4* pfx = ArrayList_OfPrefix4_get(allPrefixes, i);
- for (int j = 0; j < prefixes->length; j++) {
- struct Prefix4* pfx2 = ArrayList_OfPrefix4_get(prefixes, j);
- if (isSubsetOf4(pfx, pfx2)) {
- ArrayList_OfPrefix4_add(out, clonePrefix4(pfx, alloc));
- break;
- }
- }
- }
- Allocator_free(tempAlloc);
- return out;
- }
- // Annoyingly, this function is *exactly* the same content as genPrefixes4()
- // but with evert 4 converted to a 6...
- static struct ArrayList_OfPrefix6* genPrefixes6(struct ArrayList_OfPrefix6* prefixes,
- struct ArrayList_OfPrefix6* exceptions,
- struct ArrayList_OfPrefix6* localPrefixes,
- struct Allocator* alloc)
- {
- struct Allocator* tempAlloc = Allocator_child(alloc);
- struct ArrayList_OfPrefix6* effectiveLocalPrefixes = ArrayList_OfPrefix6_new(tempAlloc);
- for (int i = 0; i < localPrefixes->length; i++) {
- bool add = true;
- struct Prefix6* localPfx = ArrayList_OfPrefix6_get(localPrefixes, i);
- for (int j = 0; j < prefixes->length; j++) {
- struct Prefix6* pfx = ArrayList_OfPrefix6_get(prefixes, j);
- if (isSubsetOf6(pfx, localPfx)) {
- add = false;
- break;
- }
- }
- if (add) {
- ArrayList_OfPrefix6_add(effectiveLocalPrefixes, localPfx);
- }
- }
- struct ArrayList_OfPrefix6* allPrefixes = ArrayList_OfPrefix6_new(tempAlloc);
- for (int i = 0; i < exceptions->length; i++) {
- struct Prefix6* pfxToInvert = ArrayList_OfPrefix6_get(exceptions, i);
- bool add = true;
- for (int j = 0; j < effectiveLocalPrefixes->length; j++) {
- struct Prefix6* localPfx = ArrayList_OfPrefix6_get(effectiveLocalPrefixes, j);
- if (isSubsetOf6(pfxToInvert, localPfx)) {
- add = false;
- break;
- }
- }
- if (add) {
- struct ArrayList_OfPrefix6* prefixes6 = invertPrefix6(pfxToInvert, tempAlloc);
- mergePrefixSets6(allPrefixes, prefixes6, alloc);
- }
- }
- ArrayList_OfPrefix6_sort(allPrefixes);
- for (int i = allPrefixes->length - 2; i >= 0; i--) {
- struct Prefix6* pfx = ArrayList_OfPrefix6_get(allPrefixes, i);
- struct Prefix6* pfx2 = ArrayList_OfPrefix6_get(allPrefixes, i+1);
- if (isSubsetOf6(pfx2, pfx)) {
- ArrayList_OfPrefix6_remove(allPrefixes, i+1);
- if (i < (allPrefixes->length - 2)) { i++; }
- }
- }
- for (int i = 0; i < prefixes->length; i++) {
- struct Prefix6* pfx = ArrayList_OfPrefix6_get(prefixes, i);
- int addPrefix = true;
- for (int j = allPrefixes->length - 1; j >= 0; j--) {
- struct Prefix6* pfx2 = ArrayList_OfPrefix6_get(allPrefixes, j);
- if (isSubsetOf6(pfx2, pfx)) {
- addPrefix = false;
- }
- }
- if (addPrefix) {
- ArrayList_OfPrefix6_add(allPrefixes, pfx);
- }
- }
- ArrayList_OfPrefix6_sort(allPrefixes);
- struct ArrayList_OfPrefix6* out = ArrayList_OfPrefix6_new(alloc);
- for (int i = 0; i < allPrefixes->length; i++) {
- struct Prefix6* pfx = ArrayList_OfPrefix6_get(allPrefixes, i);
- for (int j = 0; j < prefixes->length; j++) {
- struct Prefix6* pfx2 = ArrayList_OfPrefix6_get(prefixes, j);
- if (isSubsetOf6(pfx, pfx2)) {
- ArrayList_OfPrefix6_add(out, clonePrefix6(pfx, alloc));
- break;
- }
- }
- }
- Allocator_free(tempAlloc);
- return out;
- }
- static struct Prefix46* getGeneratedRoutes(struct RouteGen_pvt* rp, struct Allocator* alloc)
- {
- struct Prefix46* out = Allocator_calloc(alloc, sizeof(struct Prefix46), 1);
- if (rp->prefixes4->length > 0) {
- out->prefix4 = genPrefixes4(rp->prefixes4, rp->exceptions4, rp->localPrefixes4, alloc);
- if (isDefaultRoute4(out->prefix4)) {
- out->prefix4 = mkPseudoDefault4(alloc);
- }
- } else {
- out->prefix4 = ArrayList_OfPrefix4_new(alloc);
- }
- if (rp->prefixes6->length > 0) {
- out->prefix6 = genPrefixes6(rp->prefixes6, rp->exceptions6, rp->localPrefixes6, alloc);
- if (isDefaultRoute6(out->prefix6)) {
- out->prefix6 = mkPseudoDefault6(alloc);
- }
- } else {
- out->prefix6 = ArrayList_OfPrefix6_new(alloc);
- }
- return out;
- }
- Dict* RouteGen_getGeneratedRoutes(struct RouteGen* rg, struct Allocator* alloc)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- struct Prefix46* p46 = getGeneratedRoutes(rp, alloc);
- return getSomething(rp, alloc, p46->prefix6, p46->prefix4);
- }
- Err_DEFUN RouteGen_commit(struct RouteGen* rg,
- const char* tunName,
- struct Allocator* tempAlloc)
- {
- struct RouteGen_pvt* rp = Identity_check((struct RouteGen_pvt*) rg);
- struct Prefix46* p46 = getGeneratedRoutes(rp, tempAlloc);
- struct Sockaddr** prefixSet =
- Allocator_calloc(tempAlloc, sizeof(char*), p46->prefix4->length + p46->prefix6->length);
- int prefixNum = 0;
- for (int i = 0; i < p46->prefix4->length; i++) {
- struct Prefix4* pfx4 = ArrayList_OfPrefix4_get(p46->prefix4, i);
- prefixSet[prefixNum++] = sockaddrForPrefix4(tempAlloc, pfx4);
- }
- for (int i = 0; i < p46->prefix6->length; i++) {
- struct Prefix6* pfx6 = ArrayList_OfPrefix6_get(p46->prefix6, i);
- prefixSet[prefixNum++] = sockaddrForPrefix6(tempAlloc, pfx6);
- }
- Assert_true(prefixNum == p46->prefix4->length + p46->prefix6->length);
- Err(NetDev_setRoutes(tunName, prefixSet, prefixNum, rp->log, tempAlloc));
- rp->pub.hasUncommittedChanges = false;
- return NULL;
- }
- static void setupDefaultLocalPrefixes(struct RouteGen_pvt* rp)
- {
- struct Sockaddr_storage ss;
- #define ADD_PREFIX(str) \
- Assert_true(!Sockaddr_parse(str, &ss)); \
- RouteGen_addLocalPrefix(&rp->pub, &ss.addr)
- ADD_PREFIX("fe80::/10");
- ADD_PREFIX("fd00::/8");
- ADD_PREFIX("10.0.0.0/8");
- ADD_PREFIX("172.16.0.0/12");
- ADD_PREFIX("192.168.0.0/16");
- ADD_PREFIX("127.0.0.0/8");
- #undef ADD_PREFIX
- }
- struct RouteGen* RouteGen_new(struct Allocator* allocator, struct Log* log)
- {
- struct Allocator* alloc = Allocator_child(allocator);
- struct RouteGen_pvt* rp = Allocator_calloc(alloc, sizeof(struct RouteGen_pvt), 1);
- rp->prefixes6 = ArrayList_OfPrefix6_new(alloc);
- rp->localPrefixes6 = ArrayList_OfPrefix6_new(alloc);
- rp->exceptions6 = ArrayList_OfPrefix6_new(alloc);
- rp->prefixes4 = ArrayList_OfPrefix4_new(alloc);
- rp->localPrefixes4 = ArrayList_OfPrefix4_new(alloc);
- rp->exceptions4 = ArrayList_OfPrefix4_new(alloc);
- rp->log = log;
- rp->alloc = alloc;
- Identity_set(rp);
- setupDefaultLocalPrefixes(rp);
- return &rp->pub;
- }
|