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));