[SCTP]: Add support for SCTP_CONTEXT socket option.
authorIvan Skytte Jorgensen <isj-sctp@i1.dk>
Thu, 14 Dec 2006 00:34:22 +0000 (16:34 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Thu, 14 Dec 2006 00:48:29 +0000 (16:48 -0800)
Signed-off-by: Ivan Skytte Jorgensen <isj-sctp@i1.dk>
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/sctp/structs.h
include/net/sctp/user.h
net/sctp/associola.c
net/sctp/socket.c
net/sctp/ulpevent.c

index b00d85e14fe1c5c283c7e97eb290cf0a8273c96d..8d7f26d684e5e5a02c9a67e5b6f83b038596c2df 100644 (file)
@@ -275,6 +275,7 @@ struct sctp_sock {
        __u16 default_flags;
        __u32 default_context;
        __u32 default_timetolive;
+       __u32 default_rcv_context;
 
        /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
         * the destination address every heartbeat interval. This value
@@ -1657,6 +1658,9 @@ struct sctp_association {
        __u32 default_context;
        __u32 default_timetolive;
 
+       /* Default receive parameters */
+       __u32 default_rcv_context;
+
        /* This tracks outbound ssn for a given stream.  */
        struct sctp_ssnmap *ssnmap;
 
index 1b7aae6cdd82d7a4f035362655c765cec6a35f63..9e4a39fd129d0a59214557e7ed9e648b847d3634 100644 (file)
@@ -95,6 +95,8 @@ enum sctp_optname {
 #define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO
        SCTP_DELAYED_ACK_TIME,
 #define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK_TIME
+       SCTP_CONTEXT,   /* Receive Context */
+#define SCTP_CONTEXT SCTP_CONTEXT
 
        /* Internal Socket Options. Some of the sctp library functions are 
         * implemented using these socket options.
index ad0057db0f91884b39a393b06759bdc383c9776b..5db95caed0a321f2bc10bd11ec5061fa100c3df9 100644 (file)
@@ -298,6 +298,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
        asoc->default_flags = sp->default_flags;
        asoc->default_context = sp->default_context;
        asoc->default_timetolive = sp->default_timetolive;
+       asoc->default_rcv_context = sp->default_rcv_context;
 
        return asoc;
 
index fa29eae83e91d065b2571def2aa4a88f956e3fea..bdd8bd428b64f3de8ae4fff0c9414fce324ddf30 100644 (file)
@@ -2746,6 +2746,46 @@ static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
        return 0;
 }
 
+/*
+ * 7.1.29.  Set or Get the default context (SCTP_CONTEXT)
+ *
+ * The context field in the sctp_sndrcvinfo structure is normally only
+ * used when a failed message is retrieved holding the value that was
+ * sent down on the actual send call.  This option allows the setting of
+ * a default context on an association basis that will be received on
+ * reading messages from the peer.  This is especially helpful in the
+ * one-2-many model for an application to keep some reference to an
+ * internal state machine that is processing messages on the
+ * association.  Note that the setting of this value only effects
+ * received messages from the peer and does not effect the value that is
+ * saved with outbound messages.
+ */
+static int sctp_setsockopt_context(struct sock *sk, char __user *optval,
+                                  int optlen)
+{
+       struct sctp_assoc_value params;
+       struct sctp_sock *sp;
+       struct sctp_association *asoc;
+
+       if (optlen != sizeof(struct sctp_assoc_value))
+               return -EINVAL;
+       if (copy_from_user(&params, optval, optlen))
+               return -EFAULT;
+
+       sp = sctp_sk(sk);
+
+       if (params.assoc_id != 0) {
+               asoc = sctp_id2assoc(sk, params.assoc_id);
+               if (!asoc)
+                       return -EINVAL;
+               asoc->default_rcv_context = params.assoc_value;
+       } else {
+               sp->default_rcv_context = params.assoc_value;
+       }
+
+       return 0;
+}
+
 /* API 6.2 setsockopt(), getsockopt()
  *
  * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -2857,6 +2897,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
        case SCTP_ADAPTION_LAYER:
                retval = sctp_setsockopt_adaption_layer(sk, optval, optlen);
                break;
+       case SCTP_CONTEXT:
+               retval = sctp_setsockopt_context(sk, optval, optlen);
+               break;
 
        default:
                retval = -ENOPROTOOPT;
@@ -3016,6 +3059,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
        sp->default_context = 0;
        sp->default_timetolive = 0;
 
+       sp->default_rcv_context = 0;
+
        /* Initialize default setup parameters. These parameters
         * can be modified with the SCTP_INITMSG socket option or
         * overridden by the SCTP_INIT CMSG.
@@ -4420,6 +4465,42 @@ static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
        return 0;
 }
 
+/*
+ * 7.1.29.  Set or Get the default context (SCTP_CONTEXT)
+ * (chapter and verse is quoted at sctp_setsockopt_context())
+ */
+static int sctp_getsockopt_context(struct sock *sk, int len,
+                                  char __user *optval, int __user *optlen)
+{
+       struct sctp_assoc_value params;
+       struct sctp_sock *sp;
+       struct sctp_association *asoc;
+
+       if (len != sizeof(struct sctp_assoc_value))
+               return -EINVAL;
+
+       if (copy_from_user(&params, optval, len))
+               return -EFAULT;
+
+       sp = sctp_sk(sk);
+
+       if (params.assoc_id != 0) {
+               asoc = sctp_id2assoc(sk, params.assoc_id);
+               if (!asoc)
+                       return -EINVAL;
+               params.assoc_value = asoc->default_rcv_context;
+       } else {
+               params.assoc_value = sp->default_rcv_context;
+       }
+
+       if (put_user(len, optlen))
+               return -EFAULT;
+       if (copy_to_user(optval, &params, len))
+               return -EFAULT;
+
+       return 0;
+}
+
 /*
  * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG)
  *
@@ -4558,6 +4639,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
                retval = sctp_getsockopt_adaption_layer(sk, len, optval,
                                                        optlen);
                break;
+       case SCTP_CONTEXT:
+               retval = sctp_getsockopt_context(sk, len, optval, optlen);
+               break;
        default:
                retval = -ENOPROTOOPT;
                break;
index e255a709f1b7ed867d4985b9da51f86fdee96cd5..93ac63b055ba21c5ca3e3dc06367061ff43dd68e 100644 (file)
@@ -849,8 +849,10 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
         */
        sinfo.sinfo_assoc_id = sctp_assoc2id(event->asoc);
 
+       /* context value that is set via SCTP_CONTEXT socket option. */
+       sinfo.sinfo_context = event->asoc->default_rcv_context;
+
        /* These fields are not used while receiving. */
-       sinfo.sinfo_context = 0;
        sinfo.sinfo_timetolive = 0;
 
        put_cmsg(msghdr, IPPROTO_SCTP, SCTP_SNDRCV,