Commit bbd0d59809f923ea2b540cbd781b32110e249f6e

Authored by Vlad Yasevich
Committed by David S. Miller
1 parent 4cd57c8078

[SCTP]: Implement the receive and verification of AUTH chunk

This patch implements the receive path needed to process authenticated
chunks.  Add ability to process the AUTH chunk and handle edge cases
for authenticated COOKIE-ECHO as well.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 9 changed files with 374 additions and 13 deletions Side-by-side Diff

include/net/sctp/constants.h
... ... @@ -183,7 +183,9 @@
183 183 SCTP_IERROR_NO_DATA,
184 184 SCTP_IERROR_BAD_STREAM,
185 185 SCTP_IERROR_BAD_PORTS,
186   -
  186 + SCTP_IERROR_AUTH_BAD_HMAC,
  187 + SCTP_IERROR_AUTH_BAD_KEYID,
  188 + SCTP_IERROR_PROTO_VIOLATION,
187 189 } sctp_ierror_t;
188 190  
189 191  
include/net/sctp/sm.h
... ... @@ -143,6 +143,7 @@
143 143 sctp_state_fn_t sctp_sf_do_9_2_reshutack;
144 144 sctp_state_fn_t sctp_sf_eat_fwd_tsn;
145 145 sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast;
  146 +sctp_state_fn_t sctp_sf_eat_auth;
146 147  
147 148 /* Prototypes for primitive event state functions. */
148 149 sctp_state_fn_t sctp_sf_do_prm_asoc;
include/net/sctp/structs.h
... ... @@ -724,6 +724,13 @@
724 724 */
725 725 struct sctp_transport *transport;
726 726  
  727 + /* SCTP-AUTH: For the special case inbound processing of COOKIE-ECHO
  728 + * we need save a pointer to the AUTH chunk, since the SCTP-AUTH
  729 + * spec violates the principle premis that all chunks are processed
  730 + * in order.
  731 + */
  732 + struct sk_buff *auth_chunk;
  733 +
727 734 __u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */
728 735 __u8 resent; /* Has this chunk ever been retransmitted. */
729 736 __u8 has_tsn; /* Does this chunk have a TSN yet? */
... ... @@ -1067,6 +1074,7 @@
1067 1074 void sctp_inq_free(struct sctp_inq *);
1068 1075 void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet);
1069 1076 struct sctp_chunk *sctp_inq_pop(struct sctp_inq *);
  1077 +struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *);
1070 1078 void sctp_inq_set_th_handler(struct sctp_inq *, work_func_t);
1071 1079  
1072 1080 /* This is the structure we use to hold outbound chunks. You push
net/sctp/associola.c
... ... @@ -1011,6 +1011,16 @@
1011 1011 state = asoc->state;
1012 1012 subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
1013 1013  
  1014 + /* SCTP-AUTH, Section 6.3:
  1015 + * The receiver has a list of chunk types which it expects
  1016 + * to be received only after an AUTH-chunk. This list has
  1017 + * been sent to the peer during the association setup. It
  1018 + * MUST silently discard these chunks if they are not placed
  1019 + * after an AUTH chunk in the packet.
  1020 + */
  1021 + if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth)
  1022 + continue;
  1023 +
1014 1024 /* Remember where the last DATA chunk came from so we
1015 1025 * know where to send the SACK.
1016 1026 */
net/sctp/endpointola.c
... ... @@ -400,6 +400,7 @@
400 400 sctp_subtype_t subtype;
401 401 sctp_state_t state;
402 402 int error = 0;
  403 + int first_time = 1; /* is this the first time through the looop */
403 404  
404 405 if (ep->base.dead)
405 406 return;
... ... @@ -411,6 +412,29 @@
411 412 while (NULL != (chunk = sctp_inq_pop(inqueue))) {
412 413 subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
413 414  
  415 + /* If the first chunk in the packet is AUTH, do special
  416 + * processing specified in Section 6.3 of SCTP-AUTH spec
  417 + */
  418 + if (first_time && (subtype.chunk == SCTP_CID_AUTH)) {
  419 + struct sctp_chunkhdr *next_hdr;
  420 +
  421 + next_hdr = sctp_inq_peek(inqueue);
  422 + if (!next_hdr)
  423 + goto normal;
  424 +
  425 + /* If the next chunk is COOKIE-ECHO, skip the AUTH
  426 + * chunk while saving a pointer to it so we can do
  427 + * Authentication later (during cookie-echo
  428 + * processing).
  429 + */
  430 + if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
  431 + chunk->auth_chunk = skb_clone(chunk->skb,
  432 + GFP_ATOMIC);
  433 + chunk->auth = 1;
  434 + continue;
  435 + }
  436 + }
  437 +normal:
414 438 /* We might have grown an association since last we
415 439 * looked, so try again.
416 440 *
... ... @@ -426,6 +450,8 @@
426 450 }
427 451  
428 452 state = asoc ? asoc->state : SCTP_STATE_CLOSED;
  453 + if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth)
  454 + continue;
429 455  
430 456 /* Remember where the last DATA chunk came from so we
431 457 * know where to send the SACK.
... ... @@ -449,6 +475,9 @@
449 475 */
450 476 if (!sctp_sk(sk)->ep)
451 477 break;
  478 +
  479 + if (first_time)
  480 + first_time = 0;
452 481 }
453 482 }
... ... @@ -911,15 +911,6 @@
911 911  
912 912 ch = (sctp_chunkhdr_t *) skb->data;
913 913  
914   - /* If this is INIT/INIT-ACK look inside the chunk too. */
915   - switch (ch->type) {
916   - case SCTP_CID_INIT:
917   - case SCTP_CID_INIT_ACK:
918   - break;
919   - default:
920   - return NULL;
921   - }
922   -
923 914 /* The code below will attempt to walk the chunk and extract
924 915 * parameter information. Before we do that, we need to verify
925 916 * that the chunk length doesn't cause overflow. Otherwise, we'll
... ... @@ -964,6 +955,60 @@
964 955 return NULL;
965 956 }
966 957  
  958 +/* SCTP-AUTH, Section 6.3:
  959 +* If the receiver does not find a STCB for a packet containing an AUTH
  960 +* chunk as the first chunk and not a COOKIE-ECHO chunk as the second
  961 +* chunk, it MUST use the chunks after the AUTH chunk to look up an existing
  962 +* association.
  963 +*
  964 +* This means that any chunks that can help us identify the association need
  965 +* to be looked at to find this assocation.
  966 +*
  967 +* TODO: The only chunk currently defined that can do that is ASCONF, but we
  968 +* don't support that functionality yet.
  969 +*/
  970 +static struct sctp_association *__sctp_rcv_auth_lookup(struct sk_buff *skb,
  971 + const union sctp_addr *paddr,
  972 + const union sctp_addr *laddr,
  973 + struct sctp_transport **transportp)
  974 +{
  975 + /* XXX - walk through the chunks looking for something that can
  976 + * help us find the association. INIT, and INIT-ACK are not permitted.
  977 + * That leaves ASCONF, but we don't support that yet.
  978 + */
  979 + return NULL;
  980 +}
  981 +
  982 +/*
  983 + * There are circumstances when we need to look inside the SCTP packet
  984 + * for information to help us find the association. Examples
  985 + * include looking inside of INIT/INIT-ACK chunks or after the AUTH
  986 + * chunks.
  987 + */
  988 +static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
  989 + const union sctp_addr *paddr,
  990 + const union sctp_addr *laddr,
  991 + struct sctp_transport **transportp)
  992 +{
  993 + sctp_chunkhdr_t *ch;
  994 +
  995 + ch = (sctp_chunkhdr_t *) skb->data;
  996 +
  997 + /* If this is INIT/INIT-ACK look inside the chunk too. */
  998 + switch (ch->type) {
  999 + case SCTP_CID_INIT:
  1000 + case SCTP_CID_INIT_ACK:
  1001 + return __sctp_rcv_init_lookup(skb, laddr, transportp);
  1002 + break;
  1003 +
  1004 + case SCTP_CID_AUTH:
  1005 + return __sctp_rcv_auth_lookup(skb, paddr, laddr, transportp);
  1006 + break;
  1007 + }
  1008 +
  1009 + return NULL;
  1010 +}
  1011 +
967 1012 /* Lookup an association for an inbound skb. */
968 1013 static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
969 1014 const union sctp_addr *paddr,
... ... @@ -979,7 +1024,7 @@
979 1024 * parameters within the INIT or INIT-ACK.
980 1025 */
981 1026 if (!asoc)
982   - asoc = __sctp_rcv_init_lookup(skb, laddr, transportp);
  1027 + asoc = __sctp_rcv_lookup_harder(skb, paddr, laddr, transportp);
983 1028  
984 1029 return asoc;
985 1030 }
... ... @@ -100,6 +100,25 @@
100 100 q->immediate.func(&q->immediate);
101 101 }
102 102  
  103 +/* Peek at the next chunk on the inqeue. */
  104 +struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *queue)
  105 +{
  106 + struct sctp_chunk *chunk;
  107 + sctp_chunkhdr_t *ch = NULL;
  108 +
  109 + chunk = queue->in_progress;
  110 + /* If there is no more chunks in this packet, say so */
  111 + if (chunk->singleton ||
  112 + chunk->end_of_packet ||
  113 + chunk->pdiscard)
  114 + return NULL;
  115 +
  116 + ch = (sctp_chunkhdr_t *)chunk->chunk_end;
  117 +
  118 + return ch;
  119 +}
  120 +
  121 +
103 122 /* Extract a chunk from an SCTP inqueue.
104 123 *
105 124 * WARNING: If you need to put the chunk on another queue, you need to
net/sctp/sm_statefuns.c
... ... @@ -138,6 +138,11 @@
138 138 void *arg,
139 139 sctp_cmd_seq_t *commands);
140 140  
  141 +static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep,
  142 + const struct sctp_association *asoc,
  143 + const sctp_subtype_t type,
  144 + struct sctp_chunk *chunk);
  145 +
141 146 /* Small helper function that checks if the chunk length
142 147 * is of the appropriate length. The 'required_length' argument
143 148 * is set to be the size of a specific chunk we are testing.
... ... @@ -495,8 +500,6 @@
495 500 (sctp_init_chunk_t *)chunk->chunk_hdr, chunk,
496 501 &err_chunk)) {
497 502  
498   - SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
499   -
500 503 /* This chunk contains fatal error. It is to be discarded.
501 504 * Send an ABORT, with causes if there is any.
502 505 */
... ... @@ -521,6 +524,22 @@
521 524 sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
522 525 error = SCTP_ERROR_INV_PARAM;
523 526 }
  527 +
  528 + /* SCTP-AUTH, Section 6.3:
  529 + * It should be noted that if the receiver wants to tear
  530 + * down an association in an authenticated way only, the
  531 + * handling of malformed packets should not result in
  532 + * tearing down the association.
  533 + *
  534 + * This means that if we only want to abort associations
  535 + * in an authenticated way (i.e AUTH+ABORT), then we
  536 + * can't destory this association just becuase the packet
  537 + * was malformed.
  538 + */
  539 + if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
  540 + return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
  541 +
  542 + SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
524 543 return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,
525 544 asoc, chunk->transport);
526 545 }
... ... @@ -699,6 +718,36 @@
699 718 if (error)
700 719 goto nomem_init;
701 720  
  721 + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo
  722 + * is supposed to be authenticated and we have to do delayed
  723 + * authentication. We've just recreated the association using
  724 + * the information in the cookie and now it's much easier to
  725 + * do the authentication.
  726 + */
  727 + if (chunk->auth_chunk) {
  728 + struct sctp_chunk auth;
  729 + sctp_ierror_t ret;
  730 +
  731 + /* set-up our fake chunk so that we can process it */
  732 + auth.skb = chunk->auth_chunk;
  733 + auth.asoc = chunk->asoc;
  734 + auth.sctp_hdr = chunk->sctp_hdr;
  735 + auth.chunk_hdr = (sctp_chunkhdr_t *)skb_push(chunk->auth_chunk,
  736 + sizeof(sctp_chunkhdr_t));
  737 + skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t));
  738 + auth.transport = chunk->transport;
  739 +
  740 + ret = sctp_sf_authenticate(ep, new_asoc, type, &auth);
  741 +
  742 + /* We can now safely free the auth_chunk clone */
  743 + kfree_skb(chunk->auth_chunk);
  744 +
  745 + if (ret != SCTP_IERROR_NO_ERROR) {
  746 + sctp_association_free(new_asoc);
  747 + return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
  748 + }
  749 + }
  750 +
702 751 repl = sctp_make_cookie_ack(new_asoc, chunk);
703 752 if (!repl)
704 753 goto nomem_init;
... ... @@ -3653,6 +3702,156 @@
3653 3702 }
3654 3703  
3655 3704 /*
  3705 + * SCTP-AUTH Section 6.3 Receving authenticated chukns
  3706 + *
  3707 + * The receiver MUST use the HMAC algorithm indicated in the HMAC
  3708 + * Identifier field. If this algorithm was not specified by the
  3709 + * receiver in the HMAC-ALGO parameter in the INIT or INIT-ACK chunk
  3710 + * during association setup, the AUTH chunk and all chunks after it MUST
  3711 + * be discarded and an ERROR chunk SHOULD be sent with the error cause
  3712 + * defined in Section 4.1.
  3713 + *
  3714 + * If an endpoint with no shared key receives a Shared Key Identifier
  3715 + * other than 0, it MUST silently discard all authenticated chunks. If
  3716 + * the endpoint has at least one endpoint pair shared key for the peer,
  3717 + * it MUST use the key specified by the Shared Key Identifier if a
  3718 + * key has been configured for that Shared Key Identifier. If no
  3719 + * endpoint pair shared key has been configured for that Shared Key
  3720 + * Identifier, all authenticated chunks MUST be silently discarded.
  3721 + *
  3722 + * Verification Tag: 8.5 Verification Tag [Normal verification]
  3723 + *
  3724 + * The return value is the disposition of the chunk.
  3725 + */
  3726 +static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep,
  3727 + const struct sctp_association *asoc,
  3728 + const sctp_subtype_t type,
  3729 + struct sctp_chunk *chunk)
  3730 +{
  3731 + struct sctp_authhdr *auth_hdr;
  3732 + struct sctp_hmac *hmac;
  3733 + unsigned int sig_len;
  3734 + __u16 key_id;
  3735 + __u8 *save_digest;
  3736 + __u8 *digest;
  3737 +
  3738 + /* Pull in the auth header, so we can do some more verification */
  3739 + auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
  3740 + chunk->subh.auth_hdr = auth_hdr;
  3741 + skb_pull(chunk->skb, sizeof(struct sctp_authhdr));
  3742 +
  3743 + /* Make sure that we suport the HMAC algorithm from the auth
  3744 + * chunk.
  3745 + */
  3746 + if (!sctp_auth_asoc_verify_hmac_id(asoc, auth_hdr->hmac_id))
  3747 + return SCTP_IERROR_AUTH_BAD_HMAC;
  3748 +
  3749 + /* Make sure that the provided shared key identifier has been
  3750 + * configured
  3751 + */
  3752 + key_id = ntohs(auth_hdr->shkey_id);
  3753 + if (key_id != asoc->active_key_id && !sctp_auth_get_shkey(asoc, key_id))
  3754 + return SCTP_IERROR_AUTH_BAD_KEYID;
  3755 +
  3756 +
  3757 + /* Make sure that the length of the signature matches what
  3758 + * we expect.
  3759 + */
  3760 + sig_len = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_auth_chunk_t);
  3761 + hmac = sctp_auth_get_hmac(ntohs(auth_hdr->hmac_id));
  3762 + if (sig_len != hmac->hmac_len)
  3763 + return SCTP_IERROR_PROTO_VIOLATION;
  3764 +
  3765 + /* Now that we've done validation checks, we can compute and
  3766 + * verify the hmac. The steps involved are:
  3767 + * 1. Save the digest from the chunk.
  3768 + * 2. Zero out the digest in the chunk.
  3769 + * 3. Compute the new digest
  3770 + * 4. Compare saved and new digests.
  3771 + */
  3772 + digest = auth_hdr->hmac;
  3773 + skb_pull(chunk->skb, sig_len);
  3774 +
  3775 + save_digest = kmemdup(digest, sig_len, GFP_ATOMIC);
  3776 + if (!save_digest)
  3777 + goto nomem;
  3778 +
  3779 + memset(digest, 0, sig_len);
  3780 +
  3781 + sctp_auth_calculate_hmac(asoc, chunk->skb,
  3782 + (struct sctp_auth_chunk *)chunk->chunk_hdr,
  3783 + GFP_ATOMIC);
  3784 +
  3785 + /* Discard the packet if the digests do not match */
  3786 + if (memcmp(save_digest, digest, sig_len)) {
  3787 + kfree(save_digest);
  3788 + return SCTP_IERROR_BAD_SIG;
  3789 + }
  3790 +
  3791 + kfree(save_digest);
  3792 + chunk->auth = 1;
  3793 +
  3794 + return SCTP_IERROR_NO_ERROR;
  3795 +nomem:
  3796 + return SCTP_IERROR_NOMEM;
  3797 +}
  3798 +
  3799 +sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
  3800 + const struct sctp_association *asoc,
  3801 + const sctp_subtype_t type,
  3802 + void *arg,
  3803 + sctp_cmd_seq_t *commands)
  3804 +{
  3805 + struct sctp_authhdr *auth_hdr;
  3806 + struct sctp_chunk *chunk = arg;
  3807 + struct sctp_chunk *err_chunk;
  3808 + sctp_ierror_t error;
  3809 +
  3810 + if (!sctp_vtag_verify(chunk, asoc)) {
  3811 + sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
  3812 + SCTP_NULL());
  3813 + return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
  3814 + }
  3815 +
  3816 + /* Make sure that the AUTH chunk has valid length. */
  3817 + if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_auth_chunk)))
  3818 + return sctp_sf_violation_chunklen(ep, asoc, type, arg,
  3819 + commands);
  3820 +
  3821 + auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
  3822 + error = sctp_sf_authenticate(ep, asoc, type, chunk);
  3823 + switch (error) {
  3824 + case SCTP_IERROR_AUTH_BAD_HMAC:
  3825 + /* Generate the ERROR chunk and discard the rest
  3826 + * of the packet
  3827 + */
  3828 + err_chunk = sctp_make_op_error(asoc, chunk,
  3829 + SCTP_ERROR_UNSUP_HMAC,
  3830 + &auth_hdr->hmac_id,
  3831 + sizeof(__u16));
  3832 + if (err_chunk) {
  3833 + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
  3834 + SCTP_CHUNK(err_chunk));
  3835 + }
  3836 + /* Fall Through */
  3837 + case SCTP_IERROR_AUTH_BAD_KEYID:
  3838 + case SCTP_IERROR_BAD_SIG:
  3839 + return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
  3840 + break;
  3841 + case SCTP_IERROR_PROTO_VIOLATION:
  3842 + return sctp_sf_violation_chunklen(ep, asoc, type, arg,
  3843 + commands);
  3844 + break;
  3845 + case SCTP_IERROR_NOMEM:
  3846 + return SCTP_DISPOSITION_NOMEM;
  3847 + default:
  3848 + break;
  3849 + }
  3850 +
  3851 + return SCTP_DISPOSITION_CONSUME;
  3852 +}
  3853 +
  3854 +/*
3656 3855 * Process an unknown chunk.
3657 3856 *
3658 3857 * Section: 3.2. Also, 2.1 in the implementor's guide.
... ... @@ -3857,6 +4056,20 @@
3857 4056 if (!abort)
3858 4057 goto nomem;
3859 4058  
  4059 + /* SCTP-AUTH, Section 6.3:
  4060 + * It should be noted that if the receiver wants to tear
  4061 + * down an association in an authenticated way only, the
  4062 + * handling of malformed packets should not result in
  4063 + * tearing down the association.
  4064 + *
  4065 + * This means that if we only want to abort associations
  4066 + * in an authenticated way (i.e AUTH+ABORT), then we
  4067 + * can't destory this association just becuase the packet
  4068 + * was malformed.
  4069 + */
  4070 + if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
  4071 + goto discard;
  4072 +
3860 4073 if (asoc) {
3861 4074 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
3862 4075 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
... ... @@ -3894,6 +4107,7 @@
3894 4107 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
3895 4108 }
3896 4109  
  4110 +discard:
3897 4111 sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
3898 4112  
3899 4113 SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
net/sctp/sm_statetable.c
... ... @@ -523,6 +523,34 @@
523 523 TYPE_SCTP_FWD_TSN,
524 524 }; /*state_fn_t prsctp_chunk_event_table[][] */
525 525  
  526 +#define TYPE_SCTP_AUTH { \
  527 + /* SCTP_STATE_EMPTY */ \
  528 + TYPE_SCTP_FUNC(sctp_sf_ootb), \
  529 + /* SCTP_STATE_CLOSED */ \
  530 + TYPE_SCTP_FUNC(sctp_sf_ootb), \
  531 + /* SCTP_STATE_COOKIE_WAIT */ \
  532 + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
  533 + /* SCTP_STATE_COOKIE_ECHOED */ \
  534 + TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
  535 + /* SCTP_STATE_ESTABLISHED */ \
  536 + TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
  537 + /* SCTP_STATE_SHUTDOWN_PENDING */ \
  538 + TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
  539 + /* SCTP_STATE_SHUTDOWN_SENT */ \
  540 + TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
  541 + /* SCTP_STATE_SHUTDOWN_RECEIVED */ \
  542 + TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
  543 + /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
  544 + TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
  545 +} /* TYPE_SCTP_AUTH */
  546 +
  547 +/* The primary index for this table is the chunk type.
  548 + * The secondary index for this table is the state.
  549 + */
  550 +static const sctp_sm_table_entry_t auth_chunk_event_table[SCTP_NUM_AUTH_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
  551 + TYPE_SCTP_AUTH,
  552 +}; /*state_fn_t auth_chunk_event_table[][] */
  553 +
526 554 static const sctp_sm_table_entry_t
527 555 chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
528 556 /* SCTP_STATE_EMPTY */
... ... @@ -974,6 +1002,11 @@
974 1002  
975 1003 if (cid == SCTP_CID_ASCONF_ACK)
976 1004 return &addip_chunk_event_table[1][state];
  1005 + }
  1006 +
  1007 + if (sctp_auth_enable) {
  1008 + if (cid == SCTP_CID_AUTH)
  1009 + return &auth_chunk_event_table[0][state];
977 1010 }
978 1011  
979 1012 return &chunk_event_table_unknown[state];