00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifdef USE_SCTP
00034
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <sys/types.h>
00038 #include <sys/socket.h>
00039 #include <netinet/in.h>
00040 #include <netinet/in_systm.h>
00041 #include <netinet/ip.h>
00042 #include <errno.h>
00043 #include <arpa/inet.h>
00044 #ifdef __linux__
00045 #include <linux/types.h>
00046 #include <linux/errqueue.h>
00047 #endif
00048
00049
00050 #include "sctp_server.h"
00051 #include "globals.h"
00052 #include "config.h"
00053 #include "dprint.h"
00054 #include "receive.h"
00055 #include "mem/mem.h"
00056 #include "ip_addr.h"
00057
00058 #define LISTEN_BACKLOG 5
00059
00060 int sctp_server_init(struct socket_info* sock_info)
00061 {
00062 union sockaddr_union* addr;
00063 int optval;
00064
00065 addr=&sock_info->su;
00066 sock_info->proto=PROTO_SCTP;
00067 if (init_su(addr, &sock_info->address, sock_info->port_no)<0){
00068 LM_ERR("could not init sockaddr_union\n");
00069 goto error;
00070 }
00071
00072 sock_info->socket = socket(AF2PF(addr->s.sa_family), SOCK_SEQPACKET, 0);
00073 if (sock_info->socket==-1){
00074 LM_ERR("socket: %s [%d]\n", strerror(errno), errno);
00075 goto error;
00076 }
00077
00078 optval=1;
00079 if (setsockopt(sock_info->socket, SOL_SOCKET, SO_REUSEADDR ,
00080 (void*)&optval, sizeof(optval)) ==-1){
00081 LM_ERR("setsockopt: %s\n", strerror(errno));
00082 goto error;
00083 }
00084
00085 #ifdef DISABLE_NAGLE
00086
00087 optval=1;
00088 if (setsockopt(sock_info->socket, IPPROTO_SCTP, SCTP_NODELAY,
00089 (void*)&optval, sizeof(optval))==-1){
00090 LM_WARN("setsockopt %s\n", strerror(errno));
00091
00092 }
00093 #endif
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 #if defined (__linux__) && defined(SCTP_ERRORS)
00109
00110 optval=1;
00111
00112 if(setsockopt(sock_info->socket, SOL_IP, IP_RECVERR,
00113 (void*)&optval, sizeof(optval)) ==-1){
00114 LM_ERR("setsockopt: %s\n", strerror(errno));
00115 goto error;
00116 }
00117 #endif
00118
00119
00120
00121
00122 if (bind(sock_info->socket, &addr->s, sockaddru_len(*addr))==-1){
00123 LM_ERR("bind(%x, %p, %d) on %s: %s\n",
00124 sock_info->socket, &addr->s,
00125 (unsigned)sockaddru_len(*addr),
00126 sock_info->address_str.s,
00127 strerror(errno));
00128 #ifdef USE_IPV6
00129 if (addr->s.sa_family==AF_INET6)
00130 LM_ERR("might be caused by using a link "
00131 " local address, try site local or global\n");
00132 #endif
00133 goto error;
00134 }
00135 if(listen(sock_info->socket, LISTEN_BACKLOG)<0){
00136 LM_ERR("listen(%x, %d) on %s: %s\n",
00137 sock_info->socket,
00138 LISTEN_BACKLOG,
00139 sock_info->address_str.s,
00140 strerror(errno));
00141 goto error;
00142 }
00143
00144 return 0;
00145
00146 error:
00147
00148 return -1;
00149 }
00150
00151
00152
00153 int sctp_server_rcv_loop()
00154 {
00155 int len;
00156 #ifdef DYN_BUF
00157 char* buf;
00158 #else
00159 static char buf [BUF_SIZE+1];
00160 #endif
00161 char *tmp;
00162 union sockaddr_union* from;
00163 unsigned int fromlen;
00164 struct receive_info ri;
00165 struct sctp_sndrcvinfo sinfo;
00166
00167
00168 from=(union sockaddr_union*) pkg_malloc(sizeof(union sockaddr_union));
00169 if (from==0){
00170 LM_ERR("out of pkg memory\n");
00171 goto error;
00172 }
00173 memset(&sinfo, 0 , sizeof(sinfo));
00174 ri.bind_address=bind_address;
00175 ri.dst_port=bind_address->port_no;
00176 ri.dst_ip=bind_address->address;
00177 ri.proto=PROTO_SCTP;
00178 ri.proto_reserved1=ri.proto_reserved2=0;
00179 for(;;){
00180 #ifdef DYN_BUF
00181 buf=pkg_malloc(BUF_SIZE+1);
00182 if (buf==0){
00183 LM_ERR(" could not allocate receive buffer in pkg memory\n");
00184 goto error;
00185 }
00186 #endif
00187 fromlen=sockaddru_len(bind_address->su);
00188 len = sctp_recvmsg(bind_address->socket, buf, BUF_SIZE, &from->s, &fromlen, &sinfo, 0);
00189
00190 if (len==-1){
00191 if (errno==EAGAIN){
00192 LM_DBG("packet with bad checksum received\n");
00193 continue;
00194 }
00195 LM_ERR("sctp_recvmsg:[%d] %s\n", errno, strerror(errno));
00196 if ((errno==EINTR)||(errno==EWOULDBLOCK)|| (errno==ECONNREFUSED))
00197 continue;
00198 else goto error;
00199 }
00200
00201 buf[len]=0;
00202
00203 ri.src_su=*from;
00204 su2ip_addr(&ri.src_ip, from);
00205 ri.src_port=su_getport(from);
00206
00207 #ifndef NO_ZERO_CHECKS
00208 if (buf[len-1]==0) {
00209 tmp=ip_addr2a(&ri.src_ip);
00210 LM_WARN("upstream bug - 0-terminated packet from %s %d\n",
00211 tmp, htons(ri.src_port));
00212 len--;
00213 }
00214 #endif
00215 if (ri.src_port==0){
00216 tmp=ip_addr2a(&ri.src_ip);
00217 LM_INFO("dropping 0 port packet from %s\n", tmp);
00218 continue;
00219 }
00220
00221
00222
00223 receive_msg(buf, len, &ri);
00224
00225
00226
00227 }
00228
00229
00230
00231
00232
00233 error:
00234 if (from) pkg_free(from);
00235 return -1;
00236 }
00237
00238
00239
00240
00241
00242 int sctp_server_send(struct socket_info *source, char *buf, unsigned len,
00243 union sockaddr_union* to)
00244 {
00245 int n;
00246 int tolen;
00247
00248 tolen=sockaddru_len(*to);
00249 again:
00250 n=sctp_sendmsg(source->socket, buf, len, &to->s, tolen, 0, 0, 0, 0, 0);
00251 #ifdef XL_DEBUG
00252 LM_INFO("send status: %d\n", n);
00253 #endif
00254 if (n==-1){
00255 LM_ERR("sctp_sendmsg(sock,%p,%d,%p,%d,0,0,0,0,0): %s(%d)\n",
00256 buf,len,&to->s,tolen, strerror(errno),errno);
00257
00258 if (errno==EINTR) goto again;
00259 if (errno==EINVAL) {
00260 LM_CRIT("invalid sendtoparameters\n"
00261 "one possible reason is the server is bound to localhost and\n"
00262 "attempts to send to the net\n");
00263 }
00264 }
00265 return n;
00266 }
00267
00268 #endif
00269