Index: src/auth.c =================================================================== --- src/auth.c (revision 2458) +++ src/auth.c (working copy) @@ -812,7 +812,7 @@ AuthStat(Context ctx, int ac, const char *const av[], Printf("\tAcct-Update : %u\r\n", au->params.acct_update); Printf("\tRoutes :\r\n"); SLIST_FOREACH(r, &au->params.routes, next) { - Printf("\t\t%s\r\n", u_rangetoa(&r->dest, buf, sizeof(buf))); + Printf("\t\t%s fib %d\r\n", u_rangetoa(&r->dest, buf, sizeof(buf)), r->fib); } #ifdef USE_IPFW Printf("\tIPFW rules :\r\n"); @@ -2270,9 +2270,10 @@ AuthExternal(AuthData auth) r = Malloc(MB_AUTH, sizeof(struct ifaceroute)); r->dest = range; r->ok = 0; + r->fib = gDefaultFIB; /* XXX implement FIB assignment later */ j = 0; SLIST_FOREACH(r1, &auth->params.routes, next) { - if (!u_rangecompare(&r->dest, &r1->dest)) { + if (!u_routecompare(r, r1)) { Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: Duplicate route", auth->info.lnkname)); j = 1; @@ -2298,9 +2299,10 @@ AuthExternal(AuthData auth) r = Malloc(MB_AUTH, sizeof(struct ifaceroute)); r->dest = range; r->ok = 0; + r->fib = gDefaultFIB; /* XXX implement FIB assignment later */ j = 0; SLIST_FOREACH(r1, &auth->params.routes, next) { - if (!u_rangecompare(&r->dest, &r1->dest)) { + if (!u_routecompare(r, r1)) { Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: Duplicate route", auth->info.lnkname)); j = 1; Index: src/command.c =================================================================== --- src/command.c (revision 2458) +++ src/command.c (working copy) @@ -525,8 +525,11 @@ DoCommand(Context ctx, int ac, const char *const av[], Log2(LG_ERR, ("%sIncorrect context for: '%s'", filebuf, cmd)); break; case CMD_ERR_OTHER: - Printf("%sError in '%s': %s\r\n", filebuf, cmd, ctx->errmsg); - Log2(LG_ERR, ("%sError in '%s': %s", filebuf, cmd, ctx->errmsg)); + case CMD_ERR_WARN: + Printf("%s%s in '%s': %s\r\n", filebuf, + rtn == CMD_ERR_OTHER ? "Error" : "Warning", cmd, ctx->errmsg); + Log2(LG_ERR, ("%s%s in '%s': %s", filebuf, + rtn == CMD_ERR_OTHER ? "Error" : "Warning", cmd, ctx->errmsg)); break; } @@ -1499,9 +1502,9 @@ ShowCustomer(Context ctx, int ac, const char *const av if (!SLIST_EMPTY(&iface->routes) || !SLIST_EMPTY(&b->params.routes)) { Printf("\tRoutes via peer :\r\n"); SLIST_FOREACH(r, &iface->routes, next) - Printf("\t\t: %s\r\n", u_rangetoa(&r->dest,buf,sizeof(buf))); + Printf("\t\t: %s fib %d\r\n", u_rangetoa(&r->dest, buf, sizeof(buf)), r->fib); SLIST_FOREACH(r, &b->params.routes, next) - Printf("\t\t: %s\r\n", u_rangetoa(&r->dest,buf,sizeof(buf))); + Printf("\t\t: %s fib %d\r\n", u_rangetoa(&r->dest,buf,sizeof(buf)), r->fib); } #ifdef USE_IPFW if (b->params.acl_pipe) { Index: src/command.h =================================================================== --- src/command.h (revision 2457) +++ src/command.h (working copy) @@ -25,6 +25,7 @@ #define CMD_ERR_UNFIN -5 #define CMD_ERR_NOCTX -6 #define CMD_ERR_OTHER -7 + #define CMD_ERR_WARN -8 /* Configuration options */ enum { Index: src/console.h =================================================================== --- src/console.h (revision 2457) +++ src/console.h (working copy) @@ -31,6 +31,11 @@ return(CMD_ERR_OTHER); \ } while (0) + #define Warning(fmt, args...) do { \ + snprintf(ctx->errmsg, sizeof(ctx->errmsg), \ + fmt, ## args); \ + } while (0) + /* Global configuration options */ enum { CONSOLE_AUTH /* enable authentication */ Index: src/iface.c =================================================================== --- src/iface.c (revision 2458) +++ src/iface.c (working copy) @@ -267,6 +267,14 @@ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}} static const struct in6_addr in6mask128 = IN6MASK128; +int +u_routecompare(const struct ifaceroute *r1, const struct ifaceroute *r2) +{ + if (r1->fib == r2->fib) + return (u_rangecompare(&r1->dest, &r2->dest)); + return (r1->fib < r2->fib ? -1 : 1); +} + #ifdef SIOCSIFDESCR void IfaceFreeDescr(IfaceState iface) @@ -1074,13 +1082,13 @@ IfaceIpIfaceUp(Bund b, int ready) /* Add static routes */ SLIST_FOREACH(r, &iface->routes, next) { if (u_rangefamily(&r->dest)==AF_INET) { - r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_addr) == 0); + r->ok = (IfaceSetRoute(b, RTM_ADD, r, &iface->peer_addr) == 0); } } /* Add dynamic routes */ SLIST_FOREACH(r, &b->params.routes, next) { if (u_rangefamily(&r->dest)==AF_INET) { - r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_addr) == 0); + r->ok = (IfaceSetRoute(b, RTM_ADD, r, &iface->peer_addr) == 0); } } @@ -1157,7 +1165,7 @@ IfaceIpIfaceDown(Bund b) if (u_rangefamily(&r->dest)==AF_INET) { if (!r->ok) continue; - IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_addr); + IfaceSetRoute(b, RTM_DELETE, r, &iface->peer_addr); r->ok = 0; } } @@ -1166,7 +1174,7 @@ IfaceIpIfaceDown(Bund b) if (u_rangefamily(&r->dest)==AF_INET) { if (!r->ok) continue; - IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_addr); + IfaceSetRoute(b, RTM_DELETE, r, &iface->peer_addr); r->ok = 0; } } @@ -1240,13 +1248,13 @@ IfaceIpv6IfaceUp(Bund b, int ready) /* Add static routes */ SLIST_FOREACH(r, &iface->routes, next) { if (u_rangefamily(&r->dest)==AF_INET6) { - r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_ipv6_addr) == 0); + r->ok = (IfaceSetRoute(b, RTM_ADD, r, &iface->peer_ipv6_addr) == 0); } } /* Add dynamic routes */ SLIST_FOREACH(r, &b->params.routes, next) { if (u_rangefamily(&r->dest)==AF_INET6) { - r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_ipv6_addr) == 0); + r->ok = (IfaceSetRoute(b, RTM_ADD, r, &iface->peer_ipv6_addr) == 0); } } @@ -1308,7 +1316,7 @@ IfaceIpv6IfaceDown(Bund b) if (u_rangefamily(&r->dest)==AF_INET6) { if (!r->ok) continue; - IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_ipv6_addr); + IfaceSetRoute(b, RTM_DELETE, r, &iface->peer_ipv6_addr); r->ok = 0; } } @@ -1317,7 +1325,7 @@ IfaceIpv6IfaceDown(Bund b) if (u_rangefamily(&r->dest)==AF_INET6) { if (!r->ok) continue; - IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_ipv6_addr); + IfaceSetRoute(b, RTM_DELETE, r, &iface->peer_ipv6_addr); r->ok = 0; } } @@ -1600,9 +1608,11 @@ IfaceSetCommand(Context ctx, int ac, const char *const { struct u_range range; IfaceRoute r; + char *p; + int fib; /* Check */ - if (ac != 1) + if (ac != 1 && ac != 3) return(-1); /* Get dest address */ @@ -1612,10 +1622,28 @@ IfaceSetCommand(Context ctx, int ac, const char *const } else if (!ParseRange(av[0], &range, ALLOW_IPV4|ALLOW_IPV6)) Error("Bad route dest address \"%s\"", av[0]); + + fib = 0; + if (ac >= 3) { + if (strcasecmp(av[1], "fib") != 0) + Error("Invalid keyword %s", av[1]); +#ifdef SO_SETFIB + fib = strtol(av[2], &p, 10); + if (p == av[2] || p[0] != 0 || fib < 0) + Error("Invalid FIB number %s", av[2]); +#endif + } + /* Malloc zeroes area */ r = Malloc(MB_IFACE, sizeof(struct ifaceroute)); r->dest = range; - r->ok = 0; + r->fib = fib; SLIST_INSERT_HEAD(&iface->routes, r, next); +#ifndef SO_SETFIB + if (fib > 0) { + Warning("FIB number ignored: %s", av[2]); + return (CMD_ERR_WARN); + } +#endif } break; @@ -2116,7 +2144,7 @@ memcpy_roundup(char *cp, const void *data, size_t len) } int -IfaceSetRoute(Bund b, int cmd, struct u_range *dst, +IfaceSetRoute(Bund b, int cmd, struct ifaceroute *r, struct u_addr *gw) { struct rtmsg rtmes; @@ -2131,6 +2159,10 @@ IfaceSetRoute(Bund b, int cmd, struct u_range *dst, Perror("[%s] IFACE: Can't get route socket", b->name); return (-1); } +#ifdef SO_SETFIB + if (r->fib != -1 && r->fib != gDefaultFIB) + setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&r->fib, sizeof(r->fib)); +#endif memset(&rtmes, '\0', sizeof(rtmes)); rtmes.m_rtm.rtm_version = RTM_VERSION; rtmes.m_rtm.rtm_type = cmd; @@ -2139,7 +2171,7 @@ IfaceSetRoute(Bund b, int cmd, struct u_range *dst, rtmes.m_rtm.rtm_pid = gPid; rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; - u_rangetosockaddrs(dst, &sadst, &samask); + u_rangetosockaddrs(&r->dest, &sadst, &samask); #if defined(__KAME__) && !defined(NOINET6) add_scope((struct sockaddr *)&sadst, b->iface.ifindex); #endif @@ -2159,7 +2191,7 @@ IfaceSetRoute(Bund b, int cmd, struct u_range *dst, return (-1); } - if (u_rangehost(dst)) { + if (u_rangehost(&r->dest)) { rtmes.m_rtm.rtm_flags |= RTF_HOST; } else { cp += memcpy_roundup(cp, &samask, samask.ss_len); @@ -2171,7 +2203,7 @@ IfaceSetRoute(Bund b, int cmd, struct u_range *dst, wb = write(s, &rtmes, nb); if (wb < 0) { Log(LG_ERR, ("[%s] IFACE: %s route %s %s failed: %s", - b->name, cmdstr, u_rangetoa(dst, buf, sizeof(buf)), + b->name, cmdstr, u_rangetoa(&r->dest, buf, sizeof(buf)), ((gw != NULL)?u_addrtoa(gw, buf1, sizeof(buf1)):""), (rtmes.m_rtm.rtm_errno != 0)?strerror(rtmes.m_rtm.rtm_errno):strerror(errno))); close(s); @@ -2179,7 +2211,7 @@ IfaceSetRoute(Bund b, int cmd, struct u_range *dst, } close(s); Log(LG_IFACE2, ("[%s] IFACE: %s route %s %s", - b->name, cmdstr, u_rangetoa(dst, buf, sizeof(buf)), + b->name, cmdstr, u_rangetoa(&r->dest, buf, sizeof(buf)), ((gw != NULL)?u_addrtoa(gw, buf1, sizeof(buf1)):""))); return (0); } Index: src/iface.h =================================================================== --- src/iface.h (revision 2457) +++ src/iface.h (working copy) @@ -93,6 +93,7 @@ struct ifaceroute { struct u_range dest; /* Destination of route */ u_char ok; /* Route installed OK */ + int fib; /* FIB number */ SLIST_ENTRY(ifaceroute) next; }; typedef struct ifaceroute *IfaceRoute; @@ -184,6 +185,8 @@ * FUNCTIONS */ + extern int u_routecompare(const struct ifaceroute *r1, const struct ifaceroute *r2); + extern void IfaceInit(Bund b); extern void IfaceInst(Bund b, Bund bt); extern void IfaceDestroy(Bund b); @@ -206,7 +209,7 @@ extern void IfaceSetMTU(Bund b, int mtu); extern void IfaceChangeFlags(Bund b, int clear, int set); extern int IfaceChangeAddr(Bund b, int add, struct u_range *self, struct u_addr *peer); - extern int IfaceSetRoute(Bund b, int cmd, struct u_range *dst, struct u_addr *gw); + extern int IfaceSetRoute(Bund b, int cmd, struct ifaceroute *r, struct u_addr *gw); #ifdef USE_NG_BPF extern void IfaceGetStats(Bund b, struct svcstat *stat); Index: src/main.c =================================================================== --- src/main.c (revision 2457) +++ src/main.c (working copy) @@ -26,11 +26,12 @@ #include "ccp_mppc.h" #endif +#include + #ifdef USE_BACKTRACE #include #endif #include - /* * DEFINITIONS */ @@ -105,7 +106,7 @@ int gOverload = 0; pid_t gPid; int gRouteSeq = 0; - + int gDefaultFIB = 0; #ifdef PHYSTYPE_PPTP int gPPTPto = 10; unsigned gPPTPtunlimit = 100; @@ -152,8 +153,8 @@ static void FatalSignal(int sig); static void SignalHandler(int type, void *arg); static void CloseIfaces(void); + static int GetMyFIB(void); - /* * INTERNAL VARIABLES */ @@ -179,6 +180,7 @@ main(int ac, char *av[]) const struct phystype *pt; gPid = getpid(); + gDefaultFIB = GetMyFIB(); /* enable libpdel typed_mem */ typed_mem_enable(); @@ -698,6 +700,22 @@ OptDecode(char *arg, int longform) return(opt); } return(NULL); +} + +static int +GetMyFIB(void) +{ +#ifndef SO_SETFIB + return (0); +#else + size_t len; + int fib; + + len = sizeof(fib); + if (sysctlbyname("net.my_fibnum", (void *)&fib, &len, NULL, 0) == -1) + return (-1); + return (fib); +#endif } /* Index: src/ppp.h =================================================================== --- src/ppp.h (revision 2457) +++ src/ppp.h (working copy) @@ -212,6 +212,7 @@ extern struct radsrv gRadsrv; #endif extern int gBackground; + extern int gDefaultFIB; extern int gShutdownInProgress; extern int gOverload; extern pid_t gPid; Index: src/radius.c =================================================================== --- src/radius.c (revision 2457) +++ src/radius.c (working copy) @@ -1508,9 +1508,10 @@ RadiusGetParams(AuthData auth, int eap_proxy) r = Malloc(MB_AUTH, sizeof(struct ifaceroute)); r->dest = range; r->ok = 0; + r->fib = gDefaultFIB; /* XXX implement FIB assignment later */ j = 0; SLIST_FOREACH(r1, &auth->params.routes, next) { - if (!u_rangecompare(&r->dest, &r1->dest)) { + if (!u_routecompare(r, r1)) { Log(LG_ERR|LG_RADIUS, ("[%s] RADIUS: Duplicate route %s", auth->info.lnkname, route)); j = 1; @@ -1536,9 +1537,10 @@ RadiusGetParams(AuthData auth, int eap_proxy) r = Malloc(MB_AUTH, sizeof(struct ifaceroute)); r->dest = range; r->ok = 0; + r->fib = gDefaultFIB; /* XXX implement FIB assignment later */ j = 0; SLIST_FOREACH(r1, &auth->params.routes, next) { - if (!u_rangecompare(&r->dest, &r1->dest)) { + if (!u_routecompare(r, r1)) { Log(LG_ERR|LG_RADIUS, ("[%s] RADIUS: Duplicate route %s", auth->info.lnkname, route)); j = 1; @@ -2047,9 +2049,10 @@ RadiusGetParams(AuthData auth, int eap_proxy) r->dest.addr.u.ip4.s_addr &= tmpmask.s_addr; r->dest.width = auth->params.netmask; r->ok = 0; + r->fib = gDefaultFIB; /* XXX implement FIB assignment later */ j = 0; SLIST_FOREACH(r1, &auth->params.routes, next) { - if (!u_rangecompare(&r->dest, &r1->dest)) { + if (!u_routecompare(r, r1)) { Log(LG_ERR|LG_RADIUS, ("[%s] RADIUS: Duplicate route", auth->info.lnkname)); j = 1;