1 /* SCTP kernel Implementation: User API extensions.
2 *
3 * addrs.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. 2003
17 * Copyright (c) 2001-2002 Intel Corp.
18 *
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>
23 */
24
25 #include <malloc.h>
26 #include <netinet/in.h>
27 #include <netinet/sctp.h>
28 #include <string.h>
29 #include <errno.h>
30
31 /*
32 * Common getsockopt() layer
33 * If the NEW getsockopt() API fails this function will fall back to using
34 * the old API
35 */
36 static int
sctp_getaddrs(int sd,sctp_assoc_t id,int optname_new,struct sockaddr ** addrs)37 sctp_getaddrs(int sd, sctp_assoc_t id, int optname_new,
38 struct sockaddr **addrs)
39 {
40 int cnt, err;
41 socklen_t len;
42 size_t bufsize = 4096; /*enough for most cases*/
43
44 struct sctp_getaddrs *getaddrs = (struct sctp_getaddrs*)malloc(bufsize);
45 if(!getaddrs)
46 return -1;
47
48 for(;;) {
49 char *new_buf;
50
51 len = bufsize;
52 getaddrs->assoc_id = id;
53 err = getsockopt(sd, SOL_SCTP, optname_new, getaddrs, &len);
54 if (err == 0) {
55 /*got it*/
56 break;
57 }
58 if (errno != ENOMEM ) {
59 /*unknown error*/
60 free(getaddrs);
61 return -1;
62 }
63 /*expand buffer*/
64 if (bufsize > 128*1024) {
65 /*this is getting ridiculous*/
66 free(getaddrs);
67 errno = ENOBUFS;
68 return -1;
69 }
70 new_buf = realloc(getaddrs, bufsize+4096);
71 if (!new_buf) {
72 free(getaddrs);
73 return -1;
74 }
75 bufsize += 4096;
76 getaddrs = (struct sctp_getaddrs*)new_buf;
77 }
78
79 /* we skip traversing the list, allocating a new buffer etc. and enjoy
80 * a simple hack*/
81 cnt = getaddrs->addr_num;
82 memmove(getaddrs, getaddrs + 1, len);
83 *addrs = (struct sockaddr*)getaddrs;
84
85 return cnt;
86 } /* sctp_getaddrs() */
87
88 /* Get all peer address on a socket. This is a new SCTP API
89 * described in the section 8.3 of the Sockets API Extensions for SCTP.
90 * This is implemented using the getsockopt() interface.
91 */
92 int
sctp_getpaddrs(int sd,sctp_assoc_t id,struct sockaddr ** addrs)93 sctp_getpaddrs(int sd, sctp_assoc_t id, struct sockaddr **addrs)
94 {
95 return sctp_getaddrs(sd, id,
96 SCTP_GET_PEER_ADDRS,
97 addrs);
98 } /* sctp_getpaddrs() */
99
100 /* Frees all resources allocated by sctp_getpaddrs(). This is a new SCTP API
101 * described in the section 8.4 of the Sockets API Extensions for SCTP.
102 */
103 int
sctp_freepaddrs(struct sockaddr * addrs)104 sctp_freepaddrs(struct sockaddr *addrs)
105 {
106 free(addrs);
107 return 0;
108
109 } /* sctp_freepaddrs() */
110
111 /* Get all locally bound address on a socket. This is a new SCTP API
112 * described in the section 8.5 of the Sockets API Extensions for SCTP.
113 * This is implemented using the getsockopt() interface.
114 */
115 int
sctp_getladdrs(int sd,sctp_assoc_t id,struct sockaddr ** addrs)116 sctp_getladdrs(int sd, sctp_assoc_t id, struct sockaddr **addrs)
117 {
118 return sctp_getaddrs(sd, id,
119 SCTP_GET_LOCAL_ADDRS,
120 addrs);
121 } /* sctp_getladdrs() */
122
123 /* Frees all resources allocated by sctp_getladdrs(). This is a new SCTP API
124 * described in the section 8.6 of the Sockets API Extensions for SCTP.
125 */
126 int
sctp_freeladdrs(struct sockaddr * addrs)127 sctp_freeladdrs(struct sockaddr *addrs)
128 {
129 free(addrs);
130 return 0;
131
132 } /* sctp_freeladdrs() */
133
134 int
sctp_getaddrlen(sa_family_t family)135 sctp_getaddrlen(sa_family_t family)
136 {
137 /* We could call into the kernel to see what it thinks the size should
138 * be, but hardcoding the address families here is: (a) faster,
139 * (b) easier, and (c) probably good enough for forseeable future.
140 */
141 switch(family) {
142 case AF_INET:
143 return sizeof(struct sockaddr_in);
144 case AF_INET6:
145 return sizeof(struct sockaddr_in6);
146 default:
147 /* Currently there is no defined error handling in
148 * draft-ietf-tsvwg-sctpsocket-13.txt.
149 * -1 might cause the application to overwrite buffer
150 * or misinterpret data. 0 is more likely to cause
151 * an endless loop.
152 */
153 return 0;
154 }
155 }
156