Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

socket.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 #include <ctype.h>
00058 #include <errno.h>
00059 #include <stdarg.h>
00060 #include <stdio.h>
00061 #include <stdlib.h>
00062 #include <string.h>
00063 #include <time.h>
00064 #include <unistd.h>
00065 #include <fcntl.h>
00066 
00067 #include <sys/time.h>
00068 #include <sys/types.h>
00069 #include <sys/socket.h>
00070 #include <netinet/in.h>
00071 #include <netdb.h>
00072 #include <arpa/inet.h>
00073 #include <sys/utsname.h>
00074 
00075 #include "gwlib.h"
00076 
00077 
00078 static Octstr *official_name = NULL;
00079 static Octstr *official_ip = NULL;
00080 
00081 /*
00082  * FreeBSD is not happy with our approach of allocating a sockaddr
00083  * and then filling in the fields.  It has private fields that need
00084  * to be initialized to 0.  This structure is used for that.
00085  */
00086 static const struct sockaddr_in empty_sockaddr_in;
00087 
00088 #ifndef UDP_PACKET_MAX_SIZE
00089 #define UDP_PACKET_MAX_SIZE (64*1024)
00090 #endif
00091 
00092 
00093 int make_server_socket(int port, const char *interface_name )
00094 {
00095     struct sockaddr_in addr;
00096     int s;
00097     int reuse;
00098     struct hostent hostinfo;
00099     char *buff = NULL;
00100 
00101     s = socket(PF_INET, SOCK_STREAM, 0);
00102     if (s == -1) {
00103         error(errno, "socket failed");
00104         goto error;
00105     }
00106 
00107     addr = empty_sockaddr_in;
00108     addr.sin_family = AF_INET;
00109     addr.sin_port = htons(port);
00110     if (interface_name == NULL || strcmp(interface_name, "*") == 0)
00111         addr.sin_addr.s_addr = htonl(INADDR_ANY);
00112     else {
00113         if (gw_gethostbyname(&hostinfo, interface_name, &buff) == -1) {
00114             error(errno, "gethostbyname failed");
00115             goto error;
00116         }
00117         addr.sin_addr = *(struct in_addr *) hostinfo.h_addr;
00118     }
00119 
00120     reuse = 1;
00121     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse,
00122                    sizeof(reuse)) == -1) {
00123         error(errno, "setsockopt failed for server address");
00124         goto error;
00125     }
00126 
00127     if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
00128         error(errno, "bind failed");
00129         goto error;
00130     }
00131 
00132     if (listen(s, 10) == -1) {
00133         error(errno, "listen failed");
00134         goto error;
00135     }
00136 
00137     gw_free(buff);
00138 
00139     return s;
00140 
00141 error:
00142     if (s >= 0)
00143         (void) close(s);
00144     gw_free(buff);
00145     return -1;
00146 }
00147 
00148 
00149 int tcpip_connect_to_server(char *hostname, int port, const char *interface_name)
00150 {
00151 
00152     return tcpip_connect_to_server_with_port(hostname, port, 0, interface_name);
00153 }
00154 
00155 
00156 int tcpip_connect_to_server_with_port(char *hostname, int port, int our_port, const char *interface_name)
00157 {
00158     struct sockaddr_in addr;
00159     struct sockaddr_in o_addr;
00160     struct hostent hostinfo;
00161     struct hostent o_hostinfo;
00162     int s;
00163     char *buff, *buff1;
00164 
00165     buff = buff1 = NULL;
00166 
00167     s = socket(PF_INET, SOCK_STREAM, 0);
00168     if (s == -1) {
00169         error(errno, "Couldn't create new socket.");
00170         goto error;
00171     }
00172 
00173     if (gw_gethostbyname(&hostinfo, hostname, &buff) == -1) {
00174         error(errno, "gethostbyname failed");
00175         goto error;
00176     }
00177 
00178     addr = empty_sockaddr_in;
00179     addr.sin_family = AF_INET;
00180     addr.sin_port = htons(port);
00181     addr.sin_addr = *(struct in_addr *) hostinfo.h_addr;
00182 
00183     if (our_port > 0 || (interface_name != NULL && strcmp(interface_name, "*") != 0))  {
00184         int reuse;
00185 
00186         o_addr = empty_sockaddr_in;
00187         o_addr.sin_family = AF_INET;
00188         o_addr.sin_port = htons(our_port);
00189     if (interface_name == NULL || strcmp(interface_name, "*") == 0)
00190         o_addr.sin_addr.s_addr = htonl(INADDR_ANY);
00191     else {
00192         if (gw_gethostbyname(&o_hostinfo, interface_name, &buff1) == -1) {
00193         error(errno, "gethostbyname failed");
00194         goto error;
00195         }
00196         o_addr.sin_addr = *(struct in_addr *) o_hostinfo.h_addr;
00197     }
00198 
00199         reuse = 1;
00200         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse,
00201                        sizeof(reuse)) == -1) {
00202             error(errno, "setsockopt failed before bind");
00203             goto error;
00204         }
00205         if (bind(s, (struct sockaddr *) &o_addr, sizeof(o_addr)) == -1) {
00206             error(errno, "bind to local port %d failed", our_port);
00207             goto error;
00208         }
00209     }
00210 
00211     if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
00212         error(errno, "connect failed");
00213         goto error;
00214     }
00215 
00216     gw_free(buff);
00217     gw_free(buff1);
00218     return s;
00219 
00220 error:
00221     error(0, "error connecting to server `%s' at port `%d'",
00222           hostname, port);
00223     if (s >= 0)
00224         close(s);
00225     gw_free(buff);
00226     gw_free(buff1);
00227     return -1;
00228 }
00229 
00230 int tcpip_connect_nb_to_server(char *hostname, int port, const char *interface_name, int *done)
00231 {
00232   return tcpip_connect_nb_to_server_with_port(hostname, port, 0, interface_name, done);
00233 }
00234 
00235 int tcpip_connect_nb_to_server_with_port(char *hostname, int port, int our_port, const char *interface_name, int *done) 
00236 {
00237   struct sockaddr_in addr;
00238   struct sockaddr_in o_addr;
00239   struct hostent hostinfo;
00240   struct hostent o_hostinfo;
00241   int s;
00242   int flags,rc;
00243   char *buff, *buff1;
00244 
00245   *done = 1;
00246   buff = buff1 = NULL;
00247 
00248   s = socket(PF_INET, SOCK_STREAM, 0);
00249   if (s == -1) {
00250     error(errno, "Couldn't create new socket.");
00251     goto error;
00252   }
00253 
00254   if (gw_gethostbyname(&hostinfo, hostname, &buff) == -1) {
00255     error(errno, "gethostbyname failed");
00256     goto error;
00257   }
00258 
00259   addr = empty_sockaddr_in;
00260   addr.sin_family = AF_INET;
00261   addr.sin_port = htons(port);
00262   addr.sin_addr = *(struct in_addr *) hostinfo.h_addr;
00263 
00264   if (our_port > 0 || (interface_name != NULL && strcmp(interface_name, "*") != 0)) {
00265     int reuse;
00266 
00267     o_addr = empty_sockaddr_in;
00268     o_addr.sin_family = AF_INET;
00269     o_addr.sin_port = htons(our_port);
00270     if (interface_name == NULL || strcmp(interface_name, "*") == 0)
00271       o_addr.sin_addr.s_addr = htonl(INADDR_ANY);
00272     else {
00273       if (gw_gethostbyname(&o_hostinfo, interface_name, &buff1) == -1) {
00274     error(errno, "gethostbyname failed");
00275     goto error;
00276       }
00277       o_addr.sin_addr = *(struct in_addr *) o_hostinfo.h_addr;
00278     }
00279 
00280     reuse = 1;
00281     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse,
00282            sizeof(reuse)) == -1) {
00283       error(errno, "setsockopt failed before bind");
00284       goto error;
00285     }
00286     if (bind(s, (struct sockaddr *) &o_addr, sizeof(o_addr)) == -1) {
00287       error(errno, "bind to local port %d failed", our_port);
00288       goto error;
00289     }
00290   }
00291 
00292   flags = fcntl(s, F_GETFL, 0);
00293   fcntl(s, F_SETFL, flags | O_NONBLOCK);
00294 
00295   if ((rc = connect(s, (struct sockaddr *) &addr, sizeof(addr))) < 0) {
00296     if (errno != EINPROGRESS) {
00297       error(errno, "nonblocking connect failed");
00298       goto error;
00299     }
00300   }
00301   
00302   /* May be connected immediatly
00303    * (if we connecting to localhost for example) */
00304   if (rc == 0) { 
00305     *done = 0;
00306   }
00307 
00308   gw_free(buff);
00309   gw_free(buff1);
00310 
00311   return s;
00312 
00313  error:
00314   error(0, "error connecting to server `%s' at port `%d'",
00315     hostname, port);
00316   if (s >= 0)
00317     close(s);
00318   gw_free(buff);
00319   gw_free(buff1);
00320   return -1;
00321 }
00322 
00323 
00324 int write_to_socket(int socket, char *str)
00325 {
00326     size_t len;
00327     int ret;
00328 
00329     len = strlen(str);
00330     while (len > 0) {
00331         ret = write(socket, str, len);
00332         if (ret == -1) {
00333             if (errno == EAGAIN) continue;
00334             if (errno == EINTR) continue;
00335             error(errno, "Writing to socket failed");
00336             return -1;
00337         }
00338         /* ret may be less than len, if the writing was interrupted
00339            by a signal. */
00340         len -= ret;
00341         str += ret;
00342     }
00343     return 0;
00344 }
00345 
00346 
00347 int socket_set_blocking(int fd, int blocking)
00348 {
00349     int flags, newflags;
00350 
00351     flags = fcntl(fd, F_GETFL);
00352     if (flags < 0) {
00353         error(errno, "cannot get flags for fd %d", fd);
00354         return -1;
00355     }
00356 
00357     if (blocking)
00358         newflags = flags & ~O_NONBLOCK;
00359     else
00360         newflags = flags | O_NONBLOCK;
00361 
00362     if (newflags != flags) {
00363         if (fcntl(fd, F_SETFL, newflags) < 0) {
00364             error(errno, "cannot set flags for fd %d", fd);
00365             return -1;
00366         }
00367     }
00368 
00369     return 0;
00370 }
00371 
00372 
00373 int read_available(int fd, long wait_usec)
00374 {
00375     fd_set rf;
00376     struct timeval to;
00377     int ret;
00378     div_t waits;
00379 
00380     gw_assert(fd >= 0);
00381 
00382     FD_ZERO(&rf);
00383     FD_SET(fd, &rf);
00384     waits = div(wait_usec, 1000000);
00385     to.tv_sec = waits.quot;
00386     to.tv_usec = waits.rem;
00387 retry:
00388     ret = select(fd + 1, &rf, NULL, NULL, &to);
00389     if (ret > 0 && FD_ISSET(fd, &rf))
00390         return 1;
00391     if (ret < 0) {
00392         /* In most select() implementations, to will now contain the
00393          * remaining time rather than the original time.  That is exactly
00394          * what we want when retrying after an interrupt. */
00395         switch (errno) {
00396             /*The first two entries here are OK*/
00397         case EINTR:
00398             goto retry;
00399         case EAGAIN:
00400             return 1;
00401             /* We are now sucking mud, figure things out here
00402              * as much as possible before it gets lost under
00403              * layers of abstraction.  */
00404         case EBADF:
00405             if (!FD_ISSET(fd, &rf)) {
00406                 warning(0, "Tried to select on fd %d, not in the set!\n", fd);
00407             } else {
00408                 warning(0, "Tried to select on invalid fd %d!\n", fd);
00409             }
00410             break;
00411         case EINVAL:
00412             /* Solaris catchall "It didn't work" error, lets apply
00413              * some tests and see if we can catch it. */
00414 
00415             /* First up, try invalid timeout*/
00416             if (to.tv_sec > 10000000)
00417                 warning(0, "Wait more than three years for a select?\n");
00418             if (to.tv_usec > 1000000)
00419                 warning(0, "There are only 1000000 usec in a second...\n");
00420             break;
00421 
00422 
00423         }
00424         return -1;  /* some error */
00425     }
00426     return 0;
00427 }
00428 
00429 
00430 
00431 int udp_client_socket(void)
00432 {
00433     int s;
00434 
00435     s = socket(PF_INET, SOCK_DGRAM, 0);
00436     if (s == -1) {
00437         error(errno, "Couldn't create a UDP socket");
00438         return -1;
00439     }
00440 
00441     return s;
00442 }
00443 
00444 
00445 int udp_bind(int port, const char *interface_name)
00446 {
00447     int s;
00448     struct sockaddr_in sa;
00449     struct hostent hostinfo;
00450     char *buff = NULL;
00451 
00452     s = socket(PF_INET, SOCK_DGRAM, 0);
00453     if (s == -1) {
00454         error(errno, "Couldn't create a UDP socket");
00455         return -1;
00456     }
00457 
00458     sa = empty_sockaddr_in;
00459     sa.sin_family = AF_INET;
00460     sa.sin_port = htons(port);
00461     if (strcmp(interface_name, "*") == 0)
00462         sa.sin_addr.s_addr = htonl(INADDR_ANY);
00463     else {
00464         if (gw_gethostbyname(&hostinfo, interface_name, &buff) == -1) {
00465             error(errno, "gethostbyname failed");
00466             gw_free(buff);
00467             return -1;
00468         }
00469         sa.sin_addr = *(struct in_addr *) hostinfo.h_addr;
00470     }
00471 
00472     if (bind(s, (struct sockaddr *) &sa, (int) sizeof(sa)) == -1) {
00473         error(errno, "Couldn't bind a UDP socket to port %d", port);
00474         (void) close(s);
00475         return -1;
00476     }
00477 
00478     gw_free(buff);
00479 
00480     return s;
00481 }
00482 
00483 
00484 Octstr *udp_create_address(Octstr *host_or_ip, int port)
00485 {
00486     struct sockaddr_in sa;
00487     struct hostent h;
00488     char *buff = NULL;
00489     Octstr *ret;
00490 
00491     sa = empty_sockaddr_in;
00492     sa.sin_family = AF_INET;
00493     sa.sin_port = htons(port);
00494 
00495     if (strcmp(octstr_get_cstr(host_or_ip), "*") == 0) {
00496         sa.sin_addr.s_addr = INADDR_ANY;
00497     } else {
00498         if (gw_gethostbyname(&h, octstr_get_cstr(host_or_ip), &buff) == -1) {
00499             error(0, "Couldn't find the IP number of `%s'",
00500                   octstr_get_cstr(host_or_ip));
00501             gw_free(buff);
00502             return NULL;
00503         }
00504         sa.sin_addr = *(struct in_addr *) h.h_addr;
00505     }
00506 
00507     ret = octstr_create_from_data((char *) &sa, sizeof(sa));
00508     gw_free(buff);
00509 
00510     return ret;
00511 }
00512 
00513 
00514 int udp_get_port(Octstr *addr)
00515 {
00516     struct sockaddr_in sa;
00517 
00518     gw_assert(octstr_len(addr) == sizeof(sa));
00519     memcpy(&sa, octstr_get_cstr(addr), sizeof(sa));
00520     return ntohs(sa.sin_port);
00521 }
00522 
00523 
00524 Octstr *udp_get_ip(Octstr *addr)
00525 {
00526     struct sockaddr_in sa;
00527 
00528     gw_assert(octstr_len(addr) == sizeof(sa));
00529     memcpy(&sa, octstr_get_cstr(addr), sizeof(sa));
00530     return gw_netaddr_to_octstr(AF_INET, &sa.sin_addr);
00531 }
00532 
00533 
00534 int udp_sendto(int s, Octstr *datagram, Octstr *addr)
00535 {
00536     struct sockaddr_in sa;
00537 
00538     gw_assert(octstr_len(addr) == sizeof(sa));
00539     memcpy(&sa, octstr_get_cstr(addr), sizeof(sa));
00540     if (sendto(s, octstr_get_cstr(datagram), octstr_len(datagram), 0,
00541                (struct sockaddr *) &sa, (int) sizeof(sa)) == -1) {
00542         error(errno, "Couldn't send UDP packet");
00543         return -1;
00544     }
00545     return 0;
00546 }
00547 
00548 
00549 int udp_recvfrom(int s, Octstr **datagram, Octstr **addr)
00550 {
00551     struct sockaddr_in sa;
00552     int salen;
00553     char *buf;
00554     int bytes;
00555 
00556     buf = gw_malloc(UDP_PACKET_MAX_SIZE);
00557 
00558     salen = sizeof(sa);
00559     bytes = recvfrom(s, buf, UDP_PACKET_MAX_SIZE, 0,
00560                      (struct sockaddr *) &sa, &salen);
00561     if (bytes == -1) {
00562         if (errno != EAGAIN)
00563             error(errno, "Couldn't receive UDP packet");
00564     gw_free(buf);
00565         return -1;
00566     }
00567 
00568     *datagram = octstr_create_from_data(buf, bytes);
00569     *addr = octstr_create_from_data((char *) &sa, salen);
00570     
00571     gw_free(buf);
00572 
00573     return 0;
00574 }
00575 
00576 
00577 Octstr *host_ip(struct sockaddr_in addr)
00578 {
00579     return gw_netaddr_to_octstr(AF_INET, &addr.sin_addr);
00580 }
00581 
00582 
00583 int host_port(struct sockaddr_in addr)
00584 {
00585     return ntohs(addr.sin_port);
00586 }
00587 
00588 
00589 Octstr *get_official_name(void)
00590 {
00591     gw_assert(official_name != NULL);
00592     return official_name;
00593 }
00594 
00595 
00596 Octstr *get_official_ip(void)
00597 {
00598     gw_assert(official_ip != NULL);
00599     return official_ip;
00600 }
00601 
00602 
00603 static void setup_official_name(void)
00604 {
00605     struct utsname u;
00606     struct hostent h;
00607     char *buff = NULL;
00608 
00609     gw_assert(official_name == NULL);
00610     if (uname(&u) == -1)
00611         panic(0, "uname failed - can't happen, unless " GW_NAME " is buggy.");
00612     if (gw_gethostbyname(&h, u.nodename, &buff) == -1) {
00613         error(0, "Can't find out official hostname for this host, "
00614               "using `%s' instead.", u.nodename);
00615         official_name = octstr_create(u.nodename);
00616         official_ip = octstr_create("127.0.0.1");
00617     } else {
00618         official_name = octstr_create(h.h_name);
00619         official_ip = gw_netaddr_to_octstr(AF_INET, h.h_addr);
00620     }
00621     gw_free(buff);
00622 }
00623 
00624 
00625 void socket_init(void)
00626 {
00627     setup_official_name();
00628 }
00629 
00630 void socket_shutdown(void)
00631 {
00632     octstr_destroy(official_name);
00633     official_name = NULL;
00634     octstr_destroy(official_ip);
00635     official_ip = NULL;
00636 }
00637 
00638 
00639 static Octstr *gw_netaddr_to_octstr4(unsigned char *src)
00640 {
00641     return octstr_format("%d.%d.%d.%d", src[0], src[1], src[2], src[3]);
00642 }
00643 
00644 
00645 #ifdef AF_INET6
00646 static Octstr *gw_netaddr_to_octstr6(unsigned char *src)
00647 {
00648     return octstr_format(
00649             "%x:%x:%x:%x:"
00650         "%x:%x:%x:%x:"
00651         "%x:%x:%x:%x:"
00652         "%x:%x:%x:%x",
00653              src[0],  src[1],  src[2],  src[3], 
00654          src[4],  src[5],  src[6],  src[7], 
00655          src[8],  src[9], src[10], src[11], 
00656         src[12], src[13], src[14], src[15]);
00657 }
00658 #endif
00659 
00660 Octstr *gw_netaddr_to_octstr(int af, void *src)
00661 {
00662     switch (af) {
00663     case AF_INET:
00664     return gw_netaddr_to_octstr4(src);
00665 
00666 #ifdef AF_INET6
00667     case AF_INET6:
00668     return gw_netaddr_to_octstr6(src);
00669 #endif
00670 
00671     default:
00672     return NULL;
00673     } 
00674 }
00675 
00676 
00677 int gw_accept(int fd, Octstr **client_addr)
00678 {
00679     struct sockaddr_in addr;
00680     int addrlen;
00681     int new_fd;
00682 
00683     if (gwthread_pollfd(fd, POLLIN, -1.0) != POLLIN) {
00684     debug("gwlib.socket", 0, "gwthread_pollfd interrupted or failed");
00685     return -1;
00686     }
00687     addrlen = sizeof(addr);
00688     new_fd = accept(fd, (struct sockaddr *) &addr, &addrlen);
00689     if (new_fd == -1) {
00690     error(errno, "accept system call failed.");
00691     return -1;
00692     }
00693     *client_addr = host_ip(addr);
00694     debug("test_smsc", 0, "accept() succeeded, client from %s",
00695       octstr_get_cstr(*client_addr));
00696     return new_fd;
00697 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.