diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sctp/auth.c | 193 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 13 | ||||
-rw-r--r-- | net/sctp/socket.c | 304 | ||||
-rw-r--r-- | net/sctp/ulpevent.c | 37 |
4 files changed, 547 insertions, 0 deletions
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 2a29409a38d9..781810724714 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
@@ -743,3 +743,196 @@ free: | |||
743 | if (free_key) | 743 | if (free_key) |
744 | sctp_auth_key_put(asoc_key); | 744 | sctp_auth_key_put(asoc_key); |
745 | } | 745 | } |
746 | |||
747 | /* API Helpers */ | ||
748 | |||
749 | /* Add a chunk to the endpoint authenticated chunk list */ | ||
750 | int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) | ||
751 | { | ||
752 | struct sctp_chunks_param *p = ep->auth_chunk_list; | ||
753 | __u16 nchunks; | ||
754 | __u16 param_len; | ||
755 | |||
756 | /* If this chunk is already specified, we are done */ | ||
757 | if (__sctp_auth_cid(chunk_id, p)) | ||
758 | return 0; | ||
759 | |||
760 | /* Check if we can add this chunk to the array */ | ||
761 | param_len = ntohs(p->param_hdr.length); | ||
762 | nchunks = param_len - sizeof(sctp_paramhdr_t); | ||
763 | if (nchunks == SCTP_NUM_CHUNK_TYPES) | ||
764 | return -EINVAL; | ||
765 | |||
766 | p->chunks[nchunks] = chunk_id; | ||
767 | p->param_hdr.length = htons(param_len + 1); | ||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | /* Add hmac identifires to the endpoint list of supported hmac ids */ | ||
772 | int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, | ||
773 | struct sctp_hmacalgo *hmacs) | ||
774 | { | ||
775 | int has_sha1 = 0; | ||
776 | __u16 id; | ||
777 | int i; | ||
778 | |||
779 | /* Scan the list looking for unsupported id. Also make sure that | ||
780 | * SHA1 is specified. | ||
781 | */ | ||
782 | for (i = 0; i < hmacs->shmac_num_idents; i++) { | ||
783 | id = hmacs->shmac_idents[i]; | ||
784 | |||
785 | if (SCTP_AUTH_HMAC_ID_SHA1 == id) | ||
786 | has_sha1 = 1; | ||
787 | |||
788 | if (!sctp_hmac_list[id].hmac_name) | ||
789 | return -EOPNOTSUPP; | ||
790 | } | ||
791 | |||
792 | if (!has_sha1) | ||
793 | return -EINVAL; | ||
794 | |||
795 | memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0], | ||
796 | hmacs->shmac_num_idents * sizeof(__u16)); | ||
797 | ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) + | ||
798 | hmacs->shmac_num_idents * sizeof(__u16)); | ||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | /* Set a new shared key on either endpoint or association. If the | ||
803 | * the key with a same ID already exists, replace the key (remove the | ||
804 | * old key and add a new one). | ||
805 | */ | ||
806 | int sctp_auth_set_key(struct sctp_endpoint *ep, | ||
807 | struct sctp_association *asoc, | ||
808 | struct sctp_authkey *auth_key) | ||
809 | { | ||
810 | struct sctp_shared_key *cur_key = NULL; | ||
811 | struct sctp_auth_bytes *key; | ||
812 | struct list_head *sh_keys; | ||
813 | int replace = 0; | ||
814 | |||
815 | /* Try to find the given key id to see if | ||
816 | * we are doing a replace, or adding a new key | ||
817 | */ | ||
818 | if (asoc) | ||
819 | sh_keys = &asoc->endpoint_shared_keys; | ||
820 | else | ||
821 | sh_keys = &ep->endpoint_shared_keys; | ||
822 | |||
823 | key_for_each(cur_key, sh_keys) { | ||
824 | if (cur_key->key_id == auth_key->sca_keynumber) { | ||
825 | replace = 1; | ||
826 | break; | ||
827 | } | ||
828 | } | ||
829 | |||
830 | /* If we are not replacing a key id, we need to allocate | ||
831 | * a shared key. | ||
832 | */ | ||
833 | if (!replace) { | ||
834 | cur_key = sctp_auth_shkey_create(auth_key->sca_keynumber, | ||
835 | GFP_KERNEL); | ||
836 | if (!cur_key) | ||
837 | return -ENOMEM; | ||
838 | } | ||
839 | |||
840 | /* Create a new key data based on the info passed in */ | ||
841 | key = sctp_auth_create_key(auth_key->sca_keylen, GFP_KERNEL); | ||
842 | if (!key) | ||
843 | goto nomem; | ||
844 | |||
845 | memcpy(key->data, &auth_key->sca_key[0], auth_key->sca_keylen); | ||
846 | |||
847 | /* If we are replacing, remove the old keys data from the | ||
848 | * key id. If we are adding new key id, add it to the | ||
849 | * list. | ||
850 | */ | ||
851 | if (replace) | ||
852 | sctp_auth_key_put(cur_key->key); | ||
853 | else | ||
854 | list_add(&cur_key->key_list, sh_keys); | ||
855 | |||
856 | cur_key->key = key; | ||
857 | sctp_auth_key_hold(key); | ||
858 | |||
859 | return 0; | ||
860 | nomem: | ||
861 | if (!replace) | ||
862 | sctp_auth_shkey_free(cur_key); | ||
863 | |||
864 | return -ENOMEM; | ||
865 | } | ||
866 | |||
867 | int sctp_auth_set_active_key(struct sctp_endpoint *ep, | ||
868 | struct sctp_association *asoc, | ||
869 | __u16 key_id) | ||
870 | { | ||
871 | struct sctp_shared_key *key; | ||
872 | struct list_head *sh_keys; | ||
873 | int found = 0; | ||
874 | |||
875 | /* The key identifier MUST correst to an existing key */ | ||
876 | if (asoc) | ||
877 | sh_keys = &asoc->endpoint_shared_keys; | ||
878 | else | ||
879 | sh_keys = &ep->endpoint_shared_keys; | ||
880 | |||
881 | key_for_each(key, sh_keys) { | ||
882 | if (key->key_id == key_id) { | ||
883 | found = 1; | ||
884 | break; | ||
885 | } | ||
886 | } | ||
887 | |||
888 | if (!found) | ||
889 | return -EINVAL; | ||
890 | |||
891 | if (asoc) { | ||
892 | asoc->active_key_id = key_id; | ||
893 | sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); | ||
894 | } else | ||
895 | ep->active_key_id = key_id; | ||
896 | |||
897 | return 0; | ||
898 | } | ||
899 | |||
900 | int sctp_auth_del_key_id(struct sctp_endpoint *ep, | ||
901 | struct sctp_association *asoc, | ||
902 | __u16 key_id) | ||
903 | { | ||
904 | struct sctp_shared_key *key; | ||
905 | struct list_head *sh_keys; | ||
906 | int found = 0; | ||
907 | |||
908 | /* The key identifier MUST NOT be the current active key | ||
909 | * The key identifier MUST correst to an existing key | ||
910 | */ | ||
911 | if (asoc) { | ||
912 | if (asoc->active_key_id == key_id) | ||
913 | return -EINVAL; | ||
914 | |||
915 | sh_keys = &asoc->endpoint_shared_keys; | ||
916 | } else { | ||
917 | if (ep->active_key_id == key_id) | ||
918 | return -EINVAL; | ||
919 | |||
920 | sh_keys = &ep->endpoint_shared_keys; | ||
921 | } | ||
922 | |||
923 | key_for_each(key, sh_keys) { | ||
924 | if (key->key_id == key_id) { | ||
925 | found = 1; | ||
926 | break; | ||
927 | } | ||
928 | } | ||
929 | |||
930 | if (!found) | ||
931 | return -EINVAL; | ||
932 | |||
933 | /* Delete the shared key */ | ||
934 | list_del_init(&key->key_list); | ||
935 | sctp_auth_shkey_free(key); | ||
936 | |||
937 | return 0; | ||
938 | } | ||
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 5aef4aafdfdc..f01b408508ff 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -3848,6 +3848,19 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep, | |||
3848 | break; | 3848 | break; |
3849 | } | 3849 | } |
3850 | 3850 | ||
3851 | if (asoc->active_key_id != ntohs(auth_hdr->shkey_id)) { | ||
3852 | struct sctp_ulpevent *ev; | ||
3853 | |||
3854 | ev = sctp_ulpevent_make_authkey(asoc, ntohs(auth_hdr->shkey_id), | ||
3855 | SCTP_AUTH_NEWKEY, GFP_ATOMIC); | ||
3856 | |||
3857 | if (!ev) | ||
3858 | return -ENOMEM; | ||
3859 | |||
3860 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | ||
3861 | SCTP_ULPEVENT(ev)); | ||
3862 | } | ||
3863 | |||
3851 | return SCTP_DISPOSITION_CONSUME; | 3864 | return SCTP_DISPOSITION_CONSUME; |
3852 | } | 3865 | } |
3853 | 3866 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 7738915011a0..f3e1a9c811ad 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2946,6 +2946,164 @@ static int sctp_setsockopt_maxburst(struct sock *sk, | |||
2946 | return 0; | 2946 | return 0; |
2947 | } | 2947 | } |
2948 | 2948 | ||
2949 | /* | ||
2950 | * 7.1.18. Add a chunk that must be authenticated (SCTP_AUTH_CHUNK) | ||
2951 | * | ||
2952 | * This set option adds a chunk type that the user is requesting to be | ||
2953 | * received only in an authenticated way. Changes to the list of chunks | ||
2954 | * will only effect future associations on the socket. | ||
2955 | */ | ||
2956 | static int sctp_setsockopt_auth_chunk(struct sock *sk, | ||
2957 | char __user *optval, | ||
2958 | int optlen) | ||
2959 | { | ||
2960 | struct sctp_authchunk val; | ||
2961 | |||
2962 | if (optlen != sizeof(struct sctp_authchunk)) | ||
2963 | return -EINVAL; | ||
2964 | if (copy_from_user(&val, optval, optlen)) | ||
2965 | return -EFAULT; | ||
2966 | |||
2967 | switch (val.sauth_chunk) { | ||
2968 | case SCTP_CID_INIT: | ||
2969 | case SCTP_CID_INIT_ACK: | ||
2970 | case SCTP_CID_SHUTDOWN_COMPLETE: | ||
2971 | case SCTP_CID_AUTH: | ||
2972 | return -EINVAL; | ||
2973 | } | ||
2974 | |||
2975 | /* add this chunk id to the endpoint */ | ||
2976 | return sctp_auth_ep_add_chunkid(sctp_sk(sk)->ep, val.sauth_chunk); | ||
2977 | } | ||
2978 | |||
2979 | /* | ||
2980 | * 7.1.19. Get or set the list of supported HMAC Identifiers (SCTP_HMAC_IDENT) | ||
2981 | * | ||
2982 | * This option gets or sets the list of HMAC algorithms that the local | ||
2983 | * endpoint requires the peer to use. | ||
2984 | */ | ||
2985 | static int sctp_setsockopt_hmac_ident(struct sock *sk, | ||
2986 | char __user *optval, | ||
2987 | int optlen) | ||
2988 | { | ||
2989 | struct sctp_hmacalgo *hmacs; | ||
2990 | int err; | ||
2991 | |||
2992 | if (optlen < sizeof(struct sctp_hmacalgo)) | ||
2993 | return -EINVAL; | ||
2994 | |||
2995 | hmacs = kmalloc(optlen, GFP_KERNEL); | ||
2996 | if (!hmacs) | ||
2997 | return -ENOMEM; | ||
2998 | |||
2999 | if (copy_from_user(hmacs, optval, optlen)) { | ||
3000 | err = -EFAULT; | ||
3001 | goto out; | ||
3002 | } | ||
3003 | |||
3004 | if (hmacs->shmac_num_idents == 0 || | ||
3005 | hmacs->shmac_num_idents > SCTP_AUTH_NUM_HMACS) { | ||
3006 | err = -EINVAL; | ||
3007 | goto out; | ||
3008 | } | ||
3009 | |||
3010 | err = sctp_auth_ep_set_hmacs(sctp_sk(sk)->ep, hmacs); | ||
3011 | out: | ||
3012 | kfree(hmacs); | ||
3013 | return err; | ||
3014 | } | ||
3015 | |||
3016 | /* | ||
3017 | * 7.1.20. Set a shared key (SCTP_AUTH_KEY) | ||
3018 | * | ||
3019 | * This option will set a shared secret key which is used to build an | ||
3020 | * association shared key. | ||
3021 | */ | ||
3022 | static int sctp_setsockopt_auth_key(struct sock *sk, | ||
3023 | char __user *optval, | ||
3024 | int optlen) | ||
3025 | { | ||
3026 | struct sctp_authkey *authkey; | ||
3027 | struct sctp_association *asoc; | ||
3028 | int ret; | ||
3029 | |||
3030 | if (optlen <= sizeof(struct sctp_authkey)) | ||
3031 | return -EINVAL; | ||
3032 | |||
3033 | authkey = kmalloc(optlen, GFP_KERNEL); | ||
3034 | if (!authkey) | ||
3035 | return -ENOMEM; | ||
3036 | |||
3037 | if (copy_from_user(authkey, optval, optlen)) { | ||
3038 | ret = -EFAULT; | ||
3039 | goto out; | ||
3040 | } | ||
3041 | |||
3042 | asoc = sctp_id2assoc(sk, authkey->sca_assoc_id); | ||
3043 | if (!asoc && authkey->sca_assoc_id && sctp_style(sk, UDP)) { | ||
3044 | ret = -EINVAL; | ||
3045 | goto out; | ||
3046 | } | ||
3047 | |||
3048 | ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey); | ||
3049 | out: | ||
3050 | kfree(authkey); | ||
3051 | return ret; | ||
3052 | } | ||
3053 | |||
3054 | /* | ||
3055 | * 7.1.21. Get or set the active shared key (SCTP_AUTH_ACTIVE_KEY) | ||
3056 | * | ||
3057 | * This option will get or set the active shared key to be used to build | ||
3058 | * the association shared key. | ||
3059 | */ | ||
3060 | static int sctp_setsockopt_active_key(struct sock *sk, | ||
3061 | char __user *optval, | ||
3062 | int optlen) | ||
3063 | { | ||
3064 | struct sctp_authkeyid val; | ||
3065 | struct sctp_association *asoc; | ||
3066 | |||
3067 | if (optlen != sizeof(struct sctp_authkeyid)) | ||
3068 | return -EINVAL; | ||
3069 | if (copy_from_user(&val, optval, optlen)) | ||
3070 | return -EFAULT; | ||
3071 | |||
3072 | asoc = sctp_id2assoc(sk, val.scact_assoc_id); | ||
3073 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) | ||
3074 | return -EINVAL; | ||
3075 | |||
3076 | return sctp_auth_set_active_key(sctp_sk(sk)->ep, asoc, | ||
3077 | val.scact_keynumber); | ||
3078 | } | ||
3079 | |||
3080 | /* | ||
3081 | * 7.1.22. Delete a shared key (SCTP_AUTH_DELETE_KEY) | ||
3082 | * | ||
3083 | * This set option will delete a shared secret key from use. | ||
3084 | */ | ||
3085 | static int sctp_setsockopt_del_key(struct sock *sk, | ||
3086 | char __user *optval, | ||
3087 | int optlen) | ||
3088 | { | ||
3089 | struct sctp_authkeyid val; | ||
3090 | struct sctp_association *asoc; | ||
3091 | |||
3092 | if (optlen != sizeof(struct sctp_authkeyid)) | ||
3093 | return -EINVAL; | ||
3094 | if (copy_from_user(&val, optval, optlen)) | ||
3095 | return -EFAULT; | ||
3096 | |||
3097 | asoc = sctp_id2assoc(sk, val.scact_assoc_id); | ||
3098 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) | ||
3099 | return -EINVAL; | ||
3100 | |||
3101 | return sctp_auth_del_key_id(sctp_sk(sk)->ep, asoc, | ||
3102 | val.scact_keynumber); | ||
3103 | |||
3104 | } | ||
3105 | |||
3106 | |||
2949 | /* API 6.2 setsockopt(), getsockopt() | 3107 | /* API 6.2 setsockopt(), getsockopt() |
2950 | * | 3108 | * |
2951 | * Applications use setsockopt() and getsockopt() to set or retrieve | 3109 | * Applications use setsockopt() and getsockopt() to set or retrieve |
@@ -3069,6 +3227,21 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
3069 | case SCTP_MAX_BURST: | 3227 | case SCTP_MAX_BURST: |
3070 | retval = sctp_setsockopt_maxburst(sk, optval, optlen); | 3228 | retval = sctp_setsockopt_maxburst(sk, optval, optlen); |
3071 | break; | 3229 | break; |
3230 | case SCTP_AUTH_CHUNK: | ||
3231 | retval = sctp_setsockopt_auth_chunk(sk, optval, optlen); | ||
3232 | break; | ||
3233 | case SCTP_HMAC_IDENT: | ||
3234 | retval = sctp_setsockopt_hmac_ident(sk, optval, optlen); | ||
3235 | break; | ||
3236 | case SCTP_AUTH_KEY: | ||
3237 | retval = sctp_setsockopt_auth_key(sk, optval, optlen); | ||
3238 | break; | ||
3239 | case SCTP_AUTH_ACTIVE_KEY: | ||
3240 | retval = sctp_setsockopt_active_key(sk, optval, optlen); | ||
3241 | break; | ||
3242 | case SCTP_AUTH_DELETE_KEY: | ||
3243 | retval = sctp_setsockopt_del_key(sk, optval, optlen); | ||
3244 | break; | ||
3072 | default: | 3245 | default: |
3073 | retval = -ENOPROTOOPT; | 3246 | retval = -ENOPROTOOPT; |
3074 | break; | 3247 | break; |
@@ -4840,6 +5013,118 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, | |||
4840 | return -ENOTSUPP; | 5013 | return -ENOTSUPP; |
4841 | } | 5014 | } |
4842 | 5015 | ||
5016 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, | ||
5017 | char __user *optval, int __user *optlen) | ||
5018 | { | ||
5019 | struct sctp_hmac_algo_param *hmacs; | ||
5020 | __u16 param_len; | ||
5021 | |||
5022 | hmacs = sctp_sk(sk)->ep->auth_hmacs_list; | ||
5023 | param_len = ntohs(hmacs->param_hdr.length); | ||
5024 | |||
5025 | if (len < param_len) | ||
5026 | return -EINVAL; | ||
5027 | if (put_user(len, optlen)) | ||
5028 | return -EFAULT; | ||
5029 | if (copy_to_user(optval, hmacs->hmac_ids, len)) | ||
5030 | return -EFAULT; | ||
5031 | |||
5032 | return 0; | ||
5033 | } | ||
5034 | |||
5035 | static int sctp_getsockopt_active_key(struct sock *sk, int len, | ||
5036 | char __user *optval, int __user *optlen) | ||
5037 | { | ||
5038 | struct sctp_authkeyid val; | ||
5039 | struct sctp_association *asoc; | ||
5040 | |||
5041 | if (len < sizeof(struct sctp_authkeyid)) | ||
5042 | return -EINVAL; | ||
5043 | if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid))) | ||
5044 | return -EFAULT; | ||
5045 | |||
5046 | asoc = sctp_id2assoc(sk, val.scact_assoc_id); | ||
5047 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) | ||
5048 | return -EINVAL; | ||
5049 | |||
5050 | if (asoc) | ||
5051 | val.scact_keynumber = asoc->active_key_id; | ||
5052 | else | ||
5053 | val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; | ||
5054 | |||
5055 | return 0; | ||
5056 | } | ||
5057 | |||
5058 | static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, | ||
5059 | char __user *optval, int __user *optlen) | ||
5060 | { | ||
5061 | struct sctp_authchunks val; | ||
5062 | struct sctp_association *asoc; | ||
5063 | struct sctp_chunks_param *ch; | ||
5064 | char __user *to; | ||
5065 | |||
5066 | if (len <= sizeof(struct sctp_authchunks)) | ||
5067 | return -EINVAL; | ||
5068 | |||
5069 | if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) | ||
5070 | return -EFAULT; | ||
5071 | |||
5072 | to = val.gauth_chunks; | ||
5073 | asoc = sctp_id2assoc(sk, val.gauth_assoc_id); | ||
5074 | if (!asoc) | ||
5075 | return -EINVAL; | ||
5076 | |||
5077 | ch = asoc->peer.peer_chunks; | ||
5078 | |||
5079 | /* See if the user provided enough room for all the data */ | ||
5080 | if (len < ntohs(ch->param_hdr.length)) | ||
5081 | return -EINVAL; | ||
5082 | |||
5083 | len = ntohs(ch->param_hdr.length); | ||
5084 | if (put_user(len, optlen)) | ||
5085 | return -EFAULT; | ||
5086 | if (copy_to_user(to, ch->chunks, len)) | ||
5087 | return -EFAULT; | ||
5088 | |||
5089 | return 0; | ||
5090 | } | ||
5091 | |||
5092 | static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | ||
5093 | char __user *optval, int __user *optlen) | ||
5094 | { | ||
5095 | struct sctp_authchunks val; | ||
5096 | struct sctp_association *asoc; | ||
5097 | struct sctp_chunks_param *ch; | ||
5098 | char __user *to; | ||
5099 | |||
5100 | if (len <= sizeof(struct sctp_authchunks)) | ||
5101 | return -EINVAL; | ||
5102 | |||
5103 | if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) | ||
5104 | return -EFAULT; | ||
5105 | |||
5106 | to = val.gauth_chunks; | ||
5107 | asoc = sctp_id2assoc(sk, val.gauth_assoc_id); | ||
5108 | if (!asoc && val.gauth_assoc_id && sctp_style(sk, UDP)) | ||
5109 | return -EINVAL; | ||
5110 | |||
5111 | if (asoc) | ||
5112 | ch = (struct sctp_chunks_param*)asoc->c.auth_chunks; | ||
5113 | else | ||
5114 | ch = sctp_sk(sk)->ep->auth_chunk_list; | ||
5115 | |||
5116 | if (len < ntohs(ch->param_hdr.length)) | ||
5117 | return -EINVAL; | ||
5118 | |||
5119 | len = ntohs(ch->param_hdr.length); | ||
5120 | if (put_user(len, optlen)) | ||
5121 | return -EFAULT; | ||
5122 | if (copy_to_user(to, ch->chunks, len)) | ||
5123 | return -EFAULT; | ||
5124 | |||
5125 | return 0; | ||
5126 | } | ||
5127 | |||
4843 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 5128 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, |
4844 | char __user *optval, int __user *optlen) | 5129 | char __user *optval, int __user *optlen) |
4845 | { | 5130 | { |
@@ -4963,6 +5248,25 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
4963 | case SCTP_MAX_BURST: | 5248 | case SCTP_MAX_BURST: |
4964 | retval = sctp_getsockopt_maxburst(sk, len, optval, optlen); | 5249 | retval = sctp_getsockopt_maxburst(sk, len, optval, optlen); |
4965 | break; | 5250 | break; |
5251 | case SCTP_AUTH_KEY: | ||
5252 | case SCTP_AUTH_CHUNK: | ||
5253 | case SCTP_AUTH_DELETE_KEY: | ||
5254 | retval = -EOPNOTSUPP; | ||
5255 | break; | ||
5256 | case SCTP_HMAC_IDENT: | ||
5257 | retval = sctp_getsockopt_hmac_ident(sk, len, optval, optlen); | ||
5258 | break; | ||
5259 | case SCTP_AUTH_ACTIVE_KEY: | ||
5260 | retval = sctp_getsockopt_active_key(sk, len, optval, optlen); | ||
5261 | break; | ||
5262 | case SCTP_PEER_AUTH_CHUNKS: | ||
5263 | retval = sctp_getsockopt_peer_auth_chunks(sk, len, optval, | ||
5264 | optlen); | ||
5265 | break; | ||
5266 | case SCTP_LOCAL_AUTH_CHUNKS: | ||
5267 | retval = sctp_getsockopt_local_auth_chunks(sk, len, optval, | ||
5268 | optlen); | ||
5269 | break; | ||
4966 | default: | 5270 | default: |
4967 | retval = -ENOPROTOOPT; | 5271 | retval = -ENOPROTOOPT; |
4968 | break; | 5272 | break; |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 5dc094b9732d..2c17c7efad46 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -813,6 +813,43 @@ fail: | |||
813 | return NULL; | 813 | return NULL; |
814 | } | 814 | } |
815 | 815 | ||
816 | struct sctp_ulpevent *sctp_ulpevent_make_authkey( | ||
817 | const struct sctp_association *asoc, __u16 key_id, | ||
818 | __u32 indication, gfp_t gfp) | ||
819 | { | ||
820 | struct sctp_ulpevent *event; | ||
821 | struct sctp_authkey_event *ak; | ||
822 | struct sk_buff *skb; | ||
823 | |||
824 | event = sctp_ulpevent_new(sizeof(struct sctp_authkey_event), | ||
825 | MSG_NOTIFICATION, gfp); | ||
826 | if (!event) | ||
827 | goto fail; | ||
828 | |||
829 | skb = sctp_event2skb(event); | ||
830 | ak = (struct sctp_authkey_event *) | ||
831 | skb_put(skb, sizeof(struct sctp_authkey_event)); | ||
832 | |||
833 | ak->auth_type = SCTP_AUTHENTICATION_EVENT; | ||
834 | ak->auth_flags = 0; | ||
835 | ak->auth_length = sizeof(struct sctp_authkey_event); | ||
836 | |||
837 | ak->auth_keynumber = key_id; | ||
838 | ak->auth_altkeynumber = 0; | ||
839 | ak->auth_indication = indication; | ||
840 | |||
841 | /* | ||
842 | * The association id field, holds the identifier for the association. | ||
843 | */ | ||
844 | sctp_ulpevent_set_owner(event, asoc); | ||
845 | ak->auth_assoc_id = sctp_assoc2id(asoc); | ||
846 | |||
847 | return event; | ||
848 | fail: | ||
849 | return NULL; | ||
850 | } | ||
851 | |||
852 | |||
816 | /* Return the notification type, assuming this is a notification | 853 | /* Return the notification type, assuming this is a notification |
817 | * event. | 854 | * event. |
818 | */ | 855 | */ |