Home | History | Annotate | Line # | Download | only in net
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