Stream Control Transmission Protocol (SCTP) Associations
where flags can be one of SCTP_BINDX_ADD_ADDR or SCTP_BINDX_REM_ADDR, and the second parameter is a packed list of IPv4 and IPv6 socket address structures.
It is relatively easy to use this on a server to allow clients to connect on any of the server's bound interfaces. But, how do you do this on a client? Where is the bind() operation? Well, just like TCP, this is hidden under the covers. In TCP, if a call to connect() is made and the socket is not yet bound (the usual case for a client), the TCP stack will choose one of the interfaces and an ephemeral port. You can make an explicit call to bind() that will let you choose the interface, but usually the port is left as zero, so an ephemeral port is still chosen.
You can do exactly the same with SCTP—don't call bind() and leave it to the SCTP stack. This will choose an ephemeral port like TCP, but instead of using a single interface, it will choose a set of interfaces (probably all that are available). So calling connect() without an initial bind() or sctp_bindx() will give you multihoming on the client side automatically.
If you call bind() with a specified interface before connect() in the client, you get only that single client-side interface, losing one of the advantages of SCTP! If you call bind() with the wildcard address INADDR_ANY, SCTP will choose a set of interfaces for you. So, SCTP will try to give you multihoming unless you pin it down to a single address using bind() or to a specific set of addresses using sctp_bindx().
With SCTP, I would expect a call to sctp_bindx() with all ports set to zero to choose the same ephemeral port for all addresses. Instead, the current Linux implementation (up to kernel 2.6.21) gets an ephemeral port for the first address and then throws an error, because the ports in the later addresses are still zero instead of this ephemeral value. The workaround is to call bind() with one address with port zero, see what the system set the port to, and then call bindx() on the remaining addresses with this new port number. Listing 1 (multi_homed_client.c) shows an example of this. This workaround probably will become unnecessary in the next specification of SCTP following discussion on the SCTP mailing list.
Listing 1. multi_homed_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
int main(int argc, char *argv[]) {
int sockfd;
int n;
struct sockaddr_in addr, *addresses;
int addr_size = sizeof(struct sockaddr_in);
int addr_count = argc - 2;
int port;
if (argc < 2) {
fprintf(stderr, "Usage %s client-addresses...\n", argv[0]);
exit(1);
}
/* create endpoint */
sockfd = socket(AF_INET, SOCK_STREAM,
IPPROTO_SCTP);
if (sockfd < 0) {
perror("socket");
exit(2);
}
addresses = malloc(addr_size * addr_count);
if (addresses == NULL) {
perror("malloc");
exit(1);
}
/* do bind to get ephemeral port first */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port = 0;
if (bind(sockfd, (struct sockaddr *) &addr, addr_size) == -1) {
perror("bind");
exit(1);
}
/* this gets sin.sin_port so we can find the ephemeral port */
getsockname(sockfd, (struct sockaddr *) &addr, &addr_size);
port = addr.sin_port;
printf("Ephemeral port is %d\n", port);
for ( n = 2; n < argc; n++) {
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(argv[n]);
addr.sin_port = port;
memcpy(addresses + (n-2), &addr, addr_size);
}
if (sctp_bindx(sockfd, (struct sockaddr *) addresses, addr_count,
SCTP_BINDX_ADD_ADDR) == -1) {
perror("sctp bindx");
exit(2);
}
/* get local list */
addr_count = sctp_getladdrs(sockfd, 0, (struct sockaddr**)&addresses);
for (n = 0; n < addr_count; n++) {
memcpy(&addr, addresses+n, addr_size);
printf("addr %s, port %d\n",
inet_ntoa(addr.sin_addr.s_addr),
addr.sin_port);
}
/* we don't actually connect to any server in this program */
close(sockfd);
exit(0);
}
You can set the local interfaces to be used by sctp_bindx(). A client also can specify the subset of addresses that it wants to use to connect to the server by using the call sctp_connectx(), which takes a list of socket address structures just like sctp_bindx(). Why do this? Well, using connect() with a single address is a possible point of failure at the time that the initial connection is done. This is what the function sctp_connectx() solves. It allows the client to try multiple addresses in order to connect to the server.
The set of addresses in sctp_connectx() is used just to make the initial connection. But, after the connection is established, an interchange of information takes place between the two endpoints. In that exchange, the remote peer tells the local peer which addresses it actually wants to use and vice versa. The set of remote addresses that the remote peer will use need not be the same as what the client used in the connection. However, you at least can assume that one (but you don't know which one) of the addresses passed to sctp_connectx() will appear in the list that the remote peer offers, because the local client had to connect to something!
So, if the remote peer chooses the set of addresses it uses, how does the local client find which ones they are? This is done by another function, sctp_getpaddrs(), that gives the set of remote peer addresses. There is also an sctp_getladdrs() function, in case the local peer forgets which addresses it is using!
Once an association is set up between two endpoints, messages can be sent between them. Note that SCTP does not concern itself with QoS (Quality-of-Service) issues, such as real-time delivery, but only with reliability issues. SCTP uses the multihomed capabilities to try as many possible routes as possible to get messages through. So on the sending side, there is no control over which interfaces are used; indeed, the sender might even use a scheme such as round-robin among its interfaces for each message. However, the sending application can indicate to its SCTP stack which of the remote peer's interface it would prefer to use, and it can tell the remote peer on which interfaces it would prefer to receive messages. These are done by using the setsockopt() call with option type as SCTP_PRIMARY_ADDR or SCTP_SET_PEER_PRIMARY_ADDR. Of course, if these particular addresses are not available, SCTP simply will use different addresses in the association.
Once SCTP is told which interfaces to use, it basically looks after things itself. It uses heartbeats to keep track of which interfaces are alive, and it switches interfaces transparently when failure occurs. This is to satisfy the design goals of SCTP for improved reliability over TCP. Applications can give hints to the SCTP stack about which interfaces to use, but the stack will ignore these hints on failure.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Home, My Backup Data Center
- RSS Feeds
- Trying to Tame the Tablet
- What's the tweeting protocol?
- New Products
- Dart: a New Web Programming Experience
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




1 hour 19 min ago
3 hours 41 min ago
20 hours 30 min ago
23 hours 2 min ago
1 day 20 min ago
1 day 54 min ago
1 day 1 hour ago
1 day 6 hours ago
1 day 6 hours ago
1 day 8 hours ago