sctp_sys_calls.c revision 1.1 1 1.1 rjs /* $KAME: sctp_sys_calls.c,v 1.10 2005/03/06 16:04:16 itojun Exp $ */
2 1.1 rjs /* $NetBSD: sctp_sys_calls.c,v 1.1 2018/08/02 08:40:48 rjs Exp $ */
3 1.1 rjs
4 1.1 rjs /*
5 1.1 rjs * Copyright (C) 2002, 2003, 2004 Cisco Systems Inc,
6 1.1 rjs * All rights reserved.
7 1.1 rjs *
8 1.1 rjs * Redistribution and use in source and binary forms, with or without
9 1.1 rjs * modification, are permitted provided that the following conditions
10 1.1 rjs * are met:
11 1.1 rjs * 1. Redistributions of source code must retain the above copyright
12 1.1 rjs * notice, this list of conditions and the following disclaimer.
13 1.1 rjs * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 rjs * notice, this list of conditions and the following disclaimer in the
15 1.1 rjs * documentation and/or other materials provided with the distribution.
16 1.1 rjs * 3. Neither the name of the project nor the names of its contributors
17 1.1 rjs * may be used to endorse or promote products derived from this software
18 1.1 rjs * without specific prior written permission.
19 1.1 rjs *
20 1.1 rjs * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 1.1 rjs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 1.1 rjs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 1.1 rjs * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 1.1 rjs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 1.1 rjs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 1.1 rjs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 1.1 rjs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 1.1 rjs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 1.1 rjs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 1.1 rjs * SUCH DAMAGE.
31 1.1 rjs */
32 1.1 rjs
33 1.1 rjs #include <stdio.h>
34 1.1 rjs #include <string.h>
35 1.1 rjs #include <errno.h>
36 1.1 rjs #include <stdlib.h>
37 1.1 rjs #include <unistd.h>
38 1.1 rjs #include <sys/types.h>
39 1.1 rjs #include <sys/socket.h>
40 1.1 rjs #include <sys/errno.h>
41 1.1 rjs #include <sys/syscall.h>
42 1.1 rjs #include <sys/ioctl.h>
43 1.1 rjs #include <sys/uio.h>
44 1.1 rjs #include <netinet/in.h>
45 1.1 rjs #include <arpa/inet.h>
46 1.1 rjs #include <netinet/sctp_uio.h>
47 1.1 rjs #include <netinet/sctp.h>
48 1.1 rjs
49 1.1 rjs #include <net/if_dl.h>
50 1.1 rjs
51 1.1 rjs #ifndef IN6_IS_ADDR_V4MAPPED
52 1.1 rjs #define IN6_IS_ADDR_V4MAPPED(a) \
53 1.1 rjs ((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
54 1.1 rjs (*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
55 1.1 rjs (*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff)))
56 1.1 rjs #endif
57 1.1 rjs
58 1.1 rjs #define SCTP_CONTROL_VEC_SIZE_RCV 16384
59 1.1 rjs
60 1.1 rjs #ifdef SCTP_DEBUG_PRINT_ADDRESS
61 1.1 rjs static void
62 1.1 rjs SCTPPrintAnAddress(struct sockaddr *a)
63 1.1 rjs {
64 1.1 rjs char stringToPrint[256];
65 1.1 rjs u_short prt;
66 1.1 rjs char *srcaddr, *txt;
67 1.1 rjs
68 1.1 rjs if (a == NULL) {
69 1.1 rjs printf("NULL\n");
70 1.1 rjs return;
71 1.1 rjs }
72 1.1 rjs if (a->sa_family == AF_INET) {
73 1.1 rjs srcaddr = (char *)&((struct sockaddr_in *)a)->sin_addr;
74 1.1 rjs txt = "IPv4 Address: ";
75 1.1 rjs prt = ntohs(((struct sockaddr_in *)a)->sin_port);
76 1.1 rjs } else if (a->sa_family == AF_INET6) {
77 1.1 rjs srcaddr = (char *)&((struct sockaddr_in6 *)a)->sin6_addr;
78 1.1 rjs prt = ntohs(((struct sockaddr_in6 *)a)->sin6_port);
79 1.1 rjs txt = "IPv6 Address: ";
80 1.1 rjs } else if (a->sa_family == AF_LINK) {
81 1.1 rjs int i;
82 1.1 rjs char tbuf[200];
83 1.1 rjs u_char adbuf[200];
84 1.1 rjs struct sockaddr_dl *dl;
85 1.1 rjs
86 1.1 rjs dl = (struct sockaddr_dl *)a;
87 1.1 rjs strncpy(tbuf, dl->sdl_data, dl->sdl_nlen);
88 1.1 rjs tbuf[dl->sdl_nlen] = 0;
89 1.1 rjs printf("Intf:%s (len:%d)Interface index:%d type:%x(%d) ll-len:%d ",
90 1.1 rjs tbuf, dl->sdl_nlen, dl->sdl_index, dl->sdl_type,
91 1.1 rjs dl->sdl_type, dl->sdl_alen);
92 1.1 rjs memcpy(adbuf, LLADDR(dl), dl->sdl_alen);
93 1.1 rjs for (i = 0; i < dl->sdl_alen; i++){
94 1.1 rjs printf("%2.2x", adbuf[i]);
95 1.1 rjs if (i < (dl->sdl_alen - 1))
96 1.1 rjs printf(":");
97 1.1 rjs }
98 1.1 rjs printf("\n");
99 1.1 rjs /* u_short sdl_route[16];*/ /* source routing information */
100 1.1 rjs return;
101 1.1 rjs } else {
102 1.1 rjs return;
103 1.1 rjs }
104 1.1 rjs if (inet_ntop(a->sa_family, srcaddr, stringToPrint,
105 1.1 rjs sizeof(stringToPrint))) {
106 1.1 rjs if (a->sa_family == AF_INET6) {
107 1.1 rjs printf("%s%s:%d scope:%d\n", txt, stringToPrint, prt,
108 1.1 rjs ((struct sockaddr_in6 *)a)->sin6_scope_id);
109 1.1 rjs } else {
110 1.1 rjs printf("%s%s:%d\n", txt, stringToPrint, prt);
111 1.1 rjs }
112 1.1 rjs
113 1.1 rjs } else {
114 1.1 rjs printf("%s unprintable?\n", txt);
115 1.1 rjs }
116 1.1 rjs }
117 1.1 rjs #endif /* SCTP_DEBUG_PRINT_ADDRESS */
118 1.1 rjs
119 1.1 rjs void
120 1.1 rjs in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
121 1.1 rjs {
122 1.1 rjs memset(sin, 0, sizeof(*sin));
123 1.1 rjs sin->sin_len = sizeof(struct sockaddr_in);
124 1.1 rjs sin->sin_family = AF_INET;
125 1.1 rjs sin->sin_port = sin6->sin6_port;
126 1.1 rjs sin->sin_addr.s_addr = sin6->sin6_addr.__u6_addr.__u6_addr32[3];
127 1.1 rjs }
128 1.1 rjs
129 1.1 rjs int
130 1.1 rjs sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt,
131 1.1 rjs sctp_assoc_t *id)
132 1.1 rjs {
133 1.1 rjs int i, ret, cnt;
134 1.1 rjs struct sockaddr *at;
135 1.1 rjs struct sctp_connectx_addrs sca;
136 1.1 rjs #if 0
137 1.1 rjs char *cpto;
138 1.1 rjs #endif
139 1.1 rjs size_t len;
140 1.1 rjs
141 1.1 rjs at = addrs;
142 1.1 rjs cnt = 0;
143 1.1 rjs len = 0;
144 1.1 rjs /* validate all the addresses and get the size */
145 1.1 rjs for (i = 0; i < addrcnt; i++) {
146 1.1 rjs if (at->sa_family == AF_INET) {
147 1.1 rjs len += at->sa_len;
148 1.1 rjs } else if (at->sa_family == AF_INET6){
149 1.1 rjs if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)at)->sin6_addr)){
150 1.1 rjs len += sizeof(struct sockaddr_in);
151 1.1 rjs #if 0
152 1.1 rjs in6_sin6_2_sin((struct sockaddr_in *)cpto,
153 1.1 rjs (struct sockaddr_in6 *)at);
154 1.1 rjs cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in));
155 1.1 rjs len += sizeof(struct sockaddr_in);
156 1.1 rjs #endif
157 1.1 rjs } else {
158 1.1 rjs len += at->sa_len;
159 1.1 rjs }
160 1.1 rjs } else {
161 1.1 rjs errno = EINVAL;
162 1.1 rjs return (-1);
163 1.1 rjs }
164 1.1 rjs at = (struct sockaddr *)((caddr_t)at + at->sa_len);
165 1.1 rjs cnt++;
166 1.1 rjs }
167 1.1 rjs /* do we have any? */
168 1.1 rjs if (cnt == 0) {
169 1.1 rjs errno = EINVAL;
170 1.1 rjs return(-1);
171 1.1 rjs }
172 1.1 rjs
173 1.1 rjs sca.cx_num = cnt;
174 1.1 rjs sca.cx_len = len;
175 1.1 rjs sca.cx_addrs = addrs;
176 1.1 rjs ret = ioctl(sd, SIOCCONNECTX, (void *)&sca);
177 1.1 rjs if ((ret == 0) && (id != NULL)) {
178 1.1 rjs memcpy(id, &sca.cx_num, sizeof(sctp_assoc_t));
179 1.1 rjs }
180 1.1 rjs return (ret);
181 1.1 rjs }
182 1.1 rjs
183 1.1 rjs int
184 1.1 rjs sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, int flags)
185 1.1 rjs {
186 1.1 rjs struct sctp_getaddresses *gaddrs;
187 1.1 rjs struct sockaddr *sa;
188 1.1 rjs int i, sz, fam, argsz;
189 1.1 rjs
190 1.1 rjs if ((flags != SCTP_BINDX_ADD_ADDR) &&
191 1.1 rjs (flags != SCTP_BINDX_REM_ADDR)) {
192 1.1 rjs errno = EFAULT;
193 1.1 rjs return(-1);
194 1.1 rjs }
195 1.1 rjs argsz = (sizeof(struct sockaddr_storage) +
196 1.1 rjs sizeof(struct sctp_getaddresses));
197 1.1 rjs gaddrs = (struct sctp_getaddresses *)calloc(1, argsz);
198 1.1 rjs if (gaddrs == NULL) {
199 1.1 rjs errno = ENOMEM;
200 1.1 rjs return(-1);
201 1.1 rjs }
202 1.1 rjs gaddrs->sget_assoc_id = 0;
203 1.1 rjs sa = addrs;
204 1.1 rjs for (i = 0; i < addrcnt; i++) {
205 1.1 rjs sz = sa->sa_len;
206 1.1 rjs fam = sa->sa_family;
207 1.1 rjs ((struct sockaddr_in *)&addrs[i])->sin_port = ((struct sockaddr_in *)sa)->sin_port;
208 1.1 rjs if ((fam != AF_INET) && (fam != AF_INET6)) {
209 1.1 rjs errno = EINVAL;
210 1.1 rjs return(-1);
211 1.1 rjs }
212 1.1 rjs memcpy(gaddrs->addr, sa, sz);
213 1.1 rjs if (setsockopt(sd, IPPROTO_SCTP, flags, gaddrs,
214 1.1 rjs (unsigned int)argsz) != 0) {
215 1.1 rjs free(gaddrs);
216 1.1 rjs return(-1);
217 1.1 rjs }
218 1.1 rjs memset(gaddrs, 0, argsz);
219 1.1 rjs sa = (struct sockaddr *)((caddr_t)sa + sz);
220 1.1 rjs }
221 1.1 rjs free(gaddrs);
222 1.1 rjs return(0);
223 1.1 rjs }
224 1.1 rjs
225 1.1 rjs
226 1.1 rjs int
227 1.1 rjs sctp_opt_info(int sd, sctp_assoc_t id, int opt, void *arg, socklen_t *size)
228 1.1 rjs {
229 1.1 rjs if ((opt == SCTP_RTOINFO) ||
230 1.1 rjs (opt == SCTP_ASSOCINFO) ||
231 1.1 rjs (opt == SCTP_PRIMARY_ADDR) ||
232 1.1 rjs (opt == SCTP_SET_PEER_PRIMARY_ADDR) ||
233 1.1 rjs (opt == SCTP_PEER_ADDR_PARAMS) ||
234 1.1 rjs (opt == SCTP_STATUS) ||
235 1.1 rjs (opt == SCTP_GET_PEER_ADDR_INFO)) {
236 1.1 rjs *(sctp_assoc_t *)arg = id;
237 1.1 rjs return(getsockopt2(sd, IPPROTO_SCTP, opt, arg, size));
238 1.1 rjs } else {
239 1.1 rjs errno = EOPNOTSUPP;
240 1.1 rjs return(-1);
241 1.1 rjs }
242 1.1 rjs }
243 1.1 rjs
244 1.1 rjs int
245 1.1 rjs sctp_getpaddrs(int sd, sctp_assoc_t id, struct sockaddr **raddrs)
246 1.1 rjs {
247 1.1 rjs struct sctp_getaddresses *addrs;
248 1.1 rjs struct sockaddr *sa;
249 1.1 rjs struct sockaddr *re;
250 1.1 rjs sctp_assoc_t asoc;
251 1.1 rjs caddr_t lim;
252 1.1 rjs unsigned int siz;
253 1.1 rjs int cnt;
254 1.1 rjs
255 1.1 rjs if (raddrs == NULL) {
256 1.1 rjs errno = EFAULT;
257 1.1 rjs return(-1);
258 1.1 rjs }
259 1.1 rjs asoc = id;
260 1.1 rjs siz = sizeof(sctp_assoc_t);
261 1.1 rjs if (getsockopt2(sd, IPPROTO_SCTP, SCTP_GET_REMOTE_ADDR_SIZE,
262 1.1 rjs &asoc, &siz) != 0) {
263 1.1 rjs return(-1);
264 1.1 rjs }
265 1.1 rjs siz = (unsigned int)asoc;
266 1.1 rjs siz += sizeof(struct sctp_getaddresses);
267 1.1 rjs addrs = calloc((unsigned long)1, (unsigned long)siz);
268 1.1 rjs if (addrs == NULL) {
269 1.1 rjs errno = ENOMEM;
270 1.1 rjs return(-1);
271 1.1 rjs }
272 1.1 rjs memset(addrs, 0, (size_t)siz);
273 1.1 rjs addrs->sget_assoc_id = id;
274 1.1 rjs /* Now lets get the array of addresses */
275 1.1 rjs if (getsockopt2(sd, IPPROTO_SCTP, SCTP_GET_PEER_ADDRESSES,
276 1.1 rjs addrs, &siz) != 0) {
277 1.1 rjs free(addrs);
278 1.1 rjs return(-1);
279 1.1 rjs }
280 1.1 rjs re = (struct sockaddr *)&addrs->addr[0];
281 1.1 rjs *raddrs = re;
282 1.1 rjs cnt = 0;
283 1.1 rjs sa = (struct sockaddr *)&addrs->addr[0];
284 1.1 rjs lim = (caddr_t)addrs + siz;
285 1.1 rjs while ((caddr_t)sa < lim) {
286 1.1 rjs cnt++;
287 1.1 rjs sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
288 1.1 rjs if (sa->sa_len == 0)
289 1.1 rjs break;
290 1.1 rjs }
291 1.1 rjs return(cnt);
292 1.1 rjs }
293 1.1 rjs
294 1.1 rjs void sctp_freepaddrs(struct sockaddr *addrs)
295 1.1 rjs {
296 1.1 rjs /* Take away the hidden association id */
297 1.1 rjs void *fr_addr;
298 1.1 rjs fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t));
299 1.1 rjs /* Now free it */
300 1.1 rjs free(fr_addr);
301 1.1 rjs }
302 1.1 rjs
303 1.1 rjs int
304 1.1 rjs sctp_getladdrs (int sd, sctp_assoc_t id, struct sockaddr **raddrs)
305 1.1 rjs {
306 1.1 rjs struct sctp_getaddresses *addrs;
307 1.1 rjs struct sockaddr *re;
308 1.1 rjs caddr_t lim;
309 1.1 rjs struct sockaddr *sa;
310 1.1 rjs int size_of_addresses;
311 1.1 rjs unsigned int siz;
312 1.1 rjs int cnt;
313 1.1 rjs
314 1.1 rjs if (raddrs == NULL) {
315 1.1 rjs errno = EFAULT;
316 1.1 rjs return(-1);
317 1.1 rjs }
318 1.1 rjs size_of_addresses = 0;
319 1.1 rjs siz = sizeof(int);
320 1.1 rjs if (getsockopt2(sd, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDR_SIZE,
321 1.1 rjs &size_of_addresses, &siz) != 0) {
322 1.1 rjs return(-1);
323 1.1 rjs }
324 1.1 rjs if (size_of_addresses == 0) {
325 1.1 rjs errno = ENOTCONN;
326 1.1 rjs return(-1);
327 1.1 rjs }
328 1.1 rjs siz = size_of_addresses + sizeof(struct sockaddr_storage);
329 1.1 rjs siz += sizeof(struct sctp_getaddresses);
330 1.1 rjs addrs = calloc((unsigned long)1, (unsigned long)siz);
331 1.1 rjs if (addrs == NULL) {
332 1.1 rjs errno = ENOMEM;
333 1.1 rjs return(-1);
334 1.1 rjs }
335 1.1 rjs memset(addrs, 0, (size_t)siz);
336 1.1 rjs addrs->sget_assoc_id = id;
337 1.1 rjs /* Now lets get the array of addresses */
338 1.1 rjs if (getsockopt2(sd, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDRESSES, addrs,
339 1.1 rjs &siz) != 0) {
340 1.1 rjs free(addrs);
341 1.1 rjs return(-1);
342 1.1 rjs }
343 1.1 rjs re = (struct sockaddr *)&addrs->addr[0];
344 1.1 rjs *raddrs = re;
345 1.1 rjs cnt = 0;
346 1.1 rjs sa = (struct sockaddr *)&addrs->addr[0];
347 1.1 rjs lim = (caddr_t)addrs + siz;
348 1.1 rjs while ((caddr_t)sa < lim) {
349 1.1 rjs cnt++;
350 1.1 rjs sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
351 1.1 rjs if (sa->sa_len == 0)
352 1.1 rjs break;
353 1.1 rjs }
354 1.1 rjs return(cnt);
355 1.1 rjs }
356 1.1 rjs
357 1.1 rjs void sctp_freeladdrs(struct sockaddr *addrs)
358 1.1 rjs {
359 1.1 rjs /* Take away the hidden association id */
360 1.1 rjs void *fr_addr;
361 1.1 rjs fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t));
362 1.1 rjs /* Now free it */
363 1.1 rjs free(fr_addr);
364 1.1 rjs }
365 1.1 rjs
366 1.1 rjs ssize_t
367 1.1 rjs sctp_sendmsg(int s,
368 1.1 rjs const void *data,
369 1.1 rjs size_t len,
370 1.1 rjs const struct sockaddr *to,
371 1.1 rjs socklen_t tolen __attribute__((unused)),
372 1.1 rjs u_int32_t ppid,
373 1.1 rjs u_int32_t flags,
374 1.1 rjs u_int16_t stream_no,
375 1.1 rjs u_int32_t timetolive,
376 1.1 rjs u_int32_t context)
377 1.1 rjs {
378 1.1 rjs int sz;
379 1.1 rjs struct msghdr msg;
380 1.1 rjs struct iovec iov[2];
381 1.1 rjs char controlVector[256];
382 1.1 rjs struct sctp_sndrcvinfo *s_info;
383 1.1 rjs struct cmsghdr *cmsg;
384 1.1 rjs struct sockaddr *who=NULL;
385 1.1 rjs union {
386 1.1 rjs struct sockaddr_in in;
387 1.1 rjs struct sockaddr_in6 in6;
388 1.1 rjs } addr;
389 1.1 rjs
390 1.1 rjs #if 0
391 1.1 rjs fprintf(io, "sctp_sendmsg(sd:%d, data:%x, len:%d, to:%x, tolen:%d, ppid:%x, flags:%x str:%d ttl:%d ctx:%x\n",
392 1.1 rjs s, (u_int)data, (int)len, (u_int)to, (int)tolen, ppid, flags,
393 1.1 rjs (int)stream_no, (int)timetolive, (u_int)context);
394 1.1 rjs fflush(io);
395 1.1 rjs #endif
396 1.1 rjs if (to) {
397 1.1 rjs if (to->sa_len == 0) {
398 1.1 rjs /*
399 1.1 rjs * For the lazy app, that did not
400 1.1 rjs * set sa_len, we attempt to set for them.
401 1.1 rjs */
402 1.1 rjs switch (to->sa_family) {
403 1.1 rjs case AF_INET:
404 1.1 rjs memcpy(&addr, to, sizeof(struct sockaddr_in));
405 1.1 rjs addr.in.sin_len = sizeof(struct sockaddr_in);
406 1.1 rjs break;
407 1.1 rjs case AF_INET6:
408 1.1 rjs memcpy(&addr, to, sizeof(struct sockaddr_in6));
409 1.1 rjs addr.in6.sin6_len = sizeof(struct sockaddr_in6);
410 1.1 rjs break;
411 1.1 rjs default:
412 1.1 rjs errno = EAFNOSUPPORT;
413 1.1 rjs return -1;
414 1.1 rjs }
415 1.1 rjs } else {
416 1.1 rjs memcpy (&addr, to, to->sa_len);
417 1.1 rjs }
418 1.1 rjs who = (struct sockaddr *)&addr;
419 1.1 rjs }
420 1.1 rjs iov[0].iov_base = (void *)(unsigned long)data;
421 1.1 rjs iov[0].iov_len = len;
422 1.1 rjs iov[1].iov_base = NULL;
423 1.1 rjs iov[1].iov_len = 0;
424 1.1 rjs
425 1.1 rjs if (to) {
426 1.1 rjs msg.msg_name = (caddr_t)who;
427 1.1 rjs msg.msg_namelen = who->sa_len;
428 1.1 rjs } else {
429 1.1 rjs msg.msg_name = (caddr_t)NULL;
430 1.1 rjs msg.msg_namelen = 0;
431 1.1 rjs }
432 1.1 rjs msg.msg_iov = iov;
433 1.1 rjs msg.msg_iovlen = 1;
434 1.1 rjs msg.msg_control = (caddr_t)controlVector;
435 1.1 rjs
436 1.1 rjs cmsg = (struct cmsghdr *)controlVector;
437 1.1 rjs
438 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
439 1.1 rjs cmsg->cmsg_type = SCTP_SNDRCV;
440 1.1 rjs cmsg->cmsg_len = CMSG_LEN (sizeof(struct sctp_sndrcvinfo) );
441 1.1 rjs s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
442 1.1 rjs
443 1.1 rjs s_info->sinfo_stream = stream_no;
444 1.1 rjs s_info->sinfo_ssn = 0;
445 1.1 rjs s_info->sinfo_flags = flags;
446 1.1 rjs s_info->sinfo_ppid = ppid;
447 1.1 rjs s_info->sinfo_context = context;
448 1.1 rjs s_info->sinfo_assoc_id = 0;
449 1.1 rjs s_info->sinfo_timetolive = timetolive;
450 1.1 rjs errno = 0;
451 1.1 rjs msg.msg_controllen = cmsg->cmsg_len;
452 1.1 rjs sz = sendmsg(s, &msg, 0);
453 1.1 rjs return(sz);
454 1.1 rjs }
455 1.1 rjs
456 1.1 rjs sctp_assoc_t
457 1.1 rjs sctp_getassocid(int sd, struct sockaddr *sa)
458 1.1 rjs {
459 1.1 rjs struct sctp_paddrparams sp;
460 1.1 rjs socklen_t siz;
461 1.1 rjs
462 1.1 rjs /* First get the assoc id */
463 1.1 rjs siz = sizeof(struct sctp_paddrparams);
464 1.1 rjs memset(&sp, 0, sizeof(sp));
465 1.1 rjs memcpy((caddr_t)&sp.spp_address, sa, sa->sa_len);
466 1.1 rjs errno = 0;
467 1.1 rjs if (getsockopt2(sd, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0)
468 1.1 rjs return((sctp_assoc_t)0);
469 1.1 rjs /* We depend on the fact that 0 can never be returned */
470 1.1 rjs return(sp.spp_assoc_id);
471 1.1 rjs }
472 1.1 rjs
473 1.1 rjs
474 1.1 rjs
475 1.1 rjs ssize_t
476 1.1 rjs sctp_send(int sd, const void *data, size_t len,
477 1.1 rjs const struct sctp_sndrcvinfo *sinfo,
478 1.1 rjs int flags)
479 1.1 rjs {
480 1.1 rjs int sz;
481 1.1 rjs struct msghdr msg;
482 1.1 rjs struct iovec iov[2];
483 1.1 rjs struct sctp_sndrcvinfo *s_info;
484 1.1 rjs char controlVector[256];
485 1.1 rjs struct cmsghdr *cmsg;
486 1.1 rjs
487 1.1 rjs iov[0].iov_base = (void *)(unsigned long)data;
488 1.1 rjs iov[0].iov_len = len;
489 1.1 rjs iov[1].iov_base = NULL;
490 1.1 rjs iov[1].iov_len = 0;
491 1.1 rjs
492 1.1 rjs msg.msg_name = 0;
493 1.1 rjs msg.msg_namelen = 0;
494 1.1 rjs msg.msg_iov = iov;
495 1.1 rjs msg.msg_iovlen = 1;
496 1.1 rjs msg.msg_control = (caddr_t)controlVector;
497 1.1 rjs
498 1.1 rjs cmsg = (struct cmsghdr *)controlVector;
499 1.1 rjs
500 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
501 1.1 rjs cmsg->cmsg_type = SCTP_SNDRCV;
502 1.1 rjs cmsg->cmsg_len = CMSG_LEN (sizeof(struct sctp_sndrcvinfo) );
503 1.1 rjs s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
504 1.1 rjs /* copy in the data */
505 1.1 rjs *s_info = *sinfo;
506 1.1 rjs errno = 0;
507 1.1 rjs msg.msg_controllen = cmsg->cmsg_len;
508 1.1 rjs sz = sendmsg(sd, &msg, flags);
509 1.1 rjs return(sz);
510 1.1 rjs }
511 1.1 rjs
512 1.1 rjs
513 1.1 rjs ssize_t
514 1.1 rjs sctp_sendx(int sd, const void *msg, size_t len,
515 1.1 rjs struct sockaddr *addrs, int addrcnt,
516 1.1 rjs struct sctp_sndrcvinfo *sinfo,
517 1.1 rjs int flags)
518 1.1 rjs {
519 1.1 rjs int i, ret, cnt, saved_errno;
520 1.1 rjs int add_len;
521 1.1 rjs struct sockaddr *at;
522 1.1 rjs struct sctp_connectx_addrs sca;
523 1.1 rjs
524 1.1 rjs len = 0;
525 1.1 rjs at = addrs;
526 1.1 rjs cnt = 0;
527 1.1 rjs /* validate all the addresses and get the size */
528 1.1 rjs for (i = 0; i < addrcnt; i++) {
529 1.1 rjs if (at->sa_family == AF_INET) {
530 1.1 rjs add_len = sizeof(struct sockaddr_in);
531 1.1 rjs } else if (at->sa_family == AF_INET6) {
532 1.1 rjs add_len = sizeof(struct sockaddr_in6);
533 1.1 rjs } else {
534 1.1 rjs errno = EINVAL;
535 1.1 rjs return (-1);
536 1.1 rjs }
537 1.1 rjs len += add_len;
538 1.1 rjs at = (struct sockaddr *)((caddr_t)at + add_len);
539 1.1 rjs cnt++;
540 1.1 rjs }
541 1.1 rjs /* do we have any? */
542 1.1 rjs if (cnt == 0) {
543 1.1 rjs errno = EINVAL;
544 1.1 rjs return(-1);
545 1.1 rjs }
546 1.1 rjs
547 1.1 rjs sca.cx_num = cnt;
548 1.1 rjs sca.cx_len = len;
549 1.1 rjs sca.cx_addrs = addrs;
550 1.1 rjs ret = ioctl(sd, SIOCCONNECTXDEL, (void *)&sca);
551 1.1 rjs if (ret != 0) {
552 1.1 rjs return(ret);
553 1.1 rjs }
554 1.1 rjs sinfo->sinfo_assoc_id = sctp_getassocid(sd, addrs);
555 1.1 rjs if (sinfo->sinfo_assoc_id == 0) {
556 1.1 rjs printf("Huh, can't get associd? TSNH!\n");
557 1.1 rjs (void)setsockopt(sd, IPPROTO_SCTP, SCTP_CONNECT_X_COMPLETE, (void *)addrs,
558 1.1 rjs (unsigned int)addrs->sa_len);
559 1.1 rjs errno = ENOENT;
560 1.1 rjs return (-1);
561 1.1 rjs }
562 1.1 rjs ret = sctp_send(sd, msg, len, sinfo, flags);
563 1.1 rjs saved_errno = errno;
564 1.1 rjs (void)setsockopt(sd, IPPROTO_SCTP, SCTP_CONNECT_X_COMPLETE, (void *)addrs,
565 1.1 rjs (unsigned int)addrs->sa_len);
566 1.1 rjs
567 1.1 rjs errno = saved_errno;
568 1.1 rjs return (ret);
569 1.1 rjs }
570 1.1 rjs
571 1.1 rjs ssize_t
572 1.1 rjs sctp_sendmsgx(int sd,
573 1.1 rjs const void *msg,
574 1.1 rjs size_t len,
575 1.1 rjs struct sockaddr *addrs,
576 1.1 rjs int addrcnt,
577 1.1 rjs u_int32_t ppid,
578 1.1 rjs u_int32_t flags,
579 1.1 rjs u_int16_t stream_no,
580 1.1 rjs u_int32_t timetolive,
581 1.1 rjs u_int32_t context)
582 1.1 rjs {
583 1.1 rjs struct sctp_sndrcvinfo sinfo;
584 1.1 rjs
585 1.1 rjs memset((void *) &sinfo, 0, sizeof(struct sctp_sndrcvinfo));
586 1.1 rjs sinfo.sinfo_ppid = ppid;
587 1.1 rjs sinfo.sinfo_flags = flags;
588 1.1 rjs sinfo.sinfo_ssn = stream_no;
589 1.1 rjs sinfo.sinfo_timetolive = timetolive;
590 1.1 rjs sinfo.sinfo_context = context;
591 1.1 rjs return sctp_sendx(sd, msg, len, addrs, addrcnt, &sinfo, 0);
592 1.1 rjs }
593 1.1 rjs
594 1.1 rjs ssize_t
595 1.1 rjs sctp_recvmsg (int s,
596 1.1 rjs void *dbuf,
597 1.1 rjs size_t len,
598 1.1 rjs struct sockaddr *from,
599 1.1 rjs socklen_t *fromlen,
600 1.1 rjs struct sctp_sndrcvinfo *sinfo,
601 1.1 rjs int *msg_flags)
602 1.1 rjs {
603 1.1 rjs struct sctp_sndrcvinfo *s_info;
604 1.1 rjs ssize_t sz;
605 1.1 rjs struct msghdr msg;
606 1.1 rjs struct iovec iov[2];
607 1.1 rjs char controlVector[2048];
608 1.1 rjs struct cmsghdr *cmsg;
609 1.1 rjs iov[0].iov_base = dbuf;
610 1.1 rjs iov[0].iov_len = len;
611 1.1 rjs iov[1].iov_base = NULL;
612 1.1 rjs iov[1].iov_len = 0;
613 1.1 rjs msg.msg_name = (caddr_t)from;
614 1.1 rjs msg.msg_namelen = *fromlen;
615 1.1 rjs msg.msg_iov = iov;
616 1.1 rjs msg.msg_iovlen = 1;
617 1.1 rjs msg.msg_control = (caddr_t)controlVector;
618 1.1 rjs msg.msg_controllen = sizeof(controlVector);
619 1.1 rjs errno = 0;
620 1.1 rjs sz = recvmsg(s, &msg, 0);
621 1.1 rjs
622 1.1 rjs s_info = NULL;
623 1.1 rjs len = sz;
624 1.1 rjs *msg_flags = msg.msg_flags;
625 1.1 rjs *fromlen = msg.msg_namelen;
626 1.1 rjs if ((msg.msg_controllen) && sinfo) {
627 1.1 rjs /* parse through and see if we find
628 1.1 rjs * the sctp_sndrcvinfo (if the user wants it).
629 1.1 rjs */
630 1.1 rjs cmsg = (struct cmsghdr *)controlVector;
631 1.1 rjs while (cmsg) {
632 1.1 rjs if (cmsg->cmsg_level == IPPROTO_SCTP) {
633 1.1 rjs if (cmsg->cmsg_type == SCTP_SNDRCV) {
634 1.1 rjs /* Got it */
635 1.1 rjs s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
636 1.1 rjs /* Copy it to the user */
637 1.1 rjs *sinfo = *s_info;
638 1.1 rjs break;
639 1.1 rjs }
640 1.1 rjs }
641 1.1 rjs cmsg = CMSG_NXTHDR(&msg, cmsg);
642 1.1 rjs }
643 1.1 rjs }
644 1.1 rjs return(sz);
645 1.1 rjs }
646 1.1 rjs
647 1.1 rjs ssize_t
648 1.1 rjs sctp_recvv(int sd,
649 1.1 rjs const struct iovec *iov,
650 1.1 rjs int iovlen,
651 1.1 rjs struct sockaddr *from,
652 1.1 rjs socklen_t * fromlen,
653 1.1 rjs void *info,
654 1.1 rjs socklen_t * infolen,
655 1.1 rjs unsigned int *infotype,
656 1.1 rjs int *flags)
657 1.1 rjs {
658 1.1 rjs char cmsgbuf[SCTP_CONTROL_VEC_SIZE_RCV];
659 1.1 rjs struct msghdr msg;
660 1.1 rjs struct cmsghdr *cmsg;
661 1.1 rjs ssize_t ret;
662 1.1 rjs struct sctp_rcvinfo *rcvinfo;
663 1.1 rjs struct sctp_nxtinfo *nxtinfo;
664 1.1 rjs
665 1.1 rjs if (((info != NULL) && (infolen == NULL)) ||
666 1.1 rjs ((info == NULL) && (infolen != NULL) && (*infolen != 0)) ||
667 1.1 rjs ((info != NULL) && (infotype == NULL))) {
668 1.1 rjs errno = EINVAL;
669 1.1 rjs return (-1);
670 1.1 rjs }
671 1.1 rjs if (infotype) {
672 1.1 rjs *infotype = SCTP_RECVV_NOINFO;
673 1.1 rjs }
674 1.1 rjs msg.msg_name = from;
675 1.1 rjs if (fromlen == NULL) {
676 1.1 rjs msg.msg_namelen = 0;
677 1.1 rjs } else {
678 1.1 rjs msg.msg_namelen = *fromlen;
679 1.1 rjs }
680 1.1 rjs msg.msg_iov = __UNCONST(iov);
681 1.1 rjs msg.msg_iovlen = iovlen;
682 1.1 rjs msg.msg_control = cmsgbuf;
683 1.1 rjs msg.msg_controllen = sizeof(cmsgbuf);
684 1.1 rjs msg.msg_flags = 0;
685 1.1 rjs ret = recvmsg(sd, &msg, *flags);
686 1.1 rjs *flags = msg.msg_flags;
687 1.1 rjs if ((ret > 0) &&
688 1.1 rjs (msg.msg_controllen > 0) &&
689 1.1 rjs (infotype != NULL) &&
690 1.1 rjs (infolen != NULL) &&
691 1.1 rjs (*infolen > 0)) {
692 1.1 rjs rcvinfo = NULL;
693 1.1 rjs nxtinfo = NULL;
694 1.1 rjs for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
695 1.1 rjs if (cmsg->cmsg_level != IPPROTO_SCTP) {
696 1.1 rjs continue;
697 1.1 rjs }
698 1.1 rjs if (cmsg->cmsg_type == SCTP_RCVINFO) {
699 1.1 rjs rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
700 1.1 rjs if (nxtinfo != NULL) {
701 1.1 rjs break;
702 1.1 rjs } else {
703 1.1 rjs continue;
704 1.1 rjs }
705 1.1 rjs }
706 1.1 rjs if (cmsg->cmsg_type == SCTP_NXTINFO) {
707 1.1 rjs nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmsg);
708 1.1 rjs if (rcvinfo != NULL) {
709 1.1 rjs break;
710 1.1 rjs } else {
711 1.1 rjs continue;
712 1.1 rjs }
713 1.1 rjs }
714 1.1 rjs }
715 1.1 rjs if (rcvinfo != NULL) {
716 1.1 rjs if ((nxtinfo != NULL) && (*infolen >= sizeof(struct sctp_recvv_rn))) {
717 1.1 rjs struct sctp_recvv_rn *rn_info;
718 1.1 rjs
719 1.1 rjs rn_info = (struct sctp_recvv_rn *)info;
720 1.1 rjs rn_info->recvv_rcvinfo = *rcvinfo;
721 1.1 rjs rn_info->recvv_nxtinfo = *nxtinfo;
722 1.1 rjs *infolen = (socklen_t) sizeof(struct sctp_recvv_rn);
723 1.1 rjs *infotype = SCTP_RECVV_RN;
724 1.1 rjs } else if (*infolen >= sizeof(struct sctp_rcvinfo)) {
725 1.1 rjs memcpy(info, rcvinfo, sizeof(struct sctp_rcvinfo));
726 1.1 rjs *infolen = (socklen_t) sizeof(struct sctp_rcvinfo);
727 1.1 rjs *infotype = SCTP_RECVV_RCVINFO;
728 1.1 rjs }
729 1.1 rjs } else if (nxtinfo != NULL) {
730 1.1 rjs if (*infolen >= sizeof(struct sctp_nxtinfo)) {
731 1.1 rjs memcpy(info, nxtinfo, sizeof(struct sctp_nxtinfo));
732 1.1 rjs *infolen = (socklen_t) sizeof(struct sctp_nxtinfo);
733 1.1 rjs *infotype = SCTP_RECVV_NXTINFO;
734 1.1 rjs }
735 1.1 rjs }
736 1.1 rjs }
737 1.1 rjs return (ret);
738 1.1 rjs }
739 1.1 rjs
740 1.1 rjs ssize_t
741 1.1 rjs sctp_sendv(int sd,
742 1.1 rjs const struct iovec *iov, int iovcnt,
743 1.1 rjs struct sockaddr *addrs, int addrcnt,
744 1.1 rjs void *info, socklen_t infolen, unsigned int infotype,
745 1.1 rjs int flags)
746 1.1 rjs {
747 1.1 rjs ssize_t ret;
748 1.1 rjs int i;
749 1.1 rjs socklen_t addr_len;
750 1.1 rjs struct msghdr msg;
751 1.1 rjs in_port_t port;
752 1.1 rjs struct sctp_sendv_spa *spa_info;
753 1.1 rjs struct cmsghdr *cmsg;
754 1.1 rjs char *cmsgbuf;
755 1.1 rjs struct sockaddr *addr;
756 1.1 rjs struct sockaddr_in *addr_in;
757 1.1 rjs struct sockaddr_in6 *addr_in6;
758 1.1 rjs void *assoc_id_ptr;
759 1.1 rjs sctp_assoc_t assoc_id;
760 1.1 rjs
761 1.1 rjs if ((addrcnt < 0) ||
762 1.1 rjs (iovcnt < 0) ||
763 1.1 rjs ((addrs == NULL) && (addrcnt > 0)) ||
764 1.1 rjs ((addrs != NULL) && (addrcnt == 0)) ||
765 1.1 rjs ((iov == NULL) && (iovcnt > 0)) ||
766 1.1 rjs ((iov != NULL) && (iovcnt == 0))) {
767 1.1 rjs errno = EINVAL;
768 1.1 rjs return (-1);
769 1.1 rjs }
770 1.1 rjs cmsgbuf = malloc(CMSG_SPACE(sizeof(struct sctp_sndinfo)) +
771 1.1 rjs CMSG_SPACE(sizeof(struct sctp_prinfo)) +
772 1.1 rjs CMSG_SPACE(sizeof(struct sctp_authinfo)) +
773 1.1 rjs (size_t)addrcnt * CMSG_SPACE(sizeof(struct in6_addr)));
774 1.1 rjs if (cmsgbuf == NULL) {
775 1.1 rjs errno = ENOMEM;
776 1.1 rjs return (-1);
777 1.1 rjs }
778 1.1 rjs assoc_id_ptr = NULL;
779 1.1 rjs msg.msg_control = cmsgbuf;
780 1.1 rjs msg.msg_controllen = 0;
781 1.1 rjs cmsg = (struct cmsghdr *)cmsgbuf;
782 1.1 rjs switch (infotype) {
783 1.1 rjs case SCTP_SENDV_NOINFO:
784 1.1 rjs if ((infolen != 0) || (info != NULL)) {
785 1.1 rjs free(cmsgbuf);
786 1.1 rjs errno = EINVAL;
787 1.1 rjs return (-1);
788 1.1 rjs }
789 1.1 rjs break;
790 1.1 rjs case SCTP_SENDV_SNDINFO:
791 1.1 rjs if ((info == NULL) || (infolen < sizeof(struct sctp_sndinfo))) {
792 1.1 rjs free(cmsgbuf);
793 1.1 rjs errno = EINVAL;
794 1.1 rjs return (-1);
795 1.1 rjs }
796 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
797 1.1 rjs cmsg->cmsg_type = SCTP_SNDINFO;
798 1.1 rjs cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
799 1.1 rjs memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_sndinfo));
800 1.1 rjs msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
801 1.1 rjs cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
802 1.1 rjs assoc_id_ptr = &(((struct sctp_sndinfo *)info)->snd_assoc_id);
803 1.1 rjs break;
804 1.1 rjs case SCTP_SENDV_PRINFO:
805 1.1 rjs if ((info == NULL) || (infolen < sizeof(struct sctp_prinfo))) {
806 1.1 rjs free(cmsgbuf);
807 1.1 rjs errno = EINVAL;
808 1.1 rjs return (-1);
809 1.1 rjs }
810 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
811 1.1 rjs cmsg->cmsg_type = SCTP_PRINFO;
812 1.1 rjs cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
813 1.1 rjs memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_prinfo));
814 1.1 rjs msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
815 1.1 rjs cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
816 1.1 rjs break;
817 1.1 rjs case SCTP_SENDV_AUTHINFO:
818 1.1 rjs if ((info == NULL) || (infolen < sizeof(struct sctp_authinfo))) {
819 1.1 rjs free(cmsgbuf);
820 1.1 rjs errno = EINVAL;
821 1.1 rjs return (-1);
822 1.1 rjs }
823 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
824 1.1 rjs cmsg->cmsg_type = SCTP_AUTHINFO;
825 1.1 rjs cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
826 1.1 rjs memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_authinfo));
827 1.1 rjs msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
828 1.1 rjs cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
829 1.1 rjs break;
830 1.1 rjs case SCTP_SENDV_SPA:
831 1.1 rjs if ((info == NULL) || (infolen < sizeof(struct sctp_sendv_spa))) {
832 1.1 rjs free(cmsgbuf);
833 1.1 rjs errno = EINVAL;
834 1.1 rjs return (-1);
835 1.1 rjs }
836 1.1 rjs spa_info = (struct sctp_sendv_spa *)info;
837 1.1 rjs if (spa_info->sendv_flags & SCTP_SEND_SNDINFO_VALID) {
838 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
839 1.1 rjs cmsg->cmsg_type = SCTP_SNDINFO;
840 1.1 rjs cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
841 1.1 rjs memcpy(CMSG_DATA(cmsg), &spa_info->sendv_sndinfo, sizeof(struct sctp_sndinfo));
842 1.1 rjs msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
843 1.1 rjs cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
844 1.1 rjs assoc_id_ptr = &(spa_info->sendv_sndinfo.snd_assoc_id);
845 1.1 rjs }
846 1.1 rjs if (spa_info->sendv_flags & SCTP_SEND_PRINFO_VALID) {
847 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
848 1.1 rjs cmsg->cmsg_type = SCTP_PRINFO;
849 1.1 rjs cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
850 1.1 rjs memcpy(CMSG_DATA(cmsg), &spa_info->sendv_prinfo, sizeof(struct sctp_prinfo));
851 1.1 rjs msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
852 1.1 rjs cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
853 1.1 rjs }
854 1.1 rjs if (spa_info->sendv_flags & SCTP_SEND_AUTHINFO_VALID) {
855 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
856 1.1 rjs cmsg->cmsg_type = SCTP_AUTHINFO;
857 1.1 rjs cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
858 1.1 rjs memcpy(CMSG_DATA(cmsg), &spa_info->sendv_authinfo, sizeof(struct sctp_authinfo));
859 1.1 rjs msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
860 1.1 rjs cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
861 1.1 rjs }
862 1.1 rjs break;
863 1.1 rjs default:
864 1.1 rjs free(cmsgbuf);
865 1.1 rjs errno = EINVAL;
866 1.1 rjs return (-1);
867 1.1 rjs }
868 1.1 rjs addr = addrs;
869 1.1 rjs msg.msg_name = NULL;
870 1.1 rjs msg.msg_namelen = 0;
871 1.1 rjs
872 1.1 rjs for (i = 0; i < addrcnt; i++) {
873 1.1 rjs switch (addr->sa_family) {
874 1.1 rjs case AF_INET:
875 1.1 rjs addr_len = (socklen_t) sizeof(struct sockaddr_in);
876 1.1 rjs addr_in = (struct sockaddr_in *)addr;
877 1.1 rjs if (addr_in->sin_len != addr_len) {
878 1.1 rjs free(cmsgbuf);
879 1.1 rjs errno = EINVAL;
880 1.1 rjs return (-1);
881 1.1 rjs }
882 1.1 rjs if (i == 0) {
883 1.1 rjs port = addr_in->sin_port;
884 1.1 rjs } else {
885 1.1 rjs if (port == addr_in->sin_port) {
886 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
887 1.1 rjs cmsg->cmsg_type = SCTP_DSTADDRV4;
888 1.1 rjs cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
889 1.1 rjs memcpy(CMSG_DATA(cmsg), &addr_in->sin_addr, sizeof(struct in_addr));
890 1.1 rjs msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
891 1.1 rjs cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in_addr)));
892 1.1 rjs } else {
893 1.1 rjs free(cmsgbuf);
894 1.1 rjs errno = EINVAL;
895 1.1 rjs return (-1);
896 1.1 rjs }
897 1.1 rjs }
898 1.1 rjs break;
899 1.1 rjs case AF_INET6:
900 1.1 rjs addr_len = (socklen_t) sizeof(struct sockaddr_in6);
901 1.1 rjs addr_in6 = (struct sockaddr_in6 *)addr;
902 1.1 rjs if (addr_in6->sin6_len != addr_len) {
903 1.1 rjs free(cmsgbuf);
904 1.1 rjs errno = EINVAL;
905 1.1 rjs return (-1);
906 1.1 rjs }
907 1.1 rjs if (i == 0) {
908 1.1 rjs port = addr_in6->sin6_port;
909 1.1 rjs } else {
910 1.1 rjs if (port == addr_in6->sin6_port) {
911 1.1 rjs cmsg->cmsg_level = IPPROTO_SCTP;
912 1.1 rjs cmsg->cmsg_type = SCTP_DSTADDRV6;
913 1.1 rjs cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_addr));
914 1.1 rjs memcpy(CMSG_DATA(cmsg), &addr_in6->sin6_addr, sizeof(struct in6_addr));
915 1.1 rjs msg.msg_controllen += CMSG_SPACE(sizeof(struct in6_addr));
916 1.1 rjs cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in6_addr)));
917 1.1 rjs } else {
918 1.1 rjs free(cmsgbuf);
919 1.1 rjs errno = EINVAL;
920 1.1 rjs return (-1);
921 1.1 rjs }
922 1.1 rjs }
923 1.1 rjs break;
924 1.1 rjs default:
925 1.1 rjs free(cmsgbuf);
926 1.1 rjs errno = EINVAL;
927 1.1 rjs return (-1);
928 1.1 rjs }
929 1.1 rjs if (i == 0) {
930 1.1 rjs msg.msg_name = addr;
931 1.1 rjs msg.msg_namelen = addr_len;
932 1.1 rjs }
933 1.1 rjs addr = (struct sockaddr *)((caddr_t)addr + addr_len);
934 1.1 rjs }
935 1.1 rjs if (msg.msg_controllen == 0) {
936 1.1 rjs msg.msg_control = NULL;
937 1.1 rjs }
938 1.1 rjs msg.msg_iov = __UNCONST(iov);
939 1.1 rjs msg.msg_iovlen = iovcnt;
940 1.1 rjs msg.msg_flags = 0;
941 1.1 rjs ret = sendmsg(sd, &msg, flags);
942 1.1 rjs free(cmsgbuf);
943 1.1 rjs if ((ret >= 0) && (addrs != NULL) && (assoc_id_ptr != NULL)) {
944 1.1 rjs assoc_id = sctp_getassocid(sd, addrs);
945 1.1 rjs memcpy(assoc_id_ptr, &assoc_id, sizeof(assoc_id));
946 1.1 rjs }
947 1.1 rjs return (ret);
948 1.1 rjs }
949 1.1 rjs
950 1.1 rjs int
951 1.1 rjs sctp_peeloff(int sd, sctp_assoc_t assoc_id)
952 1.1 rjs {
953 1.1 rjs int ret;
954 1.1 rjs uint32_t val;
955 1.1 rjs
956 1.1 rjs val = assoc_id;
957 1.1 rjs ret = ioctl(sd, SIOCPEELOFF, &val);
958 1.1 rjs if (ret == -1)
959 1.1 rjs return ret;
960 1.1 rjs else
961 1.1 rjs return (int) val;
962 1.1 rjs }
963 1.1 rjs
964