Imported Upstream version 1.0.10
[platform/upstream/lksctp-tools.git] / src / lib / bindx.c
1 /* SCTP kernel Implementation: User API extensions.
2  *
3  * bindx.c
4  *
5  * Distributed under the terms of the LGPL v2.1 as described in
6  *    http://www.gnu.org/copyleft/lesser.txt 
7  *
8  * This file is part of the user library that offers support for the
9  * SCTP kernel Implementation. The main purpose of this
10  * code is to provide the SCTP Socket API mappings for user
11  * application to interface with the SCTP in kernel.
12  *
13  * This implementation is based on the Socket API Extensions for SCTP
14  * defined in <draft-ietf-tsvwg-sctpsocket-10.txt.
15  *
16  * (C) Copyright IBM Corp. 2001, 2003
17  * Copyright (c) 2002 Intel Corporation.
18  *
19  * Written or modified by:
20  *   La Monte H.P. Yarroll <piggy@acm.org>
21  *   Daisy Chang           <daisyc@us.ibm.com>
22  *   Inaky Perez-Gonzalez  <inaky.gonzalez@intel.com>
23  *   Sridhar Samudrala     <sri@us.ibm.com>
24  */
25
26 #include <sys/socket.h>   /* struct sockaddr_storage, setsockopt() */
27 #include <netinet/in.h>
28 #include <netinet/sctp.h> /* SCTP_SOCKOPT_BINDX_* */
29 #include <errno.h>
30
31 /* Support the sctp_bindx() interface.
32  *
33  * See Sockets API Extensions for SCTP. Section 8.1.
34  *
35  * Instead of implementing through a socket call in sys_socketcall(),
36  * tunnel the request through setsockopt().
37  */
38 int
39 sctp_bindx(int fd, struct sockaddr *addrs, int addrcnt, int flags)
40 {
41         int setsock_option = 0;
42         void *addrbuf;
43         struct sockaddr *sa_addr;
44         socklen_t addrs_size = 0;
45         int i;
46
47         switch (flags) {
48         case SCTP_BINDX_ADD_ADDR:
49                 setsock_option = SCTP_SOCKOPT_BINDX_ADD;
50                 break;
51         case SCTP_BINDX_REM_ADDR:
52                 setsock_option = SCTP_SOCKOPT_BINDX_REM;
53                 break;
54         default:
55                 errno = EINVAL;
56                 return -1;
57         }
58
59         addrbuf = addrs;
60         for (i = 0; i < addrcnt; i++) {
61                 sa_addr = (struct sockaddr *)addrbuf;
62                 switch (sa_addr->sa_family) {
63                 case AF_INET:
64                         addrs_size += sizeof(struct sockaddr_in);
65                         addrbuf += sizeof(struct sockaddr_in);
66                         break;
67                 case AF_INET6:
68                         addrs_size += sizeof(struct sockaddr_in6);
69                         addrbuf += sizeof(struct sockaddr_in6);
70                         break;
71                 default:
72                         errno = EINVAL;
73                         return -1;
74                 }
75         }
76                         
77         return setsockopt(fd, SOL_SCTP, setsock_option, addrs, addrs_size);
78 }