On Tue, Oct 15, 2013 at 12:43:16AM +0200, Alexander Bluhm wrote:
> Convert the route expire timestamp in kernel and routing message
> to 64 bit. Add a small compatibility layer that allows to set
> routes with old user land and new kernel.
You can still config addresses with old ifconfig and new kernel.
I have increased the compatibility layer, "route get" also works
in this setup. dhclient still hangs as I have do not generate old
messages for interface address changes.
I would like to get that in as it is. ok?
bluhm
Index: net/route.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/route.h,v
retrieving revision 1.82
diff -u -p -u -p -r1.82 route.h
--- net/route.h 24 Oct 2013 18:50:16 -0000 1.82
+++ net/route.h 30 Oct 2013 16:30:40 -0000
@@ -48,10 +48,9 @@
*/
struct rt_kmetrics {
u_int64_t rmx_pksent; /* packets sent using this route */
+ int64_t rmx_expire; /* lifetime for route, e.g. redirect */
u_int rmx_locks; /* Kernel must leave these values */
u_int rmx_mtu; /* MTU for this path */
- u_int rmx_expire; /* lifetime for route, e.g. redirect */
- u_int rmx_pad;
};
/*
@@ -59,9 +58,9 @@ struct rt_kmetrics {
*/
struct rt_metrics {
u_int64_t rmx_pksent; /* packets sent using this route */
+ int64_t rmx_expire; /* lifetime for route, e.g. redirect */
u_int rmx_locks; /* Kernel must leave these values */
u_int rmx_mtu; /* MTU for this path */
- u_int rmx_expire; /* lifetime for route, e.g. redirect */
u_int rmx_refcnt; /* # references hold */
/* some apps may still need these no longer used metrics */
u_int rmx_hopcount; /* max hops expected */
@@ -70,6 +69,7 @@ struct rt_metrics {
u_int rmx_ssthresh; /* outbound gateway buffer limit */
u_int rmx_rtt; /* estimated round trip time */
u_int rmx_rttvar; /* estimated rtt variance */
+ u_int rmx_pad;
};
/*
@@ -207,7 +207,47 @@ struct rt_msghdr {
/* overload no longer used field */
#define rtm_use rtm_rmx.rmx_pksent
-#define RTM_VERSION 4 /* Up the ante and ignore older versions */
+#if defined(_KERNEL) && ! defined(SMALL_KERNEL)
+/*
+ * Compatibility structures for version 4 messages.
+ * Remove them after OpenBSD 5.5.
+ */
+struct rt_ometrics {
+ u_int64_t rmx_pksent; /* packets sent using this route */
+ u_int rmx_locks; /* Kernel must leave these values */
+ u_int rmx_mtu; /* MTU for this path */
+ u_int rmx_expire; /* lifetime for route, e.g. redirect */
+ u_int rmx_refcnt; /* # references hold */
+ /* some apps may still need these no longer used metrics */
+ u_int rmx_hopcount; /* max hops expected */
+ u_int rmx_recvpipe; /* inbound delay-bandwidth product */
+ u_int rmx_sendpipe; /* outbound delay-bandwidth product */
+ u_int rmx_ssthresh; /* outbound gateway buffer limit */
+ u_int rmx_rtt; /* estimated round trip time */
+ u_int rmx_rttvar; /* estimated rtt variance */
+};
+struct rt_omsghdr {
+ u_short rtm_msglen; /* to skip over non-understood messages */
+ u_char rtm_version; /* future binary compatibility */
+ u_char rtm_type; /* message type */
+ u_short rtm_hdrlen; /* sizeof(rt_msghdr) to skip over the header */
+ u_short rtm_index; /* index for associated ifp */
+ u_short rtm_tableid; /* routing table id */
+ u_char rtm_priority; /* routing priority */
+ u_char rtm_mpls; /* MPLS additional infos */
+ int rtm_addrs; /* bitmask identifying sockaddrs in msg */
+ int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
+ int rtm_fmask; /* bitmask used in RTM_CHANGE message */
+ pid_t rtm_pid; /* identify sender */
+ int rtm_seq; /* for sender to identify action */
+ int rtm_errno; /* why failed */
+ u_int rtm_inits; /* which metrics we are initializing */
+ struct rt_ometrics rtm_rmx; /* metrics themselves */
+};
+#define RTM_OVERSION 4 /* Provide backward compatibility */
+#endif /* defined(_KERNEL) && ! defined(SMALL_KERNEL) */
+
+#define RTM_VERSION 5 /* Up the ante and ignore older versions */
#define RTM_MAXSIZE 2048 /* Maximum size of an accepted route msg */
Index: net/rtsock.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/rtsock.c,v
retrieving revision 1.129
diff -u -p -u -p -r1.129 rtsock.c
--- net/rtsock.c 20 Oct 2013 13:21:57 -0000 1.129
+++ net/rtsock.c 30 Oct 2013 16:32:40 -0000
@@ -101,6 +101,11 @@ struct mbuf *rt_msg1(int, struct rt_addr
int rt_msg2(int, int, struct rt_addrinfo *, caddr_t,
struct walkarg *);
void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
+#ifdef RTM_OVERSION
+struct rt_msghdr *rtmsg_4to5(struct mbuf *, int *);
+struct rt_omsghdr *rtmsg_5to4(struct rt_msghdr *);
+void rt_ogetmetrics(struct rt_kmetrics *in, struct rt_ometrics *out);
+#endif /* RTM_OVERSION */
/* Sleazy use of local variables throughout file, warning!!!! */
#define dst info.rti_info[RTAX_DST]
@@ -463,6 +468,7 @@ route_output(struct mbuf *m, ...)
va_list ap;
u_int tableid;
u_int8_t prio;
+ u_char vers;
va_start(ap, m);
so = va_arg(ap, struct socket *);
@@ -480,7 +486,25 @@ route_output(struct mbuf *m, ...)
error = EINVAL;
goto fail;
}
- switch (mtod(m, struct rt_msghdr *)->rtm_version) {
+ vers = mtod(m, struct rt_msghdr *)->rtm_version;
+ switch (vers) {
+#ifdef RTM_OVERSION
+ case RTM_OVERSION:
+ if (len < sizeof(struct rt_omsghdr)) {
+ error = EINVAL;
+ goto fail;
+ }
+ if (len > RTM_MAXSIZE) {
+ error = EMSGSIZE;
+ goto fail;
+ }
+ rtm = rtmsg_4to5(m, &len);
+ if (rtm == 0) {
+ error = ENOBUFS;
+ goto fail;
+ }
+ break;
+#endif /* RTM_OVERSION */
case RTM_VERSION:
if (len < sizeof(struct rt_msghdr)) {
error = EINVAL;
@@ -903,6 +927,18 @@ fail:
if (rp)
rp->rcb_proto.sp_family = 0; /* Avoid us */
if (rtm) {
+#ifdef RTM_OVERSION
+ if (vers == RTM_OVERSION) {
+ struct rt_omsghdr *ortm;
+
+ if ((ortm = rtmsg_5to4(rtm)) == NULL ||
+ m_copyback(m, 0, ortm->rtm_msglen, ortm, M_NOWAIT)){
+ m_freem(m);
+ m = NULL;
+ } else if (m->m_pkthdr.len > ortm->rtm_msglen)
+ m_adj(m, ortm->rtm_msglen - m->m_pkthdr.len);
+ } else
+#endif /* RTM_OVERSION */
if (m_copyback(m, 0, rtm->rtm_msglen, rtm, M_NOWAIT)) {
m_freem(m);
m = NULL;
@@ -938,6 +974,18 @@ rt_getmetrics(struct rt_kmetrics *in, st
out->rmx_pksent = in->rmx_pksent;
}
+#ifdef RTM_OVERSION
+void
+rt_ogetmetrics(struct rt_kmetrics *in, struct rt_ometrics *out)
+{
+ bzero(out, sizeof(*out));
+ out->rmx_locks = in->rmx_locks;
+ out->rmx_mtu = in->rmx_mtu;
+ out->rmx_expire = (u_int)in->rmx_expire;
+ out->rmx_pksent = in->rmx_pksent;
+}
+#endif /* RTM_OVERSION */
+
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
@@ -1034,6 +1082,11 @@ again:
len = sizeof(struct if_msghdr);
break;
default:
+#ifdef RTM_OVERSION
+ if (vers == RTM_OVERSION)
+ len = sizeof(struct rt_omsghdr);
+ else
+#endif /* RTM_OVERSION */
len = sizeof(struct rt_msghdr);
break;
}
@@ -1078,6 +1131,16 @@ again:
if (cp && w) /* clear the message header */
bzero(cp0, hlen);
+#ifdef RTM_OVERSION
+ if (cp && vers == RTM_OVERSION) {
+ struct rt_omsghdr *rtm = (struct rt_omsghdr *)cp0;
+
+ rtm->rtm_version = RTM_OVERSION;
+ rtm->rtm_type = type;
+ rtm->rtm_msglen = len;
+ rtm->rtm_hdrlen = hlen;
+ } else
+#endif /* RTM_OVERSION */
if (cp) {
struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
@@ -1314,6 +1377,27 @@ sysctl_dumpentry(struct radix_node *rn,
else
w->w_where += size;
}
+#ifdef RTM_OVERSION
+ size = rt_msg2(RTM_GET, RTM_OVERSION, &info, NULL, w);
+ if (w->w_where && w->w_tmem && w->w_needed <= 0) {
+ struct rt_omsghdr *rtm = (struct rt_omsghdr *)w->w_tmem;
+
+ rtm->rtm_flags = rt->rt_flags;
+ rtm->rtm_priority = rt->rt_priority & RTP_MASK;
+ rt_ogetmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
+ rtm->rtm_rmx.rmx_refcnt = rt->rt_refcnt;
+ rtm->rtm_index = rt->rt_ifp->if_index;
+ rtm->rtm_addrs = info.rti_addrs;
+ rtm->rtm_tableid = id;
+#ifdef MPLS
+ rtm->rtm_mpls = info.rti_mpls;
+#endif
+ if ((error = copyout(rtm, w->w_where, size)) != 0)
+ w->w_where = NULL;
+ else
+ w->w_where += size;
+ }
+#endif
return (error);
}
@@ -1348,6 +1432,23 @@ sysctl_iflist(int af, struct walkarg *w)
return (error);
w->w_where += len;
}
+#ifdef RTM_OVERSION
+ len = rt_msg2(RTM_IFINFO, RTM_OVERSION, &info, 0, w);
+ if (w->w_where && w->w_tmem && w->w_needed <= 0) {
+ struct if_msghdr *ifm;
+
+ ifm = (struct if_msghdr *)w->w_tmem;
+ ifm->ifm_index = ifp->if_index;
+ ifm->ifm_tableid = ifp->if_rdomain;
+ ifm->ifm_flags = ifp->if_flags;
+ ifm->ifm_data = ifp->if_data;
+ ifm->ifm_addrs = info.rti_addrs;
+ error = copyout(ifm, w->w_where, len);
+ if (error)
+ return (error);
+ w->w_where += len;
+ }
+#endif /* RTM_OVERSION */
ifpaddr = 0;
while ((ifa = TAILQ_NEXT(ifa, ifa_list)) != NULL) {
if (af && af != ifa->ifa_addr->sa_family)
@@ -1369,6 +1470,22 @@ sysctl_iflist(int af, struct walkarg *w)
return (error);
w->w_where += len;
}
+#ifdef RTM_OVERSION
+ len = rt_msg2(RTM_NEWADDR, RTM_OVERSION, &info, 0, w);
+ if (w->w_where && w->w_tmem && w->w_needed <= 0) {
+ struct ifa_msghdr *ifam;
+
+ ifam = (struct ifa_msghdr *)w->w_tmem;
+ ifam->ifam_index = ifa->ifa_ifp->if_index;
+ ifam->ifam_flags = ifa->ifa_flags;
+ ifam->ifam_metric = ifa->ifa_metric;
+ ifam->ifam_addrs = info.rti_addrs;
+ error = copyout(w->w_tmem, w->w_where, len);
+ if (error)
+ return (error);
+ w->w_where += len;
+ }
+#endif /* RTM_OVERSION */
}
ifaaddr = netmask = brdaddr = 0;
}
@@ -1453,6 +1570,92 @@ sysctl_rtable(int *name, u_int namelen,
return (error);
}
+
+#ifdef RTM_OVERSION
+struct rt_msghdr *
+rtmsg_4to5(struct mbuf *m, int *len)
+{
+ struct rt_msghdr *rtm;
+ struct rt_omsghdr *ortm;
+
+ *len += sizeof(struct rt_msghdr) - sizeof(struct rt_omsghdr);
+ R_Malloc(rtm, struct rt_msghdr *, *len);
+ if (rtm == NULL)
+ return (NULL);
+ bzero(rtm, sizeof(struct rt_msghdr));
+ ortm = mtod(m, struct rt_omsghdr *);
+ rtm->rtm_msglen = *len;
+ rtm->rtm_version = RTM_VERSION;
+ rtm->rtm_type = ortm->rtm_type;
+ rtm->rtm_hdrlen = sizeof(struct rt_msghdr);
+
+ rtm->rtm_index = ortm->rtm_index;
+ rtm->rtm_tableid = ortm->rtm_tableid;
+ rtm->rtm_priority = ortm->rtm_priority;
+ rtm->rtm_mpls = ortm->rtm_mpls;
+ rtm->rtm_addrs = ortm->rtm_addrs;
+ rtm->rtm_flags = ortm->rtm_flags;
+ rtm->rtm_fmask = ortm->rtm_fmask;
+ rtm->rtm_pid = ortm->rtm_pid;
+ rtm->rtm_seq = ortm->rtm_seq;
+ rtm->rtm_errno = ortm->rtm_errno;
+ rtm->rtm_inits = ortm->rtm_inits;
+
+ /* copy just the interesting stuff ignore the rest */
+ rtm->rtm_rmx.rmx_pksent = ortm->rtm_rmx.rmx_pksent;
+ rtm->rtm_rmx.rmx_expire = (int64_t)ortm->rtm_rmx.rmx_expire;
+ rtm->rtm_rmx.rmx_locks = ortm->rtm_rmx.rmx_locks;
+ rtm->rtm_rmx.rmx_mtu = ortm->rtm_rmx.rmx_mtu;
+
+ m_copydata(m, sizeof(struct rt_omsghdr),
+ *len - sizeof(struct rt_msghdr),
+ (caddr_t)rtm + sizeof(struct rt_msghdr));
+
+ return (rtm);
+}
+
+struct rt_omsghdr *
+rtmsg_5to4(struct rt_msghdr *rtm)
+{
+ struct rt_omsghdr *ortm;
+ int len;
+
+ len = rtm->rtm_msglen + sizeof(struct rt_omsghdr) -
+ sizeof(struct rt_msghdr);
+ R_Malloc(ortm, struct rt_omsghdr *, len);
+ if (ortm == NULL)
+ return (NULL);
+ bzero(ortm, sizeof(struct rt_omsghdr));
+ ortm->rtm_msglen = len;
+ ortm->rtm_version = RTM_OVERSION;
+ ortm->rtm_type = rtm->rtm_type;
+ ortm->rtm_hdrlen = sizeof(struct rt_omsghdr);
+
+ ortm->rtm_index = rtm->rtm_index;
+ ortm->rtm_tableid = rtm->rtm_tableid;
+ ortm->rtm_priority = rtm->rtm_priority;
+ ortm->rtm_mpls = rtm->rtm_mpls;
+ ortm->rtm_addrs = rtm->rtm_addrs;
+ ortm->rtm_flags = rtm->rtm_flags;
+ ortm->rtm_fmask = rtm->rtm_fmask;
+ ortm->rtm_pid = rtm->rtm_pid;
+ ortm->rtm_seq = rtm->rtm_seq;
+ ortm->rtm_errno = rtm->rtm_errno;
+ ortm->rtm_inits = rtm->rtm_inits;
+
+ /* copy just the interesting stuff ignore the rest */
+ ortm->rtm_rmx.rmx_pksent = rtm->rtm_rmx.rmx_pksent;
+ ortm->rtm_rmx.rmx_expire = (u_int)rtm->rtm_rmx.rmx_expire;
+ ortm->rtm_rmx.rmx_locks = rtm->rtm_rmx.rmx_locks;
+ ortm->rtm_rmx.rmx_mtu = rtm->rtm_rmx.rmx_mtu;
+
+ memcpy((caddr_t)ortm + sizeof(struct rt_omsghdr),
+ (caddr_t)rtm + sizeof(struct rt_msghdr),
+ len - sizeof(struct rt_omsghdr));
+
+ return (ortm);
+}
+#endif /* RTM_OVERSION */
/*
* Definitions of protocols supported in the ROUTE domain.
Index: netinet/if_ether.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/if_ether.c,v
retrieving revision 1.109
diff -u -p -u -p -r1.109 if_ether.c
--- netinet/if_ether.c 28 Oct 2013 12:33:32 -0000 1.109
+++ netinet/if_ether.c 30 Oct 2013 16:30:18 -0000
@@ -1104,7 +1104,7 @@ db_show_radix_node(struct radix_node *rn
db_printf("rtentry=%p", rt);
- db_printf(" flags=0x%x refcnt=%d use=%llu expire=%u rtableid %u\n",
+ db_printf(" flags=0x%x refcnt=%d use=%llu expire=%lld rtableid=%u\n",
rt->rt_flags, rt->rt_refcnt, rt->rt_use, rt->rt_expire, id);
db_printf(" key="); db_print_sa(rt_key(rt));