[ Team LiB ] |
23.6 Binding a Subset of AddressesSome 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 arguments9–10 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 arguments11–18 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 function19 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 success20–21 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 IPv614 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 function15–16 The server calls the new sctp_bind_arg_list function, passing the argument list to it for processing. |
[ Team LiB ] |