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