The branch main has been updated by glebius:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=baad45c9c12028964acd0b58096f3aaa0fb22859

commit baad45c9c12028964acd0b58096f3aaa0fb22859
Author:     Gleb Smirnoff <gleb...@freebsd.org>
AuthorDate: 2025-03-22 23:37:37 +0000
Commit:     Gleb Smirnoff <gleb...@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;

Reply via email to