File: addrs.c

package info (click to toggle)
lksctp-tools 1.0.17%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,708 kB
  • ctags: 1,184
  • sloc: ansic: 13,499; sh: 4,162; makefile: 251
file content (155 lines) | stat: -rw-r--r-- 3,995 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* SCTP kernel Implementation: User API extensions.
 *
 * addrs.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 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. 2003
 * Copyright (c) 2001-2002 Intel Corp.
 *
 * Written or modified by:
 *  Ardelle Fan     <ardelle.fan@intel.com>
 *  Sridhar Samudrala <sri@us.ibm.com>
 *  Ivan Skytte Jørgensen <isj-sctp@i1.dk>
 */

#include <malloc.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <string.h>
#include <errno.h>

/* 
 * Common getsockopt() layer 
 * If the NEW getsockopt() API fails this function will fall back to using
 * the old API
 */
static int
sctp_getaddrs(int sd, sctp_assoc_t id, int optname_new,
	      struct sockaddr **addrs)
{
	int cnt, err;
	socklen_t len;
	size_t bufsize = 4096; /*enough for most cases*/

	struct sctp_getaddrs *getaddrs = (struct sctp_getaddrs*)malloc(bufsize);
	if(!getaddrs)
		return -1;
	
	for(;;) {
		char *new_buf;

		len = bufsize;
		getaddrs->assoc_id = id;
		err = getsockopt(sd, SOL_SCTP, optname_new, getaddrs, &len);
		if (err == 0) {
			/*got it*/
			break;
		}
		if (errno != ENOMEM ) {
			/*unknown error*/
			free(getaddrs);
			return -1;
		}
		/*expand buffer*/
		if (bufsize > 128*1024) {
			/*this is getting ridiculous*/
			free(getaddrs);
			errno = ENOBUFS;
			return -1;
		}
		new_buf = realloc(getaddrs, bufsize+4096);
		if (!new_buf) {
			free(getaddrs);
			return -1;
		}
		bufsize += 4096;
		getaddrs = (struct sctp_getaddrs*)new_buf;
	}

	/* we skip traversing the list, allocating a new buffer etc. and enjoy
	 * a simple hack*/
	cnt = getaddrs->addr_num;
	memmove(getaddrs, getaddrs + 1, len);
	*addrs = (struct sockaddr*)getaddrs;

	return cnt;
} /* sctp_getaddrs() */

/* Get all peer address on a socket.  This is a new SCTP API
 * described in the section 8.3 of the Sockets API Extensions for SCTP.
 * This is implemented using the getsockopt() interface.
 */
int
sctp_getpaddrs(int sd, sctp_assoc_t id, struct sockaddr **addrs)
{
	return sctp_getaddrs(sd, id,
			     SCTP_GET_PEER_ADDRS,
			     addrs);
} /* sctp_getpaddrs() */

/* Frees all resources allocated by sctp_getpaddrs().  This is a new SCTP API
 * described in the section 8.4 of the Sockets API Extensions for SCTP.
 */
int
sctp_freepaddrs(struct sockaddr *addrs)
{
	free(addrs);
	return 0;

} /* sctp_freepaddrs() */

/* Get all locally bound address on a socket.  This is a new SCTP API
 * described in the section 8.5 of the Sockets API Extensions for SCTP.
 * This is implemented using the getsockopt() interface.
 */
int
sctp_getladdrs(int sd, sctp_assoc_t id, struct sockaddr **addrs)
{
	return sctp_getaddrs(sd, id,
			     SCTP_GET_LOCAL_ADDRS,
			     addrs);
} /* sctp_getladdrs() */

/* Frees all resources allocated by sctp_getladdrs().  This is a new SCTP API
 * described in the section 8.6 of the Sockets API Extensions for SCTP.
 */
int
sctp_freeladdrs(struct sockaddr *addrs)
{
	free(addrs);
	return 0;

} /* sctp_freeladdrs() */

int
sctp_getaddrlen(sa_family_t family)
{
	/* We could call into the kernel to see what it thinks the size should
	 * be, but hardcoding the address families here is: (a) faster,
	 * (b) easier, and (c) probably good enough for forseeable future.
	 */
	switch(family) {
	case AF_INET:
		return sizeof(struct sockaddr_in);
	case AF_INET6:
		return sizeof(struct sockaddr_in6);
	default:
		/* Currently there is no defined error handling in
		 * draft-ietf-tsvwg-sctpsocket-13.txt.
		 * -1 might cause the application to overwrite buffer
		 * or misinterpret data. 0 is more likely to cause
		 * an endless loop.
		 */
		return 0;
	}
}