Author: tuexen
Date: Thu Jun 16 21:12:36 2011
New Revision: 223162
URL: http://svn.freebsd.org/changeset/base/223162

Log:
  Add SCTP_DEFAULT_PRINFO socket option.
  Fix the SCTP_DEFAULT_SNDINFO socket option: Don't clear the
  PR SCTP policy when setting sinfo_flags.
  
  MFC after: 1 month.

Modified:
  head/sys/netinet/sctp.h
  head/sys/netinet/sctp_uio.h
  head/sys/netinet/sctp_usrreq.c

Modified: head/sys/netinet/sctp.h
==============================================================================
--- head/sys/netinet/sctp.h     Thu Jun 16 20:58:23 2011        (r223161)
+++ head/sys/netinet/sctp.h     Thu Jun 16 21:12:36 2011        (r223162)
@@ -118,6 +118,7 @@ struct sctp_paramhdr {
 #define SCTP_RECVRCVINFO                0x0000001f
 #define SCTP_RECVNXTINFO                0x00000020
 #define SCTP_DEFAULT_SNDINFO            0x00000021
+#define SCTP_DEFAULT_PRINFO             0x00000022
 
 /*
  * read-only options

Modified: head/sys/netinet/sctp_uio.h
==============================================================================
--- head/sys/netinet/sctp_uio.h Thu Jun 16 20:58:23 2011        (r223161)
+++ head/sys/netinet/sctp_uio.h Thu Jun 16 21:12:36 2011        (r223162)
@@ -162,6 +162,12 @@ struct sctp_prinfo {
        uint32_t pr_value;
 };
 
+struct sctp_default_prinfo {
+       uint16_t pr_policy;
+       uint32_t pr_value;
+       sctp_assoc_t pr_assoc_id;
+};
+
 struct sctp_authinfo {
        uint16_t auth_keyid;
 };

Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c      Thu Jun 16 20:58:23 2011        
(r223161)
+++ head/sys/netinet/sctp_usrreq.c      Thu Jun 16 21:12:36 2011        
(r223162)
@@ -3030,6 +3030,7 @@ flags_out:
                        if (stcb) {
                                info->snd_sid = 
stcb->asoc.def_send.sinfo_stream;
                                info->snd_flags = 
stcb->asoc.def_send.sinfo_flags;
+                               info->snd_flags &= 0xfff0;
                                info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
                                info->snd_context = 
stcb->asoc.def_send.sinfo_context;
                                SCTP_TCB_UNLOCK(stcb);
@@ -3038,6 +3039,7 @@ flags_out:
                                        SCTP_INP_RLOCK(inp);
                                        info->snd_sid = 
inp->def_send.sinfo_stream;
                                        info->snd_flags = 
inp->def_send.sinfo_flags;
+                                       info->snd_flags &= 0xfff0;
                                        info->snd_ppid = 
inp->def_send.sinfo_ppid;
                                        info->snd_context = 
inp->def_send.sinfo_context;
                                        SCTP_INP_RUNLOCK(inp);
@@ -3051,6 +3053,33 @@ flags_out:
                        }
                        break;
                }
+       case SCTP_DEFAULT_PRINFO:
+               {
+                       struct sctp_default_prinfo *info;
+
+                       SCTP_CHECK_AND_CAST(info, optval, struct 
sctp_default_prinfo, *optsize);
+                       SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
+
+                       if (stcb) {
+                               info->pr_policy = 
PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
+                               info->pr_value = 
stcb->asoc.def_send.sinfo_timetolive;
+                               SCTP_TCB_UNLOCK(stcb);
+                       } else {
+                               if (info->pr_assoc_id == SCTP_FUTURE_ASSOC) {
+                                       SCTP_INP_RLOCK(inp);
+                                       info->pr_policy = 
PR_SCTP_POLICY(inp->def_send.sinfo_flags);
+                                       info->pr_value = 
inp->def_send.sinfo_timetolive;
+                                       SCTP_INP_RUNLOCK(inp);
+                               } else {
+                                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_USRREQ, EINVAL);
+                                       error = EINVAL;
+                               }
+                       }
+                       if (error == 0) {
+                               *optsize = sizeof(struct sctp_default_prinfo);
+                       }
+                       break;
+               }
        default:
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, 
ENOPROTOOPT);
                error = ENOPROTOOPT;
@@ -5043,6 +5072,7 @@ sctp_setopt(struct socket *so, int optna
        case SCTP_DEFAULT_SNDINFO:
                {
                        struct sctp_sndinfo *info;
+                       uint16_t policy;
 
                        SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, 
optsize);
                        SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
@@ -5050,7 +5080,9 @@ sctp_setopt(struct socket *so, int optna
                        if (stcb) {
                                if (info->snd_sid < stcb->asoc.streamoutcnt) {
                                        stcb->asoc.def_send.sinfo_stream = 
info->snd_sid;
+                                       policy = 
PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
                                        stcb->asoc.def_send.sinfo_flags = 
info->snd_flags;
+                                       stcb->asoc.def_send.sinfo_flags |= 
policy;
                                        stcb->asoc.def_send.sinfo_ppid = 
info->snd_ppid;
                                        stcb->asoc.def_send.sinfo_context = 
info->snd_context;
                                } else {
@@ -5063,7 +5095,9 @@ sctp_setopt(struct socket *so, int optna
                                    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
                                        SCTP_INP_WLOCK(inp);
                                        inp->def_send.sinfo_stream = 
info->snd_sid;
+                                       policy = 
PR_SCTP_POLICY(inp->def_send.sinfo_flags);
                                        inp->def_send.sinfo_flags = 
info->snd_flags;
+                                       inp->def_send.sinfo_flags |= policy;
                                        inp->def_send.sinfo_ppid = 
info->snd_ppid;
                                        inp->def_send.sinfo_context = 
info->snd_context;
                                        SCTP_INP_WUNLOCK(inp);
@@ -5075,7 +5109,9 @@ sctp_setopt(struct socket *so, int optna
                                                SCTP_TCB_LOCK(stcb);
                                                if (info->snd_sid < 
stcb->asoc.streamoutcnt) {
                                                        
stcb->asoc.def_send.sinfo_stream = info->snd_sid;
+                                                       policy = 
PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
                                                        
stcb->asoc.def_send.sinfo_flags = info->snd_flags;
+                                                       
stcb->asoc.def_send.sinfo_flags |= policy;
                                                        
stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
                                                        
stcb->asoc.def_send.sinfo_context = info->snd_context;
                                                }
@@ -5086,6 +5122,44 @@ sctp_setopt(struct socket *so, int optna
                        }
                        break;
                }
+       case SCTP_DEFAULT_PRINFO:
+               {
+                       struct sctp_default_prinfo *info;
+
+                       SCTP_CHECK_AND_CAST(info, optval, struct 
sctp_default_prinfo, optsize);
+                       SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
+
+                       if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                               break;
+                       }
+                       if (stcb) {
+                               stcb->asoc.def_send.sinfo_flags &= 0xfff0;
+                               stcb->asoc.def_send.sinfo_flags |= 
info->pr_policy;
+                               SCTP_TCB_UNLOCK(stcb);
+                       } else {
+                               if ((info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
+                                   (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
+                                       SCTP_INP_WLOCK(inp);
+                                       inp->def_send.sinfo_flags &= 0xfff0;
+                                       inp->def_send.sinfo_flags |= 
info->pr_policy;
+                                       SCTP_INP_WUNLOCK(inp);
+                               }
+                               if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
+                                   (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
+                                       SCTP_INP_RLOCK(inp);
+                                       LIST_FOREACH(stcb, 
&inp->sctp_asoc_list, sctp_tcblist) {
+                                               SCTP_TCB_LOCK(stcb);
+                                               stcb->asoc.def_send.sinfo_flags 
&= 0xfff0;
+                                               stcb->asoc.def_send.sinfo_flags 
|= info->pr_policy;
+                                               SCTP_TCB_UNLOCK(stcb);
+                                       }
+                                       SCTP_INP_RUNLOCK(inp);
+                               }
+                       }
+                       break;
+               }
        default:
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, 
ENOPROTOOPT);
                error = ENOPROTOOPT;
_______________________________________________
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