23.6 Binding a Subset of
Addresses
Some applications may want to bind a proper
subset of the IP addresses of a machine to a single socket. In TCP
and UDP, traditionally, it was not possible to bind a subset of
addresses. The bind system call allows an application to
bind a single address or the wildcard address. Due to this
restriction, the new function call sctp_bindx is provided
to allow an application to bind to more than one address. Note that
all the addresses must use the same port number, and if
bind was called, the port number must be the same as that
provided to bind. The sctp_bindx call will fail
if a different port is provided. Figure 23.7 shows a utility we will add to our
server that will bind an argument list.
Figure 23.7
Function to bind a subset of addresses.
sctp/sctp_bindargs.c
1 #include "unp.h"
2 int
3 sctp_bind_arg_list(int sock_fd, char **argv, int argc)
4 {
5 struct addrinfo *addr;
6 char *bindbuf, *p, portbuf[10];
7 int addrcnt = 0;
8 int i;
9 bindbuf = (char *) Calloc(argc, sizeof(struct sockaddr_storage));
10 p = bindbuf;
11 sprintf(portbuf, "%d", SERV_PORT);
12 for (i = 0; i < argc; i++) {
13 addr = Host_serv(argv[i], portbuf, AF_UNSPEC, SOCK_SEQPACKET);
14 memcpy(p, addr->ai_addr, addr->ai_addrlen);
15 freeaddrinfo(addr);
16 addrcnt++;
17 p += addr->ai_addrlen;
18 }
19 Sctp_bindx(sock_fd, (SA *) bindbuf, addrcnt, SCTP_BINDX_ADD_ADDR);
20 free(bindbuf);
21 return (0);
22 }
Allocate space for bind arguments
9鈥?0
Our sctp_bind_arg_list function starts off by allocating
space for the bind arguments. Note that the sctp_bindx
function can accept a mix of IPv6 and IPv4 addresses. We allocate
enough space for a sockaddr_storage for each address, even
though the address list argument to sctp_bindx is a packed
list of addresses (Figure 9.4). This
results in some memory waste but is simpler than calculating the
exact space required by processing the argument list twice.
Process arguments
11鈥?8
We set up the portbuf to be an
ASCII representation of the port number, to prepare to call our
getaddrinfo wrapper function, host_serv. We pass
each address and the port number to host_serv, along with
AF_UNSPEC to allow IPv4 or IPv6, and
SOCK_SEQPACKET to specify that we're using SCTP. We copy
the first sockaddr that is returned and ignore any others.
Since the arguments to this function are meant to be literal
address strings, as opposed to names that could have multiple
addresses associated with them, this is safe. We free the return
value from getaddrinfo, increment our count of addresses,
and move the pointer to the next element in our packed array of
sockaddr structures.
Call binding function
19 The
function now resets its pointer to the top of the bind buffer and
calls sctp_bindx with the subset of addresses decoded
earlier.
Return success
20鈥?1
If the function reaches here, we are successful, so clean up and
return.
Figure
23.8 illustrates our modified echo server that now binds a list
of addresses passed on the command line. Note that we have modified
the server slightly so it always returns any echoed message on the
stream on which it arrived.
Figure 23.8
Server using a variable set of addresses.
sctp/sctpserv07.c
12 if (argc < 2)
13 err_quit("Error, use %s [list of addresses to bind]\n", argv[0]);
14 sock_fd = Socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);
15 if (sctp_bind_arg_list(sock_fd, argv + 1, argc - 1))
16 err_sys("Can't bind the address set");
17 bzero(&evnts, sizeof(evnts));
18 evnts.sctp_data_io_event = 1;
Server code using IPv6
14
Here we see the server we have been working on throughout this
chapter, but with a slight modification. The server creates an
AF_INET6 socket. This way, the server can use both IPv4
and IPv6.
Use the new
sctp_bind_arg_list function
15鈥?6
The server calls the new sctp_bind_arg_list function,
passing the argument list to it for processing.
|