• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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