Print this page
dccp: ips_ipcl_dccp_fanout

@@ -114,10 +114,11 @@
 #include <sys/pattr.h>
 #include <inet/ipclassifier.h>
 #include <inet/sctp_ip.h>
 #include <inet/sctp/sctp_impl.h>
 #include <inet/udp_impl.h>
+#include <inet/dccp_impl.h>
 #include <sys/sunddi.h>
 
 #include <sys/tsol/label.h>
 #include <sys/tsol/tnet.h>
 

@@ -2387,10 +2388,13 @@
                 min_ulp_header_length = UDPH_SIZE;
                 break;
         case IPPROTO_ICMP:
                 min_ulp_header_length = ICMPH_SIZE;
                 break;
+        case IPPROTO_DCCP:
+                min_ulp_header_length = DCCP_MIN_HEADER_LENGTH;
+                break;
         default:
                 min_ulp_header_length = 0;
                 break;
         }
         /* Make sure we have the min ULP header length */

@@ -2712,10 +2716,73 @@
                 (connp->conn_recv)(connp, mp, NULL, ira);
                 CONN_DEC_REF(connp);
                 ira->ira_ill = ill;
                 ira->ira_rill = rill;
                 return;
+        case IPPROTO_DCCP:
+                /* For DCCP, discard broadcast and multicast packets */
+                if (iraflags & IRAF_MULTIBROADCAST) {
+                        goto discard;
+                }
+
+                /* First mblk contains IP+DCCP headers per above check */
+                ASSERT(len >= ip_hdr_length + DCCP_MIN_HEADER_LENGTH);
+
+                /* Squeue hint */
+                if (ira->ira_sqp == NULL) {
+                        ira->ira_sqp = ip_squeue_get(ira->ira_ring);
+                }
+
+                connp = ipcl_classify_v4(mp, IPPROTO_DCCP, ip_hdr_length,
+                    ira, ipst);
+                if (connp == NULL) {
+                        cmn_err(CE_NOTE, "ip_input.c: ip_fanout_v4 connp not found");
+                        /* Send the reset packet */
+                        BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCInDelivers);
+                        dccp_xmit_listeners_reset(mp, ira, ipst, NULL);
+                        return;
+                }
+
+                if (connp->conn_incoming_ifindex != 0 &&
+                    connp->conn_incoming_ifindex != ira->ira_ruifindex) {
+                        cmn_err(CE_NOTE, "ip_input.c: ip_fanout_v4 ifindex problem");
+                        /* Send the reset packet */
+                        BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCInDelivers);
+                        dccp_xmit_listeners_reset(mp, ira, ipst, NULL);
+                        return;
+                }
+
+                if (CONN_INBOUND_POLICY_PRESENT(connp, ipss) ||
+                    (iraflags & IRAF_IPSEC_SECURE)) {
+                        mp = ipsec_check_inbound_policy(mp, connp,
+                            ipha, NULL, ira);
+                        if (mp == NULL) {
+                                BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
+                                /* Note that mp is NULL */
+                                ip_drop_input("ipIfStatsInDiscards", mp, ill);
+                                CONN_DEC_REF(connp);
+                                return;
+                        }
+                }
+
+                /* Found a client; up it goes */
+                BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCInDelivers);
+                ira->ira_ill = ira->ira_rill = NULL;
+
+                /* XXX SOCK_RAW for DCCP? */
+
+                if (iraflags & IRAF_TARGET_SQP) {
+                        cmn_err(CE_NOTE, "IRAF_TARGET_SQP");
+                } else {
+                        SQUEUE_ENTER_ONE(connp->conn_sqp, mp, connp->conn_recv,
+                            connp, ira, ip_squeue_flag, SQTAG_IP_DCCP_INPUT);
+                }
+
+                ira->ira_ill = ill;
+                ira->ira_rill = rill;
+                return;
+
         default:
                 break;
         }
 
         /*