📄 addrs.c
字号:
/* SCTP kernel Implementation: User API extensions. * * addrs.c * * Distributed under the terms of the LGPL v2.1 as described in * http://www.gnu.org/copyleft/lesser.txt * * This file is part of the user library that offers support for the * SCTP kernel Implementation. The main purpose of this * code is to provide the SCTP Socket API mappings for user * application to interface with the SCTP in kernel. * * This implementation is based on the Socket API Extensions for SCTP * defined in <draft-ietf-tsvwg-sctpsocket-10.txt. * * (C) Copyright IBM Corp. 2003 * Copyright (c) 2001-2002 Intel Corp. * * Written or modified by: * Ardelle Fan <ardelle.fan@intel.com> * Sridhar Samudrala <sri@us.ibm.com> * Ivan Skytte Jørgensen <isj-sctp@i1.dk> */#include <malloc.h>#include <netinet/in.h>#include <netinet/sctp.h>#include <errno.h>/* * Get local/peer addresses using the old API * Old kernels (2.6.13 and earlier) only support this API but it breaks 32-bit * programs on 64-bit kernels. */static intsctp_getaddrs_old(int sd, sctp_assoc_t id, int optname_num, int optname_old, struct sockaddr **addrs){ socklen_t len = sizeof(sctp_assoc_t); int cnt, err; struct sctp_getaddrs_old getaddrs; cnt = getsockopt(sd, SOL_SCTP, optname_num, &id, &len); if (cnt < 0) return -1; if (0 == cnt) { *addrs = NULL; return 0; } len = cnt * sizeof(struct sockaddr_in6); getaddrs.assoc_id = id; getaddrs.addr_num = cnt; getaddrs.addrs = (struct sockaddr *)malloc(len); if (NULL == getaddrs.addrs) return -1; len = sizeof(getaddrs); err = getsockopt(sd, SOL_SCTP, optname_old, &getaddrs, &len); if (err < 0) { free(getaddrs.addrs); return -1; } *addrs = getaddrs.addrs; return getaddrs.addr_num;} /* sctp_getaddrs_old() *//* * Common getsockopt() layer * If the NEW getsockopt() API fails this function will fall back to using * the old API */static intsctp_getaddrs(int sd, sctp_assoc_t id, int optname_new, int optname_num_old, int optname_old, struct sockaddr **addrs){ int cnt, err; socklen_t len; size_t bufsize = 4096; /*enough for most cases*/ struct sctp_getaddrs *getaddrs = (struct sctp_getaddrs*)malloc(bufsize); if(!getaddrs) return -1; for(;;) { char *new_buf; len = bufsize; getaddrs->assoc_id = id; err = getsockopt(sd, SOL_SCTP, optname_new, getaddrs, &len); if (err == 0) { /*got it*/ break; } if (errno == ENOPROTOOPT) { /*Kernel does not support new API*/ free(getaddrs); return sctp_getaddrs_old(sd, id, optname_num_old, optname_old, addrs); } if (errno != ENOMEM ) { /*unknown error*/ free(getaddrs); return -1; } /*expand buffer*/ if (bufsize > 128*1024) { /*this is getting ridiculous*/ free(getaddrs); errno = ENOBUFS; return -1; } new_buf = realloc(getaddrs, bufsize+4096); if (!new_buf) { free(getaddrs); return -1; } bufsize += 4096; getaddrs = (struct sctp_getaddrs*)new_buf; } /* we skip traversing the list, allocating a new buffer etc. and enjoy * a simple hack*/ cnt = getaddrs->addr_num; memmove(getaddrs, getaddrs + 1, len); *addrs = (struct sockaddr*)getaddrs; return cnt;} /* sctp_getaddrs() *//* Get all peer address on a socket. This is a new SCTP API * described in the section 8.3 of the Sockets API Extensions for SCTP. * This is implemented using the getsockopt() interface. */intsctp_getpaddrs(int sd, sctp_assoc_t id, struct sockaddr **addrs){ return sctp_getaddrs(sd, id, SCTP_GET_PEER_ADDRS, SCTP_GET_PEER_ADDRS_NUM_OLD, SCTP_GET_PEER_ADDRS_OLD, addrs);} /* sctp_getpaddrs() *//* Frees all resources allocated by sctp_getpaddrs(). This is a new SCTP API * described in the section 8.4 of the Sockets API Extensions for SCTP. */intsctp_freepaddrs(struct sockaddr *addrs){ free(addrs); return 0;} /* sctp_freepaddrs() *//* Get all locally bound address on a socket. This is a new SCTP API * described in the section 8.5 of the Sockets API Extensions for SCTP. * This is implemented using the getsockopt() interface. */intsctp_getladdrs(int sd, sctp_assoc_t id, struct sockaddr **addrs){ return sctp_getaddrs(sd, id, SCTP_GET_LOCAL_ADDRS, SCTP_GET_LOCAL_ADDRS_NUM_OLD, SCTP_GET_LOCAL_ADDRS_OLD, addrs);} /* sctp_getladdrs() *//* Frees all resources allocated by sctp_getladdrs(). This is a new SCTP API * described in the section 8.6 of the Sockets API Extensions for SCTP. */intsctp_freeladdrs(struct sockaddr *addrs){ free(addrs); return 0;} /* sctp_freeladdrs() */intsctp_getaddrlen(sa_family_t family){ /* We could call into the kernel to see what it thinks the size should * be, but hardcoding the address families here is: (a) faster, * (b) easier, and (c) probably good enough for forseeable future. */ switch(family) { case AF_INET: return sizeof(struct sockaddr_in); case AF_INET6: return sizeof(struct sockaddr_in6); default: /* Currently there is no defined error handling in * draft-ietf-tsvwg-sctpsocket-13.txt. * -1 might cause the application to overwrite buffer * or misinterpret data. 0 is more likely to cause * an endless loop. */ return 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -