1 /* SCTP kernel Implementation: User API extensions.
5 * Distributed under the terms of the LGPL v2.1 as described in
6 * http://www.gnu.org/copyleft/lesser.txt
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.
13 * This implementation is based on the Socket API Extensions for SCTP
14 * defined in <draft-ietf-tsvwg-sctpsocket-10.txt.
16 * (C) Copyright IBM Corp. 2003
17 * Copyright (c) 2001-2002 Intel Corp.
19 * Written or modified by:
20 * Ardelle Fan <ardelle.fan@intel.com>
21 * Sridhar Samudrala <sri@us.ibm.com>
22 * Ivan Skytte Jørgensen <isj-sctp@i1.dk>
26 #include <netinet/in.h>
27 #include <netinet/sctp.h>
32 * Get local/peer addresses using the old API
33 * Old kernels (2.6.13 and earlier) only support this API but it breaks 32-bit
34 * programs on 64-bit kernels.
37 sctp_getaddrs_old(int sd, sctp_assoc_t id, int optname_num, int optname_old,
38 struct sockaddr **addrs)
40 socklen_t len = sizeof(sctp_assoc_t);
42 struct sctp_getaddrs_old getaddrs;
44 cnt = getsockopt(sd, SOL_SCTP, optname_num, &id, &len);
53 len = cnt * sizeof(struct sockaddr_in6);
55 getaddrs.assoc_id = id;
56 getaddrs.addr_num = cnt;
57 getaddrs.addrs = (struct sockaddr *)malloc(len);
58 if (NULL == getaddrs.addrs)
61 len = sizeof(getaddrs);
62 err = getsockopt(sd, SOL_SCTP, optname_old, &getaddrs, &len);
68 *addrs = getaddrs.addrs;
70 return getaddrs.addr_num;
72 } /* sctp_getaddrs_old() */
75 * Common getsockopt() layer
76 * If the NEW getsockopt() API fails this function will fall back to using
80 sctp_getaddrs(int sd, sctp_assoc_t id,
81 int optname_new, int optname_num_old, int optname_old,
82 struct sockaddr **addrs)
86 size_t bufsize = 4096; /*enough for most cases*/
88 struct sctp_getaddrs *getaddrs = (struct sctp_getaddrs*)malloc(bufsize);
96 getaddrs->assoc_id = id;
97 err = getsockopt(sd, SOL_SCTP, optname_new, getaddrs, &len);
102 if (errno == ENOPROTOOPT) {
103 /*Kernel does not support new API*/
105 return sctp_getaddrs_old(sd, id,
106 optname_num_old, optname_old,
109 if (errno != ENOMEM ) {
115 if (bufsize > 128*1024) {
116 /*this is getting ridiculous*/
121 new_buf = realloc(getaddrs, bufsize+4096);
127 getaddrs = (struct sctp_getaddrs*)new_buf;
130 /* we skip traversing the list, allocating a new buffer etc. and enjoy
132 cnt = getaddrs->addr_num;
133 memmove(getaddrs, getaddrs + 1, len);
134 *addrs = (struct sockaddr*)getaddrs;
137 } /* sctp_getaddrs() */
139 /* Get all peer address on a socket. This is a new SCTP API
140 * described in the section 8.3 of the Sockets API Extensions for SCTP.
141 * This is implemented using the getsockopt() interface.
144 sctp_getpaddrs(int sd, sctp_assoc_t id, struct sockaddr **addrs)
146 return sctp_getaddrs(sd, id,
148 SCTP_GET_PEER_ADDRS_NUM_OLD,
149 SCTP_GET_PEER_ADDRS_OLD,
151 } /* sctp_getpaddrs() */
153 /* Frees all resources allocated by sctp_getpaddrs(). This is a new SCTP API
154 * described in the section 8.4 of the Sockets API Extensions for SCTP.
157 sctp_freepaddrs(struct sockaddr *addrs)
162 } /* sctp_freepaddrs() */
164 /* Get all locally bound address on a socket. This is a new SCTP API
165 * described in the section 8.5 of the Sockets API Extensions for SCTP.
166 * This is implemented using the getsockopt() interface.
169 sctp_getladdrs(int sd, sctp_assoc_t id, struct sockaddr **addrs)
171 return sctp_getaddrs(sd, id,
172 SCTP_GET_LOCAL_ADDRS,
173 SCTP_GET_LOCAL_ADDRS_NUM_OLD,
174 SCTP_GET_LOCAL_ADDRS_OLD,
176 } /* sctp_getladdrs() */
178 /* Frees all resources allocated by sctp_getladdrs(). This is a new SCTP API
179 * described in the section 8.6 of the Sockets API Extensions for SCTP.
182 sctp_freeladdrs(struct sockaddr *addrs)
187 } /* sctp_freeladdrs() */
190 sctp_getaddrlen(sa_family_t family)
192 /* We could call into the kernel to see what it thinks the size should
193 * be, but hardcoding the address families here is: (a) faster,
194 * (b) easier, and (c) probably good enough for forseeable future.
198 return sizeof(struct sockaddr_in);
200 return sizeof(struct sockaddr_in6);
202 /* Currently there is no defined error handling in
203 * draft-ietf-tsvwg-sctpsocket-13.txt.
204 * -1 might cause the application to overwrite buffer
205 * or misinterpret data. 0 is more likely to cause