From: Alexander Bluhm Subject: in_pcbselsrc() and in6_pcbselsrc() const sockaddr parameter To: tech@openbsd.org Date: Tue, 20 May 2025 13:27:52 +0900 Hi, Functions in_pcbselsrc() and in6_pcbselsrc() use the destination sockaddr to determine a suitable source address. As the destination is only used for lookup, it should never be modified. Use const to let the compiler verify that. On the way down on the callstack, also convert the parameter a bunch of other lookup functions to const. ok? bluhm Index: netinet/in_pcb.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v diff -u -p -r1.313 in_pcb.c --- netinet/in_pcb.c 4 May 2025 23:05:17 -0000 1.313 +++ netinet/in_pcb.c 20 May 2025 03:46:14 -0000 @@ -986,12 +986,13 @@ in_pcbrtentry(struct inpcb *inp) * an entry to the caller for later use. */ int -in_pcbselsrc(struct in_addr *insrc, struct sockaddr_in *sin, +in_pcbselsrc(struct in_addr *insrc, const struct sockaddr_in *dstsock, struct inpcb *inp) { - struct ip_moptions *mopts = inp->inp_moptions; - struct rtentry *rt; + const struct in_addr *dst = &dstsock->sin_addr; const struct in_addr *laddr = &inp->inp_laddr; + struct rtentry *rt; + struct ip_moptions *mopts = inp->inp_moptions; u_int rtableid = inp->inp_rtableid; struct sockaddr *ip4_source = NULL; struct in_ifaddr *ia = NULL; @@ -1012,8 +1013,8 @@ in_pcbselsrc(struct in_addr *insrc, stru * been set as a multicast option, use the address of that * interface as our source address. */ - if ((IN_MULTICAST(sin->sin_addr.s_addr) || - sin->sin_addr.s_addr == INADDR_BROADCAST) && mopts != NULL) { + if ((IN_MULTICAST(dst->s_addr) || dst->s_addr == INADDR_BROADCAST) && + mopts != NULL) { struct ifnet *ifp; ifp = if_get(mopts->imo_ifidx); @@ -1035,7 +1036,7 @@ in_pcbselsrc(struct in_addr *insrc, stru * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ - rt = route_mpath(&inp->inp_route, &sin->sin_addr, NULL, rtableid); + rt = route_mpath(&inp->inp_route, dst, NULL, rtableid); /* * If we found a route, use the address Index: netinet/in_pcb.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.h,v diff -u -p -r1.167 in_pcb.h --- netinet/in_pcb.h 4 May 2025 23:05:17 -0000 1.167 +++ netinet/in_pcb.h 20 May 2025 03:19:29 -0000 @@ -361,7 +361,8 @@ int in_sockaddr(struct socket *, struct int in_peeraddr(struct socket *, struct mbuf *); int in_baddynamic(u_int16_t, u_int16_t); int in_rootonly(u_int16_t, u_int16_t); -int in_pcbselsrc(struct in_addr *, struct sockaddr_in *, struct inpcb *); +int in_pcbselsrc(struct in_addr *, const struct sockaddr_in *, + struct inpcb *); struct rtentry * in_pcbrtentry(struct inpcb *); Index: netinet6/in6.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6.c,v diff -u -p -r1.269 in6.c --- netinet6/in6.c 19 May 2025 06:36:48 -0000 1.269 +++ netinet6/in6.c 20 May 2025 03:38:24 -0000 @@ -1194,7 +1194,7 @@ in6ifa_ifpwithaddr(struct ifnet *ifp, st * Get a scope of the address. Node-local, link-local, site-local or global. */ int -in6_addrscope(struct in6_addr *addr) +in6_addrscope(const struct in6_addr *addr) { int scope; @@ -1249,7 +1249,7 @@ in6_addrscope(struct in6_addr *addr) } int -in6_addr2scopeid(unsigned int ifidx, struct in6_addr *addr) +in6_addr2scopeid(unsigned int ifidx, const struct in6_addr *addr) { int scope = in6_addrscope(addr); @@ -1272,7 +1272,7 @@ in6_addr2scopeid(unsigned int ifidx, str * hard coding... */ int -in6_matchlen(struct in6_addr *src, struct in6_addr *dst) +in6_matchlen(const struct in6_addr *src, const struct in6_addr *dst) { int match = 0; u_char *s = (u_char *)src, *d = (u_char *)dst; @@ -1317,7 +1317,7 @@ in6_prefixlen2mask(struct in6_addr *mask * return the best address out of the same scope */ struct in6_ifaddr * -in6_ifawithscope(struct ifnet *oifp, struct in6_addr *dst, u_int rdomain, +in6_ifawithscope(struct ifnet *oifp, const struct in6_addr *dst, u_int rdomain, struct rtentry *rt) { int dst_scope = in6_addrscope(dst), src_scope, best_scope = 0; Index: netinet6/in6.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6.h,v diff -u -p -r1.120 in6.h --- netinet6/in6.h 2 Mar 2025 21:28:32 -0000 1.120 +++ netinet6/in6.h 20 May 2025 03:37:00 -0000 @@ -413,9 +413,9 @@ struct mbuf * int in6_cksum(struct mbuf *, uint8_t, uint32_t, uint32_t); void in6_proto_cksum_out(struct mbuf *, struct ifnet *); -int in6_addrscope(struct in6_addr *); -struct in6_ifaddr *in6_ifawithscope(struct ifnet *, struct in6_addr *, u_int, - struct rtentry *); +int in6_addrscope(const struct in6_addr *); +struct in6_ifaddr *in6_ifawithscope(struct ifnet *, const struct in6_addr *, + u_int, struct rtentry *); int in6_mask2len(struct in6_addr *, u_char *); int in6_nam2sin6(const struct mbuf *, struct sockaddr_in6 **); int in6_sa2sin6(struct sockaddr *, struct sockaddr_in6 **); Index: netinet6/in6_src.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_src.c,v diff -u -p -r1.100 in6_src.c --- netinet6/in6_src.c 1 Jan 2025 13:44:22 -0000 1.100 +++ netinet6/in6_src.c 20 May 2025 03:46:11 -0000 @@ -91,22 +91,21 @@ int in6_selectif(const struct in6_addr * * the values set at pcb level can be overridden via cmsg. */ int -in6_pcbselsrc(const struct in6_addr **in6src, struct sockaddr_in6 *dstsock, - struct inpcb *inp, struct ip6_pktopts *opts) +in6_pcbselsrc(const struct in6_addr **in6src, + const struct sockaddr_in6 *dstsock, struct inpcb *inp, + struct ip6_pktopts *opts) { - struct ip6_moptions *mopts = inp->inp_moptions6; - struct rtentry *rt; + const struct in6_addr *dst = &dstsock->sin6_addr; const struct in6_addr *laddr = &inp->inp_laddr6; + struct rtentry *rt; + struct ip6_moptions *mopts = inp->inp_moptions6; u_int rtableid = inp->inp_rtableid; struct ifnet *ifp = NULL; struct sockaddr *ip6_source = NULL; - struct in6_addr *dst; struct in6_ifaddr *ia6 = NULL; struct in6_pktinfo *pi = NULL; int error; - dst = &dstsock->sin6_addr; - /* * If the source address is explicitly specified by the caller, * check if the requested source address is indeed a unicast address @@ -232,14 +231,13 @@ in6_pcbselsrc(const struct in6_addr **in * an entry to the caller for later use. */ int -in6_selectsrc(const struct in6_addr **in6src, struct sockaddr_in6 *dstsock, +in6_selectsrc(const struct in6_addr **in6src, + const struct sockaddr_in6 *dstsock, struct ip6_moptions *mopts, unsigned int rtableid) { + const struct in6_addr *dst = &dstsock->sin6_addr; struct ifnet *ifp = NULL; - struct in6_addr *dst; struct in6_ifaddr *ia6 = NULL; - - dst = &dstsock->sin6_addr; /* * If the destination address is a link-local unicast address or Index: netinet6/in6_var.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_var.h,v diff -u -p -r1.80 in6_var.h --- netinet6/in6_var.h 13 May 2024 01:15:53 -0000 1.80 +++ netinet6/in6_var.h 20 May 2025 03:38:12 -0000 @@ -364,8 +364,8 @@ void in6_purgeaddr(struct ifaddr *); int in6if_do_dad(struct ifnet *); struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int); struct in6_ifaddr *in6ifa_ifpwithaddr(struct ifnet *, struct in6_addr *); -int in6_addr2scopeid(unsigned int, struct in6_addr *); -int in6_matchlen(struct in6_addr *, struct in6_addr *); +int in6_addr2scopeid(unsigned int, const struct in6_addr *); +int in6_matchlen(const struct in6_addr *, const struct in6_addr *); void in6_prefixlen2mask(struct in6_addr *, int); #endif /* _KERNEL */ Index: netinet6/ip6_var.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_var.h,v diff -u -p -r1.123 ip6_var.h --- netinet6/ip6_var.h 2 Mar 2025 21:28:32 -0000 1.123 +++ netinet6/ip6_var.h 20 May 2025 03:33:40 -0000 @@ -366,9 +366,9 @@ int rip6_sysctl(int *, u_int, void *, si int dest6_input(struct mbuf **, int *, int, int, struct netstack *); -int in6_pcbselsrc(const struct in6_addr **, struct sockaddr_in6 *, +int in6_pcbselsrc(const struct in6_addr **, const struct sockaddr_in6 *, struct inpcb *, struct ip6_pktopts *); -int in6_selectsrc(const struct in6_addr **, struct sockaddr_in6 *, +int in6_selectsrc(const struct in6_addr **, const struct sockaddr_in6 *, struct ip6_moptions *, unsigned int); struct rtentry *in6_selectroute(const struct in6_addr *, struct ip6_pktopts *, struct route *, unsigned int rtableid);