Author: tuexen
Date: Thu Mar  7 21:08:19 2013
New Revision: 247941
URL: http://svnweb.freebsd.org/changeset/base/247941

Log:
  MFC r236956:
  
  Unify the sending of ABORT, SHUTDOWN-COMPLETE and ERROR chunks.
  While there: Fix also some minor bugs and prepare for SCTP/DTLS.

Modified:
  stable/8/sys/netinet/sctp_input.c
  stable/8/sys/netinet/sctp_output.c
  stable/8/sys/netinet/sctp_output.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/netinet/   (props changed)

Modified: stable/8/sys/netinet/sctp_input.c
==============================================================================
--- stable/8/sys/netinet/sctp_input.c   Thu Mar  7 20:48:36 2013        
(r247940)
+++ stable/8/sys/netinet/sctp_input.c   Thu Mar  7 21:08:19 2013        
(r247941)
@@ -1442,7 +1442,7 @@ sctp_process_cookie_existing(struct mbuf
                ph = mtod(op_err, struct sctp_paramhdr *);
                ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN);
                ph->param_length = htons(sizeof(struct sctp_paramhdr));
-               sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag,
+               sctp_send_operr_to(m, sh, cookie->peers_vtag, op_err,
                    vrf_id, net->port);
                if (how_indx < sizeof(asoc->cookie_how))
                        asoc->cookie_how[how_indx] = 2;
@@ -2570,7 +2570,7 @@ sctp_handle_cookie_echo(struct mbuf *m, 
                if (tim == 0)
                        tim = now.tv_usec - cookie->time_entered.tv_usec;
                scm->time_usec = htonl(tim);
-               sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag,
+               sctp_send_operr_to(m, sh, cookie->peers_vtag, op_err,
                    vrf_id, port);
                return (NULL);
        }

Modified: stable/8/sys/netinet/sctp_output.c
==============================================================================
--- stable/8/sys/netinet/sctp_output.c  Thu Mar  7 20:48:36 2013        
(r247940)
+++ stable/8/sys/netinet/sctp_output.c  Thu Mar  7 21:08:19 2013        
(r247941)
@@ -10854,19 +10854,20 @@ sctp_send_shutdown_complete(struct sctp_
        return;
 }
 
-void
-sctp_send_shutdown_complete2(struct mbuf *m, struct sctphdr *sh,
-    uint32_t vrf_id, uint16_t port)
+static void
+sctp_send_resp_msg(struct mbuf *m, struct sctphdr *sh, uint32_t vtag,
+    uint8_t type, struct mbuf *cause, uint32_t vrf_id, uint16_t port)
 {
-       /* formulate and SEND a SHUTDOWN-COMPLETE */
        struct mbuf *o_pak;
        struct mbuf *mout;
+       struct sctphdr *shout;
+       struct sctp_chunkhdr *ch;
        struct ip *iph;
-       struct udphdr *udp = NULL;
-       int offset_out, len, mlen;
-       struct sctp_shutdown_complete_msg *comp_cp;
+       struct udphdr *udp;
+       int len, cause_len, padding_len, ret;
 
 #ifdef INET
+       sctp_route_t ro;
        struct ip *iph_out;
 
 #endif
@@ -10875,31 +10876,59 @@ sctp_send_shutdown_complete2(struct mbuf
 
 #endif
 
+       /* Compute the length of the cause and add final padding. */
+       cause_len = 0;
+       if (cause != NULL) {
+               struct mbuf *m_at, *m_last = NULL;
+
+               for (m_at = cause; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
+                       if (SCTP_BUF_NEXT(m_at) == NULL)
+                               m_last = m_at;
+                       cause_len += SCTP_BUF_LEN(m_at);
+               }
+               padding_len = cause_len % 4;
+               if (padding_len != 0) {
+                       padding_len = 4 - padding_len;
+               }
+               if (padding_len != 0) {
+                       if (sctp_add_pad_tombuf(m_last, padding_len)) {
+                               sctp_m_freem(cause);
+                               return;
+                       }
+               }
+       } else {
+               padding_len = 0;
+       }
+       /* Get an mbuf for the header. */
+       len = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
        iph = mtod(m, struct ip *);
        switch (iph->ip_v) {
 #ifdef INET
        case IPVERSION:
-               len = (sizeof(struct ip) + sizeof(struct 
sctp_shutdown_complete_msg));
+               len += sizeof(struct ip);
                break;
 #endif
 #ifdef INET6
        case IPV6_VERSION >> 4:
-               len = (sizeof(struct ip6_hdr) + sizeof(struct 
sctp_shutdown_complete_msg));
+               len += sizeof(struct ip6_hdr);
                break;
 #endif
        default:
-               return;
+               break;
        }
        if (port) {
                len += sizeof(struct udphdr);
        }
        mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_DONTWAIT, 1, 
MT_DATA);
        if (mout == NULL) {
+               if (cause) {
+                       sctp_m_freem(cause);
+               }
                return;
        }
        SCTP_BUF_RESV_UF(mout, max_linkhdr);
        SCTP_BUF_LEN(mout) = len;
-       SCTP_BUF_NEXT(mout) = NULL;
+       SCTP_BUF_NEXT(mout) = cause;
        if (m->m_flags & M_FLOWID) {
                mout->m_pkthdr.flowid = m->m_pkthdr.flowid;
                mout->m_flags |= M_FLOWID;
@@ -10910,18 +10939,14 @@ sctp_send_shutdown_complete2(struct mbuf
 #ifdef INET6
        ip6_out = NULL;
 #endif
-       offset_out = 0;
-
        switch (iph->ip_v) {
 #ifdef INET
        case IPVERSION:
                iph_out = mtod(mout, struct ip *);
-
-               /* Fill in the IP header for the ABORT */
                iph_out->ip_v = IPVERSION;
-               iph_out->ip_hl = (sizeof(struct ip) / 4);
-               iph_out->ip_tos = (u_char)0;
-               iph_out->ip_id = 0;
+               iph_out->ip_hl = (sizeof(struct ip) >> 2);
+               iph_out->ip_tos = 0;
+               iph_out->ip_id = ip_newid();
                iph_out->ip_off = 0;
                iph_out->ip_ttl = MODULE_GLOBAL(ip_defttl);
                if (port) {
@@ -10931,21 +10956,19 @@ sctp_send_shutdown_complete2(struct mbuf
                }
                iph_out->ip_src.s_addr = iph->ip_dst.s_addr;
                iph_out->ip_dst.s_addr = iph->ip_src.s_addr;
-
-               /* let IP layer calculate this */
                iph_out->ip_sum = 0;
-               offset_out += sizeof(*iph_out);
-               comp_cp = (struct sctp_shutdown_complete_msg *)(
-                   (caddr_t)iph_out + offset_out);
+               len = sizeof(struct ip);
+               shout = (struct sctphdr *)((caddr_t)iph_out + len);
                break;
 #endif
 #ifdef INET6
        case IPV6_VERSION >> 4:
                ip6 = (struct ip6_hdr *)iph;
                ip6_out = mtod(mout, struct ip6_hdr *);
-
-               /* Fill in the IPv6 header for the ABORT */
-               ip6_out->ip6_flow = ip6->ip6_flow;
+               ip6_out->ip6_flow = htonl(0x60000000);
+               if (V_ip6_auto_flowlabel) {
+                       ip6_out->ip6_flow |= (htonl(ip6_randomflowlabel()) & 
IPV6_FLOWLABEL_MASK);
+               }
                ip6_out->ip6_hlim = MODULE_GLOBAL(ip6_defhlim);
                if (port) {
                        ip6_out->ip6_nxt = IPPROTO_UDP;
@@ -10954,78 +10977,84 @@ sctp_send_shutdown_complete2(struct mbuf
                }
                ip6_out->ip6_src = ip6->ip6_dst;
                ip6_out->ip6_dst = ip6->ip6_src;
-               /*
-                * ?? The old code had both the iph len + payload, I think
-                * this is wrong and would never have worked
-                */
-               ip6_out->ip6_plen = sizeof(struct sctp_shutdown_complete_msg);
-               offset_out += sizeof(*ip6_out);
-               comp_cp = (struct sctp_shutdown_complete_msg *)(
-                   (caddr_t)ip6_out + offset_out);
+               len = sizeof(struct ip6_hdr);
+               shout = (struct sctphdr *)((caddr_t)ip6_out + len);
                break;
-#endif                         /* INET6 */
+#endif
        default:
-               /* Currently not supported. */
-               sctp_m_freem(mout);
-               return;
+               len = 0;
+               shout = mtod(mout, struct sctphdr *);
+               break;
        }
        if (port) {
                if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
                        sctp_m_freem(mout);
                        return;
                }
-               udp = (struct udphdr *)comp_cp;
+               udp = (struct udphdr *)shout;
                udp->uh_sport = 
htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
                udp->uh_dport = port;
-               udp->uh_ulen = htons(sizeof(struct sctp_shutdown_complete_msg) 
+ sizeof(struct udphdr));
-#ifdef INET
-               if (iph_out) {
-                       if (V_udp_cksum) {
-                               udp->uh_sum = in_pseudo(iph_out->ip_src.s_addr, 
iph_out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
-                       } else {
-                               udp->uh_sum = 0;
-                       }
-               }
-#endif
-               offset_out += sizeof(struct udphdr);
-               comp_cp = (struct sctp_shutdown_complete_msg 
*)((caddr_t)comp_cp + sizeof(struct udphdr));
+               udp->uh_sum = 0;
+               udp->uh_ulen = htons(sizeof(struct udphdr) +
+                   sizeof(struct sctphdr) +
+                   sizeof(struct sctp_chunkhdr) +
+                   cause_len + padding_len);
+               len += sizeof(struct udphdr);
+               shout = (struct sctphdr *)((caddr_t)shout + sizeof(struct 
udphdr));
+       } else {
+               udp = NULL;
        }
+       shout->src_port = sh->dest_port;
+       shout->dest_port = sh->src_port;
+       shout->checksum = 0;
+       if (vtag) {
+               shout->v_tag = htonl(vtag);
+       } else {
+               shout->v_tag = sh->v_tag;
+       }
+       len += sizeof(struct sctphdr);
+       ch = (struct sctp_chunkhdr *)((caddr_t)shout + sizeof(struct sctphdr));
+       ch->chunk_type = type;
+       if (vtag) {
+               ch->chunk_flags = 0;
+       } else {
+               ch->chunk_flags = SCTP_HAD_NO_TCB;
+       }
+       ch->chunk_length = htons(sizeof(struct sctp_chunkhdr) + cause_len);
+       len += sizeof(struct sctp_chunkhdr);
+       len += cause_len + padding_len;
+
        if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
-               /* no mbuf's */
                sctp_m_freem(mout);
                return;
        }
-       /* Now copy in and fill in the ABORT tags etc. */
-       comp_cp->sh.src_port = sh->dest_port;
-       comp_cp->sh.dest_port = sh->src_port;
-       comp_cp->sh.checksum = 0;
-       comp_cp->sh.v_tag = sh->v_tag;
-       comp_cp->shut_cmp.ch.chunk_flags = SCTP_HAD_NO_TCB;
-       comp_cp->shut_cmp.ch.chunk_type = SCTP_SHUTDOWN_COMPLETE;
-       comp_cp->shut_cmp.ch.chunk_length = htons(sizeof(struct 
sctp_shutdown_complete_chunk));
-
+       SCTP_ATTACH_CHAIN(o_pak, mout, len);
 #ifdef INET
        if (iph_out != NULL) {
-               sctp_route_t ro;
-               int ret;
-
-               mlen = SCTP_BUF_LEN(mout);
-               bzero(&ro, sizeof ro);
-               /* set IPv4 length */
-               iph_out->ip_len = mlen;
-#ifdef  SCTP_PACKET_LOGGING
-               if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_LAST_PACKET_TRACING)
-                       sctp_packet_log(mout, mlen);
+               /* zap the stack pointer to the route */
+               bzero(&ro, sizeof(sctp_route_t));
+               if (port) {
+                       if (V_udp_cksum) {
+                               udp->uh_sum = in_pseudo(iph_out->ip_src.s_addr, 
iph_out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
+                       } else {
+                               udp->uh_sum = 0;
+                       }
+               }
+               iph_out->ip_len = len;
+#ifdef SCTP_PACKET_LOGGING
+               if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_LAST_PACKET_TRACING) {
+                       sctp_packet_log(mout, len);
+               }
 #endif
                if (port) {
 #if defined(SCTP_WITH_NO_CSUM)
                        SCTP_STAT_INCR(sctps_sendnocrc);
 #else
-                       comp_cp->sh.checksum = sctp_calculate_cksum(mout, 
offset_out);
+                       shout->checksum = sctp_calculate_cksum(mout, 
sizeof(struct ip) + sizeof(struct udphdr));
                        SCTP_STAT_INCR(sctps_sendswcrc);
 #endif
                        if (V_udp_cksum) {
-                               SCTP_ENABLE_UDP_CSUM(mout);
+                               SCTP_ENABLE_UDP_CSUM(o_pak);
                        }
                } else {
 #if defined(SCTP_WITH_NO_CSUM)
@@ -11036,33 +11065,29 @@ sctp_send_shutdown_complete2(struct mbuf
                        SCTP_STAT_INCR(sctps_sendhwcrc);
 #endif
                }
-               SCTP_ATTACH_CHAIN(o_pak, mout, mlen);
-               /* out it goes */
                SCTP_IP_OUTPUT(ret, o_pak, &ro, NULL, vrf_id);
-
                /* Free the route if we got one back */
-               if (ro.ro_rt)
+               if (ro.ro_rt) {
                        RTFREE(ro.ro_rt);
+               }
        }
 #endif
 #ifdef INET6
        if (ip6_out != NULL) {
-               int ret;
-
-               mlen = SCTP_BUF_LEN(mout);
+               ip6_out->ip6_plen = len - sizeof(struct ip6_hdr);
 #ifdef  SCTP_PACKET_LOGGING
-               if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_LAST_PACKET_TRACING)
-                       sctp_packet_log(mout, mlen);
+               if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_LAST_PACKET_TRACING) {
+                       sctp_packet_log(mout, len);
+               }
 #endif
-               SCTP_ATTACH_CHAIN(o_pak, mout, mlen);
                if (port) {
 #if defined(SCTP_WITH_NO_CSUM)
                        SCTP_STAT_INCR(sctps_sendnocrc);
 #else
-                       comp_cp->sh.checksum = sctp_calculate_cksum(mout, 
sizeof(struct ip6_hdr) + sizeof(struct udphdr));
+                       shout->checksum = sctp_calculate_cksum(mout, 
sizeof(struct ip6_hdr) + sizeof(struct udphdr));
                        SCTP_STAT_INCR(sctps_sendswcrc);
 #endif
-                       if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, 
sizeof(struct ip6_hdr), mlen - sizeof(struct ip6_hdr))) == 0) {
+                       if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, 
sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) {
                                udp->uh_sum = 0xffff;
                        }
                } else {
@@ -11081,7 +11106,13 @@ sctp_send_shutdown_complete2(struct mbuf
        SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
        SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
        return;
+}
 
+void
+sctp_send_shutdown_complete2(struct mbuf *m, struct sctphdr *sh,
+    uint32_t vrf_id, uint16_t port)
+{
+       sctp_send_resp_msg(m, sh, 0, SCTP_SHUTDOWN_COMPLETE, NULL, vrf_id, 
port);
 }
 
 void
@@ -11913,528 +11944,24 @@ skip_stuff:
 
 void
 sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
-    struct mbuf *err_cause, uint32_t vrf_id, uint16_t port)
+    struct mbuf *cause, uint32_t vrf_id, uint16_t port)
 {
-       /*-
-        * Formulate the abort message, and send it back down.
-        */
-       struct mbuf *o_pak;
-       struct mbuf *mout;
-       struct sctp_abort_msg *abm;
-       struct ip *iph;
-       struct udphdr *udp;
-       int iphlen_out, len;
-
-#ifdef INET
-       struct ip *iph_out;
-
-#endif
-#ifdef INET6
-       struct ip6_hdr *ip6, *ip6_out;
-
-#endif
-
-       /* don't respond to ABORT with ABORT */
+       /* Don't respond to an ABORT with an ABORT. */
        if (sctp_is_there_an_abort_here(m, iphlen, &vtag)) {
-               if (err_cause)
-                       sctp_m_freem(err_cause);
-               return;
-       }
-       iph = mtod(m, struct ip *);
-       switch (iph->ip_v) {
-#ifdef INET
-       case IPVERSION:
-               len = (sizeof(struct ip) + sizeof(struct sctp_abort_msg));
-               break;
-#endif
-#ifdef INET6
-       case IPV6_VERSION >> 4:
-               len = (sizeof(struct ip6_hdr) + sizeof(struct sctp_abort_msg));
-               break;
-#endif
-       default:
-               if (err_cause) {
-                       sctp_m_freem(err_cause);
-               }
-               return;
-       }
-       if (port) {
-               len += sizeof(struct udphdr);
-       }
-       mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_DONTWAIT, 1, 
MT_DATA);
-       if (mout == NULL) {
-               if (err_cause) {
-                       sctp_m_freem(err_cause);
-               }
+               if (cause)
+                       sctp_m_freem(cause);
                return;
        }
-       SCTP_BUF_RESV_UF(mout, max_linkhdr);
-       SCTP_BUF_LEN(mout) = len;
-       SCTP_BUF_NEXT(mout) = err_cause;
-       if (m->m_flags & M_FLOWID) {
-               mout->m_pkthdr.flowid = m->m_pkthdr.flowid;
-               mout->m_flags |= M_FLOWID;
-       }
-#ifdef INET
-       iph_out = NULL;
-#endif
-#ifdef INET6
-       ip6_out = NULL;
-#endif
-       switch (iph->ip_v) {
-#ifdef INET
-       case IPVERSION:
-               iph_out = mtod(mout, struct ip *);
-
-               /* Fill in the IP header for the ABORT */
-               iph_out->ip_v = IPVERSION;
-               iph_out->ip_hl = (sizeof(struct ip) / 4);
-               iph_out->ip_tos = (u_char)0;
-               iph_out->ip_id = 0;
-               iph_out->ip_off = 0;
-               iph_out->ip_ttl = MODULE_GLOBAL(ip_defttl);
-               if (port) {
-                       iph_out->ip_p = IPPROTO_UDP;
-               } else {
-                       iph_out->ip_p = IPPROTO_SCTP;
-               }
-               iph_out->ip_src.s_addr = iph->ip_dst.s_addr;
-               iph_out->ip_dst.s_addr = iph->ip_src.s_addr;
-               /* let IP layer calculate this */
-               iph_out->ip_sum = 0;
-
-               iphlen_out = sizeof(*iph_out);
-               abm = (struct sctp_abort_msg *)((caddr_t)iph_out + iphlen_out);
-               break;
-#endif
-#ifdef INET6
-       case IPV6_VERSION >> 4:
-               ip6 = (struct ip6_hdr *)iph;
-               ip6_out = mtod(mout, struct ip6_hdr *);
-
-               /* Fill in the IP6 header for the ABORT */
-               ip6_out->ip6_flow = ip6->ip6_flow;
-               ip6_out->ip6_hlim = MODULE_GLOBAL(ip6_defhlim);
-               if (port) {
-                       ip6_out->ip6_nxt = IPPROTO_UDP;
-               } else {
-                       ip6_out->ip6_nxt = IPPROTO_SCTP;
-               }
-               ip6_out->ip6_src = ip6->ip6_dst;
-               ip6_out->ip6_dst = ip6->ip6_src;
-
-               iphlen_out = sizeof(*ip6_out);
-               abm = (struct sctp_abort_msg *)((caddr_t)ip6_out + iphlen_out);
-               break;
-#endif                         /* INET6 */
-       default:
-               /* Currently not supported */
-               sctp_m_freem(mout);
-               return;
-       }
-
-       udp = (struct udphdr *)abm;
-       if (port) {
-               if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
-                       sctp_m_freem(mout);
-                       return;
-               }
-               udp->uh_sport = 
htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
-               udp->uh_dport = port;
-               /* set udp->uh_ulen later */
-               udp->uh_sum = 0;
-               iphlen_out += sizeof(struct udphdr);
-               abm = (struct sctp_abort_msg *)((caddr_t)abm + sizeof(struct 
udphdr));
-       }
-       abm->sh.src_port = sh->dest_port;
-       abm->sh.dest_port = sh->src_port;
-       abm->sh.checksum = 0;
-       if (vtag == 0) {
-               abm->sh.v_tag = sh->v_tag;
-               abm->msg.ch.chunk_flags = SCTP_HAD_NO_TCB;
-       } else {
-               abm->sh.v_tag = htonl(vtag);
-               abm->msg.ch.chunk_flags = 0;
-       }
-       abm->msg.ch.chunk_type = SCTP_ABORT_ASSOCIATION;
-
-       if (err_cause) {
-               struct mbuf *m_tmp = err_cause;
-               int err_len = 0;
-
-               /* get length of the err_cause chain */
-               while (m_tmp != NULL) {
-                       err_len += SCTP_BUF_LEN(m_tmp);
-                       m_tmp = SCTP_BUF_NEXT(m_tmp);
-               }
-               len = SCTP_BUF_LEN(mout) + err_len;
-               if (err_len % 4) {
-                       /* need pad at end of chunk */
-                       uint32_t cpthis = 0;
-                       int padlen;
-
-                       padlen = 4 - (len % 4);
-                       m_copyback(mout, len, padlen, (caddr_t)&cpthis);
-                       len += padlen;
-               }
-               abm->msg.ch.chunk_length = htons(sizeof(abm->msg.ch) + err_len);
-       } else {
-               len = SCTP_BUF_LEN(mout);
-               abm->msg.ch.chunk_length = htons(sizeof(abm->msg.ch));
-       }
-
-       if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
-               /* no mbuf's */
-               sctp_m_freem(mout);
-               return;
-       }
-#ifdef INET
-       if (iph_out != NULL) {
-               sctp_route_t ro;
-               int ret;
-
-               /* zap the stack pointer to the route */
-               bzero(&ro, sizeof ro);
-               if (port) {
-                       udp->uh_ulen = htons(len - sizeof(struct ip));
-                       if (V_udp_cksum) {
-                               udp->uh_sum = in_pseudo(iph_out->ip_src.s_addr, 
iph_out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
-                       } else {
-                               udp->uh_sum = 0;
-                       }
-               }
-               SCTPDBG(SCTP_DEBUG_OUTPUT2, "sctp_send_abort calling 
ip_output:\n");
-               SCTPDBG_PKT(SCTP_DEBUG_OUTPUT2, iph_out, &abm->sh);
-               /* set IPv4 length */
-               iph_out->ip_len = len;
-               /* out it goes */
-#ifdef  SCTP_PACKET_LOGGING
-               if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_LAST_PACKET_TRACING)
-                       sctp_packet_log(mout, len);
-#endif
-               SCTP_ATTACH_CHAIN(o_pak, mout, len);
-               if (port) {
-#if defined(SCTP_WITH_NO_CSUM)
-                       SCTP_STAT_INCR(sctps_sendnocrc);
-#else
-                       abm->sh.checksum = sctp_calculate_cksum(mout, 
iphlen_out);
-                       SCTP_STAT_INCR(sctps_sendswcrc);
-#endif
-                       if (V_udp_cksum) {
-                               SCTP_ENABLE_UDP_CSUM(o_pak);
-                       }
-               } else {
-#if defined(SCTP_WITH_NO_CSUM)
-                       SCTP_STAT_INCR(sctps_sendnocrc);
-#else
-                       mout->m_pkthdr.csum_flags = CSUM_SCTP;
-                       mout->m_pkthdr.csum_data = 0;
-                       SCTP_STAT_INCR(sctps_sendhwcrc);
-#endif
-               }
-               SCTP_IP_OUTPUT(ret, o_pak, &ro, NULL, vrf_id);
-
-               /* Free the route if we got one back */
-               if (ro.ro_rt)
-                       RTFREE(ro.ro_rt);
-       }
-#endif
-#ifdef INET6
-       if (ip6_out != NULL) {
-               int ret;
-
-               if (port) {
-                       udp->uh_ulen = htons(len - sizeof(struct ip6_hdr));
-               }
-               SCTPDBG(SCTP_DEBUG_OUTPUT2, "sctp_send_abort calling 
ip6_output:\n");
-               SCTPDBG_PKT(SCTP_DEBUG_OUTPUT2, (struct ip *)ip6_out, &abm->sh);
-               ip6_out->ip6_plen = len - sizeof(*ip6_out);
-#ifdef  SCTP_PACKET_LOGGING
-               if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_LAST_PACKET_TRACING)
-                       sctp_packet_log(mout, len);
-#endif
-               SCTP_ATTACH_CHAIN(o_pak, mout, len);
-               if (port) {
-#if defined(SCTP_WITH_NO_CSUM)
-                       SCTP_STAT_INCR(sctps_sendnocrc);
-#else
-                       abm->sh.checksum = sctp_calculate_cksum(mout, 
sizeof(struct ip6_hdr) + sizeof(struct udphdr));
-                       SCTP_STAT_INCR(sctps_sendswcrc);
-#endif
-                       if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, 
sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) {
-                               udp->uh_sum = 0xffff;
-                       }
-               } else {
-#if defined(SCTP_WITH_NO_CSUM)
-                       SCTP_STAT_INCR(sctps_sendnocrc);
-#else
-                       mout->m_pkthdr.csum_flags = CSUM_SCTP;
-                       mout->m_pkthdr.csum_data = 0;
-                       SCTP_STAT_INCR(sctps_sendhwcrc);
-#endif
-               }
-               SCTP_IP6_OUTPUT(ret, o_pak, NULL, NULL, NULL, vrf_id);
-       }
-#endif
-       SCTP_STAT_INCR(sctps_sendpackets);
-       SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
-       SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
+       sctp_send_resp_msg(m, sh, vtag, SCTP_ABORT_ASSOCIATION, cause, vrf_id, 
port);
+       return;
 }
 
 void
-sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag,
-    uint32_t vrf_id, uint16_t port)
+sctp_send_operr_to(struct mbuf *m, struct sctphdr *sh, uint32_t vtag,
+    struct mbuf *cause, uint32_t vrf_id, uint16_t port)
 {
-       struct mbuf *o_pak;
-       struct sctphdr *sh, *sh_out;
-       struct sctp_chunkhdr *ch;
-       struct ip *iph;
-       struct udphdr *udp = NULL;
-       struct mbuf *mout;
-       int iphlen_out, len;
-
-#ifdef INET
-       struct ip *iph_out;
-
-#endif
-#ifdef INET6
-       struct ip6_hdr *ip6, *ip6_out;
-
-#endif
-
-       iph = mtod(m, struct ip *);
-       sh = (struct sctphdr *)((caddr_t)iph + iphlen);
-       switch (iph->ip_v) {
-#ifdef INET
-       case IPVERSION:
-               len = (sizeof(struct ip) + sizeof(struct sctphdr) + 
sizeof(struct sctp_chunkhdr));
-               break;
-#endif
-#ifdef INET6
-       case IPV6_VERSION >> 4:
-               len = (sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + 
sizeof(struct sctp_chunkhdr));
-               break;
-#endif
-       default:
-               if (scm) {
-                       sctp_m_freem(scm);
-               }
-               return;
-       }
-       if (port) {
-               len += sizeof(struct udphdr);
-       }
-       mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_DONTWAIT, 1, 
MT_DATA);
-       if (mout == NULL) {
-               if (scm) {
-                       sctp_m_freem(scm);
-               }
-               return;
-       }
-       SCTP_BUF_RESV_UF(mout, max_linkhdr);
-       SCTP_BUF_LEN(mout) = len;
-       SCTP_BUF_NEXT(mout) = scm;
-       if (m->m_flags & M_FLOWID) {
-               mout->m_pkthdr.flowid = m->m_pkthdr.flowid;
-               mout->m_flags |= M_FLOWID;
-       }
-#ifdef INET
-       iph_out = NULL;
-#endif
-#ifdef INET6
-       ip6_out = NULL;
-#endif
-       switch (iph->ip_v) {
-#ifdef INET
-       case IPVERSION:
-               iph_out = mtod(mout, struct ip *);
-
-               /* Fill in the IP header for the ABORT */
-               iph_out->ip_v = IPVERSION;
-               iph_out->ip_hl = (sizeof(struct ip) / 4);
-               iph_out->ip_tos = (u_char)0;
-               iph_out->ip_id = 0;
-               iph_out->ip_off = 0;
-               iph_out->ip_ttl = MODULE_GLOBAL(ip_defttl);
-               if (port) {
-                       iph_out->ip_p = IPPROTO_UDP;
-               } else {
-                       iph_out->ip_p = IPPROTO_SCTP;
-               }
-               iph_out->ip_src.s_addr = iph->ip_dst.s_addr;
-               iph_out->ip_dst.s_addr = iph->ip_src.s_addr;
-               /* let IP layer calculate this */
-               iph_out->ip_sum = 0;
-
-               iphlen_out = sizeof(struct ip);
-               sh_out = (struct sctphdr *)((caddr_t)iph_out + iphlen_out);
-               break;
-#endif
-#ifdef INET6
-       case IPV6_VERSION >> 4:
-               ip6 = (struct ip6_hdr *)iph;
-               ip6_out = mtod(mout, struct ip6_hdr *);
-
-               /* Fill in the IP6 header for the ABORT */
-               ip6_out->ip6_flow = ip6->ip6_flow;
-               ip6_out->ip6_hlim = MODULE_GLOBAL(ip6_defhlim);
-               if (port) {
-                       ip6_out->ip6_nxt = IPPROTO_UDP;
-               } else {
-                       ip6_out->ip6_nxt = IPPROTO_SCTP;
-               }
-               ip6_out->ip6_src = ip6->ip6_dst;
-               ip6_out->ip6_dst = ip6->ip6_src;
-
-               iphlen_out = sizeof(struct ip6_hdr);
-               sh_out = (struct sctphdr *)((caddr_t)ip6_out + iphlen_out);
-               break;
-#endif                         /* INET6 */
-       default:
-               /* Currently not supported */
-               sctp_m_freem(mout);
-               return;
-       }
-
-       udp = (struct udphdr *)sh_out;
-       if (port) {
-               if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
-                       sctp_m_freem(mout);
-                       return;
-               }
-               udp->uh_sport = 
htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
-               udp->uh_dport = port;
-               /* set udp->uh_ulen later */
-               udp->uh_sum = 0;
-               iphlen_out += sizeof(struct udphdr);
-               sh_out = (struct sctphdr *)((caddr_t)udp + sizeof(struct 
udphdr));
-       }
-       sh_out->src_port = sh->dest_port;
-       sh_out->dest_port = sh->src_port;
-       sh_out->v_tag = vtag;
-       sh_out->checksum = 0;
-
-       ch = (struct sctp_chunkhdr *)((caddr_t)sh_out + sizeof(struct sctphdr));
-       ch->chunk_type = SCTP_OPERATION_ERROR;
-       ch->chunk_flags = 0;
-
-       if (scm) {
-               struct mbuf *m_tmp = scm;
-               int cause_len = 0;
-
-               /* get length of the err_cause chain */
-               while (m_tmp != NULL) {
-                       cause_len += SCTP_BUF_LEN(m_tmp);
-                       m_tmp = SCTP_BUF_NEXT(m_tmp);
-               }
-               len = SCTP_BUF_LEN(mout) + cause_len;
-               if (cause_len % 4) {
-                       /* need pad at end of chunk */
-                       uint32_t cpthis = 0;
-                       int padlen;
-
-                       padlen = 4 - (len % 4);
-                       m_copyback(mout, len, padlen, (caddr_t)&cpthis);
-                       len += padlen;
-               }
-               ch->chunk_length = htons(sizeof(struct sctp_chunkhdr) + 
cause_len);
-       } else {
-               len = SCTP_BUF_LEN(mout);
-               ch->chunk_length = htons(sizeof(struct sctp_chunkhdr));
-       }
-
-       if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
-               /* no mbuf's */
-               sctp_m_freem(mout);
-               return;
-       }
-#ifdef INET
-       if (iph_out != NULL) {
-               sctp_route_t ro;
-               int ret;
-
-               /* zap the stack pointer to the route */
-               bzero(&ro, sizeof ro);
-               if (port) {
-                       udp->uh_ulen = htons(len - sizeof(struct ip));
-                       if (V_udp_cksum) {
-                               udp->uh_sum = in_pseudo(iph_out->ip_src.s_addr, 
iph_out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
-                       } else {
-                               udp->uh_sum = 0;
-                       }
-               }
-               /* set IPv4 length */
-               iph_out->ip_len = len;
-               /* out it goes */
-#ifdef  SCTP_PACKET_LOGGING
-               if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_LAST_PACKET_TRACING)
-                       sctp_packet_log(mout, len);
-#endif
-               SCTP_ATTACH_CHAIN(o_pak, mout, len);
-               if (port) {
-#if defined(SCTP_WITH_NO_CSUM)
-                       SCTP_STAT_INCR(sctps_sendnocrc);
-#else
-                       sh_out->checksum = sctp_calculate_cksum(mout, 
iphlen_out);
-                       SCTP_STAT_INCR(sctps_sendswcrc);
-#endif
-                       if (V_udp_cksum) {
-                               SCTP_ENABLE_UDP_CSUM(o_pak);
-                       }
-               } else {
-#if defined(SCTP_WITH_NO_CSUM)
-                       SCTP_STAT_INCR(sctps_sendnocrc);
-#else
-                       mout->m_pkthdr.csum_flags = CSUM_SCTP;
-                       mout->m_pkthdr.csum_data = 0;
-                       SCTP_STAT_INCR(sctps_sendhwcrc);
-#endif
-               }
-               SCTP_IP_OUTPUT(ret, o_pak, &ro, NULL, vrf_id);
-
-               /* Free the route if we got one back */
-               if (ro.ro_rt)
-                       RTFREE(ro.ro_rt);
-       }
-#endif
-#ifdef INET6
-       if (ip6_out != NULL) {
-               int ret;
-
-               if (port) {
-                       udp->uh_ulen = htons(len - sizeof(struct ip6_hdr));
-               }
-               ip6_out->ip6_plen = len - sizeof(*ip6_out);
-#ifdef  SCTP_PACKET_LOGGING
-               if (SCTP_BASE_SYSCTL(sctp_logging_level) & 
SCTP_LAST_PACKET_TRACING)
-                       sctp_packet_log(mout, len);
-#endif
-               SCTP_ATTACH_CHAIN(o_pak, mout, len);
-               if (port) {
-#if defined(SCTP_WITH_NO_CSUM)
-                       SCTP_STAT_INCR(sctps_sendnocrc);
-#else
-                       sh_out->checksum = sctp_calculate_cksum(mout, 
sizeof(struct ip6_hdr) + sizeof(struct udphdr));
-                       SCTP_STAT_INCR(sctps_sendswcrc);
-#endif
-                       if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, 
sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) {
-                               udp->uh_sum = 0xffff;
-                       }
-               } else {
-#if defined(SCTP_WITH_NO_CSUM)
-                       SCTP_STAT_INCR(sctps_sendnocrc);
-#else
-                       mout->m_pkthdr.csum_flags = CSUM_SCTP;
-                       mout->m_pkthdr.csum_data = 0;
-                       SCTP_STAT_INCR(sctps_sendhwcrc);
-#endif
-               }
-               SCTP_IP6_OUTPUT(ret, o_pak, NULL, NULL, NULL, vrf_id);
-       }
-#endif
-       SCTP_STAT_INCR(sctps_sendpackets);
-       SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
-       SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
+       sctp_send_resp_msg(m, sh, vtag, SCTP_OPERATION_ERROR, cause, vrf_id, 
port);
+       return;
 }
 
 static struct mbuf *

Modified: stable/8/sys/netinet/sctp_output.h
==============================================================================
--- stable/8/sys/netinet/sctp_output.h  Thu Mar  7 20:48:36 2013        
(r247940)
+++ stable/8/sys/netinet/sctp_output.h  Thu Mar  7 21:08:19 2013        
(r247941)
@@ -204,7 +204,9 @@ void
 sctp_send_abort(struct mbuf *, int, struct sctphdr *, uint32_t,
     struct mbuf *, uint32_t, uint16_t);
 
-void sctp_send_operr_to(struct mbuf *, int, struct mbuf *, uint32_t, uint32_t, 
uint16_t);
+void 
+sctp_send_operr_to(struct mbuf *, struct sctphdr *, uint32_t,
+    struct mbuf *, uint32_t, uint16_t);
 
 #endif                         /* _KERNEL || __Userspace__ */
 
_______________________________________________
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