Hi, 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.
ok? bluhm Index: net/route.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/route.h,v retrieving revision 1.78 diff -u -p -u -p -r1.78 route.h --- net/route.h 19 Sep 2012 16:14:01 -0000 1.78 +++ net/route.h 14 Oct 2013 18:19:10 -0000 @@ -61,10 +61,9 @@ struct route { */ 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; }; /* @@ -72,9 +71,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 */ @@ -83,6 +82,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; }; /* @@ -214,7 +214,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.127 diff -u -p -u -p -r1.127 rtsock.c --- net/rtsock.c 28 Aug 2013 06:58:57 -0000 1.127 +++ net/rtsock.c 14 Oct 2013 22:31:58 -0000 @@ -101,6 +101,10 @@ 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 *); +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] @@ -480,6 +484,23 @@ route_output(struct mbuf *m, ...) goto fail; } switch (mtod(m, struct rt_msghdr *)->rtm_version) { +#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; @@ -935,6 +956,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)) @@ -1031,6 +1064,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; } @@ -1075,6 +1113,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; @@ -1311,6 +1359,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); } @@ -1345,6 +1414,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) @@ -1366,6 +1452,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; } @@ -1450,6 +1552,50 @@ 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 == 0) + 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); +} +#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.108 diff -u -p -u -p -r1.108 if_ether.c --- netinet/if_ether.c 14 Oct 2013 16:06:33 -0000 1.108 +++ netinet/if_ether.c 14 Oct 2013 16:10:47 -0000 @@ -1133,7 +1133,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));