sctp: avoid identifying address family many times for a chunk
[cascardo/linux.git] / net / sctp / sm_make_chunk.c
index 56f364d..8c77b87 100644 (file)
@@ -108,14 +108,9 @@ static void sctp_control_set_owner_w(struct sctp_chunk *chunk)
 /* What was the inbound interface for this chunk? */
 int sctp_chunk_iif(const struct sctp_chunk *chunk)
 {
-       struct sctp_af *af;
-       int iif = 0;
-
-       af = sctp_get_af_specific(ipver2af(ip_hdr(chunk->skb)->version));
-       if (af)
-               iif = af->skb_iif(chunk->skb);
+       struct sk_buff *skb = chunk->skb;
 
-       return iif;
+       return SCTP_INPUT_CB(skb)->af->skb_iif(skb);
 }
 
 /* RFC 2960 3.3.2 Initiation (INIT) (1)
@@ -261,7 +256,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
        chunksize += WORD_ROUND(SCTP_SAT_LEN(num_types));
        chunksize += sizeof(ecap_param);
 
-       if (net->sctp.prsctp_enable)
+       if (asoc->prsctp_enable)
                chunksize += sizeof(prsctp_param);
 
        /* ADDIP: Section 4.2.7:
@@ -355,7 +350,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
                sctp_addto_param(retval, num_ext, extensions);
        }
 
-       if (net->sctp.prsctp_enable)
+       if (asoc->prsctp_enable)
                sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
 
        if (sp->adaptation_ind) {
@@ -711,6 +706,20 @@ nodata:
        return retval;
 }
 
+static void sctp_set_prsctp_policy(struct sctp_chunk *chunk,
+                                  const struct sctp_sndrcvinfo *sinfo)
+{
+       if (!chunk->asoc->prsctp_enable)
+               return;
+
+       if (SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags))
+               chunk->prsctp_param =
+                       jiffies + msecs_to_jiffies(sinfo->sinfo_timetolive);
+       else if (SCTP_PR_RTX_ENABLED(sinfo->sinfo_flags) ||
+                SCTP_PR_PRIO_ENABLED(sinfo->sinfo_flags))
+               chunk->prsctp_param = sinfo->sinfo_timetolive;
+}
+
 /* Make a DATA chunk for the given association from the provided
  * parameters.  However, do not populate the data payload.
  */
@@ -744,6 +753,7 @@ struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
 
        retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);
        memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));
+       sctp_set_prsctp_policy(retval, sinfo);
 
 nodata:
        return retval;
@@ -1585,7 +1595,6 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
        struct sctp_association *asoc;
        struct sk_buff *skb;
        sctp_scope_t scope;
-       struct sctp_af *af;
 
        /* Create the bare association.  */
        scope = sctp_scope(sctp_source(chunk));
@@ -1595,16 +1604,10 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
        asoc->temp = 1;
        skb = chunk->skb;
        /* Create an entry for the source address of the packet.  */
-       af = sctp_get_af_specific(ipver2af(ip_hdr(skb)->version));
-       if (unlikely(!af))
-               goto fail;
-       af->from_skb(&asoc->c.peer_addr, skb, 1);
+       SCTP_INPUT_CB(skb)->af->from_skb(&asoc->c.peer_addr, skb, 1);
+
 nodata:
        return asoc;
-
-fail:
-       sctp_association_free(asoc);
-       return NULL;
 }
 
 /* Build a cookie representing asoc.
@@ -2024,8 +2027,8 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
        for (i = 0; i < num_ext; i++) {
                switch (param.ext->chunks[i]) {
                case SCTP_CID_FWD_TSN:
-                       if (net->sctp.prsctp_enable && !asoc->peer.prsctp_capable)
-                                   asoc->peer.prsctp_capable = 1;
+                       if (asoc->prsctp_enable && !asoc->peer.prsctp_capable)
+                               asoc->peer.prsctp_capable = 1;
                        break;
                case SCTP_CID_AUTH:
                        /* if the peer reports AUTH, assume that he
@@ -2169,7 +2172,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net,
                break;
 
        case SCTP_PARAM_FWD_TSN_SUPPORT:
-               if (net->sctp.prsctp_enable)
+               if (ep->prsctp_enable)
                        break;
                goto fallthrough;
 
@@ -2653,7 +2656,7 @@ do_addr_param:
                break;
 
        case SCTP_PARAM_FWD_TSN_SUPPORT:
-               if (net->sctp.prsctp_enable) {
+               if (asoc->prsctp_enable) {
                        asoc->peer.prsctp_capable = 1;
                        break;
                }