#define _XOPEN_SOURCE 500 #define __EXTENSIONS__ /* * Simple networking server which uses SCTP 1-N */ #include #include #include #include #include #include #include #include #define MAXIDLETIME 1 static void print_src(int fd, sctp_assoc_t assoc_id) { struct sctp_status sstat; struct sctp_paddrinfo *spinfo; char tmpname[INET_ADDRSTRLEN]; unsigned int port; unsigned int ulen; struct sockaddr_in *s_in; bzero(&sstat, sizeof (sstat)); ulen = sizeof (sstat); if (sctp_opt_info(fd, assoc_id, SCTP_STATUS, &sstat, &ulen) < 0) { perror("sctp_opt_info()"); return; } spinfo = &sstat.sstat_primary; s_in = (struct sockaddr_in *)&spinfo->spinfo_address; inet_ntop(AF_INET, &s_in->sin_addr, tmpname, sizeof (tmpname)); port = ntohs(s_in->sin_port); printf("Msg from %d: %s/%d\n", assoc_id, tmpname, port); } int main(int argc, char **argv) { int echo_s; struct sockaddr_in laddr; struct sctp_event_subscribe ses; int ret; struct msghdr mhdr; struct iovec iov; char data[8192]; char cdata[sizeof (struct sctp_sndrcvinfo) + sizeof (struct cmsghdr)]; struct cmsghdr *cmsg; struct sctp_sndrcvinfo *sinfo; struct sctp_assoc_change *sac; struct sockaddr_in from; socklen_t fromlen = sizeof (struct sockaddr_in); fd_set rset; int i; if (argc < 2) { printf("usage: sctp_server \n"); exit(0); } echo_s = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); bzero(&laddr, sizeof (laddr)); laddr.sin_family = AF_INET; laddr.sin_port = htons(atoi(argv[1])); if (bind(echo_s, (struct sockaddr *)&laddr, sizeof (laddr)) < 0) { perror("bind(ECHO_PORT)"); exit(1); } listen(echo_s, 1) ; i = 1; setsockopt(echo_s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i)); i = MAXIDLETIME; setsockopt(echo_s, IPPROTO_SCTP, SCTP_AUTOCLOSE, &i, sizeof (i)); bzero(&ses, sizeof (ses)); ses.sctp_data_io_event = 1; setsockopt(echo_s, IPPROTO_SCTP, SCTP_EVENTS, &ses, sizeof (ses)); FD_ZERO(&rset); while (1) { FD_SET(echo_s, &rset); select(5, &rset, NULL, NULL, NULL); if (FD_ISSET(echo_s, &rset) ) { bzero(cdata, sizeof (cdata)); bzero(&mhdr, sizeof (mhdr)); mhdr.msg_name = &from; mhdr.msg_namelen = fromlen; mhdr.msg_iov = &iov; mhdr.msg_iovlen = 1; mhdr.msg_control = cdata; mhdr.msg_controllen = sizeof (cdata); iov.iov_base = data; iov.iov_len = sizeof (data); cmsg = (struct cmsghdr *)cdata; sinfo = (struct sctp_sndrcvinfo *)(cmsg + 1); if ((ret = recvmsg(echo_s, &mhdr, MSG_DONTWAIT)) < 0) { perror("recvmsg()"); } if (mhdr.msg_controllen) { print_src(echo_s, sinfo->sinfo_assoc_id); } /* echo back */ iov.iov_len = ret; if (sendmsg(echo_s, &mhdr, MSG_DONTWAIT) < 0) { perror("sendmsg()"); } printf("received:"); fflush(stdout); write(1, data, ret); } } }