int main(int argc,char **argv) { int sock_fd; int msg_flags; // 記錄要傳送訊息時的相關設定,包括association... char readbuf[BUFFERSIZE]; struct sockaddr_in cliaddr, servaddr; struct sctp_sndrcvinfo sri; struct sctp_event_subscribe evnts; socklen_t len; size_t rd_sz; // size_t指的就是unsigned long int ret_value=0; struct sockaddr *laddrs; // 用來記錄local addresses struct sockaddr *paddrs; union sctp_notification *snp; // 用來轉換傳送過來的訊息 struct sctp_shutdown_event *sse; // 當傳送過來的是shutdown event,則可以用這一個指標指到傳送過來的資料 struct sctp_assoc_change *sac; struct sctp_paddr_change *spc; struct sctp_remote_error *sre; struct sctp_send_failed *ssf; #ifdef UN_MOD struct sctp_adaptation_event *ae; #else struct sctp_adaption_event *ae; #endif struct sctp_pdapi_event *pdapi; int close_time = 30; const char *str; if (argc < 2) { printf("Error, use %s [list of addresses to bind]\n",argv[0]); exit(-1); } // 建立socket的型態為SCTP的one-to-many的型態 sock_fd = Socket(AF_INET,SOCK_SEQPACKET, IPPROTO_SCTP); if (sock_fd == -1) { printf("socket error\n"); exit(-1); } // 初始化要bind的server資料,連續加入多個要綁的ip address int i; for (i=1;i<argc;i++) { memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET,argv[i],&servaddr.sin_addr); // 把socket與此ip綁在一起 servaddr.sin_port = htons(SERV_PORT); // 把這一個ip與socket綁在一起 if ((ret_value=sctp_bindx(sock_fd,(struct sockaddr*) &servaddr,1,SCTP_BINDX_ADD_ADDR))==-1) { printf("Can't bind the address %s\n",argv[i]); exit(-1); } else { // 無論如何一定會bind成功,因為,若給錯的ip,則會bind此host端的所有ip printf("Bind %s success!!\n",argv[i]); } } // 設定事件 bzero(&evnts,sizeof(evnts)); evnts.sctp_data_io_event=1; // Enable sctp_sndrcvinfo to come with each recvmsg,否則就接收不到對方的資訊了 evnts.sctp_shutdown_event=1; // 喔耶!當client端shutdown時,會通知server evnts.sctp_association_event=1; // 監測 evnts.sctp_address_event = 1; evnts.sctp_send_failure_event = 1; evnts.sctp_peer_error_event = 1; evnts.sctp_partial_delivery_event = 1; #ifdef UN_MOD evnts.sctp_adaptation_layer_event = 1; #else evnts.sctp_adaption_layer_event = 1; #endif ret_value = setsockopt(sock_fd,IPPROTO_SCTP,SCTP_EVENTS,&evnts,sizeof(evnts)); if (ret_value == -1) { printf("setsockopt error\n"); exit(-1); } ret_value = setsockopt(sock_fd,IPPROTO_SCTP,SCTP_AUTOCLOSE,&close_time,sizeof(close_time)); if (ret_value == -1) { printf("setsockopt error\n"); exit(-1); } // 設定多少個client可以連線 ret_value = listen(sock_fd,LISTENQ); if (ret_value == -1) { printf("listen error\n"); exit(-1); } printf("start wait...\n"); for (;;) { memset(readbuf,0,sizeof(readbuf)); len = sizeof(struct sockaddr_in); rd_sz = sctp_recvmsg(sock_fd,readbuf,sizeof(readbuf),(struct sockaddr *) &cliaddr,&len,&sri,&msg_flags); //======================================================================== // test the sctp_getladdrs function - start ret_value = sctp_getladdrs(sock_fd,sri.sinfo_assoc_id,&laddrs); printf("The sctp_getladdrs return value is %d\n",ret_value); // test the sctp_getladdrs function - end // test the sctp_getpaddrs function - start ret_value = sctp_getpaddrs(sock_fd,sri.sinfo_assoc_id,&paddrs); printf("The sctp_getpaddrs return value is %d\n",ret_value); // test the sctp_getpaddrs function - end //======================================================================== if (msg_flags & MSG_NOTIFICATION) { // 表示收到一個事件通告,而非一個資料 snp = (union sctp_notification *) readbuf; switch (snp->sn_header.sn_type) { case SCTP_SHUTDOWN_EVENT: sse = &snp->sn_shutdown_event; printf("SCTP_SHUTDOWN_EVENT: assoc=0x%x\n",(uint32_t) sse->sse_assoc_id); break; case SCTP_ASSOC_CHANGE: sac = &snp->sn_assoc_change; switch (sac->sac_state) { case SCTP_COMM_UP: printf("COMMUNICATION UP\n"); break; case SCTP_COMM_LOST: printf("COMMUNICATION LOST\n"); break; case SCTP_RESTART: printf("RESTART\n"); break; case SCTP_SHUTDOWN_COMP: printf("SHUTDOWN COMPLETE\n"); break; case SCTP_CANT_STR_ASSOC: printf("CAN'T START ASSOC\n"); break; default: printf("UNKNOW\n"); break; } break; case SCTP_PEER_ADDR_CHANGE: spc = &snp->sn_paddr_change; switch(spc->spc_state) { case SCTP_ADDR_AVAILABLE: str = "ADDRESS AVAILABLE"; break; case SCTP_ADDR_UNREACHABLE: str = "ADDRESS UNREACHABLE"; break; case SCTP_ADDR_REMOVED: str = "ADDRESS REMOVED"; break; case SCTP_ADDR_ADDED: str = "ADDRESS ADDED"; break; case SCTP_ADDR_MADE_PRIM: str = "ADDRESS MADE PRIMARY"; break; case SCTP_ADDR_CONFIRMED: str = "ADDRESS MADE CONFIRMED"; break; default: str = "UNKNOW"; break; } printf("SCTP_PEER_ADDR_CHANGE: %s\n",str); break; case SCTP_REMOTE_ERROR: sre = &snp->sn_remote_error; printf("SCTP_REMOTE_ERROR\n"); break; case SCTP_SEND_FAILED: ssf = &snp->sn_send_failed; printf("SCTP_SEND_FAILED\n"); break; #ifdef UN_MOD case SCTP_ADAPTATION_INDICATION: ae = &snp->sn_adaptation_event; printf("SCTP_ADAPTION_INDICATION\n"); break; #else case SCTP_ADAPTION_INDICATION: ae = &snp->sn_adaption_event; printf("SCTP_ADAPTION_INDICATION\n"); break; #endif case SCTP_PARTIAL_DELIVERY_EVENT: pdapi = &snp->sn_pdapi_event; if (pdapi->pdapi_indication == SCTP_PARTIAL_DELIVERY_ABORTED) printf("SCTP_PARTIAL_DELIEVERY_ABORTED\n"); else printf("Unknown SCTP_PARTIAL_DELIVERY_EVENT\n"); break; default: printf("UNKNOWN notification\n"); break; } continue; } printf("%s",readbuf); ret_value = sctp_sendmsg(sock_fd,readbuf,rd_sz,(struct sockaddr *) &cliaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0); if (ret_value == -1) { printf("sctp_sendmsg error\n"); exit(-1); } } return 0; }
int SctpSocket::RemoveAddress(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, "RemoveAddress called with invalid file descriptor", LOG_LEVEL_ERROR); return -1; } int n = sctp_bindx(GetSocket(), ad, ad, SCTP_BINDX_REM_ADDR); if (n == -1) { Handler().LogError(this, "SctpSocket", -1, "sctp_bindx() failed", LOG_LEVEL_ERROR); } return n; }
int bindx_r(int sk, struct sockaddr *addrs, int count, int flag) { 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(local_port); aptr += sizeof(struct sockaddr_in); break; case AF_INET6: ((struct sockaddr_in6 *)sa_addr)->sin6_port = htons(local_port); aptr += sizeof(struct sockaddr_in6); break; default: fprintf(stderr, "Invalid address family\n"); exit(1); } } error = sctp_bindx(sk, addrs, count, flag); if (error != 0) { fprintf(stderr, "\n\n\t\t***bindx_r: error adding addrs:" " %s. ***\n", strerror(errno)); exit(1); } return 0; } /* bindx_r() */
int main(int argc, char **argv) { int fd, *cfdptr, c; size_t intlen; char *buffer; socklen_t addr_len; union sock_union{ struct sockaddr sa; struct sockaddr_in s4; struct sockaddr_in6 s6; } remote_addr; struct sockaddr_storage local_addr[MAX_LOCAL_ADDR]; char *local_addr_ptr = (char*) local_addr; unsigned int nr_local_addr = 0; struct timeval start_time, now, diff_time; int length, client; uint16_t local_port, remote_port, port; #ifdef SCTP_REMOTE_UDP_ENCAPS_PORT uint16_t udp_port = 0; struct sctp_udpencaps encaps; #endif double seconds; double throughput; const int on = 1; const int off = 0; int nodelay = 0; unsigned long i, number_of_messages; pthread_t tid; int rcvbufsize=0, sndbufsize=0, myrcvbufsize, mysndbufsize; struct linger linger; int fragpoint = 0; unsigned int timetolive = 0; unsigned int runtime = 0; struct sctp_setadaptation ind = {0}; #ifdef SCTP_AUTH_CHUNK unsigned int number_of_chunks_to_auth = 0; unsigned int chunk_number; unsigned char chunk[256]; struct sctp_authchunk sac; #endif struct sctp_assoc_value av; int unordered = 0; int ipv4only = 0; int ipv6only = 0; length = DEFAULT_LENGTH; number_of_messages = DEFAULT_NUMBER_OF_MESSAGES; port = DEFAULT_PORT; verbose = 0; very_verbose = 0; memset((void *) &remote_addr, 0, sizeof(remote_addr)); while ((c = getopt(argc, argv, "a:" #ifdef SCTP_AUTH_CHUNK "A:" #endif "Df:l:L:n:p:R:S:t:T:u" #ifdef SCTP_REMOTE_UDP_ENCAPS_PORT "U:" #endif "vV46")) != -1) switch(c) { case 'a': ind.ssb_adaptation_ind = atoi(optarg); break; #ifdef SCTP_AUTH_CHUNK case 'A': if (number_of_chunks_to_auth < 256) { chunk[number_of_chunks_to_auth++] = (unsigned char)atoi(optarg); } break; #endif case 'D': nodelay = 1; break; case 'f': fragpoint = atoi(optarg); break; case 'l': length = atoi(optarg); break; case 'L': if (nr_local_addr < MAX_LOCAL_ADDR) { struct sockaddr_in *s4 = (struct sockaddr_in*) local_addr_ptr; struct sockaddr_in6 *s6 = (struct sockaddr_in6*) local_addr_ptr; if (inet_pton(AF_INET6, optarg, &s6->sin6_addr)) { s6->sin6_family = AF_INET6; #ifdef HAVE_SIN_LEN s6->sin6_len = sizeof(struct sockaddr_in6); #endif local_addr_ptr += sizeof(struct sockaddr_in6); nr_local_addr++; } else { if (inet_pton(AF_INET, optarg, &s4->sin_addr)) { s4->sin_family = AF_INET; #ifdef HAVE_SIN_LEN s4->sin_len = sizeof(struct sockaddr_in); #endif local_addr_ptr += sizeof(struct sockaddr_in); nr_local_addr++; } else { printf("Invalid address\n"); fprintf(stderr, "%s", Usage); exit(1); } } } break; case 'n': number_of_messages = atoi(optarg); break; case 'p': port = atoi(optarg); break; case 'R': rcvbufsize = atoi(optarg); break; case 'S': sndbufsize = atoi(optarg); break; case 't': timetolive = atoi(optarg); break; case 'T': runtime = atoi(optarg); number_of_messages = 0; break; case 'u': unordered = 1; break; #ifdef SCTP_REMOTE_UDP_ENCAPS_PORT case 'U': udp_port = atoi(optarg); break; #endif case 'v': verbose = 1; break; case 'V': verbose = 1; very_verbose = 1; break; case '4': ipv4only = 1; if (ipv6only) { printf("IPv6 only already\n"); exit(1); } break; case '6': ipv6only = 1; if (ipv4only) { printf("IPv4 only already\n"); exit(1); } break; default: fprintf(stderr, "%s", Usage); exit(1); } if (optind == argc) { client = 0; local_port = port; remote_port = 0; } else { client = 1; local_port = 0; remote_port = port; } if (nr_local_addr == 0) { memset((void *) local_addr, 0, sizeof(local_addr)); if (ipv4only) { struct sockaddr_in *s4 = (struct sockaddr_in*) local_addr; s4->sin_family = AF_INET; #ifdef HAVE_SIN_LEN s4->sin_len = sizeof(struct sockaddr_in); #endif s4->sin_addr.s_addr = htonl(INADDR_ANY); } else { struct sockaddr_in6 *s6 = (struct sockaddr_in6*) local_addr; s6->sin6_family = AF_INET6; #ifdef HAVE_SIN_LEN s6->sin6_len = sizeof(struct sockaddr_in6); #endif s6->sin6_addr = in6addr_any; } nr_local_addr = 1; } local_addr_ptr = (char*) local_addr; for (i = 0; i < nr_local_addr; i++) { struct sockaddr_in *s4 = (struct sockaddr_in*) local_addr_ptr; struct sockaddr_in6 *s6 = (struct sockaddr_in6*) local_addr_ptr; if (s4->sin_family == AF_INET) { s4->sin_port = htons(local_port); local_addr_ptr += sizeof(struct sockaddr_in); if (ipv6only) { printf("Can't use IPv4 address when IPv6 only\n"); exit(1); } } else if (s6->sin6_family == AF_INET6) { s6->sin6_port = htons(local_port); local_addr_ptr += sizeof(struct sockaddr_in6); if (ipv4only) { printf("Can't use IPv6 address when IPv4 only\n"); exit(1); } } } if ((fd = socket((ipv4only ? AF_INET : AF_INET6), SOCK_STREAM, IPPROTO_SCTP)) < 0) perror("socket"); if (!ipv4only) { if (ipv6only) { if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) perror("ipv6only"); } else { if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&off, (socklen_t)sizeof(off)) < 0) perror("ipv6only"); } } #ifdef SCTP_AUTH_CHUNK for (chunk_number = 0; chunk_number < number_of_chunks_to_auth; chunk_number++) { sac.sauth_chunk = chunk[chunk_number]; if (setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &sac, (socklen_t)sizeof(struct sctp_authchunk)) < 0) perror("setsockopt"); } #endif if (ind.ssb_adaptation_ind > 0) { if (setsockopt(fd, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, (const void*)&ind, (socklen_t)sizeof(struct sctp_setadaptation)) < 0) { perror("setsockopt"); } } if (!client) { setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*)&on, (socklen_t)sizeof(on)); } #ifdef SCTP_REMOTE_UDP_ENCAPS_PORT memset(&encaps, 0, sizeof(struct sctp_udpencaps)); encaps.sue_address.ss_family = (ipv4only ? AF_INET : AF_INET6); encaps.sue_port = htons(udp_port); if (setsockopt(fd, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { perror("setsockopt"); } #endif if (nr_local_addr > 0) { if (sctp_bindx(fd, (struct sockaddr *)local_addr, nr_local_addr, SCTP_BINDX_ADD_ADDR) != 0) perror("bind"); } if (!client) { struct sctp_event_subscribe event; if (listen(fd, 100) < 0) perror("listen"); if (rcvbufsize) if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(int)) < 0) perror("setsockopt: rcvbuf"); if (verbose) { intlen = sizeof(int); if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &myrcvbufsize, (socklen_t *)&intlen) < 0) { perror("setsockopt: rcvbuf"); } else { fprintf(stdout,"Receive buffer size: %d.\n", myrcvbufsize); } } memset(&event, 0, sizeof(event)); event.sctp_data_io_event=1; if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) { perror("set event failed"); } while (1) { memset(&remote_addr, 0, sizeof(remote_addr)); if (ipv4only) { addr_len = sizeof(struct sockaddr_in); } else { addr_len = sizeof(struct sockaddr_in6); } cfdptr = malloc(sizeof(int)); if ((*cfdptr = accept(fd, (struct sockaddr *)&remote_addr, &addr_len)) < 0) { perror("accept"); continue; } if (verbose) { char temp[INET6_ADDRSTRLEN]; if (remote_addr.sa.sa_family == AF_INET) { fprintf(stdout,"Connection accepted from %s:%d\n", inet_ntop(AF_INET, &remote_addr.s4.sin_addr, temp, INET_ADDRSTRLEN), ntohs(remote_addr.s4.sin_port)); } else { fprintf(stdout,"Connection accepted from %s:%d\n", inet_ntop(AF_INET6, &remote_addr.s6.sin6_addr, temp, INET6_ADDRSTRLEN), ntohs(remote_addr.s6.sin6_port)); } } pthread_create(&tid, NULL, &handle_connection, (void *) cfdptr); } close(fd); } else { if (inet_pton(AF_INET6, argv[optind], &remote_addr.s6.sin6_addr)) { remote_addr.s6.sin6_family = AF_INET6; #ifdef HAVE_SIN_LEN remote_addr.s6.sin6_len = sizeof(struct sockaddr_in6); #endif remote_addr.s6.sin6_port = htons(remote_port); addr_len = sizeof(struct sockaddr_in6); if (ipv4only) { printf("Can't use IPv6 address when IPv4 only\n"); exit(1); } } else { if (inet_pton(AF_INET, argv[optind], &remote_addr.s4.sin_addr)) { remote_addr.s4.sin_family = AF_INET; #ifdef HAVE_SIN_LEN remote_addr.s4.sin_len = sizeof(struct sockaddr_in); #endif remote_addr.s4.sin_port = htons(remote_port); addr_len = sizeof(struct sockaddr_in); if (ipv6only) { printf("Can't use IPv4 address when IPv6 only\n"); exit(1); } } else { printf("Invalid address\n"); fprintf(stderr, "%s", Usage); exit(1); } } if (fragpoint) { av.assoc_id = 0; av.assoc_value = fragpoint; if (setsockopt(fd, IPPROTO_SCTP, SCTP_MAXSEG, &av, sizeof(av)) < 0) { perror("setsockopt: SCTP_MAXSEG"); } } if (connect(fd, (struct sockaddr *)&remote_addr, addr_len) < 0) { perror("connect"); } #ifdef SCTP_NODELAY /* Explicit settings, because LKSCTP does not enable it by default */ if (nodelay == 1) { if (setsockopt(fd, IPPROTO_SCTP, SCTP_NODELAY, (char *)&on, sizeof(on)) < 0) { perror("setsockopt: nodelay"); } } else { if (setsockopt(fd, IPPROTO_SCTP, SCTP_NODELAY, (char *)&off, sizeof(off)) < 0) { perror("setsockopt: nodelay"); } } #endif if (sndbufsize) if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(int)) < 0) { perror("setsockopt: sndbuf"); } if (verbose) { intlen = sizeof(int); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &mysndbufsize, (socklen_t *)&intlen) < 0) { perror("setsockopt: sndbuf"); } else { fprintf(stdout,"Send buffer size: %d.\n", mysndbufsize); } } buffer = malloc(length); memset(buffer, 'A', length); gettimeofday(&start_time, NULL); if (verbose) { printf("Start sending %ld messages...", (long)number_of_messages); fflush(stdout); } i = 0; done = 0; if (runtime > 0) { signal(SIGALRM, stop_sender); alarm(runtime); } while (!done && ((number_of_messages == 0) || (i < (number_of_messages - 1)))) { if (very_verbose) { printf("Sending message number %lu.\n", i); } if (sctp_sendmsg(fd, buffer, length, NULL, 0, 0, unordered?SCTP_UNORDERED:0, 0, timetolive, 0) < 0) { perror("sctp_sendmsg"); break; } i++; } if (sctp_sendmsg(fd, buffer, length, NULL, 0, 0, unordered?SCTP_EOF|SCTP_UNORDERED:SCTP_EOF, 0, timetolive, 0) < 0) { perror("sctp_sendmsg"); } i++; if (verbose) printf("done.\n"); linger.l_onoff = 1; linger.l_linger = LINGERTIME; if (setsockopt(fd, SOL_SOCKET, SO_LINGER,(char*)&linger, sizeof(struct linger)) < 0) { perror("setsockopt"); } close(fd); gettimeofday(&now, NULL); timersub(&now, &start_time, &diff_time); seconds = diff_time.tv_sec + (double)diff_time.tv_usec/1000000; fprintf(stdout, "%s of %ld messages of length %u took %f seconds.\n", "Sending", i, length, seconds); throughput = (double)i * (double)length / seconds; fprintf(stdout, "Throughput was %f Byte/sec.\n", throughput); } return 0; }
/* book add for multi-homing and normal sctp connection, 2012-12-29 */ int make_lep_v2(udp_addr_t p_addr, udp_addr_t s_addr, m3_u32 proc, m3_u8 multi_switch) { iu_log_debug("%s %d: %s\n",__FILE__, __LINE__, __func__); if(proc >= MAX_LOCAL_EP) { iu_log_error("Error: invalid value of proc\n"); return -1; } int idx = proc; int enable = 1; struct sockaddr_in *paddr = NULL; struct sockaddr_in *saddr = NULL; struct sockaddr_in *addrs = NULL; struct sctp_event_subscribe evt; int addr_count = multi_switch ? 2 : 1; int addr_size = sizeof(struct sockaddr_in); addrs = (struct sockaddr_in*)malloc(addr_size*addr_count); if(addrs == NULL) { perror("malloc"); return -1; } if (0 == from[idx].e_state) { paddr = (struct sockaddr_in*)&from[idx].addr[0]; paddr->sin_family = AF_INET; paddr->sin_port = htons(p_addr.port); paddr->sin_addr.s_addr = htonl(p_addr.ipaddr); /* copy primary_addr to addrs */ memcpy(addrs+0, paddr, addr_size); from[idx].e_state = 1; from[idx].sockid = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); iu_log_debug("socketid = %d, idx = %d, primary_ip = %x, primary_port = %x \n", from[idx].sockid, idx, from[idx].addr[0].sin_addr.s_addr, from[idx].addr[0].sin_port); if(multi_switch) { saddr = (struct sockaddr_in*)&from[idx].addr[1]; saddr->sin_family = AF_INET; saddr->sin_port = htons(s_addr.port); saddr->sin_addr.s_addr = htonl(s_addr.ipaddr); /* copy secondary_addr to addrs */ memcpy(addrs+1, saddr, addr_size); iu_log_debug("secondary_ip = %x, secondary_port = %x \n", from[idx].addr[1].sin_addr.s_addr, from[idx].addr[1].sin_port); } setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); if (-1 == sctp_bindx(from[idx].sockid, (struct sockaddr*)addrs, addr_count, SCTP_BINDX_ADD_ADDR)) { iu_log_debug("ERRNO:%d sctp lep bindx failed\n", errno); perror("sctp E_bind_Fail"); free(addrs); return -1; } memset(&evt, 0, sizeof(evt)); /* all event paras set default value to be 1 */ evt.sctp_data_io_event = 1; evt.sctp_association_event = 1; evt.sctp_address_event = 1; evt.sctp_send_failure_event = 1; evt.sctp_peer_error_event = 1; evt.sctp_shutdown_event = 1; evt.sctp_partial_delivery_event = 1; //evt.sctp_adaption_layer_event = 1; if (setsockopt(from[idx].sockid, IPPROTO_SCTP, SCTP_EVENTS, &evt, sizeof(evt)) != 0) { iu_log_debug("ERRNO:%d sctp lep setsockopt failed\n", errno); perror("setevent failed"); free(addrs); return -1; } if (-1 == listen(from[idx].sockid, 2)) { iu_log_debug("ERRNO:%d sctp lep listen failed\n", errno); perror("E_listen_Fail"); free(addrs); return -1; } } free(addrs); return idx; }
sctpAdaptorMod * create_SCTP_adaptor(distributor *o,uint16_t port, int model, int rwnd , int swnd ) { sctpAdaptorMod *r; socklen_t length; struct sockaddr_in6 inAddr6,myAddr6; struct sctp_event_subscribe event; int optval; socklen_t optlen; int bindsa_len; memset(&inAddr6,0,sizeof(inAddr6)); memset(&myAddr6,0,sizeof(myAddr6)); inAddr6.sin6_port = htons(port); myAddr6.sin6_port = 0; inAddr6.sin6_family = AF_INET6; myAddr6.sin6_family = AF_INET6; #ifdef HAVE_SA_LEN inAddr6.sin6_len = sizeof(struct sockaddr_in6); myAddr6.sin6_len = sizeof(struct sockaddr_in6); #endif memset(to_ip,0,sizeof(to_ip)); r = calloc(1,sizeof(sctpAdaptorMod)); if(r == NULL) return(r); r->o = o; if(model & SCTP_UDP_TYPE){ if (v4only) { mainFd = r->fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); } else { mainFd = r->fd = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP); } }else{ if (v4only) { mainFd = r->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); } else { mainFd = r->fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP); } } if(r->fd < 0){ printf("errno:%d\n", errno); free(r); return(NULL); } optval = 1; errno = 0; /* ret = ioctl(r->fd,FIONBIO,&optval); printf("ret from FIONBIO ioctl is %d err:%d\n", ret,errno); */ r->model = model & (SCTP_UDP_TYPE|SCTP_TCP_TYPE); if (v6only) { /* set this to v6 only... */ optval = 1; if (setsockopt(r->fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&optval, sizeof(optval)) == -1) { close(r->fd); free(r); return(NULL); } } /* fill in specific local server address if doing bind specific */ if (bindSpecific) { int i, ret; for (i=0; i<bindSpecific; i++) { struct sockaddr *sa = (struct sockaddr *)&bind_ss[i]; /* copy bind address in */ memcpy(&inAddr6, &bind_ss[i], sizeof(struct sockaddr_in6)); /* set desired port */ if (sa->sa_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *)&inAddr6; sin->sin_port = htons(port); bindsa_len = sizeof(struct sockaddr_in); } else { inAddr6.sin6_port = htons(port); bindsa_len = sizeof(struct sockaddr_in6); inAddr6.sin6_scope_id = scope_id; } errno = 0; ret = sctp_bindx(r->fd, (struct sockaddr *)&inAddr6, 1, SCTP_BINDX_ADD_ADDR); } } else { if (v4only) { struct sockaddr_in *sin = (struct sockaddr_in *)&inAddr6; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; #ifdef HAVE_SA_LEN sin->sin_len = sizeof(struct sockaddr_in); #endif sin->sin_port = htons(port); bindsa_len = sizeof(struct sockaddr_in); } else { inAddr6.sin6_port = htons(port); bindsa_len = sizeof(struct sockaddr_in6); inAddr6.sin6_scope_id = scope_id; } } /* enable all event notifications */ event.sctp_data_io_event = 1; event.sctp_association_event = 1; event.sctp_address_event = 1; event.sctp_send_failure_event = 1; event.sctp_peer_error_event = 1; event.sctp_shutdown_event = 1; event.sctp_partial_delivery_event = 1; #if defined(__BSD_SCTP_STACK__) event.sctp_adaptation_layer_event = 1; #else event.sctp_adaption_layer_event = 1; #endif #if defined(__BSD_SCTP_STACK__) event.sctp_authentication_event = 1; event.sctp_sender_dry_event = 1; event.sctp_stream_reset_event = 1; #endif if (setsockopt(r->fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) { printf("Can't do SET_EVENTS socket option! err:%d\n", errno); } optlen = 4; if(swnd) { optval = swnd; if(setsockopt(r->fd, SOL_SOCKET, SO_SNDBUF, &optval, optlen) != 0){ printf("err:%d could not set sndbuf\n",errno); } } if (rwnd){ optval = rwnd; if(setsockopt(r->fd, SOL_SOCKET, SO_RCVBUF, &optval, optlen) != 0){ printf("err:%d could not set rcvbuf\n",errno); } } optval = 0; if(getsockopt(r->fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) != 0) printf("err:%d could not read sndbuf\n",errno); else printf("snd buffer is %d\n",optval); optval = 0; if(getsockopt(r->fd, SOL_SOCKET, SO_RCVBUF, &optval, &optlen) != 0) printf("err:%d could not read rcvbuf\n",errno); else printf("rcv buffer is %d\n",optval); if ((port) && (bindSpecific == 0)) { if(bind(r->fd,(struct sockaddr *)&inAddr6, bindsa_len) < 0){ printf("bind failed err:%d\n",errno); close(r->fd); free(r); return(NULL); } } if(model & SCTP_UDP_TYPE){ printf("Calling listen for one-to-many model\n"); listen(r->fd,1); #ifdef __APPLE__ { int opt = 0; /* fix Apple listen() issue */ setsockopt(r->fd, IPPROTO_SCTP, SCTP_LISTEN_FIX, &opt, sizeof(opt)); } #endif } if(port){ length = sizeof(myAddr6); if(getsockname(r->fd, (struct sockaddr *)&myAddr6, &length) < 0){ printf("get sockname failed err:%d\n",errno); close(r->fd); free(r); return(NULL); } if(port != ntohs(myAddr6.sin6_port)){ printf("Can't get my port:%d got %d\n",port,ntohs(myAddr6.sin6_port)); close(r->fd); free(r); return(NULL); } } dist_addFd(o,r->fd,sctpFdInput,POLLIN,(void *)r); object_in = r; return(r); }
int main(int argc, char **argv) { int opt, sock, newsock, result, flags, if_index = 0, on = 1; socklen_t sinlen, opt_len; struct sockaddr_storage sin; struct addrinfo hints, *res; struct sctp_sndrcvinfo sinfo; struct pollfd poll_fd; char getsockopt_peerlabel[1024]; char byte, *peerlabel, msglabel[1024], if_name[30]; bool nopeer = false, verbose = false, ipv4 = false, snd_opt = false; char *context, *host_addr = NULL, *bindx_addr = NULL; struct sockaddr_in ipv4_addr; unsigned short port; while ((opt = getopt(argc, argv, "4b:h:inv")) != -1) { switch (opt) { case '4': ipv4 = true; break; case 'b': bindx_addr = optarg; break; case 'h': host_addr = optarg; break; case 'i': snd_opt = true; break; case 'n': nopeer = true; break; case 'v': verbose = true; break; default: usage(argv[0]); } } if ((argc - optind) != 2) usage(argv[0]); port = atoi(argv[optind + 1]); if (!port) usage(argv[0]); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_protocol = IPPROTO_SCTP; if (ipv4) hints.ai_family = AF_INET; else hints.ai_family = AF_INET6; if (!strcmp(argv[optind], "stream")) hints.ai_socktype = SOCK_STREAM; else if (!strcmp(argv[optind], "seq")) hints.ai_socktype = SOCK_SEQPACKET; else usage(argv[0]); if (verbose) { if (getcon(&context) < 0) context = strdup("unavailable"); printf("Server process context: %s\n", context); free(context); } if (host_addr) { char *ptr; ptr = strpbrk(host_addr, "%"); if (ptr) strcpy(if_name, ptr + 1); if_index = if_nametoindex(if_name); if (!if_index) { perror("Server if_nametoindex"); exit(1); } result = getaddrinfo(host_addr, argv[optind + 1], &hints, &res); } else { result = getaddrinfo(NULL, argv[optind + 1], &hints, &res); } if (result < 0) { fprintf(stderr, "Server getaddrinfo: %s\n", gai_strerror(result)); exit(1); } sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) { perror("Server socket"); exit(1); } result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (result < 0) { perror("Server setsockopt: SO_REUSEADDR"); close(sock); exit(1); } /* Enables sctp_data_io_events for sctp_recvmsg(3) for assoc_id. */ result = setsockopt(sock, SOL_SCTP, SCTP_EVENTS, &on, sizeof(on)); if (result < 0) { perror("Server setsockopt: SCTP_EVENTS"); close(sock); exit(1); } if (bindx_addr) { memset(&ipv4_addr, 0, sizeof(struct sockaddr_in)); ipv4_addr.sin_family = AF_INET; ipv4_addr.sin_port = htons(port); ipv4_addr.sin_addr.s_addr = inet_addr(bindx_addr); result = sctp_bindx(sock, (struct sockaddr *)&ipv4_addr, 1, SCTP_BINDX_ADD_ADDR); if (result < 0) { perror("Server sctp_bindx ADD - ipv4"); close(sock); exit(1); } } else { result = bind(sock, res->ai_addr, res->ai_addrlen); if (result < 0) { perror("Server bind"); close(sock); exit(1); } } if (verbose) { print_context(sock, "Server LISTEN"); print_ip_option(sock, ipv4, "Server LISTEN"); } if (listen(sock, SOMAXCONN)) { perror("Server listen"); close(sock); exit(1); } if (hints.ai_socktype == SOCK_STREAM) { if (verbose) print_context(sock, "Server STREAM"); do { socklen_t labellen = sizeof(getsockopt_peerlabel); sinlen = sizeof(sin); newsock = accept(sock, (struct sockaddr *)&sin, &sinlen); if (newsock < 0) { perror("Server accept"); close(sock); exit(1); } if (verbose) { print_context(newsock, "Server STREAM accept on newsock"); print_addr_info((struct sockaddr *)&sin, "Server connected to Client"); print_ip_option(newsock, ipv4, "Server STREAM accept on newsock"); } if (nopeer) { peerlabel = strdup("nopeer"); } else if (snd_opt) { peerlabel = get_ip_option(newsock, ipv4, &opt_len); if (!peerlabel) peerlabel = strdup("no_ip_options"); } else { result = getpeercon(newsock, &peerlabel); if (result < 0) { perror("Server getpeercon"); close(sock); close(newsock); exit(1); } /* Also test the getsockopt version */ result = getsockopt(newsock, SOL_SOCKET, SO_PEERSEC, getsockopt_peerlabel, &labellen); if (result < 0) { perror("Server getsockopt: SO_PEERSEC"); close(sock); close(newsock); exit(1); } if (verbose) printf("Server STREAM SO_PEERSEC peer label: %s\n", getsockopt_peerlabel); } printf("Server STREAM %s: %s\n", snd_opt ? "sock_opt" : "peer label", peerlabel); result = read(newsock, &byte, 1); if (result < 0) { perror("Server read"); close(sock); close(newsock); exit(1); } result = write(newsock, peerlabel, strlen(peerlabel)); if (result < 0) { perror("Server write"); close(sock); close(newsock); exit(1); } if (verbose) printf("Server STREAM sent: %s\n", peerlabel); free(peerlabel); /* Let the client close the connection first as this * will stop OOTB chunks if newsock closed early. */ poll_fd.fd = newsock; poll_fd.events = POLLRDHUP; poll_fd.revents = 1; result = poll(&poll_fd, 1, 1000); if (verbose && result == 1) printf("Server STREAM: Client closed connection\n"); else if (verbose && result == 0) printf("Server: poll(2) timed out - OKAY\n"); else if (result < 0) perror("Server - poll"); close(newsock); } while (1); } else { /* hints.ai_socktype == SOCK_SEQPACKET */ if (verbose) print_context(sock, "Server SEQPACKET sock"); do { sinlen = sizeof(sin); result = sctp_recvmsg(sock, msglabel, sizeof(msglabel), (struct sockaddr *)&sin, &sinlen, &sinfo, &flags); if (result < 0) { perror("Server sctp_recvmsg"); close(sock); exit(1); } if (verbose) { print_context(sock, "Server SEQPACKET recvmsg"); print_addr_info((struct sockaddr *)&sin, "Server SEQPACKET recvmsg"); print_ip_option(sock, ipv4, "Server SEQPACKET recvmsg"); } if (nopeer) { peerlabel = strdup("nopeer"); } else if (snd_opt) { peerlabel = get_ip_option(sock, ipv4, &opt_len); if (!peerlabel) peerlabel = strdup("no_ip_options"); } else { result = getpeercon(sock, &peerlabel); if (result < 0) { perror("Server getpeercon"); close(sock); exit(1); } } printf("Server SEQPACKET %s: %s\n", snd_opt ? "sock_opt" : "peer label", peerlabel); if (sin.ss_family == AF_INET6 && host_addr) ((struct sockaddr_in6 *)&sin)->sin6_scope_id = if_index; result = sctp_sendmsg(sock, peerlabel, strlen(peerlabel), (struct sockaddr *)&sin, sinlen, 0, 0, 0, 0, 0); if (result < 0) { perror("Server sctp_sendmsg"); close(sock); exit(1); } if (verbose) printf("Server SEQPACKET sent: %s\n", peerlabel); free(peerlabel); } while (1); } close(sock); exit(0); }
static int mca_btl_sctp_create(int if_index, const char* if_name) { if(mca_btl_sctp_component.sctp_if_11) { char param[256]; struct mca_btl_sctp_module_t* btl = (struct mca_btl_sctp_module_t *)malloc(sizeof(mca_btl_sctp_module_t)); if(NULL == btl) { return OMPI_ERR_OUT_OF_RESOURCE; } memcpy(btl, &mca_btl_sctp_module, sizeof(mca_btl_sctp_module)); OBJ_CONSTRUCT(&btl->sctp_endpoints, opal_list_t); mca_btl_sctp_component.sctp_btls[mca_btl_sctp_component.sctp_num_btls++] = btl; /* initialize the btl */ btl->sctp_ifindex = if_index; #if MCA_BTL_SCTP_STATISTICS btl->sctp_bytes_recv = 0; btl->sctp_bytes_sent = 0; btl->sctp_send_handler = 0; #endif opal_ifindextoaddr(if_index, (struct sockaddr*)&btl->sctp_ifaddr, sizeof(btl->sctp_ifaddr)); /* prepare for bind call later before connect */ btl->sctp_ifaddr.sin_family = AF_INET; #ifdef FREEBSD btl->sctp_ifaddr.sin_len = sizeof(struct sockaddr); #endif btl->sctp_ifaddr.sin_port = 0; opal_ifindextomask(if_index, (uint32_t *)&btl->sctp_ifmask, sizeof(btl->sctp_ifmask)); /* allow user to specify interface bandwidth */ sprintf(param, "bandwidth_%s", if_name); btl->super.btl_bandwidth = mca_btl_sctp_param_register_int(param, 0); /* allow user to override/specify latency ranking */ sprintf(param, "latency_%s", if_name); btl->super.btl_latency = mca_btl_sctp_param_register_int(param, 0); #if 0 && OPAL_ENABLE_DEBUG BTL_OUTPUT(("interface: %s bandwidth %d latency %d", if_name, btl->super.btl_bandwidth, btl->super.btl_latency)); #endif return OMPI_SUCCESS; } else { /* 1 to many */ struct mca_btl_sctp_module_t* btl; char param[256]; struct sockaddr_in next_ifaddr; socklen_t len = sizeof(struct sockaddr_in); opal_socklen_t addrlen; /* check if this is the first time this function is being called */ if(0 == mca_btl_sctp_component.sctp_num_btls) { /* fill in btl struct with first interface's information (arbitary) */ btl = (struct mca_btl_sctp_module_t *)malloc(sizeof(mca_btl_sctp_module_t)); if(NULL == btl) { return OMPI_ERR_OUT_OF_RESOURCE; } memcpy(btl, &mca_btl_sctp_module, sizeof(mca_btl_sctp_module)); OBJ_CONSTRUCT(&btl->sctp_endpoints, opal_list_t); mca_btl_sctp_component.sctp_btls[mca_btl_sctp_component.sctp_num_btls++] = btl; /* initialize the btl */ btl->sctp_ifindex = if_index; #if MCA_BTL_SCTP_STATISTICS btl->sctp_bytes_recv = 0; btl->sctp_bytes_sent = 0; btl->sctp_send_handler = 0; #endif opal_ifindextoaddr(if_index, (struct sockaddr*)&btl->sctp_ifaddr, sizeof(btl->sctp_ifaddr)); opal_ifindextomask(if_index, (uint32_t *)&btl->sctp_ifmask, sizeof(btl->sctp_ifmask)); /* allow user to specify interface bandwidth */ sprintf(param, "bandwidth_%s", if_name); btl->super.btl_bandwidth = mca_btl_sctp_param_register_int(param, 0); /* allow user to override/specify latency ranking */ sprintf(param, "latency_%s", if_name); btl->super.btl_latency = mca_btl_sctp_param_register_int(param, 0); #if 0 && OPAL_ENABLE_DEBUG BTL_OUTPUT(("interface: %s bandwidth %d latency %d", if_name, btl->super.btl_bandwidth, btl->super.btl_latency)); #endif /* call bind to this (initial) addr */ opal_ifindextoaddr(if_index, (struct sockaddr*)&next_ifaddr, sizeof(next_ifaddr)); next_ifaddr.sin_family = AF_INET; #ifdef FREEBSD next_ifaddr.sin_len = sizeof(struct sockaddr); #endif next_ifaddr.sin_port = 0; if(bind(mca_btl_sctp_component.sctp_listen_sd, (struct sockaddr *) &next_ifaddr, len) < 0) { return OMPI_ERR_FATAL; } /* resolve system assignend port */ addrlen = sizeof(struct sockaddr_in); if(getsockname(mca_btl_sctp_component.sctp_listen_sd, (struct sockaddr*)&next_ifaddr, &addrlen) < 0) { BTL_ERROR(("getsockname() failed with errno=%d", opal_socket_errno)); return OMPI_ERROR; } /* need to get the port after the first bind call for subsequent * sctp_bindx calls. */ mca_btl_sctp_component.sctp_listen_port = next_ifaddr.sin_port; } else { next_ifaddr.sin_port = htons((unsigned short) mca_btl_sctp_component.sctp_listen_port); /* add this addr to bindx */ opal_ifindextoaddr(if_index, (struct sockaddr*)&next_ifaddr, sizeof(next_ifaddr)); next_ifaddr.sin_family = AF_INET; #ifdef FREEBSD next_ifaddr.sin_len = sizeof(struct sockaddr); #endif if(sctp_bindx(mca_btl_sctp_component.sctp_listen_sd, (struct sockaddr *) &next_ifaddr, 1, SCTP_BINDX_ADD_ADDR) < 0) { return OMPI_ERR_FATAL; } } return OMPI_SUCCESS; } }
static PyObject* bindx(PyObject* dummy, PyObject* args) { PyObject* ret = 0; int fd; PyObject* addrs; struct sockaddr saddr; struct sockaddr* saddrs; int saddr_len, saddrs_len; int addrcount; int flags; int x; if (! PyArg_ParseTuple(args, "iOi", &fd, &addrs, &flags)) { return ret; } if (! PySequence_Check(addrs)) { PyErr_SetString(PyExc_ValueError, "Second parameter must be a sequence of address/port tuples"); return ret; } addrcount = PySequence_Length(addrs); if (addrcount <= 0) { PyErr_SetString(PyExc_ValueError, "Second parameter must be a non-empty sequence"); return ret; } saddrs_len = 0; saddrs = (struct sockaddr*) malloc(saddrs_len); for(x = 0; x < addrcount; ++x) { const char* caddr; int iport; PyObject* otuple = PySequence_GetItem(addrs, x); if (! PyArg_ParseTuple(otuple, "si", &caddr, &iport)) { free(saddrs); return ret; } if (! to_sockaddr(caddr, iport, &saddr, &saddr_len)) { PyErr_Format(PyExc_ValueError, "Invalid address: %s", caddr); free(saddrs); return ret; } if (saddr_len == 0) { PyErr_Format(PyExc_ValueError, "Invalid address family: %s", caddr); free(saddrs); return ret; } saddrs = realloc(saddrs, saddrs_len + saddr_len); memcpy( ((char*) saddrs) + saddrs_len, &saddr, saddr_len); saddrs_len += saddr_len; } if (sctp_bindx(fd, saddrs, addrcount, flags)) { PyErr_SetFromErrno(PyExc_IOError); } else { ret = Py_None; Py_INCREF(ret); } free(saddrs); return ret; }
int main(int argc, char **argv) { unsigned int i, j, k; int num_messages=24; struct sockaddr_in bindaddr[10]; char *baddr[10]; int bndcnt=0; char *toaddr = NULL; int port = htons(DISCARD_PORT); while((i= getopt(argc,argv,"P:I:B:b:h:p:m:?")) != EOF) { switch(i) { case 'p': port = htons(strtol(optarg, NULL, 0)); break; case 'P': pframe_rel = strtol(optarg, NULL, 0); break; case 'I': iframe_rel = strtol(optarg, NULL, 0); break; case 'B': bframe_rel = strtol(optarg, NULL, 0); break; case 'b': if (bndcnt < 10) { baddr[bndcnt] = optarg; bndcnt++; } break; case 'h': toaddr = optarg; break; case 'm': num_messages = strtol(optarg, NULL, 0); break; case '?': default: goto use; break; }; } if (toaddr == NULL) { use: printf("use %s -h to-addr-in-dot-notation [-m message-cnt -b bindaddr]\n", argv[0]); printf(" [-P rel -I rel -B rel]\n"); exit(0); } memset((void *)buffer, 'A', SIZE_OF_MESSAGE); if ((fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0) perror("socket"); i = 1; if(setsockopt(fd, IPPROTO_SCTP, SCTP_NODELAY, &i, sizeof(int))<0) { perror("SCTP_NODELAY"); } if (bndcnt) { /* prepare */ memset(bindaddr, 0, sizeof(bindaddr)); for(i=0; i<bndcnt; i++) { bindaddr[i].sin_len = sizeof(struct sockaddr_in); bindaddr[i].sin_family = AF_INET; bindaddr[i].sin_port = 0; inet_pton(AF_INET, baddr[i], &bindaddr[i].sin_addr); } /* bindx */ if (sctp_bindx(fd, (struct sockaddr *)bindaddr, bndcnt, SCTP_BINDX_ADD_ADDR) != 0) { perror("bind failed"); exit(0); } } memset((void *)&addr, 0, sizeof(struct sockaddr_in)); addr.sin_len = sizeof(struct sockaddr_in); addr.sin_family = AF_INET; addr.sin_port = port; inet_pton(AF_INET, toaddr, &addr.sin_addr); for (i = 0; i < num_messages; i++) { if (send_iframe() < 0) { exit(-4); } if (send_pframe() < 0) { exit(-3); } for (j=0; j<5; j++) { if (send_pframe() < 0) { exit(-2); } for (k=0; k<6; k++) { if (send_bframe() < 0) { exit(-1); } } } } if (close(fd) < 0) perror("close"); printf("\n"); return(0); }
static int sctp_create_new_listener(SctpInit *init_p) { struct sctp_event_subscribe event; struct sockaddr *addr; struct sctp_arg_s *sctp_arg_p; uint16_t i = 0, j; int sd; int used_addresses = 0; DevAssert(init_p != NULL); if (init_p->ipv4 == 0 && init_p->ipv6 == 0) { SCTP_ERROR("Illegal IP configuration upper layer should request at" "least ipv4 and/or ipv6 config\n"); return -1; } if ((used_addresses = init_p->nb_ipv4_addr + init_p->nb_ipv6_addr) == 0) { SCTP_WARN("No address provided...\n"); return -1; } addr = calloc(used_addresses, sizeof(struct sockaddr)); SCTP_DEBUG("Creating new listen socket on port %u with\n", init_p->port); if (init_p->ipv4 == 1) { struct sockaddr_in *ip4_addr; SCTP_DEBUG("ipv4 addresses:\n"); for (i = 0; i < init_p->nb_ipv4_addr; i++) { SCTP_DEBUG("\t- "IPV4_ADDR"\n", IPV4_ADDR_FORMAT(init_p->ipv4_address[i])); ip4_addr = (struct sockaddr_in *)&addr[i]; ip4_addr->sin_family = AF_INET; ip4_addr->sin_port = htons(init_p->port); ip4_addr->sin_addr.s_addr = init_p->ipv4_address[i]; } } if (init_p->ipv6 == 1) { struct sockaddr_in6 *ip6_addr; SCTP_DEBUG("ipv6 addresses:\n"); for (j = 0; j < init_p->nb_ipv6_addr; j++) { SCTP_DEBUG("\t- %s\n", init_p->ipv6_address[j]); ip6_addr = (struct sockaddr_in6 *)&addr[i + j]; ip6_addr->sin6_family = AF_INET6; ip6_addr->sin6_port = htons(init_p->port); if (inet_pton(AF_INET6, init_p->ipv6_address[j], ip6_addr->sin6_addr.s6_addr) <= 0) { SCTP_WARN("Provided ipv6 address %s is not valid\n", init_p->ipv6_address[j]); } } } if ((sd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0) { SCTP_ERROR("socket: %s:%d\n", strerror(errno), errno); return -1; } memset((void *)&event, 1, sizeof(struct sctp_event_subscribe)); if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe)) < 0) { SCTP_ERROR("setsockopt: %s:%d\n", strerror(errno), errno); return -1; } /* Some pre-bind socket configuration */ if (sctp_set_init_opt(sd, sctp_desc.nb_instreams, sctp_desc.nb_outstreams, 0, 0) < 0) { goto err; } if (sctp_bindx(sd, addr, used_addresses, SCTP_BINDX_ADD_ADDR) != 0) { SCTP_ERROR("sctp_bindx: %s:%d\n", strerror(errno), errno); return -1; } if (listen(sd, 5) < 0) { SCTP_ERROR("listen: %s:%d\n", strerror(errno), errno); return -1; } if ((sctp_arg_p = malloc(sizeof(struct sctp_arg_s))) == NULL) { return -1; } sctp_arg_p->sd = sd; sctp_arg_p->ppid = init_p->ppid; if (pthread_create(&assoc_thread, NULL, &sctp_receiver_thread, (void *)sctp_arg_p) < 0) { SCTP_ERROR("pthread_create: %s:%d\n", strerror(errno), errno); return -1; } return sd; err: if (sd != -1) { close(sd); sd = -1; } return -1; }
int Sctp_bindx(int sock_fd, struct sockaddr_storage* at, int num, int op) { int ret; ret = sctp_bindx(sock_fd, at, num, op); if (ret < 0) { err_sys("sctp_bindx error"); } return (ret); }
/* sctp address format sctp:127.0.0.1,192.168.0.17:3031 */ int bind_to_sctp(char *socket_name, int listen_queue, char *sctp_port) { int serverfd; struct sockaddr_in uws_addr[MAX_SCTP_ADDRESS]; int num_ip = 0; struct sctp_initmsg sctp_im; sctp_port[0] = 0; memset(uws_addr, 0, sizeof(struct sockaddr_in) * MAX_SCTP_ADDRESS); memset(&sctp_im, 0, sizeof(struct sctp_initmsg)); while (socket_name != NULL && num_ip < MAX_SCTP_ADDRESS) { char *ap; while ((ap = strsep(&socket_name, ",")) != NULL) { if (*ap != '\0') { uws_addr[num_ip].sin_family = AF_INET; uws_addr[num_ip].sin_port = htons(atoi(sctp_port + 1)); uws_addr[num_ip].sin_addr.s_addr = inet_addr(ap); num_ip++; } } } serverfd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); if (serverfd < 0) { uwsgi_error("socket()"); exit(1); } fprintf(stderr, "binding on %d SCTP interfaces on port: %d\n", num_ip, ntohs(uws_addr[0].sin_port)); if (sctp_bindx(serverfd, (struct sockaddr *) uws_addr, num_ip, SCTP_BINDX_ADD_ADDR) != 0) { uwsgi_error("sctp_bindx()"); exit(1); } sctp_im.sinit_max_instreams = 0xFFFF; sctp_im.sinit_num_ostreams = 0xFFFF; if (setsockopt(serverfd, IPPROTO_SCTP, SCTP_INITMSG, &sctp_im, sizeof(sctp_im))) { uwsgi_error("setsockopt()"); } if (listen(serverfd, listen_queue) != 0) { uwsgi_error("listen()"); exit(1); } return serverfd; }