static int check_link_local_addresses(struct interface *ifp) { struct kernel_route ll[32]; int rc, i; rc = kernel_addresses(ifp->ifindex, 1, ll, 32); if(rc <= 0) { if(rc < 0) perror("kernel_addresses(link local)"); else fprintf(stderr, "Interface %s has no link-local address.\n", ifp->name); if(ifp->ll) { free(ifp->ll); ifp->numll = 0; ifp->ll = NULL; } local_notify_interface(ifp, LOCAL_CHANGE); /* Most probably DAD hasn't finished yet. Reschedule us real soon. */ schedule_interfaces_check(2000, 0); return -1; } else { int changed; if(rc == ifp->numll) { changed = 0; for(i = 0; i < rc; i++) { if(memcmp(ifp->ll[i], ll[i].prefix, 16) != 0) { changed = 1; break; } } } else { changed = 1; } if(changed) { free(ifp->ll); ifp->numll = 0; ifp->ll = malloc(16 * rc); if(ifp->ll == NULL) { perror("malloc(ll)"); } else { for(i = 0; i < rc; i++) memcpy(ifp->ll[i], ll[i].prefix, 16); ifp->numll = rc; } local_notify_interface(ifp, LOCAL_CHANGE); } } 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; } } }