While here, add src to struct rt6 as well for future use.
#endif
if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
- int subnet;
-
- rtm.hdr.rtm_addrs |= RTA_GATEWAY | RTA_IFA | RTA_IFP;
+ rtm.hdr.rtm_addrs |= RTA_GATEWAY | RTA_IFP;
+ if (rt->src.s_addr != htonl(INADDR_ANY))
+ rtm.hdr.rtm_addrs |= RTA_IFA;
/* Subnet routes are clonning or connected if supported.
* All other routes are static. */
- subnet = ipv4_srcaddr(rt, &src_addr);
- if (subnet == 1) {
+ if (rt->gate.s_addr == htonl(INADDR_ANY)) {
#ifdef RTF_CLONING
rtm.hdr.rtm_flags |= RTF_CLONING;
#endif
#endif
} else
rtm.hdr.rtm_flags |= RTF_STATIC;
- if (subnet == -1) /* unikely */
- rtm.hdr.rtm_addrs &= ~RTA_IFA;
}
if (rt->mask.s_addr == htonl(INADDR_BROADCAST) &&
rt->gate.s_addr == htonl(INADDR_ANY))
if_route(unsigned char cmd, const struct rt *rt)
{
struct nlmr nlm;
- struct in_addr src_addr;
- int subnet;
memset(&nlm, 0, sizeof(nlm));
nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
if (cmd == RTM_DELETE) {
nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
- subnet = -1;
} else {
/* Subnet routes are RTPROT_KERNEL otherwise RTPROT_BOOT */
- if ((subnet = ipv4_srcaddr(rt, &src_addr)) == 1)
+ if (rt->gate.s_addr == ntohl(INADDR_ANY))
nlm.rt.rtm_protocol = RTPROT_KERNEL;
else
nlm.rt.rtm_protocol = RTPROT_BOOT;
if (rt->gate.s_addr != htonl(INADDR_ANY))
add_attr_l(&nlm.hdr, sizeof(nlm), RTA_GATEWAY,
&rt->gate.s_addr, sizeof(rt->gate.s_addr));
- if (subnet != -1) {
+ if (rt->src.s_addr != ntohl(INADDR_ANY)) {
add_attr_l(&nlm.hdr, sizeof(nlm), RTA_PREFSRC,
- &src_addr.s_addr, sizeof(src_addr.s_addr));
+ &rt->src.s_addr, sizeof(rt->src.s_addr));
}
if (rt->mtu) {
char metricsbuf[32];
if (rt->metric)
add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY, rt->metric);
- if (cmd != RTM_DELETE && rt->mtu) {
- char metricsbuf[32];
- struct rtattr *metrics = (void *)metricsbuf;
+ if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
+#if 0
+ /* XXX This fails to work, why? */
+ if (!IN6_IS_ADDR_UNSPECIFIED(&rt->src)) {
+ add_attr_l(&nlm.hdr, sizeof(nlm), RTA_PREFSRC,
+ &rt->src.s6_addr, sizeof(rt->src.s6_addr));
+ }
+#endif
+ if (rt->mtu) {
+ char metricsbuf[32];
+ struct rtattr *metrics = (void *)metricsbuf;
- metrics->rta_type = RTA_METRICS;
- metrics->rta_len = RTA_LENGTH(0);
- rta_add_attr_32(metrics, sizeof(metricsbuf), RTAX_MTU, rt->mtu);
- add_attr_l(&nlm.hdr, sizeof(nlm), RTA_METRICS,
- RTA_DATA(metrics), (unsigned short)RTA_PAYLOAD(metrics));
+ metrics->rta_type = RTA_METRICS;
+ metrics->rta_len = RTA_LENGTH(0);
+ rta_add_attr_32(metrics, sizeof(metricsbuf),
+ RTAX_MTU, rt->mtu);
+ add_attr_l(&nlm.hdr, sizeof(nlm), RTA_METRICS,
+ RTA_DATA(metrics),
+ (unsigned short)RTA_PAYLOAD(metrics));
+ }
}
return send_netlink(rt->iface->ctx, NULL,
return NULL;
}
-int
-ipv4_srcaddr(const struct rt *rt, struct in_addr *addr)
-{
- const struct dhcp_state *dstate;
- const struct ipv4ll_state *istate;
-
- if (rt->iface == NULL) {
- errno = ENOENT;
- return -1;
- }
-
- /* Prefer DHCP source address if matching */
- dstate = D_CSTATE(rt->iface);
- if (dstate && dstate->addr &&
- rt->mask.s_addr == dstate->addr->mask.s_addr &&
- rt->dest.s_addr ==
- (dstate->addr->addr.s_addr & dstate->addr->mask.s_addr))
- {
- *addr = dstate->addr->addr;
- return 1;
- }
-
- /* Then IPv4LL source address if matching */
- istate = IPV4LL_CSTATE(rt->iface);
- if (istate && istate->addr &&
- rt->mask.s_addr == istate->addr->mask.s_addr &&
- rt->dest.s_addr ==
- (istate->addr->addr.s_addr & istate->addr->mask.s_addr))
- {
- *addr = istate->addr->addr;
- return 1;
- }
-
- /* If neither match, return DHCP then IPv4LL */
- if (dstate && dstate->addr) {
- *addr = dstate->addr->addr;
- return 0;
- }
- if (istate && istate->addr) {
- *addr = istate->addr->addr;
- return 0;
- }
-
- errno = ESRCH;
- return -1;
-}
-
int
ipv4_hasaddr(const struct interface *ifp)
{
#ifdef HAVE_ROUTE_METRIC
or->metric != rt->metric ||
#endif
- or->src.s_addr != rt->src.s_addr ||
or->gate.s_addr != rt->gate.s_addr ||
+ or->src.s_addr != rt->src.s_addr ||
or->mtu != rt->mtu)
{
if (c_route(or, rt) != 0)
struct ipv4_addr *ipv4_findaddr(struct dhcpcd_ctx *, const struct in_addr *);
struct ipv4_addr *ipv4_findmaskaddr(struct dhcpcd_ctx *,
const struct in_addr *);
-int ipv4_srcaddr(const struct rt *, struct in_addr *);
void ipv4_handleifa(struct dhcpcd_ctx *, int, struct if_head *, const char *,
const struct in_addr *, const struct in_addr *, const struct in_addr *,
int);
r->gate = in6addr_loopback;
} else
r->gate = in6addr_any;
+ r->src = addr->addr;
return r;
}
/* Is this route already in our table? */
if (find_route6(nrs, rt) != NULL)
continue;
- //rt->src.s_addr = ifp->addr.s_addr;
/* Do we already manage it? */
if ((or = find_route6(ctx->ipv6->routes, rt))) {
if (or->iface != rt->iface ||
#ifdef HAVE_ROUTE_METRIC
rt->metric != or->metric ||
#endif
- // or->src.s_addr != ifp->addr.s_addr ||
!IN6_ARE_ADDR_EQUAL(&or->gate, &rt->gate) ||
+ // !IN6_ARE_ADDR_EQUAL(&or->src, &rt->src) ||
or->mtu != rt->mtu)
{
if (c_route(or, rt) != 0)
struct in6_addr mask;
struct in6_addr gate;
const struct interface *iface;
+ struct in6_addr src;
unsigned int flags;
#ifdef HAVE_ROUTE_METRIC
unsigned int metric;