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 (at) intel.com> 21 * Sridhar Samudrala <sri (at) us.ibm.com> 22 * Ivan Skytte Jrgensen <isj-sctp (at) 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 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 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 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 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 127 sctp_freeladdrs(struct sockaddr *addrs) 128 { 129 free(addrs); 130 return 0; 131 132 } /* sctp_freeladdrs() */ 133 134 int 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