Mercurial > hg > waaad
changeset 123:d1cef88ac5f2
Added new directives in conf, improved peer internal dsecription, replaces sockaddr with aliases
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Fri, 08 Aug 2008 18:04:38 +0900 |
parents | 9a341105760a |
children | b4d229d647b7 |
files | doc/waaad.conf.sample include/waaad/conf-api.h include/waaad/security-api.h waaad/conf-gram.y waaad/conf-token.l waaad/conf.c waaad/dict-base.c waaad/peer-internal.h waaad/security.c waaad/security.h waaad/waaad-internal.h |
diffstat | 11 files changed, 395 insertions(+), 72 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/waaad.conf.sample Thu Aug 07 11:25:59 2008 +0900 +++ b/doc/waaad.conf.sample Fri Aug 08 18:04:38 2008 +0900 @@ -9,12 +9,32 @@ # The Diameter-Id of this peer. # This must be a valid FQDN that resolves to the local host. # Default: no default -diameter-id = "test.local"; +diameter-id = "aaa.koganei.wide.ad.jp"; # The port this peer is listening on for incoming connections (TCP and SCTP). # Default: 3868 # LocalPort = 3868; +# Directives for the addresses that the local peer will use. +# The following directives are defined: +# 'no_tcp;' : do not listen for TCP traffic, or attempt TCP connections. -- SCTP cannot be disabled. +# 'no_ip4;' : do not use local IP addresses. +# 'no_ip6;' : do not use local IPv6 addresses. +# 'primary = "xxx.xxx.xxx.xxx";' : Listen TCP and SCTP connections on this address. +# 'primary = "aaaa:bbbb::dddd:eeee";' : Listen TCP and SCTP connections on this address. +# 'secondary = "xxx.xxx.xxx.xxx";' : also use this IP for SCTP multihoming, but not as TCP server. +# 'secondary = "aaaa:bbbb::dddd:eeee";': also use this IPv6 for SCTP multihoming, but not as TCP server. +# +# Note that: +# If no_ip4 is specified, no_ip6, primary4 and secondary4 are forbidden. +# If no_ip6 is specified, no_ip4, primary6 and secondary6 are forbidden. +# primary* directives use more resources than secondary* (one thread per primary sockets). +# The first "primary" directive that appears will be used as primary for SCTP and as +# value for Host-IP-Address for CER/CEA exchanged over TCP. +# +# The default is to use both IP and IPv6, allow TCP, and let the system select the addresses. +# In that case, the address used in CER/CEA will be the first value returned by DNS for the diameter-id resolution. + # Where the messages are sent? # Valid values: console, syslog. # Multiple values are allowed. Separator is ','. Example:
--- a/include/waaad/conf-api.h Thu Aug 07 11:25:59 2008 +0900 +++ b/include/waaad/conf-api.h Fri Aug 08 18:04:38 2008 +0900 @@ -40,23 +40,39 @@ #define _CONF_API_H #include <stddef.h> +#include <sys/socket.h> +#include <netinet/in.h> /* The version of this API, to check binary compatibility -- increment each time a change is made in api_conf_t */ #define WAAAD_API_CONF_VER 1 +#ifndef sSA_ALIASES +#define sSS struct sockaddr_storage +#define sSA struct sockaddr +#define sSA4 struct sockaddr_in +#define sSA6 struct sockaddr_in6 +#define sSA_ALIASES +#endif /* sSA_ALIASES */ + /* This type contains all the parts of the global configuration of the daemon that can be accessed by the extensions */ typedef struct { char *diameter_identity; /* The Diameter Identity of the local peer */ + uint16_t local_port; /* The port on which to listen for incoming connexions. */ - uint16_t local_port; /* The port on which to listen for incoming connexions. */ + sSS local_addr_diamid[2]; /* The first address resolved from the Diameter Id (IP and IPv6), + to use in Host-IP-Address if following list is empty. */ + sSS *local_addr_pri_sa; /* points to a 0-terminated array of sSS containing the primary addresses from conf file. */ + sSS *local_addr_sec_sa; /* points to a 0-terminated array of sSS containing the secondary addresses from conf file. */ + + int disable_inet4; /* if != 0, the local host does not use the IP protocol */ + int disable_inet6; /* if != 0, the local host does not use the IPv6 protocol */ + int disable_tcp; /* if != 0, the local host does not use the TCP protocol */ + int disable_relay; /* if != 0, the local host does not relay Diameter messages */ int tctimer; /* The value in seconds of the Tc timer */ - int twtimer; /* The value in seconds of the Tw timer */ - int disable_relay; /* if != 0, the local host do not relay Diameter messages */ - } ext_conf_t; /* One should use the always-defined "g_pconf" pointer to access these fields */ /* Now define the type of the structure that contains the callback to pass to extensions */
--- a/include/waaad/security-api.h Thu Aug 07 11:25:59 2008 +0900 +++ b/include/waaad/security-api.h Fri Aug 08 18:04:38 2008 +0900 @@ -87,7 +87,13 @@ #include <sys/types.h> #include <sys/socket.h> - +#ifndef sSA_ALIASES +#define sSS struct sockaddr_storage +#define sSA struct sockaddr +#define sSA4 struct sockaddr_in +#define sSA6 struct sockaddr_in6 +#define sSA_ALIASES +#endif /* sSA_ALIASES */ /* The following type represents a "connection" object (for example, a socket) */ typedef void sec_conn_t; @@ -231,7 +237,7 @@ * 0 : Operation complete. * !0 : An error occurred. The module will not be used for this peer. */ -typedef int (*sec_is_supported_peer_cb_t) (char * diamid, struct sockaddr * sa, int * priority); +typedef int (*sec_is_supported_peer_cb_t) (char * diamid, sSA * sa, int * priority); /* The following type contains all the information needed to register a security module. */
--- a/waaad/conf-gram.y Thu Aug 07 11:25:59 2008 +0900 +++ b/waaad/conf-gram.y Fri Aug 08 18:04:38 2008 +0900 @@ -59,6 +59,7 @@ #include "conf-gram.h" /* bison is not smart enough to define the YYLTYPE before including this code, so... */ #include <string.h> +#include <stdlib.h> #include <sys/stat.h> #include <errno.h> #include <sys/socket.h> @@ -113,6 +114,98 @@ return 1; } +/* Global variable to store a sockaddr checked by is_valid_addr */ +static sSS _ss; + +static int have_ip4 = 0; /* have some ip4 been added already? */ +static int have_ip6 = 0; /* have some ip6 been added already? */ + +/* This function converts a string into an IP or IPv6 address */ +static int is_valid_addr( char * candidate, waaad_conf_t * pconfig) +{ + int ret=0; + + /* Clean the storage area */ + memset(&_ss, 0, sizeof(_ss)); + + /* Search for a ":" in the string */ + if (!strchr(candidate, ':')) { + sSA4 * sin = (sSA4 *) &_ss; + /* Assume this is IPv4 */ + ret = inet_pton(AF_INET, candidate, &sin->sin_addr.s_addr); + if (ret == 1) { + if (pconfig->pub.disable_inet4) { + log_error("Cannot use the address '%s' since NO_IP4 was defined\n", candidate); + return 0; + } + have_ip4++; + sin->sin_family = AF_INET; + sin->sin_port = htons(pconfig->pub.local_port); + return 1; /* the IP is valid */ + } + if (ret == 0) { + log_error("Error on IP address '%s': unrecognized.\n", candidate); + } else { + log_error("Error on IP address '%s': %s.\n", candidate, strerror(errno)); + } + } else { + sSA6 * sin6 = (sSA6 *)&_ss; + /* Assume this is IPv6 */ + ret = inet_pton(AF_INET6, candidate, &sin6->sin6_addr.s6_addr); + if (ret == 1) { + if (pconfig->pub.disable_inet6) { + log_error("Cannot use the address '%s' since NO_IP6 was defined\n", candidate); + return 0; + } + have_ip6++; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = htons(pconfig->pub.local_port); + return 1; /* the IPv6 is valid */ + } + if (ret == 0) { + log_error("Error on IPv6 address '%s': unrecognized.\n", candidate); + } else { + log_error("Error on IPv6 address '%s': %s.\n", candidate, strerror(errno)); + } + } + + /* This candidate is not valid */ + return 0; +} + +/* This function extends the list of addresses and stores the new value of _ss inside */ +static int queue_ss( sSS ** plist ) +{ + sSS * new; + + if (*plist == NULL) { + /* If the array has not been alloc'd yet */ + *plist = malloc( sizeof (sSS) * 2 ); + if (! *plist) { + log_error("Memory allocation failed."); + return ENOMEM; + } + new = *plist; + } else { + /* otherwise, we need to resize the array to add the new element */ + int cnt = 0; + new = *plist; + while (new->ss_family != 0) + cnt++, new++; + *plist = realloc(*plist, sizeof(sSS) * (cnt + 2)); + if (! *plist) { + log_error("Memory allocation failed."); + return ENOMEM; + } + new = (*plist) + cnt; + } + + /* Now, new points to the beginning of the location where the _ss must be stored */ + memcpy(new, &_ss, sizeof(sSS)); + memset(new+1, 0, sizeof(sSS)); + return 0; +} + /* Function to report the errors */ void yyerror (YYLTYPE *ploc, waaad_conf_t * pconfig, char const *s) { @@ -131,12 +224,12 @@ } ext_detail={NULL, NULL}; /* Global variable to store temporarily peer information */ - static struct _peer_detail { char * locator; uint16_t port; char flags; } peer_detail={NULL, 0, 0}; + /* Flags values; 0 is default behavior */ #define PEER_NO_SEC 0x1 #define PEER_TCP 0x2 @@ -158,6 +251,7 @@ /* Strings subtypes */ %type <string> FQDN /* This is a fqdn. We check that the syntax is correct. */ %type <string> FILENAME /* This is a filename. existence of the file is checked. */ +%type <string> IPADDRESS /* This is an IP. the numerical value is stored in _ss. */ /* An integer value */ %token <integer> INTEGER @@ -174,6 +268,11 @@ %token GEN_TCTIMER %token GEN_TWTIMER %token GEN_DISABLERELAY +%token GEN_DISABLETCP +%token GEN_DISABLEIP4 +%token GEN_DISABLEIP6 +%token GEN_PRIMARY +%token GEN_SECONDARY /* In the "extension" section */ %token SECTION_EXTENSION @@ -191,21 +290,12 @@ %token PEER_TRANS_SCTP %token PEER_TRANS_TCP -/* In the "routing" section */ -%token SECTION_ROUTING - /* -------------------------------------- */ %% - /* The grammar definition - Sections blocs. General and Extension are mandatory (but may be empty) */ -conffile: other_sections general_section other_sections extensions_section other_sections - | other_sections extensions_section other_sections general_section other_sections - ; - - /* Other sections are not mandatory and may appear in any order */ -other_sections: /* empty */ - | other_sections peers_section - | other_sections routing_section + /* The grammar definition - Sections blocs. */ +conffile: general_section extensions_section peers_section + | general_section peers_section extensions_section ; /* These types are used several times: */ @@ -231,6 +321,19 @@ } ; +IPADDRESS: QSTRING + { + /* Verify this is a valid IP */ + if (!is_valid_addr($1, pconfig)) { + yyerror (&yylloc, pconfig, "An error was detected on an IP address, aborting..."); + YYERROR; + } + /* _ss is set with the IP numerical value during the check */ + /* Return the string anyway, to be freed */ + $$ = $1; + } + ; + /* Define the [general] section grammar */ general_section: SECTION_GENERAL general_content @@ -243,6 +346,11 @@ | general_content gen_tctimer | general_content gen_twtimer | general_content gen_disablerelay + | general_content gen_disabletcp + | general_content gen_disableip4 + | general_content gen_disableip6 + | general_content gen_primary + | general_content gen_secondary ; gen_log: GEN_LOG '=' gen_log_type ';' @@ -331,6 +439,68 @@ } ; +gen_disabletcp: GEN_DISABLETCP ';' + { + pconfig->pub.disable_tcp = 1; + } + ; + +gen_disableip4: GEN_DISABLEIP4 ';' + { + if (pconfig->pub.disable_inet6) { + yyerror (&yylloc, pconfig, "NO_IP6 and NO_IP4 can not be used together."); + YYERROR; + } + if (have_ip4) { + yyerror (&yylloc, pconfig, "A primary or secondary IP address was defined, but NO_IP4 appears."); + YYERROR; + } + pconfig->pub.disable_inet4 = 1; + } + ; + +gen_disableip6: GEN_DISABLEIP6 ';' + { + if (pconfig->pub.disable_inet4) { + yyerror (&yylloc, pconfig, "NO_IP4 and NO_IP6 can not be used together."); + YYERROR; + } + if (have_ip6) { + yyerror (&yylloc, pconfig, "A primary or secondary IPv6 address was defined, but NO_IP6 appears."); + YYERROR; + } + pconfig->pub.disable_inet6 = 1; + } + ; + +gen_primary: GEN_PRIMARY '=' IPADDRESS ';' + { + /* queue the sa in _ss into pconfig->pub.local_addr_pri_sa */ + if (queue_ss(&pconfig->pub.local_addr_pri_sa) != 0) { + yyerror (&yylloc, pconfig, "An error occurred while saving an address, aborting..."); + YYERROR; + } + + + /* we don't need the string anymore */ + free($3); + } + ; + +gen_secondary: GEN_SECONDARY '=' IPADDRESS ';' + { + /* queue the sa in _ss into pconfig->pub.local_addr_sec_sa */ + if (queue_ss(&pconfig->pub.local_addr_sec_sa) != 0) { + yyerror (&yylloc, pconfig, "An error occurred while saving an address, aborting..."); + YYERROR; + } + + /* we don't need the string anymore */ + free($3); + } + ; + + /* Define the [extensions] section grammar */ extensions_section: SECTION_EXTENSION extensions_content ; @@ -472,11 +642,3 @@ peer_detail.flags |= PEER_TCP; } ; - - /* Define the [routing] section grammar */ -routing_section: SECTION_ROUTING routing_content - ; - -routing_content: /* empty is allowed */ - ; -
--- a/waaad/conf-token.l Thu Aug 07 11:25:59 2008 +0900 +++ b/waaad/conf-token.l Fri Aug 08 18:04:38 2008 +0900 @@ -119,15 +119,17 @@ (?i:"console") { return GEN_LOG_CONSOLE; } /* Log messages to console */ (?i:"syslog") { return GEN_LOG_SYSLOG; } /* Log messages to syslog */ -(?i:"Diameter-Id") { return GEN_DIAMID; } /* How to specify the Diameter Identity of the local peer */ - -(?i:"LocalPort") { return GEN_PORT; } /* The port the local peer is listening on */ +(?i:"TcTimer") { return GEN_TCTIMER; } /* Specify the Tc timer value */ +(?i:"TwTimer") { return GEN_TWTIMER; } /* Specify the Tw timer value */ +(?i:"DisableRelay") { return GEN_DISABLERELAY; } /* Is relaying disabled? */ -(?i:"TcTimer") { return GEN_TCTIMER; } /* Specify the Tc timer value */ - -(?i:"TwTimer") { return GEN_TWTIMER; } /* Specify the Tw timer value */ - -(?i:"DisableRelay") { return GEN_DISABLERELAY; } /* Is relaying disabled? */ +(?i:"Diameter-Id") { return GEN_DIAMID; } /* How to specify the Diameter Identity of the local peer */ +(?i:"LocalPort") { return GEN_PORT; } /* The port the local peer is listening on */ +(?i:"no_tcp") { return GEN_DISABLETCP; } /* Is TCP disabled? */ +(?i:"no_ip4") { return GEN_DISABLEIP4; } /* Is IP disabled? */ +(?i:"no_ip6") { return GEN_DISABLEIP6; } /* Is IPv6 disabled? */ +(?i:"primary") { return GEN_PRIMARY; } /* An address to listen to TCP and SCTP connections */ +(?i:"secondary") { return GEN_SECONDARY; } /* An address to use in SCTP multihoming (+ all primaries) */ /* The EXTENSION section tokens */ (?i:"[extensions]") { return SECTION_EXTENSION; } /* enter the Extension section */
--- a/waaad/conf.c Thu Aug 07 11:25:59 2008 +0900 +++ b/waaad/conf.c Fri Aug 08 18:04:38 2008 +0900 @@ -51,6 +51,8 @@ #include <string.h> #include <errno.h> #include <stdio.h> +#include <arpa/inet.h> +#include <netdb.h> waaad_conf_t * g_conf=NULL; @@ -78,15 +80,79 @@ return 0; } +/* dump a list of SA */ +static void conf_dump_addr(char * name, sSS * array) +{ + sSS * ptr = array; + if (!array) { + TRACE_DEBUG( INFO, " %-11s : -", name); + } else { + TRACE_DEBUG( INFO, " %-11s :", name); + while (ptr->ss_family != 0) { + switch (ptr->ss_family) { + case AF_INET: + { + char buf[INET_ADDRSTRLEN]; + sSA4 * sin = (sSA4 *)ptr; + if (inet_ntop(sin->sin_family, &sin->sin_addr, buf, sizeof(buf)) == NULL) { + TRACE_DEBUG( INFO, " (error in inet_ntop: %s)", strerror(errno)); + } else { + TRACE_DEBUG( INFO, " %s", &buf); + } + } + break; + + case AF_INET6: + { + char buf[INET6_ADDRSTRLEN]; + sSA6 * sin6 = (sSA6 *)ptr; + if (inet_ntop(sin6->sin6_family, &sin6->sin6_addr, buf, sizeof(buf)) == NULL) { + TRACE_DEBUG( INFO, " (error in inet_ntop: %s)", strerror(errno)); + } else { + TRACE_DEBUG( INFO, " %s", &buf); + } + } + break; + + default: + TRACE_DEBUG( INFO, " (invalid AF: %d)", ptr->ss_family) + } + ptr++; + } + } +} + /* Output the parsed configuration */ static void conf_dump(void) { + char buf4[INET_ADDRSTRLEN]; + char buf6[INET6_ADDRSTRLEN]; + char *str4 = "-"; + char *str6 = "-"; + if (g_pconf->local_addr_diamid[0].ss_family == AF_INET) { + sSA4 * sin = (sSA4 *)&g_pconf->local_addr_diamid[0]; + if (inet_ntop(sin->sin_family, &sin->sin_addr, buf4, sizeof(buf4))) { + str4 = buf4; + } + } + if (g_pconf->local_addr_diamid[1].ss_family == AF_INET6) { + sSA6 * sin6 = (sSA6 *)&g_pconf->local_addr_diamid[1]; + if (inet_ntop(sin6->sin6_family, &sin6->sin6_addr, buf6, sizeof(buf6))) { + str6 = buf6; + } + } + TRACE_DEBUG( INFO, "--- Parsed configuration : ---"); - TRACE_DEBUG( INFO, " Diameter-Id : %s", g_pconf->diameter_identity); + TRACE_DEBUG( INFO, " Diameter-Id : %s ( %s / %s )", g_pconf->diameter_identity, str4, str6); TRACE_DEBUG( INFO, " Local port : %hd",g_pconf->local_port); TRACE_DEBUG( INFO, " Tc timer : %d", g_pconf->tctimer); TRACE_DEBUG( INFO, " Tw timer : %d", g_pconf->twtimer); TRACE_DEBUG( INFO, " Relaying : %s", g_pconf->disable_relay ? "Disabled" : "Enabled"); + TRACE_DEBUG( INFO, " TCP : %s", g_pconf->disable_tcp ? "Disabled" : "Enabled"); + TRACE_DEBUG( INFO, " IP : %s", g_pconf->disable_inet4 ? "Disabled" : "Enabled"); + TRACE_DEBUG( INFO, " IPv6 : %s", g_pconf->disable_inet6 ? "Disabled" : "Enabled"); + conf_dump_addr( "Primary", g_pconf->local_addr_pri_sa ); + conf_dump_addr( "Secondary", g_pconf->local_addr_sec_sa ); TRACE_DEBUG( INFO, "------------------------------"); } @@ -105,7 +171,6 @@ int conf_parse ( void ) { extern FILE * yyin; - int ret; if (!g_conf) { @@ -132,6 +197,42 @@ return EINVAL; } + /* We now resolv the diameter-id */ + { + struct addrinfo *ai = NULL, *p, hints; + int gotip4 = 0; + int gotip6 = 0; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG; + + ret = getaddrinfo(g_pconf->diameter_identity, NULL, &hints, &ai); + if (ret != 0) { + log_error("Error resolving Diameter-Id '%s': %s.\n", g_pconf->diameter_identity, gai_strerror(ret)); + return EINVAL; + } + for (p = ai; p != NULL; p = p->ai_next) { + switch (p->ai_family) { + case AF_INET: + if (gotip4) + break; + memcpy(&g_pconf->local_addr_diamid[0], p->ai_addr, sizeof(sSA4)); + gotip4++; + break; + + case AF_INET6: + if (gotip6) + break; + memcpy(&g_pconf->local_addr_diamid[1], p->ai_addr, sizeof(sSA6)); + gotip6++; + break; + } + if (gotip4 && gotip6) + break; + } + + freeaddrinfo(ai); + } conf_dump(); return 0;
--- a/waaad/dict-base.c Thu Aug 07 11:25:59 2008 +0900 +++ b/waaad/dict-base.c Fri Aug 08 18:04:38 2008 +0900 @@ -51,7 +51,7 @@ /* Address AVP <-> struct sockaddr_storage */ static int Address_encode(void * data, avp_value_t * avp_value) { - struct sockaddr_storage * ss = (struct sockaddr_storage *) data; + sSS * ss = (sSS *) data; uint16_t AddressType = 0; size_t size = 0; unsigned char * buf = NULL; @@ -67,7 +67,7 @@ case AF_INET: { /* We are encoding a IP address */ - struct sockaddr_in * sin = (struct sockaddr_in *)ss; + sSA4 * sin = (sSA4 *)ss; AddressType = 1;/* see http://www.iana.org/assignments/address-family-numbers/ */ size = 6; /* 2 for AddressType + 4 for data */ @@ -88,7 +88,7 @@ case AF_INET6: { /* We are encoding a IP address */ - struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *)ss; + sSA6 * sin6 = (sSA6 *)ss; AddressType = 2;/* see http://www.iana.org/assignments/address-family-numbers/ */ size = 18; /* 2 for AddressType + 16 for data */ @@ -136,7 +136,7 @@ switch (AddressType) { case 1 /* IP */: { - struct sockaddr_in * sin = (struct sockaddr_in *)interpreted; + sSA4 * sin = (sSA4 *)interpreted; if (avp_value->os.len != 6) { TRACE_DEBUG(INFO, "Received invalid buffer size (%d instead of %d)", avp_value->os.len, 6); @@ -152,7 +152,7 @@ case 2 /* IP6 */: { - struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *)interpreted; + sSA6 * sin6 = (sSA6 *)interpreted; if (avp_value->os.len != 18) { TRACE_DEBUG(INFO, "Received invalid buffer size (%d instead of %d)", avp_value->os.len, 18);
--- a/waaad/peer-internal.h Thu Aug 07 11:25:59 2008 +0900 +++ b/waaad/peer-internal.h Fri Aug 08 18:04:38 2008 +0900 @@ -66,20 +66,24 @@ /* Stable states */ STATE_DISABLED = 1, /* No connexion must be attempted */ STATE_OPEN, /* Connexion established */ - /* Transitional states */ - STATE_SUSPECT, /* Connexion established but maybe broken */ - STATE_CLOSED, /* No connexion established, will re-attempt after TcTimer. */ - STATE_CLOSING, /* the connexion is being shutdown */ - STATE_WAIT_CNX, /* Trying to establish a connexion at transport level, waiting for ACK/NACK or new cnx initiated by remote peer (concurrent attempts) */ - STATE_WAIT_CEA /* CER has been sent, waiting for CEA or timeout */ - /* TBC... */ - - /* Other states from the RFC: are they needed? Wait-Conn-Ack/Elect, Wait-Returns */ + + /* Peer state machine */ + STATE_CLOSED, /* No connection established, will re-attempt after TcTimer. */ + STATE_CLOSING, /* the connection is being shutdown (DPR/DPA in progress) */ + STATE_WAITCNXACK, /* Attempting to establish transport-level connection */ + STATE_WAITCNXACK_ELEC, /* Received a CER from this same peer on an incoming connection (other peer object), while we were waiting for cnx ack */ + STATE_WAITCEA, /* Connection established, CER sent, waiting for CEA */ + STATE_WAITRETURNS_ELEC, /* We have sent a CER on our initiated connection, and received a CER from the remote peer on another connection. Election. + If we win the election, we must disconnect the initiated connection and send a CEA on the other => we go to OPEN state. + If we lose, we disconnect the other connection (receiver) and fallback to WAITCEA state. */ + + /* Failover state machine */ + STATE_SUSPECT, /* A DWR was sent and not answered within TwTime. Failover in progress. */ + STATE_REOPEN /* Connection has been re-established, waiting for 3 DWR/DWA exchanges before putting back to service */ } peer_state_t; - -/* List of sent requests, ordered by hop-by-hop id */ +/* List of sent requests to this peer, ordered by hop-by-hop id */ typedef struct _sent_r { /* Chaining information */ struct _sent_r *next; /* The next sent request */ @@ -88,13 +92,12 @@ /* Pointer to the message */ msg_t *msg; - /* The following two fields are copied from message for faster processing on message reception */ + /* The following two fields are copied from message for faster processing on message reception and failover */ uint32_t hbh; /* The hop-by-hop value of the message */ - int rtb; /* Is this a routable message? */ + int rtb; /* Is this a routable message? => discarded or requeued on failover */ } _sent_req_t; - struct _peer; /* A list element for peers lists */ @@ -106,42 +109,46 @@ } _pi_t; /* Flags definitions */ -#define PEERFL_DYNAMIC ( 1 << 0 ) /* The peer is not statically configured and will expire */ -#define PEERFL_EXPIRETS ( 1 << 1 ) /* The peer expires at the p_expire time. If not set, the peer expires at transport disconnection */ +#define PEERFL_DYNAMIC ( 1 << 0 ) /* The peer is not statically configured and will expire */ +#define PEERFL_EXPIRETS ( 1 << 1 ) /* The peer expires at the p_expire time. If not set, the (dynamic) peer expires at transport disconnection */ +#define PEERFL_DW_PENDING ( 1 << 2 ) /* A DWR message was sent and not answered yet */ +#define PEERFL_CNX_PB ( 1 << 3 ) /* The peer was disconnected because of watchdogs; must exchange 3 watchdogs before putting back to normal */ /* Peer internal description */ typedef struct _peer { /* Chaining of the peer in global lists */ _pi_t p_global; /* List of peers this peer belongs to */ - _pi_t p_active; /* Sublist containing only the active peers */ + _pi_t p_active; /* Sublist containing only the active peers (in STATE_OPEN) */ - /* For debug only */ + /* For debug */ uint32_t p_eyec; /* An eyecatcher to verify object is valid. Must be PEER_EYEC. */ /* Peer data */ char *p_diamid; /* The Diameter-Id of this peer, once known */ char *p_realm; /* pointer to the beginning of the realm in the diamid string. */ - uint32_t p_hbh; /* current Hop-by-hop value */ + uint32_t p_hbh; /* next Hop-by-hop free value */ pthread_mutex_t p_lock; /* Mutex to protect this object */ + uint32_t p_flags; /* The PEERFL_* flags */ + struct timespec p_expire; /* Lifetime of the peer, for dynamic peers */ /* Peer state */ peer_state_t p_state; /* State of the peer */ pthread_t p_psm; /* The thread handling this peer state machine. */ - uint32_t p_flags; /* Some PEERFL_* flags */ - struct timespec p_expire; /* Lifetime of the peer, for dynamic peers */ + pthread_cond_t p_condvar; /* The cond var to be waited in the peer state machine (for timeouts and DWR) */ struct timespec p_ts; /* multi-purpose timespec (meaning depends on the state) */ /* Messages handling */ - meq_t *p_in_q; /* Incoming message queue */ + meq_t *p_in_q; /* Incoming (received) message queue */ pthread_t p_in_th; /* The thread handling messages reception, created by p_psm */ - meq_t *p_out_q; /* Outgoing message queue */ pthread_t p_out_th; /* The thread handling messages envoy, created by p_psm */ - - _sent_req_t p_sent; /* List of sent requests */ + _sent_req_t p_sent; /* List of sent requests without answer */ /* Connection information */ int p_sock; /* We use standard Berkeley sockets for both TCP and SCTP connections */ + int p_sock_tmp; /* In case of election, store the socket on which the CER was received here, temporarily */ + size_t p_peeraddr_sz; /* Number of items in the array p_peeraddr bellow */ + sSS *p_peeraddr; /* Array of the attachment points of the remote peer (received in Host-IP-Address AVPs) */ /* Security information */ _sec_item_t *p_sec_list; /* Used only before a sucessful CER/CEA exchange */ @@ -150,9 +157,9 @@ sec_session_t p_sec_session; /* structure passed back to the security module, for connection information */ void *p_ext_session; /* opaque data that can be used by the security extension to store internal states */ - /* Supported applications (result of CER/CEA) */ + /* Supported applications (result of CER/CEA) -- contains all applications advertized by remote */ size_t p_app_size; /* The size of the array pointed by p_app_list */ - peer_appl_t *p_app_list; /* points to a 0-terminated array of supported applications */ + peer_appl_t *p_app_list; /* points to an array of supported applications, of size p_app_size + 1, and the last element is always 0 */ } _peer_t;
--- a/waaad/security.c Thu Aug 07 11:25:59 2008 +0900 +++ b/waaad/security.c Fri Aug 08 18:04:38 2008 +0900 @@ -254,7 +254,7 @@ } /* Create a list of _sec_item_t */ -int sec_getmodules(char * diamid, struct sockaddr * sa, _sec_item_t **modules) +int sec_getmodules(char * diamid, sSA * sa, _sec_item_t **modules) { int ret = 0; int prio;
--- a/waaad/security.h Thu Aug 07 11:25:59 2008 +0900 +++ b/waaad/security.h Fri Aug 08 18:04:38 2008 +0900 @@ -123,7 +123,7 @@ * 0 : List created properly * !0 : an error occurred */ -int sec_getmodules(char * diamid, struct sockaddr * sa, _sec_item_t **modules); +int sec_getmodules(char * diamid, sSA * sa, _sec_item_t **modules); /* * FUNCTION: sec_freemodules
--- a/waaad/waaad-internal.h Thu Aug 07 11:25:59 2008 +0900 +++ b/waaad/waaad-internal.h Fri Aug 08 18:04:38 2008 +0900 @@ -41,6 +41,15 @@ #ifndef _WAAAD_INTERNAL_H #define _WAAAD_INTERNAL_H +/* Some aliases to socket addresses structures */ +#ifndef sSA_ALIASES +#define sSS struct sockaddr_storage +#define sSA struct sockaddr +#define sSA4 struct sockaddr_in +#define sSA6 struct sockaddr_in6 +#define sSA_ALIASES +#endif /* sSA_ALIASES */ + /* Configuration generated by the configure script. Contains host-specific environment information */ #include "config.h"