Navigation


Changeset 23:db6c40b8b307 in freeDiameter for freeDiameter/sctp.c


Ignore:
Timestamp:
Oct 20, 2009, 5:30:20 PM (15 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Added some code in cnxctx.c mainly

File:
1 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/sctp.c

    r22 r23  
    3535
    3636#include "fD.h"
     37#include <netinet/sctp.h>
     38#include <sys/uio.h>
     39
     40/* Pre-binding socket options -- # streams read in config */
     41static int fd_setsockopt_prebind(int sk)
     42{
     43        #ifdef DEBUG_SCTP
     44        socklen_t sz;
     45        #endif /* DEBUG_SCTP */
     46       
     47        TRACE_ENTRY( "%d", sk);
     48       
     49        CHECK_PARAMS( sk > 0 );
     50       
     51        /* Subscribe to some notifications */
     52        {
     53                struct sctp_event_subscribe event;
     54
     55                memset(&event, 0, sizeof(event));
     56                event.sctp_data_io_event        = 1;    /* to receive the stream ID in SCTP_SNDRCV ancilliary data on message reception */
     57                event.sctp_association_event    = 0;    /* new or closed associations (mostly for one-to-many style sockets) */
     58                event.sctp_address_event        = 1;    /* address changes */
     59                event.sctp_send_failure_event   = 1;    /* delivery failures */
     60                event.sctp_peer_error_event     = 1;    /* remote peer sends an error */
     61                event.sctp_shutdown_event       = 1;    /* peer has sent a SHUTDOWN */
     62                event.sctp_partial_delivery_event = 1;  /* a partial delivery is aborted, probably indicating the connection is being shutdown */
     63                // event.sctp_adaptation_layer_event = 0;       /* adaptation layer notifications */
     64                // event.sctp_authentication_event = 0; /* when new key is made active */
     65
     66                /* Set the option to the socket */
     67                CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) );
     68               
     69                #ifdef DEBUG_SCTP
     70                sz = sizeof(event);
     71                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, &sz) );
     72                if (sz != sizeof(event))
     73                {
     74                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(event));
     75                        return ENOTSUP;
     76                }
     77               
     78                TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_data_io_event          : %hhu", event.sctp_data_io_event);
     79                TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_association_event      : %hhu", event.sctp_association_event);
     80                TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_address_event          : %hhu", event.sctp_address_event);
     81                TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_send_failure_event     : %hhu", event.sctp_send_failure_event);
     82                TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_peer_error_event       : %hhu", event.sctp_peer_error_event);
     83                TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_shutdown_event         : %hhu", event.sctp_shutdown_event);
     84                TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_partial_delivery_event : %hhu", event.sctp_partial_delivery_event);
     85                TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_adaptation_layer_event : %hhu", event.sctp_adaptation_layer_event);
     86                // TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_authentication_event   : %hhu", event.sctp_authentication_event);
     87                #endif /* DEBUG_SCTP */
     88               
     89        }
     90       
     91        /* Set the INIT parameters, such as number of streams */
     92        {
     93                struct sctp_initmsg init;
     94                memset(&init, 0, sizeof(init));
     95               
     96                #ifdef DEBUG_SCTP
     97                sz = sizeof(init);
     98               
     99                /* Read socket defaults */
     100                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz)  );
     101                if (sz != sizeof(init))
     102                {
     103                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(init));
     104                        return ENOTSUP;
     105                }
     106                TRACE_DEBUG(FULL, "Def SCTP_INITMSG sinit_num_ostreams   : %hu", init.sinit_num_ostreams);
     107                TRACE_DEBUG(FULL, "Def SCTP_INITMSG sinit_max_instreams  : %hu", init.sinit_max_instreams);
     108                TRACE_DEBUG(FULL, "Def SCTP_INITMSG sinit_max_attempts   : %hu", init.sinit_max_attempts);
     109                TRACE_DEBUG(FULL, "Def SCTP_INITMSG sinit_max_init_timeo : %hu", init.sinit_max_init_timeo);
     110                #endif /* DEBUG_SCTP */
     111
     112                /* Set the init options -- need to receive SCTP_COMM_UP to confirm the requested parameters */
     113                init.sinit_num_ostreams   = fd_g_config->cnf_sctp_str;  /* desired number of outgoing streams */
     114                init.sinit_max_init_timeo = CNX_TIMEOUT * 1000;
     115
     116                /* Set the option to the socket */
     117                CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init))  );
     118               
     119                #ifdef DEBUG_SCTP
     120                /* Check new values */
     121                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz)  );
     122                TRACE_DEBUG(FULL, "New SCTP_INITMSG sinit_num_ostreams   : %hu", init.sinit_num_ostreams);
     123                TRACE_DEBUG(FULL, "New SCTP_INITMSG sinit_max_instreams  : %hu", init.sinit_max_instreams);
     124                TRACE_DEBUG(FULL, "New SCTP_INITMSG sinit_max_attempts   : %hu", init.sinit_max_attempts);
     125                TRACE_DEBUG(FULL, "New SCTP_INITMSG sinit_max_init_timeo : %hu", init.sinit_max_init_timeo);
     126                #endif /* DEBUG_SCTP */
     127        }
     128       
     129        /* Set the SCTP_DISABLE_FRAGMENTS option, required for TLS */
     130        #ifdef SCTP_DISABLE_FRAGMENTS
     131        {
     132                int nofrag;
     133               
     134                #ifdef DEBUG_SCTP
     135                sz = sizeof(nofrag);
     136                /* Read socket defaults */
     137                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz)  );
     138                if (sz != sizeof(nofrag))
     139                {
     140                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nofrag));
     141                        return ENOTSUP;
     142                }
     143                TRACE_DEBUG(FULL, "Def SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false");
     144                #endif /* DEBUG_SCTP */
     145
     146                nofrag = 0;     /* We turn ON the fragmentation */
     147               
     148                /* Set the option to the socket */
     149                CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, sizeof(nofrag))  );
     150               
     151                #ifdef DEBUG_SCTP
     152                /* Check new values */
     153                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz)  );
     154                TRACE_DEBUG(FULL, "New SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false");
     155                #endif /* DEBUG_SCTP */
     156        }
     157        #else /* SCTP_DISABLE_FRAGMENTS */
     158        # error "TLS requires support of SCTP_DISABLE_FRAGMENTS"
     159        #endif /* SCTP_DISABLE_FRAGMENTS */
     160       
     161       
     162        /* Set the RETRANSMIT parameters */
     163        #ifdef SCTP_RTOINFO
     164        {
     165                struct sctp_rtoinfo rtoinfo;
     166                memset(&rtoinfo, 0, sizeof(rtoinfo));
     167
     168                #ifdef DEBUG_SCTP
     169                sz = sizeof(rtoinfo);
     170                /* Read socket defaults */
     171                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz)  );
     172                if (sz != sizeof(rtoinfo))
     173                {
     174                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(rtoinfo));
     175                        return ENOTSUP;
     176                }
     177                TRACE_DEBUG(FULL, "Def SCTP_RTOINFO srto_initial : %u", rtoinfo.srto_initial);
     178                TRACE_DEBUG(FULL, "Def SCTP_RTOINFO srto_max     : %u", rtoinfo.srto_max);
     179                TRACE_DEBUG(FULL, "Def SCTP_RTOINFO srto_min     : %u", rtoinfo.srto_min);
     180                #endif /* DEBUG_SCTP */
     181
     182                rtoinfo.srto_max     = fd_g_config->cnf_timer_tw * 500 - 1000;  /* Maximum retransmit timer (in ms) (set to Tw / 2 - 1) */
     183
     184                /* Set the option to the socket */
     185                CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo))  );
     186               
     187                #ifdef DEBUG_SCTP
     188                /* Check new values */
     189                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz)  );
     190                TRACE_DEBUG(FULL, "New SCTP_RTOINFO srto_initial : %u", rtoinfo.srto_initial);
     191                TRACE_DEBUG(FULL, "New SCTP_RTOINFO srto_max     : %u", rtoinfo.srto_max);
     192                TRACE_DEBUG(FULL, "New SCTP_RTOINFO srto_min     : %u", rtoinfo.srto_min);
     193                #endif /* DEBUG_SCTP */
     194        }
     195        #else /* SCTP_RTOINFO */
     196        # ifdef DEBUG_SCTP
     197        TRACE_DEBUG(FULL, "Skipping SCTP_RTOINFO");
     198        # endif /* DEBUG_SCTP */
     199        #endif /* SCTP_RTOINFO */
     200       
     201        /* Set the ASSOCIATION parameters */
     202        #ifdef SCTP_ASSOCINFO
     203        {
     204                struct sctp_assocparams assoc;
     205                memset(&assoc, 0, sizeof(assoc));
     206
     207                #ifdef DEBUG_SCTP
     208                sz = sizeof(assoc);
     209                /* Read socket defaults */
     210                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz)  );
     211                if (sz != sizeof(assoc))
     212                {
     213                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(assoc));
     214                        return ENOTSUP;
     215                }
     216                TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_asocmaxrxt               : %hu", assoc.sasoc_asocmaxrxt);
     217                TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations);
     218                TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_peer_rwnd                : %u" , assoc.sasoc_peer_rwnd);
     219                TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_local_rwnd               : %u" , assoc.sasoc_local_rwnd);
     220                TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_cookie_life              : %u" , assoc.sasoc_cookie_life);
     221                #endif /* DEBUG_SCTP */
     222
     223                assoc.sasoc_asocmaxrxt = 5;     /* Maximum retransmission attempts: we want fast detection of errors */
     224               
     225                /* Set the option to the socket */
     226                CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc))  );
     227               
     228                #ifdef DEBUG_SCTP
     229                /* Check new values */
     230                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz)  );
     231                TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_asocmaxrxt               : %hu", assoc.sasoc_asocmaxrxt);
     232                TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations);
     233                TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_peer_rwnd                : %u" , assoc.sasoc_peer_rwnd);
     234                TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_local_rwnd               : %u" , assoc.sasoc_local_rwnd);
     235                TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_cookie_life              : %u" , assoc.sasoc_cookie_life);
     236                #endif /* DEBUG_SCTP */
     237        }
     238        #else /* SCTP_ASSOCINFO */
     239        # ifdef DEBUG_SCTP
     240        TRACE_DEBUG(FULL, "Skipping SCTP_ASSOCINFO");
     241        # endif /* DEBUG_SCTP */
     242        #endif /* SCTP_ASSOCINFO */
     243       
     244       
     245        /* The SO_LINGER option will be re-set if we want to perform SCTP ABORT */
     246        #ifdef SO_LINGER
     247        {
     248                struct linger linger;
     249                memset(&linger, 0, sizeof(linger));
     250               
     251                #ifdef DEBUG_SCTP
     252                sz = sizeof(linger);
     253                /* Read socket defaults */
     254                CHECK_SYS(  getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz)  );
     255                if (sz != sizeof(linger))
     256                {
     257                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(linger));
     258                        return ENOTSUP;
     259                }
     260                TRACE_DEBUG(FULL, "Def SO_LINGER l_onoff  : %d", linger.l_onoff);
     261                TRACE_DEBUG(FULL, "Def SO_LINGER l_linger : %d", linger.l_linger);
     262                #endif /* DEBUG_SCTP */
     263               
     264                linger.l_onoff  = 0;    /* Do not activate the linger */
     265                linger.l_linger = 0;    /* Return immediately when closing (=> abort) */
     266               
     267                /* Set the option */
     268                CHECK_SYS(  setsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger))  );
     269               
     270                #ifdef DEBUG_SCTP
     271                /* Check new values */
     272                CHECK_SYS(  getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz)  );
     273                TRACE_DEBUG(FULL, "New SO_LINGER l_onoff  : %d", linger.l_onoff);
     274                TRACE_DEBUG(FULL, "New SO_LINGER l_linger : %d", linger.l_linger);
     275                #endif /* DEBUG_SCTP */
     276        }
     277        #else /* SO_LINGER */
     278        # ifdef DEBUG_SCTP
     279        TRACE_DEBUG(FULL, "Skipping SO_LINGER");
     280        # endif /* DEBUG_SCTP */
     281        #endif /* SO_LINGER */
     282       
     283        /* Set the NODELAY option (Nagle-like algorithm) */
     284        #ifdef SCTP_NODELAY
     285        {
     286                int nodelay;
     287               
     288                #ifdef DEBUG_SCTP
     289                sz = sizeof(nodelay);
     290                /* Read socket defaults */
     291                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz)  );
     292                if (sz != sizeof(nodelay))
     293                {
     294                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nodelay));
     295                        return ENOTSUP;
     296                }
     297                TRACE_DEBUG(FULL, "Def SCTP_NODELAY value : %s", nodelay ? "true" : "false");
     298                #endif /* DEBUG_SCTP */
     299
     300                nodelay = 0;    /* We turn ON the Nagle algorithm (probably the default already) */
     301               
     302                /* Set the option to the socket */
     303                CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay))  );
     304               
     305                #ifdef DEBUG_SCTP
     306                /* Check new values */
     307                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz)  );
     308                TRACE_DEBUG(FULL, "New SCTP_NODELAY value : %s", nodelay ? "true" : "false");
     309                #endif /* DEBUG_SCTP */
     310        }
     311        #else /* SCTP_NODELAY */
     312        # ifdef DEBUG_SCTP
     313        TRACE_DEBUG(FULL, "Skipping SCTP_NODELAY");
     314        # endif /* DEBUG_SCTP */
     315        #endif /* SCTP_NODELAY */
     316       
     317        /* Set the interleaving option */
     318        #ifdef SCTP_FRAGMENT_INTERLEAVE
     319        {
     320                int interleave;
     321               
     322                #ifdef DEBUG_SCTP
     323                sz = sizeof(interleave);
     324                /* Read socket defaults */
     325                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz)  );
     326                if (sz != sizeof(interleave))
     327                {
     328                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(interleave));
     329                        return ENOTSUP;
     330                }
     331                TRACE_DEBUG(FULL, "Def SCTP_FRAGMENT_INTERLEAVE value : %d", interleave);
     332                #endif /* DEBUG_SCTP */
     333
     334                #if 0
     335                interleave = 2; /* Allow partial delivery on several streams at the same time, since we are stream-aware in our security modules */
     336                #else /* 0 */
     337                interleave = 1; /* hmmm actually, we are not yet capable of handling this, and we don t need it. */
     338                #endif /* 0 */
     339               
     340                /* Set the option to the socket */
     341                CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, sizeof(interleave))  );
     342               
     343                #ifdef DEBUG_SCTP
     344                /* Check new values */
     345                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz)  );
     346                TRACE_DEBUG(FULL, "New SCTP_FRAGMENT_INTERLEAVE value : %d", interleave);
     347                #endif /* DEBUG_SCTP */
     348        }
     349        #else /* SCTP_FRAGMENT_INTERLEAVE */
     350        # ifdef DEBUG_SCTP
     351        TRACE_DEBUG(FULL, "Skipping SCTP_FRAGMENT_INTERLEAVE");
     352        # endif /* DEBUG_SCTP */
     353        #endif /* SCTP_FRAGMENT_INTERLEAVE */
     354       
     355        /* Set the v4 mapped addresses option */
     356        #ifdef SCTP_I_WANT_MAPPED_V4_ADDR
     357        {
     358                int v4mapped;
     359               
     360                #ifdef DEBUG_SCTP
     361                sz = sizeof(v4mapped);
     362                /* Read socket defaults */
     363                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz)  );
     364                if (sz != sizeof(v4mapped))
     365                {
     366                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(v4mapped));
     367                        return ENOTSUP;
     368                }
     369                TRACE_DEBUG(FULL, "Def SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false");
     370                #endif /* DEBUG_SCTP */
     371
     372                v4mapped = 0;   /* We don't want v4 mapped addresses */
     373                v4mapped = 1;   /* but we have to, otherwise the bind fails in linux currently ... (Ok, It'd be better with a cmake test, any volunteer?) */
     374               
     375                /* Set the option to the socket */
     376                CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, sizeof(v4mapped))  );
     377               
     378                #ifdef DEBUG_SCTP
     379                /* Check new values */
     380                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz)  );
     381                TRACE_DEBUG(FULL, "New SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false");
     382                #endif /* DEBUG_SCTP */
     383        }
     384        #else /* SCTP_I_WANT_MAPPED_V4_ADDR */
     385        # ifdef DEBUG_SCTP
     386        TRACE_DEBUG(FULL, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR");
     387        # endif /* DEBUG_SCTP */
     388        #endif /* SCTP_I_WANT_MAPPED_V4_ADDR */
     389                           
     390                           
     391        /* Other settable options (draft-ietf-tsvwg-sctpsocket-17):
     392           SO_RCVBUF                    size of receiver window
     393           SO_SNDBUF                    size of pending data to send
     394           SCTP_AUTOCLOSE               for one-to-many only
     395           SCTP_SET_PEER_PRIMARY_ADDR   ask remote peer to use this local address as primary
     396           SCTP_PRIMARY_ADDR            use this address as primary locally
     397           SCTP_ADAPTATION_LAYER        set adaptation layer indication
     398           SCTP_PEER_ADDR_PARAMS        control heartbeat per peer address
     399           SCTP_DEFAULT_SEND_PARAM      parameters for the sendto() call
     400           SCTP_MAXSEG                  max size of fragmented segments -- bound to PMTU
     401           SCTP_AUTH_CHUNK              request authentication of some type of chunk
     402            SCTP_HMAC_IDENT             authentication algorithms
     403            SCTP_AUTH_KEY               set a shared key
     404            SCTP_AUTH_ACTIVE_KEY        set the active key
     405            SCTP_AUTH_DELETE_KEY        remove a key
     406            SCTP_AUTH_DEACTIVATE_KEY    will not use that key anymore
     407           SCTP_DELAYED_SACK            control delayed acks
     408           SCTP_PARTIAL_DELIVERY_POINT  control partial delivery size
     409           SCTP_USE_EXT_RCVINFO         use extended receive info structure (information about the next message if available)
     410           SCTP_MAX_BURST               number of packets that can be burst emitted
     411           SCTP_CONTEXT                 save a context information along with the association.
     412           SCTP_EXPLICIT_EOR            enable sending one message across several send calls
     413           SCTP_REUSE_PORT              share one listening port with several sockets
     414           
     415           read-only options:
     416           SCTP_STATUS                  retrieve info such as number of streams, pending packets, state, ...
     417           SCTP_GET_PEER_ADDR_INFO      get information about a specific peer address of the association.
     418           SCTP_PEER_AUTH_CHUNKS        list of chunks the remote peer wants authenticated
     419           SCTP_LOCAL_AUTH_CHUNKS       list of chunks the local peer wants authenticated
     420           SCTP_GET_ASSOC_NUMBER        number of associations in a one-to-many socket
     421           SCTP_GET_ASSOC_ID_LIST       list of these associations
     422        */
     423       
     424        /* In case of no_ip4, force the v6only option */
     425        #ifdef IPV6_V6ONLY
     426        if (fd_g_config->cnf_flags.no_ip4) {
     427                int opt = 1;
     428                CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)));
     429        }
     430        #endif /* IPV6_V6ONLY */
     431       
     432        return 0;
     433}
     434
     435
     436/* Post-binding socket options */
     437static int fd_setsockopt_postbind(int sk, int bound_to_default)
     438{
     439        TRACE_ENTRY( "%d %d", sk, bound_to_default);
     440       
     441        CHECK_PARAMS( (sk > 0) );
     442       
     443        /* Set the ASCONF option */
     444        #ifdef SCTP_AUTO_ASCONF
     445        {
     446                int asconf;
     447               
     448                #ifdef DEBUG_SCTP
     449                socklen_t sz;
     450               
     451                sz = sizeof(asconf);
     452                /* Read socket defaults */
     453                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz)  );
     454                if (sz != sizeof(asconf))
     455                {
     456                        TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(asconf));
     457                        return ENOTSUP;
     458                }
     459                TRACE_DEBUG(FULL, "Def SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false");
     460                #endif /* DEBUG_SCTP */
     461
     462                asconf = bound_to_default ? 1 : 0;      /* allow automatic use of added or removed addresses in the association (for bound-all sockets) */
     463               
     464                /* Set the option to the socket */
     465                CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, sizeof(asconf))  );
     466               
     467                #ifdef DEBUG_SCTP
     468                /* Check new values */
     469                CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz)  );
     470                TRACE_DEBUG(FULL, "New SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false");
     471                #endif /* DEBUG_SCTP */
     472        }
     473        #else /* SCTP_AUTO_ASCONF */
     474        # ifdef DEBUG_SCTP
     475        TRACE_DEBUG(FULL, "Skipping SCTP_AUTO_ASCONF");
     476        # endif /* DEBUG_SCTP */
     477        #endif /* SCTP_AUTO_ASCONF */
     478       
     479        return 0;
     480}
    37481
    38482/* Create a socket server and bind it according to daemon s configuration */
    39483int fd_sctp_create_bind_server( int * sock, struct fd_list * list, uint16_t port )
    40484{
    41         TODO("Create sctp server, using fd_g_config: cnf_endpoints, no_ip4, no_ip6, cnf_sctp_str");
    42        
    43         return ENOTSUP;
     485        int family;
     486        int bind_default;
     487       
     488        TRACE_ENTRY("%p %p %hu", sock, list, port);
     489        CHECK_PARAMS(sock);
     490       
     491        if (fd_g_config->cnf_flags.no_ip6) {
     492                family = AF_INET;
     493        } else {
     494                family = AF_INET6; /* can create socket for both IP and IPv6 */
     495        }
     496       
     497        /* Create the socket */
     498        CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) );
     499       
     500        /* Set pre-binding socket options, including number of streams etc... */
     501        CHECK_FCT( fd_setsockopt_prebind(*sock) );
     502       
     503        bind_default = (! list) || (FD_IS_LIST_EMPTY(list)) ;
     504redo:
     505        if ( bind_default ) {
     506                /* Implicit endpoints : bind to default addresses */
     507                union {
     508                        sSS  ss;
     509                        sSA  sa;
     510                        sSA4 sin;
     511                        sSA6 sin6;
     512                } s;
     513               
     514                /* 0.0.0.0 and [::] are all zeros */
     515                memset(&s, 0, sizeof(s));
     516               
     517                s.sa.sa_family = family;
     518               
     519                if (family == AF_INET)
     520                        s.sin.sin_port = htons(port);
     521                else
     522                        s.sin6.sin6_port = htons(port);
     523               
     524                CHECK_SYS( bind(*sock, &s.sa, sizeof(s)) );
     525               
     526        } else {
     527                /* Explicit endpoints to bind to from config */
     528                union {
     529                        sSA     *sa;
     530                        sSA4    *sin;
     531                        sSA6    *sin6;
     532                } sar; /* build the list of endpoints to bind to */
     533                int count = 0; /* number of sock addr in sar array */
     534                struct fd_list * li;
     535               
     536                sar.sa = NULL;
     537               
     538                /* Create a flat array from the list of configured addresses */
     539                for (li = list->next; li != list; li = li->next) {
     540                        struct fd_endpoint * ep = (struct fd_endpoint *)li;
     541                       
     542                        if ( ! ep->meta.conf )
     543                                continue;
     544                       
     545                        count++;
     546                        if (fd_g_config->cnf_flags.no_ip6) {
     547                                ASSERT(ep->sa.sa_family == AF_INET);
     548                                CHECK_MALLOC( sar.sa = realloc(sar.sa, count * sizeof(sSA4))  );
     549                                memcpy(&sar.sin[count - 1], &ep->sin, sizeof(sSA4));
     550                                sar.sin[count - 1].sin_port = htons(port);
     551                        } else {
     552                                /* Pass all addresses as IPv6, eventually mapped -- we already filtered out IPv4 addresses if no_ip4 flag is set */
     553                                CHECK_MALLOC( sar.sa = realloc(sar.sa, count * sizeof(sSA6))  );
     554                                if (ep->sa.sa_family == AF_INET) {
     555                                        memset(&sar.sin6[count - 1], 0, sizeof(sSA6));
     556                                        sar.sin6[count - 1].sin6_family = AF_INET6;
     557                                        IN6_ADDR_V4MAP( &sar.sin6[count - 1].sin6_addr.s6_addr, ep->sin.sin_addr.s_addr );
     558                                } else {
     559                                        memcpy(&sar.sin6[count - 1], &ep->sin6, sizeof(sSA6));
     560                                }
     561                                sar.sin6[count - 1].sin6_port = htons(port);
     562                        }
     563                }
     564               
     565                if (!count) {
     566                        /* None of the addresses in the list came from configuration, we bind to default */
     567                        bind_default = 1;
     568                        goto redo;
     569                }
     570               
     571                # ifdef DEBUG_SCTP
     572                if (TRACE_BOOL(FULL)) {
     573                        int i;
     574                        fd_log_debug("Calling sctp_bindx with the following array:\n");
     575                        for (i = 0; i < count; i++) {
     576                                fd_log_debug("    - ");
     577                                sSA_DUMP_NODE_SERV( (sar.sa[0].sa_family == AF_INET) ? (sSA *)(&sar.sin[i]) : (sSA *)(&sar.sin6[i]), NI_NUMERICHOST | NI_NUMERICSERV );
     578                                fd_log_debug("\n");
     579                        }
     580                }
     581                #endif /* DEBUG_SCTP */
     582               
     583                CHECK_SYS(  sctp_bindx(*sock, sar.sa, count, SCTP_BINDX_ADD_ADDR)  );
     584               
     585        }
     586       
     587        /* Now, the server is bound, set remaining sockopt */
     588        CHECK_FCT( fd_setsockopt_postbind(*sock, bind_default) );
     589       
     590        #ifdef DEBUG_SCTP
     591        /* Debug: show all local listening addresses */
     592        if (TRACE_BOOL(FULL)) {
     593                sSA *sa, *sar;
     594                int sz;
     595               
     596                CHECK_SYS(  sz = sctp_getladdrs(*sock, 0, &sar)  );
     597               
     598                fd_log_debug("SCTP server bound on :\n");
     599                for (sa = sar; sz-- > 0; sa = (sSA *)(((uint8_t *)sa) + ((sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6)))) {
     600                        fd_log_debug("    - ");
     601                        sSA_DUMP_NODE_SERV( sa, NI_NUMERICHOST | NI_NUMERICSERV );
     602                        fd_log_debug("\n");
     603                }
     604                sctp_freeladdrs(sar);
     605        }
     606        #endif /* DEBUG_SCTP */
     607
     608        return 0;
    44609}
    45610
     
    60625}
    61626
     627/* Get the list of local endpoints of the socket */
     628int fd_sctp_get_local_ep(int sock, struct fd_list * list)
     629{
     630        union {
     631                sSA     *sa;
     632                sSA4    *sin;
     633                sSA6    *sin6;
     634                uint8_t *buf;
     635        } ptr;
     636       
     637        sSA * data;
     638        int count;
     639       
     640        TRACE_ENTRY("%d %p", sock, list);
     641        CHECK_PARAMS(list);
     642       
     643        /* Read the list on the socket */
     644        CHECK_SYS( count = sctp_getladdrs(sock, 0, &data)  );
     645        ptr.sa = data;
     646       
     647        while (count) {
     648                TODO("get the data from ptr");
     649                TODO("Increment ptr to the next sa in data");
     650               
     651                count --;
     652        }
     653       
     654        /* And now, free the list and return */
     655        sctp_freeladdrs(data);
     656       
     657        return ENOTSUP;
     658}
     659
     660/* Get the list of remote endpoints of the socket */
     661int fd_sctp_get_remote_ep(int sock, struct fd_list * list)
     662{
     663        TODO("SCTP: sctp_getpaddrs");
     664               
     665       
     666        return ENOTSUP;
     667}
     668
Note: See TracChangeset for help on using the changeset viewer.