123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- /*
- Copyright (c) 2007, 2008 by Juliusz Chroboczek
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <assert.h>
- #include <sys/time.h>
- #include <netinet/in.h>
- #include "babeld.h"
- #include "kernel.h"
- #include "neighbour.h"
- #include "message.h"
- #include "route.h"
- #include "xroute.h"
- #include "util.h"
- #include "configuration.h"
- #include "interface.h"
- #include "local.h"
- #include "lorauth.h"
- static struct xroute *xroutes;
- static int numxroutes = 0, maxxroutes = 0;
- struct xroute *
- find_xroute(const unsigned char *prefix, unsigned char plen,
- const unsigned char *src_prefix, unsigned char src_plen)
- {
- int i;
- debugf(" -- find_xroute(): numxroutes:%d\n", numxroutes);
- debugf(" prefix:%s, src_prefix:%s\n",
- format_prefix(prefix, plen),
- format_prefix(src_prefix, src_plen));
- for(i = 0; i < numxroutes; i++) {
- debugf("\t xroutes[%d].prefix: %s\n", i,
- format_prefix(xroutes[i].prefix, xroutes[i].plen));
- debugf("\t xroutes[%d].cipher: %s\n", i,
- reduced_lorauth_token(xroutes[i].cipher));
- if(xroutes[i].plen == plen &&
- memcmp(xroutes[i].prefix, prefix, 16) == 0 &&
- xroutes[i].src_plen == src_plen &&
- memcmp(xroutes[i].src_prefix, src_prefix, 16) == 0)
- return &xroutes[i];
- }
- return NULL;
- }
- void
- flush_xroute(struct xroute *xroute)
- {
- int i;
- i = xroute - xroutes;
- assert(i >= 0 && i < numxroutes);
- local_notify_xroute(xroute, LOCAL_FLUSH);
- if(i != numxroutes - 1)
- memcpy(xroutes + i, xroutes + numxroutes - 1, sizeof(struct xroute));
- numxroutes--;
- VALGRIND_MAKE_MEM_UNDEFINED(xroutes + numxroutes, sizeof(struct xroute));
- if(numxroutes == 0) {
- free(xroutes);
- xroutes = NULL;
- maxxroutes = 0;
- } else if(maxxroutes > 8 && numxroutes < maxxroutes / 4) {
- struct xroute *new_xroutes;
- int n = maxxroutes / 2;
- new_xroutes = realloc(xroutes, n * sizeof(struct xroute));
- if(new_xroutes == NULL)
- return;
- xroutes = new_xroutes;
- maxxroutes = n;
- }
- }
- int
- add_xroute(unsigned char prefix[16], unsigned char plen,
- unsigned char src_prefix[16], unsigned char src_plen,
- unsigned short metric, unsigned int ifindex, int proto,
- unsigned short clen, unsigned char cipher[514])
- {
- debugf(" add_xroute:\n");
- struct xroute *xroute = find_xroute(prefix, plen, src_prefix, src_plen);
- if(xroute) { // xroute exists
- if(xroute->metric <= metric)
- return 0;
- xroute->metric = metric;
- local_notify_xroute(xroute, LOCAL_CHANGE);
- return 1;
- }
- if(numxroutes >= maxxroutes) {
- struct xroute *new_xroutes;
- int n = maxxroutes < 1 ? 8 : 2 * maxxroutes;
- new_xroutes = realloc(xroutes, n * sizeof(struct xroute));
- if(new_xroutes == NULL)
- return -1;
- maxxroutes = n;
- xroutes = new_xroutes;
- }
- debugf(" -- adding new xroute\n");
- memcpy(xroutes[numxroutes].prefix, prefix, 16);
- xroutes[numxroutes].plen = plen;
- memcpy(xroutes[numxroutes].src_prefix, src_prefix, 16);
- xroutes[numxroutes].src_plen = src_plen;
- xroutes[numxroutes].metric = metric;
- xroutes[numxroutes].ifindex = ifindex;
- xroutes[numxroutes].proto = proto;
- // -- lorauth --
- xroutes[numxroutes].clen = clen;
- if(strlen((char *)xroutes[numxroutes].cipher)>3)
- {
- debugf(" adding cipher\n");
- strncpy((char *)xroutes[numxroutes].cipher, (char *)cipher, LORAUTH_CIPHER_LEN);
- //memcpy(xroutes[numxroutes].cipher, cipher, LORAUTH_CIPHER_LEN);
- }
- else
- {
- debugf(" empty cipher to xroute.\n");
- memset(xroutes[numxroutes].cipher, 0, LORAUTH_CIPHER_LEN+1);
- }
- // ----
- numxroutes++;
- local_notify_xroute(&xroutes[numxroutes - 1], LOCAL_ADD);
- return 1;
- }
- /* Returns an overestimate of the number of xroutes. */
- int
- xroutes_estimate()
- {
- return numxroutes;
- }
- struct xroute_stream {
- int index;
- };
- struct
- xroute_stream *
- xroute_stream()
- {
- struct xroute_stream *stream = calloc(1, sizeof(struct xroute_stream));
- if(stream == NULL)
- return NULL;
- return stream;
- }
- struct xroute *
- xroute_stream_next(struct xroute_stream *stream)
- {
- if(stream->index < numxroutes)
- return &xroutes[stream->index++];
- else
- return NULL;
- }
- void
- xroute_stream_done(struct xroute_stream *stream)
- {
- free(stream);
- }
- static int
- filter_route(struct kernel_route *route, void *data) {
- void **args = (void**)data;
- int maxroutes = *(int*)args[0];
- struct kernel_route *routes = (struct kernel_route *)args[1];
- int *found = (int*)args[2];
- debugf(" filter_route: found %d, maxroutes %d \n",
- found[0], maxroutes);
- if(*found >= maxroutes)
- return -1;
- if(martian_prefix(route->prefix, route->plen) ||
- martian_prefix(route->src_prefix, route->src_plen))
- return 0;
- routes[*found] = *route;
- ++ *found;
- return 0;
- }
- static int
- kernel_routes(struct kernel_route *routes, int maxroutes)
- {
- int found = 0;
- void *data[3] = { &maxroutes, routes, &found };
- struct kernel_filter filter = {0};
- filter.route = filter_route;
- filter.route_closure = data;
- kernel_dump(CHANGE_ROUTE, &filter);
- return found;
- }
- static int
- filter_address(struct kernel_addr *addr, void *data) {
- void **args = (void **)data;
- int maxroutes = *(int *)args[0];
- struct kernel_route *routes = (struct kernel_route*)args[1];
- int *found = (int *)args[2];
- int ifindex = *(int*)args[3];
- int ll = args[4] ? !!*(int*)args[4] : 0;
- struct kernel_route *route = NULL;
- if(*found >= maxroutes)
- return 0;
- if(ll == !IN6_IS_ADDR_LINKLOCAL(&addr->addr))
- return 0;
- /* ifindex may be 0 -- see kernel_addresses */
- if(ifindex && addr->ifindex != ifindex)
- return 0;
- route = &routes[*found];
- memcpy(route->prefix, addr->addr.s6_addr, 16);
- route->plen = 128;
- route->metric = 0;
- route->ifindex = addr->ifindex;
- route->proto = RTPROT_BABEL_LOCAL;
- memset(route->gw, 0, 16);
- ++ *found;
- return 1;
- }
- /* ifindex is 0 for all interfaces. ll indicates whether we are
- interested in link-local or global addresses. */
- int
- kernel_addresses(int ifindex, int ll, struct kernel_route *routes,
- int maxroutes)
- {
- int found = 0;
- void *data[5] = { &maxroutes, routes, &found, &ifindex, &ll };
- struct kernel_filter filter = {0};
- filter.addr = filter_address;
- filter.addr_closure = data;
- kernel_dump(CHANGE_ADDR, &filter);
- return found;
- }
- int
- check_xroutes(int send_updates)
- {
- int i, j, metric, export, change = 0, rc;
- struct kernel_route *routes;
- struct filter_result filter_result = {0};
- int numroutes, numaddresses;
- static int maxroutes = 8;
- const int maxmaxroutes = 16 * 1024;
- debugf("\nChecking kernel routes, send_updates=%d.\n",
- send_updates);
- again:
- routes = calloc(maxroutes, sizeof(struct kernel_route));
- if(routes == NULL)
- return -1;
- rc = kernel_addresses(0, 0, routes, maxroutes);
- if(rc < 0) {
- perror("kernel_addresses");
- numroutes = 0;
- } else {
- numroutes = rc;
- }
- if(numroutes >= maxroutes)
- goto resize;
- numaddresses = numroutes;
- rc = kernel_routes(routes + numroutes, maxroutes - numroutes);
- if(rc < 0)
- fprintf(stderr, "Couldn't get kernel routes.\n");
- else
- numroutes += rc;
- if(numroutes >= maxroutes)
- goto resize;
- /* Apply filter to kernel routes (e.g. change the source prefix). */
- for(i = numaddresses; i < numroutes; i++) {
- filter_result.src_prefix = NULL;
- redistribute_filter(routes[i].prefix, routes[i].plen,
- routes[i].src_prefix, routes[i].src_plen,
- routes[i].ifindex, routes[i].proto,
- &filter_result);
- if(filter_result.src_prefix) {
- memcpy(routes[i].src_prefix, filter_result.src_prefix, 16);
- routes[i].src_plen = filter_result.src_plen;
- }
- }
- /* Check for any routes that need to be flushed */
- i = 0;
- while(i < numxroutes) {
- export = 0;
- metric = redistribute_filter(xroutes[i].prefix, xroutes[i].plen,
- xroutes[i].src_prefix, xroutes[i].src_plen,
- xroutes[i].ifindex, xroutes[i].proto,
- NULL);
- //-- lorauth note: metric, should here need to be added cipher and clen? --
- debugf("----checking xroutes metric: %d\n", metric);
- if (metric == 0)
- {
- debugf(" :: metric==0 ::\n");
- debugf(" myid: %s \n", format_eui64(myid));
- int rc;
- unsigned char *cipher = calloc(1, LORAUTH_CIPHER_LEN + 1);
-
- debugf(" lorauth_index: %d\n", lorauth_token_index(myid, myseqno));
- rc = lorauth_token(cipher,
- myid,
- myseqno);
- if (rc != 0)
- debugf(" Couldn't find loruauth token, rc %d\n", rc);
- else {
- strncpy((char *)xroutes[i].cipher, (char *)cipher, LORAUTH_CIPHER_LEN);
- xroutes[i].clen = LORAUTH_CIPHER_LEN;
- debugf(" lorauth token found: %s\n",
- reduced_lorauth_token(xroutes[i].cipher));
- }
- free(cipher);
- }
- // ----
-
-
- if(metric < INFINITY && metric == xroutes[i].metric) {
- for(j = 0; j < numroutes; j++) {
- if(xroutes[i].plen == routes[j].plen &&
- memcmp(xroutes[i].prefix, routes[j].prefix, 16) == 0 &&
- xroutes[i].ifindex == routes[j].ifindex &&
- xroutes[i].proto == routes[j].proto) {
- export = 1;
- break;
- }
- }
- }
- if(!export) {
- unsigned char prefix[16], plen;
- unsigned char src_prefix[16], src_plen;
- struct babel_route *route;
- // -- lorauth --
- unsigned short clen;
- unsigned char *cipher = calloc(1, LORAUTH_CIPHER_LEN + 1);
- // ----
- memcpy(prefix, xroutes[i].prefix, 16);
- plen = xroutes[i].plen;
- memcpy(src_prefix, xroutes[i].src_prefix, 16);
- src_plen = xroutes[i].src_plen;
- flush_xroute(&xroutes[i]);
- route = find_best_route(prefix, plen, src_prefix, src_plen, 1,NULL);
- // testing
- if(route)
- debugf(" best_route_found: cost:%d", route->cost );
- else
- debugf(" not found best route");
- // -- lorauth --
- clen = xroutes[i].clen;
- memcpy(cipher, xroutes[i].cipher, LORAUTH_CIPHER_LEN);
- // ----
- if(route)
- install_route(route);
- /* send_update_resend only records the prefix, so the update
- will only be sent after we perform all of the changes. */
- if(send_updates)
- send_update_resend(NULL, prefix, plen, src_prefix, src_plen,
- // -- lorauth --
- cipher, clen);
- // NULL, 0);
- free(cipher);
- change = 1;
- } else {
- i++;
- }
- } // end while(i < numxroutes)
- /* Add any new routes */
- for(i = 0; i < numroutes; i++) {
- if(martian_prefix(routes[i].prefix, routes[i].plen))
- continue;
- metric = redistribute_filter(routes[i].prefix, routes[i].plen,
- routes[i].src_prefix, routes[i].src_plen,
- routes[i].ifindex, routes[i].proto, NULL);
- if(metric < INFINITY) {
- /* lorauth note: here if metric == 0 add own cipher and clen to xroute */
-
- /* according to line 185 routes is now storing kernel_route struct
- So in order to not changing that struct i will try to get the
- cipher, clen related to that (prefix, plen) from xroutes
- */
- if (metric == 0) { // own route
- debugf(" -- metric == 0\n");
- struct xroute *a_xroute =
- find_xroute(routes[i].prefix,
- (unsigned char)routes[i].plen,
- routes[i].src_prefix,
- (unsigned char)routes[i].src_plen);
- if(a_xroute) {
- debugf(" -- found_xroute: prefix: %s cipher: %s\n",
- format_prefix(a_xroute->prefix, a_xroute->plen),
- reduced_lorauth_token(a_xroute->cipher));
- rc = add_xroute(routes[i].prefix, routes[i].plen,
- routes[i].src_prefix, routes[i].src_plen,
- metric, routes[i].ifindex, routes[i].proto,
- a_xroute->clen, a_xroute->cipher);
- }
- else{
- debugf(" -- not found xroute\n");
-
- rc = add_xroute(routes[i].prefix, routes[i].plen,
- routes[i].src_prefix, routes[i].src_plen,
- metric, routes[i].ifindex, routes[i].proto,
- 0, NULL);
- }
- }
- else {
- debugf(" [[--- metric %d \n", metric);
- // here should look for cipher, clen from babel_routes?
- /* rc = add_xroute(routes[i].prefix, routes[i].plen, */
- /* routes[i],src_prefix, routes[i].src_plen, */
- /* metric, routes[i].ifindex, routes[i].proto, */
- /* routes[i].src.clen, routes[i].src.cipher); */
- }
- // -- lorauth --
- /* lorauth note: is the following necessary? */
- if(rc > 0) {
- debugf(" rc > 0\n");
- struct babel_route *route;
- route = find_installed_route(routes[i].prefix, routes[i].plen,
- routes[i].src_prefix,
- routes[i].src_plen);
- if(route) {
- debugf(" found route\n");
- if(allow_duplicates < 0 ||
- routes[i].metric < allow_duplicates)
- uninstall_route(route);
- } else
- debugf(" not found installed route\n");
- change = 1;
- if(send_updates){
- debugf(" - - - not found installed route, using kernel route\n prefix:%s",
- format_prefix(routes[i].prefix, routes[i].plen));
- send_update(NULL, 0, routes[i].prefix, routes[i].plen,
- routes[i].src_prefix, routes[i].src_plen,
- // lorauth
- //TODO: check the following
- NULL, 0);
- }
- }
- }
- }
- free(routes);
- /* Set up maxroutes for the next call. */
- maxroutes = MIN(numroutes + 8, maxmaxroutes);
- return change;
- resize:
- free(routes);
- if(maxroutes >= maxmaxroutes)
- return -1;
- maxroutes = MIN(maxmaxroutes, 2 * maxroutes);
- goto again;
- }
|