git: baad45c9c120 - main - inpcb: push multicast case local address selection logic into in_pcbladdr()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 22 Mar 2025 23:40:45 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=baad45c9c12028964acd0b58096f3aaa0fb22859
commit baad45c9c12028964acd0b58096f3aaa0fb22859
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-03-22 23:37:37 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-03-22 23:37:37 +0000
inpcb: push multicast case local address selection logic into in_pcbladdr()
When destination is multicast and inpcb has multicast options configured,
we use completely different logic than in a normal case. Before this
change, in in_pcbconnect() we would run in_pcbladdr() and then just ignore
its results and run the multicast case block, that would override any
earlier selection or failure. Let's embed the case in in_pcbladdr() and
also check it earlier.
Also, 69c05f428714 switched UDP unconnected sendto(2) to use in_pcbladdr()
instead of in_pcbconnect_setup() and due to that lost the multicast case.
Reviewed by: markj
Differential Revision: https://reviews.freebsd.org/D49435
Fixes: 69c05f42871406b4b2b2dac00a268d1da0cacd3e
---
sys/netinet/in_pcb.c | 44 +++++++++++++++++++++-----------------------
1 file changed, 21 insertions(+), 23 deletions(-)
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 9a49353f1538..3774f73a7a8f 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1127,29 +1127,6 @@ in_pcbconnect(struct inpcb *inp, struct sockaddr_in *sin, struct ucred *cred)
if (in_nullhost(inp->inp_laddr)) {
error = in_pcbladdr(inp, &faddr, &laddr, cred);
- /*
- * If the destination address is multicast and an outgoing
- * interface has been set as a multicast option, prefer the
- * address of that interface as our source address.
- */
- if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
- inp->inp_moptions != NULL &&
- inp->inp_moptions->imo_multicast_ifp != NULL) {
- struct ifnet *ifp =
- inp->inp_moptions->imo_multicast_ifp;
- struct in_ifaddr *ia;
-
- CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
- if (ia->ia_ifp == ifp &&
- prison_check_ip4(cred,
- &ia->ia_addr.sin_addr) == 0)
- break;
- }
- if (ia == NULL)
- return (EADDRNOTAVAIL);
- laddr = ia->ia_addr.sin_addr;
- error = 0;
- }
if (error)
return (error);
} else
@@ -1231,6 +1208,27 @@ in_pcbladdr(const struct inpcb *inp, struct in_addr *faddr,
if (!prison_saddrsel_ip4(cred, laddr))
return (0);
+ /*
+ * If the destination address is multicast and an outgoing
+ * interface has been set as a multicast option, prefer the
+ * address of that interface as our source address.
+ */
+ if (IN_MULTICAST(ntohl(faddr->s_addr)) && inp->inp_moptions != NULL &&
+ inp->inp_moptions->imo_multicast_ifp != NULL) {
+ struct ifnet *ifp = inp->inp_moptions->imo_multicast_ifp;
+ struct in_ifaddr *ia;
+
+ CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
+ if (ia->ia_ifp == ifp &&
+ prison_check_ip4(cred, &ia->ia_addr.sin_addr) == 0)
+ break;
+ }
+ if (ia == NULL)
+ return (EADDRNOTAVAIL);
+ *laddr = ia->ia_addr.sin_addr;
+ return (0);
+ }
+
error = 0;
nh = NULL;