#define _XOPEN_SOURCE 500 #define __EXTENSIONS__ #include #include #include #include #include #include #include #include #include #include #include #define MAXIDLETIME 1 #define BUFLEN 1024 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 echo_s; struct sockaddr_in laddr; int main(int argc, char **argv) { struct sockaddr_in toaddr; struct sctp_event_subscribe ses; int ret; int i; struct msghdr In_mhdr; struct msghdr Out_mhdr; struct iovec iov; char data[BUFLEN]; 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); socklen_t tolen = sizeof (struct sockaddr_in); fd_set rset; struct hostent *hp; int error; int lport, rport; if (argc < 4) { printf("usage: sctp_client \n"); exit(0); } lport = atoi(argv[1]); rport = atoi(argv[3]); bzero(&laddr, sizeof (laddr)); laddr.sin_family = AF_INET; laddr.sin_addr.s_addr = INADDR_ANY; laddr.sin_port = htons(lport); CreateSocket(); /* 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(&toaddr, sizeof (toaddr)); hp = getipnodebyname(argv[2], AF_INET, AI_DEFAULT, &error); if (hp == NULL) { fprintf(stderr, "host not found\n"); exit(1); } toaddr.sin_family = AF_INET; toaddr.sin_addr.s_addr = *(ipaddr_t *)hp->h_addr_list[0]; toaddr.sin_port = htons(rport); 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); FD_SET(0, &rset); select(5, &rset, NULL, NULL, NULL); if (FD_ISSET (echo_s, &rset)) { bzero(cdata, sizeof (cdata)); bzero(&In_mhdr, sizeof (In_mhdr)); In_mhdr.msg_name = &from; In_mhdr.msg_namelen = fromlen; In_mhdr.msg_iov = &iov; In_mhdr.msg_iovlen = 1; In_mhdr.msg_control = cdata; In_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, &In_mhdr, MSG_DONTWAIT)) < 0) { perror("recvmsg()"); } if (In_mhdr.msg_controllen) { print_src(echo_s, sinfo->sinfo_assoc_id); } printf("got back: "); fflush (stdout); write(1, data, ret); } if (FD_ISSET (0, &rset)) { bzero(cdata, sizeof (cdata)); bzero(&Out_mhdr, sizeof (Out_mhdr)); Out_mhdr.msg_name = &toaddr; Out_mhdr.msg_namelen = tolen; Out_mhdr.msg_iov = &iov; Out_mhdr.msg_iovlen = 1; Out_mhdr.msg_control = cdata; Out_mhdr.msg_controllen = sizeof (cdata); iov.iov_base = data; iov.iov_len = sizeof (data); cmsg = (struct cmsghdr *)cdata; sinfo = (struct sctp_sndrcvinfo *)(cmsg + 1); ret = read(0, data, BUFLEN); printf("data input: "); fflush(stdout); write (1, data, ret); iov.iov_len = ret; if (sendmsg(echo_s, &Out_mhdr, MSG_DONTWAIT) < 0) { perror("sendmsg()"); } } } } CreateSocket() { echo_s = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (bind(echo_s, (struct sockaddr *)&laddr, sizeof (laddr)) < 0) { perror("bind(ECHO_PORT)"); exit(1); } }