📄 sctp_darn.c
字号:
}} /* rcvbuf_func() */static struct sockaddr *get_bindx_addr(char *in, int *count){ struct sockaddr *tmp_addrs = NULL; char *p = in; /* Set the buffer for address parsing. */ while ('\n' != *p) { p++; } *p = '\0'; *count = 0; tmp_addrs = append_addr(in, tmp_addrs, count); if (NULL == tmp_addrs) { /* We have no memory, so keep fprintf() * from trying to allocate more. */ fprintf(stderr, "No memory to add "); fprintf(stderr, in); fprintf(stderr, "\n"); exit(2); } return tmp_addrs;} /* get_bindx_addr() */static intbindx_func(char *argv0, int sk, struct sockaddr *addrs, int count, int flag, int portnum){ int error; int i; struct sockaddr *sa_addr; void *aptr; if (0 == portnum) { fprintf(stderr, "%s: A non-0 local port number is ", argv0); fprintf(stderr, "required for bindx to work!\n"); return -1 ; } /* 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(portnum); aptr += sizeof(struct sockaddr_in); break; case AF_INET6: ((struct sockaddr_in6 *)sa_addr)->sin6_port = htons(portnum); aptr += sizeof(struct sockaddr_in6); break; default: fprintf(stderr, "Invalid address family\n"); return -1; } } error = sctp_bindx(sk, addrs, count, flag); if (error != 0) { if (flag == SCTP_BINDX_ADD_ADDR) { fprintf(stderr, "%s: error adding addrs: %s.\n", argv0, strerror(errno)); return -1; } else { fprintf(stderr, "%s: error removing addrs: %s.\n", argv0, strerror(errno)); return -1; } } return 0;} /* bindx_func() */static intconnectx_func(char *argv0, int sk, struct sockaddr *addrs, int count){ int error; int i; struct sockaddr *sa_addr; void *aptr; if (0 == remote_port) { fprintf(stderr, "%s: A non-0 remote port number is ", argv0); fprintf(stderr, "required for connectx to work!\n"); return -1 ; } /* 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"); return -1; } } error = sctp_connectx(sk, addrs, count); if (error != 0) { if (errno == ECONNREFUSED) return -2; fprintf(stderr, "%s: error connecting to addrs: %s.\n", argv0, strerror(errno)); return -1; } return 0;} /* connectx_func() */static voidprimary_func(char *argv0, int sk, char *cp, int set){ struct sctp_prim prim; struct sockaddr_in *in_addr; struct sockaddr_in6 *in6_addr; struct sockaddr *saddr; socklen_t prim_len; int ret; char *p = cp; char addr_buf[INET6_ADDRSTRLEN]; const char *ap = NULL; prim_len = sizeof(struct sctp_prim); if (!set) { prim.ssp_assoc_id = associd; ret = getsockopt(sk, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, &prim_len); if (ret < 0) goto err; saddr = (struct sockaddr *)&prim.ssp_addr; if (AF_INET == saddr->sa_family) { in_addr = (struct sockaddr_in *)&prim.ssp_addr; ap = inet_ntop(AF_INET, &in_addr->sin_addr, addr_buf, INET6_ADDRSTRLEN); } else if (AF_INET6 == saddr->sa_family) { in6_addr = (struct sockaddr_in6 *)&prim.ssp_addr; ap = inet_ntop(AF_INET6, &in6_addr->sin6_addr, addr_buf, INET6_ADDRSTRLEN); } if (!ap) goto err; printf("%s\n", ap); return; } /* Set the buffer for address parsing. */ while ('\n' != *p) p++; *p = '\0'; prim.ssp_assoc_id = associd; if (strchr(cp, '.')) { in_addr = (struct sockaddr_in *)&prim.ssp_addr; in_addr->sin_port = htons(remote_port); in_addr->sin_family = AF_INET; ret = inet_pton (AF_INET, cp, &in_addr->sin_addr); if (ret <= 0) goto err; } else if (strchr(cp, ':')) { in6_addr = (struct sockaddr_in6 *)&prim.ssp_addr; in6_addr->sin6_port = htons(remote_port); in6_addr->sin6_family = AF_INET6; ret = inet_pton(AF_INET6, cp, &in6_addr->sin6_addr); if (ret <= 0) goto err; } else goto err; ret = setsockopt(sk, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, sizeof(struct sctp_prim)); if (ret < 0) goto err; return;err: if (!errno) errno = EINVAL; fprintf(stderr, "%s: error %s primary: %s.\n", argv0, (set)?"setting":"getting", strerror(errno));}static voidpeer_primary_func(char *argv0, int sk, char *cp, int set){ struct sctp_setpeerprim setpeerprim; struct sockaddr_in *in_addr; struct sockaddr_in6 *in6_addr; int peer_prim_len, ret; char *p = cp; if (!set) { goto err; } peer_prim_len = sizeof(struct sctp_setpeerprim); /* Set the buffer for address parsing. */ while ('\n' != *p) p++; *p = '\0'; setpeerprim.sspp_assoc_id = associd; if (strchr(cp, '.')) { in_addr = (struct sockaddr_in *)&setpeerprim.sspp_addr; in_addr->sin_port = htons(local_port); in_addr->sin_family = AF_INET; ret = inet_pton (AF_INET, cp, &in_addr->sin_addr); if (ret <= 0) goto err; } else if (strchr(cp, ':')) { in6_addr = (struct sockaddr_in6 *)&setpeerprim.sspp_addr; in6_addr->sin6_port = htons(local_port); in6_addr->sin6_family = AF_INET6; ret = inet_pton(AF_INET6, cp, &in6_addr->sin6_addr); if (ret <= 0) goto err; } else goto err; ret = setsockopt(sk, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR, &setpeerprim, sizeof(struct sctp_setpeerprim)); if (ret < 0) goto err; return;err: if (!errno) errno = EINVAL; fprintf(stderr, "%s: error %s peer_primary: %s.\n", argv0, (set)?"setting":"getting", strerror(errno));}static intnodelay_func(char *argv0, int sk, int val, int set){ socklen_t optlen; int error; if (set) { error = setsockopt(sk, SOL_SCTP, SCTP_NODELAY, (char *)&val, sizeof(val)); } else { optlen = sizeof(val); error = getsockopt(sk, SOL_SCTP, SCTP_NODELAY, (char *)&val, &optlen); } if (error != 0) { fprintf(stderr, "%s: Error setting/getting nodelay: %s.\n", argv0, strerror(errno)); exit(1); } if (!set) { printf("nodelay is %d.\n", val); } return error;}static intmaxseg_func(char *argv0, int sk, int val, int set){ socklen_t optlen; int error; if (set) { error = setsockopt(sk, SOL_SCTP, SCTP_MAXSEG, (char *)&val, sizeof(val)); } else { optlen = sizeof(val); error = getsockopt(sk, SOL_SCTP, SCTP_MAXSEG, (char *)&val, &optlen); } if (error != 0) { fprintf(stderr, "%s: Error setting/getting maxseg: %s.\n", argv0, strerror(errno)); exit(1); } if (!set) { printf("maxseg is %d.\n", val); } return error;}static intshutdown_func(char *argv0, int *skp, int shutdown_type){ struct msghdr outmessage; char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; struct cmsghdr *cmsg; int error=0, bytes_sent; struct sctp_sndrcvinfo *sinfo; struct hostent *hst; char *sd_type; int sk = *skp; if (shutdown_type == SHUTDOWN_ABORT) sd_type = "ABORT"; else sd_type = "SHUTDOWN"; /* Verify that the association is present. */ error = test_sk_for_assoc(sk, associd); if (error != 0) { printf("The association isn't present yet! Cannot %s!\n", sd_type); return -1; } if (socket_type == SOCK_SEQPACKET) { /* Set up the destination. */ if (remote_host) { hst = gethostbyname(remote_host); if (hst == NULL) { hst = gethostbyname2(remote_host, AF_INET6); } if (hst == NULL || hst->h_length < 1) { fprintf(stderr, "%s: bad hostname: %s\n", argv0, remote_host); exit(1); } ra_family = hst->h_addrtype; switch (ra_family) { case AF_INET: ra_len = sizeof(remote_addr.v4); ra_raw = &remote_addr.v4.sin_addr; remote_addr.v4.sin_port = htons(remote_port); remote_addr.v4.sin_family = AF_INET; break; case AF_INET6: ra_len = sizeof(remote_addr.v6); ra_raw = &remote_addr.v6.sin6_addr; remote_addr.v6.sin6_port = htons(remote_port); remote_addr.v6.sin6_family = AF_INET6; break; default: fprintf(stderr, "Invalid address type.\n"); exit(1); break; } memcpy(ra_raw, hst->h_addr_list[0], hst->h_length); } /* Initialize the message struct we use to pass messages to * the remote socket. */ outmessage.msg_name = &remote_addr; outmessage.msg_namelen = ra_len; outmessage.msg_iov = NULL; outmessage.msg_iovlen = 0; outmessage.msg_control = outcmsg; outmessage.msg_controllen = sizeof(outcmsg); outmessage.msg_flags = 0; cmsg = CMSG_FIRSTHDR(&outmessage); cmsg->cmsg_level = IPPROTO_SCTP; cmsg->cmsg_type = SCTP_SNDRCV; cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); outmessage.msg_controllen = cmsg->cmsg_len; sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); if (shutdown_type == SHUTDOWN_ABORT) sinfo->sinfo_flags |= SCTP_ABORT; else sinfo->sinfo_flags |= SCTP_EOF; sinfo->sinfo_assoc_id = associd; bytes_sent = sendmsg(sk, &outmessage, 0); if (bytes_sent != 0) { printf("Failure: %s.\n", strerror(errno)); return -1; } /* Receive the COMM_LOST or SHUTDOWN_COMP event. */ test_recv_assoc_change(sk); } else { if (shutdown_type == SHUTDOWN_ABORT) { struct linger { int l_onoff; int l_linger; } data = {1, 0}; error = setsockopt(sk, SOL_SOCKET, SO_LINGER, (char *)&data, sizeof(data)); if (error != 0) { printf("setsockopt failed %s\n", strerror(errno)); exit(1); } } error = close(sk); if (error != 0) { printf("close failed %s\n", strerror(errno)); exit(1); } *skp = sk = build_endpoint(argv0, local_port); } /* Verify that the association is no longer present. */ error = test_sk_for_assoc(sk, associd); if (error != 0) { printf("Successfully %s the original association\n", sd_type); associd = 0; new_connection = 1; } else { printf("%s failed\n", sd_type); exit(1); } return 0;}static inttest_sk_for_assoc(int sk, sctp_assoc_t assoc_id){ int error = 0; struct sctp_status status; socklen_t status_len; memset(&status, 0, sizeof(status)); if (assoc_id) status.sstat_assoc_id = assoc_id; status_len = sizeof(struct sctp_status); error = getsockopt(sk, SOL_SCTP, SCTP_STATUS, (char *)&status, &status_len); return error;}/* Receive a notification and return the corresponding associd if the event is * SCTP_COMM_UP. Return 0 for any other event. */static sctp_assoc_ttest_recv_assoc_change(int sk){ struct msghdr inmessage; struct iovec iov; char incmsg[CMSG_SPACE(sizeof(_sctp_cmsg_data_t))]; int error; /* Initialize inmessage with enough space for DATA... */ memset(&inmessage, 0, sizeof(inmessage)); if ((iov.iov_base = malloc(REALLY_BIG)) == NULL) { printf("%s: Can't allocate memory.\n", __FUNCTION__); exit(1); } iov.iov_len = REALLY_BIG; inmessage.msg_iov = &iov; inmessage.msg_iovlen = 1; /* or a control message. */ inmessage.msg_control = incmsg; inmessage.msg_controllen = sizeof(incmsg); error = recvmsg(sk, &inmessage, MSG_WAITALL); if (error < 0) { printf("%s: recvmsg: %s\n", __FUNCTION__, strerror(errno)); exit(1); } return test_verify_assoc_change(&inmessage);}/* Verify a notification and return the corresponding associd if the event is * SCTP_COMM_UP. Return 0 for any other event. */static sctp_assoc_ttest_verify_assoc_change(struct msghdr *msg){ union sctp_notification *sn; if (!(msg->msg_flags & MSG_NOTIFICATION)) { fprintf(stderr, "%s: Received data when notification is expected\n", __FUNCTION__); exit(1); } sn = (union sctp_notification *)msg->msg_iov->iov_base; if (SCTP_ASSOC_CHANGE != sn->sn_header.sn_type) { fprintf(stderr, "%s: Received unexpected notification: %d", __FUNCTION__, sn->sn_header.sn_type); exit(1); } switch(sn->sn_assoc_change.sac_state) { case SCTP_COMM_UP: printf("Recieved SCTP_COMM_UP\n"); break; case SCTP_COMM_LOST: printf("Recieved SCTP_COMM_LOST\n"); break; case SCTP_RESTART: printf("Recieved SCTP_RESTART\n"); break; case SCTP_SHUTDOWN_COMP: printf("Recieved SCTP_SHUTDOWN_COMP\n"); break; case SCTP_CANT_STR_ASSOC: printf("Recieved SCTP_CANT_STR_ASSOC\n"); break; } if (SCTP_COMM_UP == sn->sn_assoc_change.sac_state) return sn->sn_assoc_change.sac_assoc_id; else return 0;}void print_addr_buf(void * laddrs, int n_laddrs){ void *addr_buf = laddrs; int i; for (i = 0; i < n_laddrs; i++) { addr_buf += print_sockaddr((struct sockaddr *)addr_buf); printf("\n"); }}int print_sockaddr(struct sockaddr *sa_addr){ struct sockaddr_in *in_addr; struct sockaddr_in6 *in6_addr; if (AF_INET == sa_addr->sa_family) { in_addr = (struct sockaddr_in *)sa_addr; printf("%d.%d.%d.%d:%d", NIPQUAD(in_addr->sin_addr), ntohs(in_addr->sin_port)); return sizeof(struct sockaddr_in); } else { in6_addr = (struct sockaddr_in6 *)sa_addr; printf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%d", NIP6(in6_addr->sin6_addr), ntohs(in6_addr->sin6_port)); return sizeof(struct sockaddr_in6); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -