Mercurial > hg > freeDiameter
diff freeDiameter/sctp.c @ 38:68c1890f7049
Fixed a small bug in SCTP close
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Thu, 05 Nov 2009 17:29:12 +0900 |
parents | e6fcdf12b9a0 |
children | 43dc87ac5e11 |
line wrap: on
line diff
--- a/freeDiameter/sctp.c Thu Nov 05 14:28:46 2009 +0900 +++ b/freeDiameter/sctp.c Thu Nov 05 17:29:12 2009 +0900 @@ -640,23 +640,71 @@ return 0; } +/* Add addresses from the list that match the flags to the array */ +static int add_addresses_from_list_mask(uint8_t ** array, int * count, size_t * offset, uint16_t port, struct fd_list * list, uint32_t mask, uint32_t val) +{ + size_t sz; + struct fd_list * li; + union { + uint8_t *buf; + sSA4 *sin; + sSA6 *sin6; + } ptr; + + for (li = list->next; li != list; li = li->next) { + struct fd_endpoint * ep = (struct fd_endpoint *) li; + + /* Do the flag match ? */ + if ((val & mask) != (ep->flags & mask)) + continue; + + /* We add this endpoint at the end of array */ + (*count)++; + + /* Size of the new SA we are adding (array may contain a mix of sockaddr_in and sockaddr_in6) */ +#ifndef SCTP_USE_MAPPED_ADDRESSES + if (ep->sa.sa_family == AF_INET6) +#else /* SCTP_USE_MAPPED_ADDRESSES */ + if (family == AF_INET6) +#endif /* SCTP_USE_MAPPED_ADDRESSES */ + sz = sizeof(sSA6); + else + sz = sizeof(sSA4); + + /* augment array to contain the additional info */ + CHECK_MALLOC( *array = realloc(*array, (*offset) + sz) ); + + ptr.buf = *array + *offset; /* place of the new SA */ + (*offset) += sz; /* update to end of sar */ + + if (sz == sizeof(sSA4)) { + memcpy(ptr.buf, &ep->sin, sz); + ptr.sin->sin_port = port; + } else { + if (ep->sa.sa_family == AF_INET) { /* We must map the address */ + memset(ptr.buf, 0, sz); + ptr.sin6->sin6_family = AF_INET6; + IN6_ADDR_V4MAP( &ptr.sin6->sin6_addr.s6_addr, ep->sin.sin_addr.s_addr ); + } else { + memcpy(ptr.sin6, &ep->sin6, sz); + } + ptr.sin6->sin6_port = port; + } + } + + return 0; +} + /* Create a client socket and connect to remote server */ int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list ) { int family; int count = 0; - size_t offset = 0, sz; + size_t offset = 0; union { uint8_t *buf; sSA *sa; } sar; - union { - uint8_t *buf; - sSA *sa; - sSA4 *sin; - sSA6 *sin6; - } ptr; - struct fd_list * li; int ret; sar.buf = NULL; @@ -679,42 +727,10 @@ /* Set the socket options */ CHECK_FCT_DO( ret = fd_setsockopt_prebind(*sock), goto fail ); - /* Create the array of addresses for sctp_connectx */ - for (li = list->next; li != list; li = li->next) { - struct fd_endpoint * ep = (struct fd_endpoint *) li; - - count++; - - /* Size of the new SA we are adding (sar may contain a mix of sockaddr_in and sockaddr_in6) */ -#ifndef SCTP_USE_MAPPED_ADDRESSES - if (ep->sa.sa_family == AF_INET6) -#else /* SCTP_USE_MAPPED_ADDRESSES */ - if (family == AF_INET6) -#endif /* SCTP_USE_MAPPED_ADDRESSES */ - sz = sizeof(sSA6); - else - sz = sizeof(sSA4); - - /* augment sar to contain the additional info */ - CHECK_MALLOC_DO( sar.buf = realloc(sar.buf, offset + sz), { ret = ENOMEM; goto fail; } ); - - ptr.buf = sar.buf + offset; /* place of the new SA */ - offset += sz; /* update to end of sar */ - - if (sz == sizeof(sSA4)) { - memcpy(ptr.buf, &ep->sin, sz); - ptr.sin->sin_port = htons(port); - } else { - if (ep->sa.sa_family == AF_INET) { /* We must map the address */ - memset(ptr.buf, 0, sz); - ptr.sin6->sin6_family = AF_INET6; - IN6_ADDR_V4MAP( &ptr.sin6->sin6_addr.s6_addr, ep->sin.sin_addr.s_addr ); - } else { - memcpy(ptr.sin6, &ep->sin6, sz); - } - ptr.sin6->sin6_port = htons(port); - } - } + /* Create the array of addresses, add first the configured addresses, then the discovered, then the other ones */ + CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &count, &offset, htons(port), list, EP_FL_CONF, EP_FL_CONF ), goto fail ); + CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &count, &offset, htons(port), list, EP_FL_CONF | EP_FL_DISC, EP_FL_DISC ), goto fail ); + CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &count, &offset, htons(port), list, EP_FL_CONF | EP_FL_DISC, 0 ), goto fail ); /* Try connecting */ TRACE_DEBUG(FULL, "Attempting SCTP connection (%d addresses attempted)...", count);