Author: tuexen
Date: Fri Feb 10 23:00:24 2012
New Revision: 231463
URL: http://svn.freebsd.org/changeset/base/231463

Log:
  MFC r225571:
  Make sure that SCTP rejects broadcast, multicast and wildcard addresses
  as remote addresses.

Modified:
  stable/8/sys/netinet/sctp_asconf.c
  stable/8/sys/netinet/sctp_output.c
  stable/8/sys/netinet/sctp_pcb.c
  stable/8/sys/netinet/sctp_usrreq.c
  stable/8/sys/netinet/sctputil.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/boot/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/e1000/   (props changed)

Modified: stable/8/sys/netinet/sctp_asconf.c
==============================================================================
--- stable/8/sys/netinet/sctp_asconf.c  Fri Feb 10 22:57:50 2012        
(r231462)
+++ stable/8/sys/netinet/sctp_asconf.c  Fri Feb 10 23:00:24 2012        
(r231463)
@@ -207,6 +207,7 @@ sctp_process_asconf_add_ip(struct mbuf *
        uint16_t param_type, param_length, aparam_length;
        struct sockaddr *sa;
        int zero_address = 0;
+       int bad_address = 0;
 
 #ifdef INET
        struct sockaddr_in *sin;
@@ -239,6 +240,10 @@ sctp_process_asconf_add_ip(struct mbuf *
                sin->sin_len = sizeof(struct sockaddr_in);
                sin->sin_port = stcb->rport;
                sin->sin_addr.s_addr = v4addr->addr;
+               if ((sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+                   IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
+                       bad_address = 1;;
+               }
                if (sin->sin_addr.s_addr == INADDR_ANY)
                        zero_address = 1;
                SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
@@ -259,6 +264,9 @@ sctp_process_asconf_add_ip(struct mbuf *
                sin6->sin6_port = stcb->rport;
                memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
                    sizeof(struct in6_addr));
+               if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+                       bad_address = 1;
+               }
                if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
                        zero_address = 1;
                SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
@@ -266,12 +274,8 @@ sctp_process_asconf_add_ip(struct mbuf *
                break;
 #endif
        default:
-               /*
-                * XXX: Is this the correct error cause? Maybe
-                * SCTP_CAUSE_INVALID_PARAM is a better choice.
-                */
                m_reply = sctp_asconf_error_response(aph->correlation_id,
-                   SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
+                   SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
                    aparam_length);
                return m_reply;
        }                       /* end switch */
@@ -285,7 +289,11 @@ sctp_process_asconf_add_ip(struct mbuf *
                SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
        }
        /* add the address */
-       if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE,
+       if (bad_address) {
+               m_reply = sctp_asconf_error_response(aph->correlation_id,
+                   SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
+                   aparam_length);
+       } else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE,
            SCTP_ADDR_DYNAMIC_ADDED) != 0) {
                SCTPDBG(SCTP_DEBUG_ASCONF1,
                    "process_asconf_add_ip: error adding address\n");

Modified: stable/8/sys/netinet/sctp_output.c
==============================================================================
--- stable/8/sys/netinet/sctp_output.c  Fri Feb 10 22:57:50 2012        
(r231462)
+++ stable/8/sys/netinet/sctp_output.c  Fri Feb 10 23:00:24 2012        
(r231463)
@@ -3541,7 +3541,7 @@ sctp_process_cmsgs_for_init(struct sctp_
                                    (sin.sin_addr.s_addr == INADDR_BROADCAST) ||
                                    IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
                                        *error = EINVAL;
-                                       return (-1);
+                                       return (1);
                                }
                                if (sctp_add_remote_addr(stcb, (struct sockaddr 
*)&sin, NULL,
                                    SCTP_DONOT_SETSCOPE, 
SCTP_ADDR_IS_CONFIRMED)) {
@@ -3564,7 +3564,7 @@ sctp_process_cmsgs_for_init(struct sctp_
                                if (IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr) ||
                                    IN6_IS_ADDR_MULTICAST(&sin6.sin6_addr)) {
                                        *error = EINVAL;
-                                       return (-1);
+                                       return (1);
                                }
 #ifdef INET
                                if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
@@ -3573,7 +3573,7 @@ sctp_process_cmsgs_for_init(struct sctp_
                                            (sin.sin_addr.s_addr == 
INADDR_BROADCAST) ||
                                            
IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
                                                *error = EINVAL;
-                                               return (-1);
+                                               return (1);
                                        }
                                        if (sctp_add_remote_addr(stcb, (struct 
sockaddr *)&sin, NULL,
                                            SCTP_DONOT_SETSCOPE, 
SCTP_ADDR_IS_CONFIRMED)) {

Modified: stable/8/sys/netinet/sctp_pcb.c
==============================================================================
--- stable/8/sys/netinet/sctp_pcb.c     Fri Feb 10 22:57:50 2012        
(r231462)
+++ stable/8/sys/netinet/sctp_pcb.c     Fri Feb 10 23:00:24 2012        
(r231463)
@@ -4332,7 +4332,10 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, 
                        struct sockaddr_in *sin;
 
                        sin = (struct sockaddr_in *)firstaddr;
-                       if ((sin->sin_port == 0) || (sin->sin_addr.s_addr == 
0)) {
+                       if ((ntohs(sin->sin_port) == 0) ||
+                           (sin->sin_addr.s_addr == INADDR_ANY) ||
+                           (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+                           IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
                                /* Invalid address */
                                SCTP_INP_RUNLOCK(inp);
                                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_PCB, EINVAL);
@@ -4349,8 +4352,9 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, 
                        struct sockaddr_in6 *sin6;
 
                        sin6 = (struct sockaddr_in6 *)firstaddr;
-                       if ((sin6->sin6_port == 0) ||
-                           (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
+                       if ((ntohs(sin6->sin6_port) == 0) ||
+                           IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
+                           IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
                                /* Invalid address */
                                SCTP_INP_RUNLOCK(inp);
                                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_PCB, EINVAL);

Modified: stable/8/sys/netinet/sctp_usrreq.c
==============================================================================
--- stable/8/sys/netinet/sctp_usrreq.c  Fri Feb 10 22:57:50 2012        
(r231462)
+++ stable/8/sys/netinet/sctp_usrreq.c  Fri Feb 10 23:00:24 2012        
(r231463)
@@ -560,7 +560,7 @@ sctp_bind(struct socket *so, struct sock
        struct sctp_inpcb *inp = NULL;
        int error;
 
-#ifdef INET6
+#ifdef INET
        if (addr && addr->sa_family != AF_INET) {
                /* must be a v4 address! */
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, 
EINVAL);

Modified: stable/8/sys/netinet/sctputil.c
==============================================================================
--- stable/8/sys/netinet/sctputil.c     Fri Feb 10 22:57:50 2012        
(r231462)
+++ stable/8/sys/netinet/sctputil.c     Fri Feb 10 23:00:24 2012        
(r231463)
@@ -6080,6 +6080,15 @@ sctp_connectx_helper_add(struct sctp_tcb
        struct sockaddr *sa;
        size_t incr = 0;
 
+#ifdef INET
+       struct sockaddr_in *sin;
+
+#endif
+#ifdef INET6
+       struct sockaddr_in6 *sin6;
+
+#endif
+
        sa = addr;
        inp = stcb->sctp_ep;
        *error = 0;
@@ -6088,6 +6097,15 @@ sctp_connectx_helper_add(struct sctp_tcb
 #ifdef INET
                case AF_INET:
                        incr = sizeof(struct sockaddr_in);
+                       sin = (struct sockaddr_in *)sa;
+                       if ((sin->sin_addr.s_addr == INADDR_ANY) ||
+                           (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+                           IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
+                               SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, 
SCTP_FROM_SCTPUTIL, EINVAL);
+                               (void)sctp_free_assoc(inp, stcb, 
SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
+                               *error = EINVAL;
+                               goto out_now;
+                       }
                        if (sctp_add_remote_addr(stcb, sa, NULL, 
SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
                                /* assoc gone no un-lock */
                                SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, 
SCTP_FROM_SCTPUTIL, ENOBUFS);
@@ -6101,6 +6119,14 @@ sctp_connectx_helper_add(struct sctp_tcb
 #ifdef INET6
                case AF_INET6:
                        incr = sizeof(struct sockaddr_in6);
+                       sin6 = (struct sockaddr_in6 *)sa;
+                       if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
+                           IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+                               SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, 
SCTP_FROM_SCTPUTIL, EINVAL);
+                               (void)sctp_free_assoc(inp, stcb, 
SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
+                               *error = EINVAL;
+                               goto out_now;
+                       }
                        if (sctp_add_remote_addr(stcb, sa, NULL, 
SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
                                /* assoc gone no un-lock */
                                SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, 
SCTP_FROM_SCTPUTIL, ENOBUFS);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to