/* add an xroute, verifying some conditions; return 0 if there is no changes */ static int xroute_add_new_route(unsigned char prefix[16], unsigned char plen, unsigned short metric, unsigned int ifindex, int proto, int send_updates) { int rc; if(martian_prefix(prefix, plen)) return 0; metric = redistribute_filter(prefix, plen, ifindex, proto); if(metric < INFINITY) { rc = add_xroute(prefix, plen, metric, ifindex, proto); if(rc > 0) { struct babel_route *route; route = find_installed_route(prefix, plen); if(route) uninstall_route(route); if(send_updates) send_update(NULL, 0, prefix, plen); return 1; } } return 0; }
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.\n"); 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); 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; } } }