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

addr.c

00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: addr.c,v 1.16 2006/05/27 16:34:01 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <stdlib.h>
00013 #ifdef HAVE_STDINT
00014 #include <stdint.h>
00015 #endif /* HAVE_STDINT */
00016 #include <klone/addr.h>
00017 #include <klone/server.h>
00018 #include <u/libu.h>
00019 
00020 int addr_free(addr_t *a)
00021 {
00022     U_FREE(a);
00023     return 0;
00024 }
00025 
00026 static int addr_ipv4_create(u_config_t *c, addr_t *addr)
00027 {
00028     u_config_t *subkey;
00029     int portn;
00030 
00031     dbg_return_if (c == NULL, ~0);
00032     dbg_return_if (addr == NULL, ~0);
00033     
00034     /* set default values */
00035     addr->type = ADDR_IPV4;
00036     addr->sa.sin.sin_family = AF_INET;
00037 
00038     /* use user-defined ip or port */
00039     if(!u_config_get_subkey(c, "ip", &subkey))
00040     {
00041 #ifdef OS_UNIX
00042         warn_err_ifm(inet_pton(AF_INET, u_config_get_value(subkey), 
00043             &addr->sa.sin.sin_addr) <= 0, 
00044                 "bad '<servname>.addr.ip' value");
00045 #else
00046         addr->sa.sin.sin_addr.s_addr = inet_addr(u_config_get_value(subkey));
00047         warn_err_ifm(addr->sa.sin.sin_addr.s_addr == INADDR_NONE,
00048                 "bad '<servname>.addr.ip' value");
00049 #endif
00050     }
00051 
00052     if(!u_config_get_subkey(c, "port", &subkey))
00053     {
00054         portn = atoi(u_config_get_value(subkey));
00055         warn_err_ifm(portn < 1 || portn > 65535, "port out of range");
00056         addr->sa.sin.sin_port = htons(portn);
00057     }
00058 
00059     return 0;
00060 err:
00061     return ~0;
00062 }
00063 
00064 static int addr_is_ipv4(const char *ip)
00065 {
00066     size_t i, len = strlen(ip);
00067 
00068     dbg_return_if (ip == NULL, 0);
00069 
00070     /* assume ip it's of type IPv4 if it contains a dot '.' */
00071     for(i = 0; i < len; ++i)
00072         if(ip[i] == '.')
00073             return 1;
00074     
00075     return 0;
00076 }
00077 
00078 int addr_set_ipv4_port(addr_t *addr, int port)
00079 {
00080     dbg_return_if (addr == NULL, ~0);
00081     dbg_return_if (port == 0, ~0);
00082 
00083     addr->sa.sin.sin_port = htons(port);
00084 
00085     return 0;
00086 }
00087 
00088 int addr_set_ipv4_ip(addr_t *addr, const char *ip)
00089 {
00090     dbg_return_if (addr == NULL, ~0);
00091     dbg_return_if (ip == NULL, ~0);
00092 
00093     addr->type = ADDR_IPV4;
00094 
00095     /* set default values */
00096     memset(&addr->sa.sin, 0, sizeof(addr->sa.sin));
00097     addr->sa.sin.sin_family = AF_INET;
00098     addr->sa.sin.sin_addr.s_addr = inet_addr(ip);
00099 
00100     return 0;
00101 }
00102 
00103 int addr_set(addr_t *addr, const char *ip, int port)
00104 {
00105     dbg_return_if (addr == NULL, ~0);
00106     dbg_return_if (ip == NULL, ~0);
00107     dbg_return_if (port == 0, ~0);
00108 
00109     if(addr_is_ipv4(ip))
00110     {
00111         addr->type = ADDR_IPV4;
00112 
00113         /* set default values */
00114         memset(&addr->sa.sin, 0, sizeof(addr->sa.sin));
00115         addr->sa.sin.sin_family = AF_INET;
00116         addr->sa.sin.sin_addr.s_addr = inet_addr(ip);
00117         addr->sa.sin.sin_port = htons(port);
00118     } else {
00119         return ~0; /* FIXME IPv6 */
00120     }
00121 
00122     return 0;
00123 }
00124 
00125 int addr_set_from_sa(addr_t *addr, struct sockaddr *sa, size_t sz)
00126 {
00127     dbg_return_if (addr == NULL, ~0);
00128     dbg_return_if (sa == NULL, ~0);
00129     
00130     switch(sz)
00131     {
00132     case sizeof(struct sockaddr_in):
00133         addr->type = ADDR_IPV4;
00134         memcpy(&addr->sa.sin, sa, sz);
00135         break;
00136 #ifndef NO_IPV6
00137     case sizeof(struct sockaddr_in6):
00138         addr->type = ADDR_IPV6;
00139         memcpy(&addr->sa.sin6, sa, sz);
00140         break;
00141 #endif
00142 #ifndef NO_UNIXSOCK
00143     case sizeof(struct sockaddr_un):
00144         addr->type = ADDR_UNIX;
00145         memcpy(&addr->sa.sun, sa, sz);
00146         break;
00147 #endif  
00148     default:
00149         dbg("bad sockaddr size");
00150         return ~0;
00151     }
00152 
00153     return 0;
00154 }
00155 
00156 int addr_set_from_config(addr_t *addr, u_config_t *c)
00157 {
00158     u_config_t *subkey;
00159     const char *type;
00160 
00161     dbg_return_if (addr == NULL, ~0);
00162     dbg_return_if (c == NULL, ~0);
00163     
00164     dbg_err_if(strcasecmp(u_config_get_key(c), "addr"));
00165 
00166     warn_err_ifm(u_config_get_subkey(c, "type", &subkey),
00167         "missing or bad '<servname>.addr.type' value");
00168 
00169     type = u_config_get_value(subkey); /* IPv4, IPv6, unix, etc.  */
00170 
00171     if(!strcasecmp(type, "IPv4"))
00172         dbg_err_if(addr_ipv4_create(c, addr));
00173     else 
00174         warn_err_if("bad '<servname>.addr.type', only IPv4 is supported");
00175 
00176     return 0;
00177 err:
00178     return ~0;
00179 }
00180 
00181 int addr_create(addr_t **pa)
00182 {
00183     addr_t *addr = NULL;
00184 
00185     dbg_return_if (pa == NULL, ~0);
00186     
00187     addr = u_zalloc(sizeof(addr_t));
00188     dbg_err_if(addr == NULL);
00189 
00190     /* set default ipv4 values */
00191     memset(&addr->sa.sin, 0, sizeof(addr->sa.sin));
00192     addr->sa.sin.sin_family = AF_INET;
00193     addr->sa.sin.sin_addr.s_addr = htonl(INADDR_ANY);
00194     addr->sa.sin.sin_port = htons(0);
00195 
00196     *pa = addr;
00197 
00198     return 0;
00199 err:
00200     if(addr)
00201         addr_free(addr);
00202     return ~0;
00203 }