DEFINE_APITEST(peeloff, goodcase) { int lfd, cfd, pfd; struct sockaddr_in addr; socklen_t addr_len; sctp_assoc_t assoc_id; if ((lfd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0) { RETURN_FAILED_WITH_ERRNO; } if (sctp_bind(lfd, INADDR_LOOPBACK, 0) < 0) { close(lfd); RETURN_FAILED_WITH_ERRNO; } if (listen(lfd, 1) < 0) { close(lfd); RETURN_FAILED_WITH_ERRNO; } if ((cfd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0) { close(lfd); RETURN_FAILED_WITH_ERRNO; } if (sctp_bind(cfd, INADDR_LOOPBACK, 0) < 0) { close(lfd); close(cfd); RETURN_FAILED_WITH_ERRNO; } addr_len = (socklen_t)sizeof(struct sockaddr_in); if (getsockname (lfd, (struct sockaddr *) &addr, &addr_len) < 0) { close(lfd); close(cfd); RETURN_FAILED_WITH_ERRNO; } if (sctp_connectx(cfd, (struct sockaddr *) &addr, 1, &assoc_id) < 0) { close(lfd); close(cfd); RETURN_FAILED_WITH_ERRNO; } sctp_delay(SCTP_SLEEP_MS); if ((pfd = sctp_peeloff(cfd, assoc_id)) < 0) { close(lfd); close(cfd); RETURN_FAILED_WITH_ERRNO; } if (close(pfd) < 0) { close(cfd); close(lfd); RETURN_FAILED_WITH_ERRNO; } if (close(cfd) < 0) { close(lfd); RETURN_FAILED_WITH_ERRNO; } if (close(lfd) < 0) { RETURN_FAILED_WITH_ERRNO; } RETURN_PASSED; }
int connectx_r(int sk, struct sockaddr *addrs, int count) { int error; int i; struct sockaddr *sa_addr; void *aptr; /* Set the port in every address. */ aptr = addrs; for (i = 0; i < count; i++) { sa_addr = (struct sockaddr *)aptr; switch(sa_addr->sa_family) { case AF_INET: ((struct sockaddr_in *)sa_addr)->sin_port = htons(remote_port); aptr += sizeof(struct sockaddr_in); break; case AF_INET6: ((struct sockaddr_in6 *)sa_addr)->sin6_port = htons(remote_port); aptr += sizeof(struct sockaddr_in6); break; default: fprintf(stderr, "Invalid address family\n"); exit(1); } } error = sctp_connectx(sk, addrs, count, NULL); if (error != 0) { fprintf(stderr, "\n\n\t\t*** connectx_r: error connecting" " to addrs: %s ***\n", strerror(errno)); exit(1); } return 0; } /* connectx_r() */
int SctpSocket::AddConnection(SocketAddress& ad) { if (!ad.IsValid()) { Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR); return -1; } if (GetSocket() == INVALID_SOCKET) { Handler().LogError(this, "SctpSocket", -1, "AddConnection called with invalid file descriptor", LOG_LEVEL_ERROR); return -1; } // int n = sctp_connectx(GetSocket(), ad, ad); int n = sctp_connectx(GetSocket(), ad, 1, NULL); if (n == -1) { Handler().LogError(this, "SctpSocket", -1, "sctp_connectx() failed", LOG_LEVEL_ERROR); } else { SetConnecting(); } return n; }
int main(int argc, char *argv[]) { int error,i; socklen_t len; int sk,lstn_sk,clnt_sk[SK_MAX],acpt_sk[SK_MAX],pf_class; int sk1,clnt2_sk; struct sockaddr_in conn_addr,lstn_addr,acpt_addr; struct sockaddr *tmp_addr; /* Rather than fflush() throughout the code, set stdout to * be unbuffered. */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); pf_class = PF_INET; sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); sk1 = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); /*Creating a listen socket*/ lstn_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); /*Creating a regular socket*/ for (i = 0 ; i < SK_MAX ; i++) clnt_sk[i] = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); clnt2_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); conn_addr.sin_family = AF_INET; conn_addr.sin_addr.s_addr = SCTP_IP_LOOPBACK; conn_addr.sin_port = htons(SCTP_TESTPORT_1); lstn_addr.sin_family = AF_INET; lstn_addr.sin_addr.s_addr = SCTP_IP_LOOPBACK; lstn_addr.sin_port = htons(SCTP_TESTPORT_1); /*Binding the listen socket*/ test_bind(lstn_sk, (struct sockaddr *) &lstn_addr, sizeof(lstn_addr)); /*Listening the socket*/ test_listen(lstn_sk, SK_MAX-1); /*sctp_connectx () TEST1: Bad socket descriptor, EBADF Expected error*/ len = sizeof(struct sockaddr_in); error = sctp_connectx(-1, (struct sockaddr *) &conn_addr, 1, NULL); if (error != -1 || errno != EBADF) tst_brkm(TBROK, tst_exit, "sctp_connectx with bad socket " "descriptor error:%d, errno:%d", error, errno); tst_resm(TPASS, "sctp_connectx() with bad socket descriptor - EBADF"); /*sctp_connectx () TEST2: Invalid socket, ENOTSOCK Expected error*/ error = sctp_connectx(0, (struct sockaddr *) &conn_addr, 1, NULL); if (error != -1 || errno != ENOTSOCK) tst_brkm(TBROK, tst_exit, "sctp_connectx with invalid socket " "error:%d, errno:%d", error, errno); tst_resm(TPASS, "sctp_connectx() with invalid socket - ENOTSOCK"); /*sctp_connectx () TEST3: Invalid address, EINVAL Expected error*/ tmp_addr = (struct sockaddr *) malloc(sizeof(struct sockaddr) - 1); tmp_addr->sa_family = AF_INET; error = sctp_connectx(sk, tmp_addr, 1, NULL); if (error != -1 || errno != EINVAL) tst_brkm(TBROK, tst_exit, "sctp_connectx with invalid address " "error:%d, errno:%d", error, errno); tst_resm(TPASS, "sctp_connectx() with invalid address - EINVAL"); /*sctp_connectx () TEST4: Invalid address length, EINVAL Expected error*/ error = sctp_connectx(sk, (struct sockaddr *) &conn_addr, 0, NULL); if (error != -1 || errno != EINVAL) tst_brkm(TBROK, tst_exit, "sctp_connectx with invalid address length " "error:%d, errno:%d", error, errno); tst_resm(TPASS, "sctp_connectx() with invalid address length - EINVAL"); /*sctp_connectx () TEST5: Invalid address family, EINVAL Expect error*/ conn_addr.sin_family = 9090; /*Assigning invalid address family*/ error = sctp_connectx(sk, (struct sockaddr *) &conn_addr, 1, NULL); if (error != -1 || errno != EINVAL) tst_brkm(TBROK, tst_exit, "sctp_connectx with invalid address family " "error:%d, errno:%d", error, errno); tst_resm(TPASS, "sctp_connectx() with invalid address family - EINVAL"); conn_addr.sin_family = AF_INET; /*sctp_connectx () TEST6: Blocking sctp_connectx, should pass*/ /*All the be below blocking sctp_connectx should pass as socket will be listening SK_MAX clients*/ for (i = 0 ; i < SK_MAX ; i++) { error = sctp_connectx(clnt_sk[i], (struct sockaddr *)&conn_addr, 1, NULL); if (error < 0) tst_brkm(TBROK, tst_exit, "valid blocking sctp_connectx " "error:%d, errno:%d", error, errno); } tst_resm(TPASS, "valid blocking sctp_connectx() - SUCCESS"); /*sctp_connectx () TEST7: sctp_connectx when accept queue is full, ECONNREFUSED Expect error*/ /*Now that accept queue is full, the below sctp_connectx should fail*/ error = sctp_connectx(clnt2_sk, (struct sockaddr *) &conn_addr, 1, NULL); if (error != -1 || errno != ECONNREFUSED) tst_brkm(TBROK, tst_exit, "sctp_connectx when accept queue is full " "error:%d, errno:%d", error, errno); tst_resm(TPASS, "sctp_connectx() when accept queue is full - ECONNREFUSED"); /*Calling a accept first to estblish the pending sctp_connectxions*/ for (i=0 ; i < SK_MAX ; i++) acpt_sk[i] = test_accept(lstn_sk, (struct sockaddr *) &acpt_addr, &len); /*sctp_connectx () TEST8: from a listening socket, EISCONN Expect error*/ error = sctp_connectx(lstn_sk, (struct sockaddr *) &lstn_addr, 1, NULL); if (error != -1 || errno != EISCONN) tst_brkm(TBROK, tst_exit, "sctp_connectx on a listening socket " "error:%d, errno:%d", error, errno); tst_resm(TPASS, "sctp_connectx() on a listening socket - EISCONN"); /*sctp_connectx() TEST9: On established socket, EISCONN Expect error*/ i=0; error = sctp_connectx(acpt_sk[i], (struct sockaddr *) &lstn_addr, 1, NULL); if (error != -1 || errno != EISCONN) tst_brkm(TBROK, tst_exit, "sctp_connectx on an established socket " "error:%d, errno:%d", error, errno); tst_resm(TPASS, "sctp_connectx() on an established socket - EISCONN"); for (i = 0 ; i < 4 ; i++) { close(clnt_sk[i]); close(acpt_sk[i]); } /* sctp_connectx() TEST10: Re-establish an association that is closed. * should succeed. */ error = sctp_connectx(sk1, (struct sockaddr *)&conn_addr, 1, NULL); if (error < 0) tst_brkm(TBROK, tst_exit, "Re-establish an association that " "is closed error:%d, errno:%d", error, errno); tst_resm(TPASS, "sctp_connectx() to re-establish a closed association - " "SUCCESS"); close(sk); close(sk1); close(lstn_sk); return 0; }
/* book add for multi-homing and normal sctp connection, 2012-12-29 */ int make_assoc_v2(int fid, int tid, unsigned char isServ, unsigned char multi_switch) { iu_log_debug("%s %d: %s\n",__FILE__, __LINE__, __func__); int idx = fid*MAX_REMOTE_EP + tid; int sock_fd = from[fid].sockid; int nRet = 0; struct sockaddr_in *paddr = (struct sockaddr_in*)&to[tid].addr[0]; struct sockaddr_in *saddr = (struct sockaddr_in*)&to[tid].addr[1]; struct sockaddr_in *addrs = NULL; int addr_count = multi_switch ? 2 : 1; int addr_size = sizeof(struct sockaddr_in); struct timeval tm; fd_set set; unsigned long ul = 1; ioctl(sock_fd, FIONBIO, &ul); // set to unblock mode int result = 0; int ret = 0; int error = -1; int len = sizeof(int); addrs = (struct sockaddr_in*)malloc(addr_size * addr_count); if(addrs == NULL) { perror("malloc"); return -1; } iu_log_debug("make_assoc sockid = %d, idx %d, tid %d, fid %d\n", sock_fd, idx, tid, fid); /* copy primary_addr to addrs */ memcpy(addrs+0, paddr, addr_size); iu_log_debug("make_assoc primary_ip = %x ,primary_port = %x\n", to[tid].addr[0].sin_addr.s_addr, to[tid].addr[0].sin_port); /* copy secondary_addr to addrs */ if(multi_switch) { memcpy(addrs+1, saddr, addr_size); iu_log_debug("make_assoc secondary_ip = %x ,secondary_port = %x\n", to[tid].addr[1].sin_addr.s_addr, to[tid].addr[1].sin_port); } if(!isServ) { nRet = sctp_connectx(sock_fd, (struct sockaddr*)addrs, addr_count); iu_log_debug("nRet = %d\n",nRet); } if(nRet == -1) { iu_log_debug("reset the connect block time\n"); tm.tv_sec = CONN_TIME_OUT; tm.tv_usec = 0; FD_ZERO(&set); FD_SET(sock_fd, &set); if( select(sock_fd+1, &set, NULL, NULL, &tm) > 0) { iu_log_debug("select result > 0\n"); getsockopt(sock_fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len); if(error == 0) { ret = 1; } else { iu_log_debug("use secondary addr successful."); to[tid].issecondary = 1; ret = 1; } } else { ret = 0;// true of false? } iu_log_debug("ret = %d\n",ret); ul = 0; ioctl(sock_fd, FIONBIO, &ul); //set to block mode if(!ret) { close(sock_fd); free(addrs); return -1; } else { iu_log_debug ("\n ### Connected to [%s]\n", (0==to[tid].issecondary)?inet_ntoa(paddr->sin_addr):inet_ntoa(saddr->sin_addr)); if (0 == assoc_table[idx].e_state) { assoc_table[idx].e_state = 1; assoc_table[idx].from = fid; assoc_table[idx].to = tid; assoc_table[idx].isClient = !isServ; FD_SET(from[fid].sockid, &readfds); if(from[fid].sockid > gMaxSock) { gMaxSock = from[fid].sockid; } iu_log_debug("idx = %d, assoc_table[%d].from = %d, assoc_table[%d].to = %d\n", idx, idx, assoc_table[idx].from, idx, assoc_table[idx].to); free(addrs); return idx; } } iu_log_debug("Cannot Connect the server!n"); } else if (nRet < 0) { iu_log_debug ("\n Unable to connect to remote server [%s] !! \n\n", inet_ntoa(paddr->sin_addr)); free(addrs); return -1; } else { iu_log_debug ("\nConnected to [%s]\n", inet_ntoa(paddr->sin_addr)); if (0 == assoc_table[idx].e_state) { assoc_table[idx].e_state = 1; assoc_table[idx].from = fid; assoc_table[idx].to = tid; assoc_table[idx].isClient = !isServ; FD_SET(from[fid].sockid, &readfds); if(from[fid].sockid > gMaxSock) { gMaxSock = from[fid].sockid; } iu_log_debug("idx = %d, assoc_table[%d].from = %d, assoc_table[%d].to = %d\n", idx, idx, assoc_table[idx].from, idx, assoc_table[idx].to); free(addrs); return idx; } } free(addrs); return -1; }
int main(int argc, char *argv[]) { int svr_sk, clt_sk1, clt_sk2, peeloff_sk; sctp_assoc_t svr_associd1, svr_associd2, clt_associd1, clt_associd2; struct iovec iov; struct msghdr inmessage; int error, i; struct sctp_assoc_change *sac; char *big_buffer; int flags; struct sockaddr_in svr_loop[NUMADDR]; struct sockaddr_in svr_try[NUMADDR]; struct sockaddr_in clt_loop1[NUMADDR]; struct sockaddr_in clt_loop2[NUMADDR]; struct sockaddr_in clt_loop3[NUMADDR]; sockaddr_storage_t svr_test[NUMADDR], clt_test1[NUMADDR], clt_test2[NUMADDR]; /* Rather than fflush() throughout the code, set stdout to * be unbuffered. */ setvbuf(stdout, NULL, _IONBF, 0); for (i = 0; i < NUMADDR; i++) { /* Initialize the server and client addresses. */ svr_loop[i].sin_family = AF_INET; svr_loop[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i); svr_loop[i].sin_port = htons(SCTP_TESTPORT_1); svr_test[i].v4.sin_family = AF_INET; svr_test[i].v4.sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i); svr_test[i].v4.sin_port = htons(SCTP_TESTPORT_1); svr_try[i].sin_family = AF_INET; if (i < (NUMADDR-1)) { svr_try[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i); } else { /* Make last address invalid. */ svr_try[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x400); } svr_try[i].sin_port = htons(SCTP_TESTPORT_1); clt_loop1[i].sin_family = AF_INET; clt_loop1[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x100); clt_loop1[i].sin_port = htons(SCTP_TESTPORT_2); clt_test1[i].v4.sin_family = AF_INET; clt_test1[i].v4.sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x100); clt_test1[i].v4.sin_port = htons(SCTP_TESTPORT_2); clt_loop2[i].sin_family = AF_INET; clt_loop2[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x200); clt_loop2[i].sin_port = htons(SCTP_TESTPORT_2+1); clt_test2[i].v4.sin_family = AF_INET; clt_test2[i].v4.sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x200); clt_test2[i].v4.sin_port = htons(SCTP_TESTPORT_2+1); clt_loop3[i].sin_family = AF_INET; clt_loop3[i].sin_addr.s_addr = SCTP_IP_LOOPBACK_I(i + 0x300); clt_loop3[i].sin_port = htons(SCTP_TESTPORT_2+2); } /* Create and bind the server socket. */ svr_sk = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); test_bind(svr_sk, (struct sockaddr *)&svr_loop[0], sizeof(svr_loop[0])); test_bindx_add(svr_sk, (struct sockaddr *)&svr_loop[1], NUMADDR-1); /* Mark server socket as being able to accept new associations. */ test_listen(svr_sk, 1); /* Create and bind the client sockets. */ clt_sk1 = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); test_bind(clt_sk1, (struct sockaddr *)&clt_loop1[0], sizeof(clt_loop1)); test_bindx_add(clt_sk1, (struct sockaddr *)&clt_loop1[1], NUMADDR-1); clt_sk2 = test_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); test_bind(clt_sk2, (struct sockaddr *)&clt_loop2[0], sizeof(clt_loop2)); test_bindx_add(clt_sk2, (struct sockaddr *)&clt_loop2[1], NUMADDR-1); /* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */ test_enable_assoc_change(svr_sk); test_enable_assoc_change(clt_sk1); test_enable_assoc_change(clt_sk2); /* Set clt_sk1 as non-blocking. */ flags = fcntl(clt_sk1, F_GETFL, 0); if (flags < 0) tst_brkm(TBROK, tst_exit, "fcntl F_GETFL: %s", strerror(errno)); if (fcntl(clt_sk1, F_SETFL, flags | O_NONBLOCK) < 0) tst_brkm(TBROK, tst_exit, "fcntl F_SETFL: %s", strerror(errno)); /* Do a non-blocking connectx from clt_sk1 to svr_sk */ error = sctp_connectx(clt_sk1, (struct sockaddr *)svr_try, NUMADDR); /* Non-blocking connectx should return immediately with EINPROGRESS. */ if ((error != -1) || (EINPROGRESS != errno)) tst_brkm(TBROK, tst_exit, "non-blocking connectx error: %d" "errno:%d", error, errno); tst_resm(TPASS, "non-blocking connectx"); /* Doing a connectx on a socket to create an association that is * is already established should return EISCONN. */ error = sctp_connectx(clt_sk1, (struct sockaddr *)svr_try, NUMADDR); if ((error != -1) || (EISCONN != errno)) tst_brkm(TBROK, tst_exit, "connectx on a socket to create an " "assoc that is already established error:%d errno:%d", error, errno); tst_resm(TPASS, "connectx on a socket to create an assoc that is " "already established"); /* Initialize inmessage for all receives. */ memset(&inmessage, 0, sizeof(inmessage)); big_buffer = test_malloc(REALLY_BIG); iov.iov_base = big_buffer; iov.iov_len = REALLY_BIG; inmessage.msg_iov = &iov; inmessage.msg_iovlen = 1; inmessage.msg_control = NULL; /* Get COMM_UP on clt_sk1 */ error = test_recvmsg(clt_sk1, &inmessage, MSG_WAITALL); test_check_msg_notification(&inmessage, error, sizeof(struct sctp_assoc_change), SCTP_ASSOC_CHANGE, SCTP_COMM_UP); sac = (struct sctp_assoc_change *)iov.iov_base; clt_associd1 = sac->sac_assoc_id; /* Get COMM_UP on svr_sk */ error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); test_check_msg_notification(&inmessage, error, sizeof(struct sctp_assoc_change), SCTP_ASSOC_CHANGE, SCTP_COMM_UP); sac = (struct sctp_assoc_change *)iov.iov_base; svr_associd1 = sac->sac_assoc_id; /* Do a blocking connectx from clt_sk2 to svr_sk. * Blocking connectx should block until the association is established * and return success. */ test_connectx(clt_sk2, (struct sockaddr *)svr_try, NUMADDR); /* Get COMM_UP on clt_sk2 */ error = test_recvmsg(clt_sk2, &inmessage, MSG_WAITALL); test_check_msg_notification(&inmessage, error, sizeof(struct sctp_assoc_change), SCTP_ASSOC_CHANGE, SCTP_COMM_UP); sac = (struct sctp_assoc_change *)iov.iov_base; clt_associd2 = sac->sac_assoc_id; /* Get COMM_UP on svr_sk */ error = test_recvmsg(svr_sk, &inmessage, MSG_WAITALL); test_check_msg_notification(&inmessage, error, sizeof(struct sctp_assoc_change), SCTP_ASSOC_CHANGE, SCTP_COMM_UP); sac = (struct sctp_assoc_change *)iov.iov_base; svr_associd2 = sac->sac_assoc_id; tst_resm(TPASS, "blocking connectx"); peeloff_sk = test_sctp_peeloff(svr_sk, svr_associd1); /* Doing a connectx on a peeled off socket should fail. */ error = sctp_connectx(peeloff_sk, (struct sockaddr *)clt_loop3, NUMADDR); if ((error != -1) || (EISCONN != errno)) tst_brkm(TBROK, tst_exit, "connectx on a peeled off socket " "error:%d, errno:%d", error, errno); tst_resm(TPASS, "connectx on a peeled off socket"); /* Trying to create an association on a socket that matches an * existing peeled-off association should fail. */ error = sctp_connectx(svr_sk, (struct sockaddr *)clt_loop1, NUMADDR); if ((error != -1) || (EADDRNOTAVAIL != errno)) tst_brkm(TBROK, tst_exit, "connectx to create an assoc that " "matches a peeled off assoc error:%d errno:%d", error, errno); tst_resm(TPASS, "connectx to create an assoc that matches a peeled off " "assoc"); test_peer_addr(peeloff_sk, svr_associd1, clt_test1, NUMADDR); tst_resm(TPASS, "server association 1 peers ok"); test_peer_addr(svr_sk, svr_associd2, clt_test2, NUMADDR); tst_resm(TPASS, "server association 2 peers ok"); test_peer_addr(clt_sk1, clt_associd1, svr_test, NUMADDR); tst_resm(TPASS, "client association 1 peers ok"); test_peer_addr(clt_sk2, clt_associd2, svr_test, NUMADDR); tst_resm(TPASS, "client association 2 peers ok"); close(svr_sk); close(clt_sk1); close(clt_sk2); close(peeloff_sk); /* Indicate successful completion. */ return 0; }
int main(int argc, char *argv[]) { int sockfd; int len; struct sockaddr_in serv_addr; struct sockaddr_in *addresses; int addr_size = sizeof(struct sockaddr_in); int addr_count = argc - 1; int port = ECHO_PORT; char *message = "hello\n"; struct sctp_initmsg initmsg; struct sctp_status status; struct sctp_sndrcvinfo sinfo; int ochannel; char *strr; //if (argc != 2) usage(); /* create endpoint */ sockfd = socket(AF_INET, SOCK_STREAM,IPPROTO_SCTP); if (sockfd < 0) { perror(NULL); exit(2); } /* connect to server */ addresses = malloc(addr_size); if (addresses == NULL) { exit(1); } serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(port); memcpy(addresses, &serv_addr, addr_size); memset(&initmsg, 0, sizeof(initmsg)); initmsg.sinit_max_instreams =2; initmsg.sinit_num_ostreams = 2; printf("Asking for: input streams: %d, output streams: %d\n",initmsg.sinit_max_instreams,initmsg.sinit_num_ostreams); if (setsockopt(sockfd, IPPROTO_SCTP,SCTP_INITMSG, &initmsg, sizeof(initmsg))) { perror("set sock opt\n"); } if (sctp_connectx(sockfd, (struct sockaddr *) addresses, 1,0) < 0) { perror("connectx"); exit(3); } memset(&status, 0, sizeof(status)); len = sizeof(status); status.sstat_assoc_id = 1; if (getsockopt(sockfd, IPPROTO_SCTP,SCTP_STATUS, &status, &len) == -1) { perror("get sock opt\n"); } printf("Got: input streams: %d, output streams: %d\n",status.sstat_instrms,status.sstat_outstrms); /* sanity check channel */ ochannel = 0; if (ochannel >= status.sstat_outstrms) printf("Writing on illegal channel %d\n", ochannel); time_t ctime_t; struct tm *gtime; time_t gmtime_t; time_t curtime; time(&curtime); printf("Current time = %s", ctime(&curtime)); // transfer data strr=ctime(&curtime); bzero(&sinfo, sizeof(sinfo)); sinfo.sinfo_stream = ochannel; sctp_send(sockfd, strr,strlen(strr), &sinfo, 0); sinfo.sinfo_flags = SCTP_EOF; sctp_send(sockfd, NULL, 0, &sinfo, 0); time_t ltime; time(<ime); printf ("Coordinated Universal Time is %s\n",asctime(gmtime(<ime))); //transfer data strr= asctime(gmtime(<ime)); bzero(&sinfo, sizeof(sinfo)); sinfo.sinfo_stream = 1; sctp_send(sockfd, strr, strlen(strr), &sinfo, 0); sinfo.sinfo_flags = SCTP_EOF; sctp_send(sockfd, NULL, 0, &sinfo, 0); close(sockfd); exit(0); }