Home | History | Annotate | Download | only in lib
      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