blob: 92f58cde787b094e7533c2421b5f5c11f5b2fb19 [file] [log] [blame]
/* SCTP kernel reference Implementation: User API extensions.
*
* bindx.c
*
* Distributed under the terms of the LGPL v2.1 as described in
* http://www.gnu.org/copyleft/lesser.txt
*
* This file is part of the user library that offers support for the
* SCTP kernel reference Implementation. The main purpose of this
* code is to provide the SCTP Socket API mappings for user
* application to interface with the SCTP in kernel.
*
* This implementation is based on the Socket API Extensions for SCTP
* defined in <draft-ietf-tsvwg-sctpsocket-10.txt.
*
* (C) Copyright IBM Corp. 2001, 2003
* Copyright (c) 2002 Intel Corporation.
*
* Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org>
* Daisy Chang <daisyc@us.ibm.com>
* Inaky Perez-Gonzalez <inaky.gonzalez@intel.com>
* Sridhar Samudrala <sri@us.ibm.com>
*/
#include <sys/socket.h> /* struct sockaddr_storage, setsockopt() */
#include <netinet/in.h>
#include <netinet/sctp.h> /* SCTP_SOCKOPT_BINDX_* */
#include <errno.h>
/* Support the sctp_bindx() interface.
*
* See Sockets API Extensions for SCTP. Section 8.1.
*
* Instead of implementing through a socket call in sys_socketcall(),
* tunnel the request through setsockopt().
*/
int
sctp_bindx(int fd, struct sockaddr *addrs, int addrcnt, int flags)
{
int setsock_option = 0;
void *addrbuf;
struct sockaddr *sa_addr;
socklen_t addrs_size = 0;
int i;
switch (flags) {
case SCTP_BINDX_ADD_ADDR:
setsock_option = SCTP_SOCKOPT_BINDX_ADD;
break;
case SCTP_BINDX_REM_ADDR:
setsock_option = SCTP_SOCKOPT_BINDX_REM;
break;
default:
errno = EINVAL;
return -1;
}
addrbuf = addrs;
for (i = 0; i < addrcnt; i++) {
sa_addr = (struct sockaddr *)addrbuf;
switch (sa_addr->sa_family) {
case AF_INET:
addrs_size += sizeof(struct sockaddr_in);
addrbuf += sizeof(struct sockaddr_in);
break;
case AF_INET6:
addrs_size += sizeof(struct sockaddr_in6);
addrbuf += sizeof(struct sockaddr_in6);
break;
default:
errno = EINVAL;
return -1;
}
}
return setsockopt(fd, SOL_SCTP, setsock_option, addrs, addrs_size);
}