Mercurial > hg > freeDiameter
changeset 12:418d2ce80dc8
Added support in configuration file for peers declaration
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Mon, 28 Sep 2009 17:29:25 +0900 |
parents | 6576ef5e01eb |
children | ef9ef3bf4752 |
files | doc/freediameter.conf.sample freeDiameter/fD.h freeDiameter/fdd.l freeDiameter/fdd.y freeDiameter/main.c freeDiameter/peers.c include/freeDiameter/freeDiameter.h |
diffstat | 7 files changed, 357 insertions(+), 62 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/freediameter.conf.sample Fri Sep 25 18:05:06 2009 +0900 +++ b/doc/freediameter.conf.sample Mon Sep 28 17:29:25 2009 +0900 @@ -6,23 +6,23 @@ # The Diameter Identity of this daemon. # This must be a valid FQDN that resolves to the local host. # Default: hostname's FQDN -#LocalIdentity = "aaa.koganei.wide.ad.jp"; +#Identity = "aaa.koganei.wide.ad.jp"; # The Diameter Realm of this daemon. -# Default: the domain part of LocalIdentity. -#LocalRealm = "wide.ad.jp"; +# Default: the domain part of Identity. +#Realm = "wide.ad.jp"; ############################################################## ## Transport protocol configuration # The port this peer is listening on for incoming connections (TCP and SCTP). # Default: 3868 -#LocalPort = 3868; +#Port = 3868; # The port this peer is listening on for incoming TLS connections (TCP and SCTP). # See TLS_old_method for more information. # Default: 3869 -#LocalSecPort = 3869; +#SecPort = 3869; # Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA # on the same port. This only affects outgoing connections. It can be overwritten @@ -93,7 +93,7 @@ # Default: Relaying is enabled. #NoRelay; -# Other applications are configured by extensions. +# Other applications are configured by loading appropriate extensions. ############################################################## ## Extensions configuration @@ -104,21 +104,51 @@ # by loadable extensions (plug-ins). # These extensions may in addition receive the name of a # configuration file, the format of which is extension-specific. - +# # Format: #LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ; +# # Exemples: #LoadExtension = "extensions/sample.so"; #LoadExtension = "extensions/sample.so":"conf/sample.conf"; +############################################################## +## Peers configuration + +# The local server listens for incoming connections. By default, +# all unknown connecting peers are rejected. Extensions can override this behavior. +# +# In addition to incoming connections, the local peer can +# be configured to establish and maintain connections to some +# Diameter nodes and allow connections from these nodes. +# This is achieved with the ConnectPeer directive described bellow. +# +# Note that the configured Diameter Id MUST match +# the information received inside CEA, or the connection will be aborted. +# +# Format: +#ConnectPeer = "diameterid" [ { parameter1; parameter2; ...} ] ; +# Parameters that can be specified in the peer's parameter list: +# No_TCP; No_SCTP; No_IP; No_IPv6; Prefer_TCP; TLS_old_method; +# No_TLS; # assume transparent security instead of TLS +# Port = 3868; # The port to connect to +# SCTP_streams = 30; +# TcTimer = 30; +# TwTimer = 30; +# ConnectTo = "202.249.37.5"; +# ConnectTo = "2001:200:903:2::202:1"; +# Examples: +#ConnectPeer = "aaa.wide.ad.jp"; +#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; } ; + ############################################################## # -------- Test configuration --------- -LocalIdentity = "aaa.koganei.wide.ad.jp"; -LocalRealm = "wide.ad.jp"; -LocalPort = 3866; -LocalSecPort = 3867; +Identity = "aaa.koganei.wide.ad.jp"; +Realm = "wide.ad.jp"; +Port = 3866; +SecPort = 3867; TLS_old_method; No_IP; Prefer_TCP; @@ -131,3 +161,4 @@ LoadExtension = "extensions/dbg_monitor.fdx"; LoadExtension = "extensions/dict_nasreq.fdx"; LoadExtension = "extensions/dict_eap.fdx"; +ConnectPeer = "jules.nautilus6.org" ;
--- a/freeDiameter/fD.h Fri Sep 25 18:05:06 2009 +0900 +++ b/freeDiameter/fD.h Mon Sep 28 17:29:25 2009 +0900 @@ -71,18 +71,89 @@ /* Peers */ struct fd_peer { /* The "real" definition of the peer structure */ - struct peer_hdr p_hdr; /* contains all public data */ + /* The public data */ + struct peer_hdr p_hdr; - int p_eyec; /* Eye catcher, EYEC_PEER */ + /* Eye catcher, EYEC_PEER */ + int p_eyec; #define EYEC_PEER 0x373C9336 - /* threads, message queues, socket & callbacks */ + /* Origin of this peer object, for debug */ + char *p_dbgorig; + + /* Mutex that protect this peer structure */ + pthread_mutex_t p_mtx; + + /* Reference counter -- freed only when this reaches 0 */ + unsigned p_refcount; + + /* Chaining in peers sublists */ + struct fd_list p_expiry; /* list of expiring peers, ordered by their timeout value */ + struct fd_list p_actives; /* list of peers in the STATE_OPEN state -- faster routing creation */ + + /* The next hop-by-hop id value for the link */ + uint32_t p_hbh; + + /* Some flags influencing the peer state machine */ + struct { + unsigned pf_responder : 1; /* The local peer is responder on the connection */ + + unsigned pf_dw_pending : 1; /* A DWR message was sent and not answered yet */ + + unsigned pf_cnx_pb : 1; /* The peer was disconnected because of watchdogs; must exchange 3 watchdogs before putting back to normal */ + unsigned pf_reopen_cnt : 2; /* remaining DW to be exchanged after re-established connection */ + + /* to be completed */ + + } p_flags; + + /* The events queue, peer state machine thread, timer for states timeouts */ + struct fifo *p_events; + pthread_t p_psm; + struct timespec p_psm_timer; + + /* Received message queue, and thread managing reception of messages */ + struct fifo *p_recv; + pthread_t p_inthr; + + /* Outgoing message queue, and thread managing sending the messages */ + struct fifo *p_tosend; + pthread_t p_outthr; + + /* Sent requests (for fallback), list of struct sentreq ordered by hbh */ + struct fd_list p_sentreq; + + /* connection context: socket & other metadata */ + struct cnxctx *p_cnxctx; }; +#define CHECK_PEER( _p ) \ + (((_p) != NULL) && (((struct fd_peer *)(_p))->p_eyec == EYEC_PEER)) +/* Events codespace for struct fd_peer->p_events */ +enum { + /* request to terminate this peer : disconnect, requeue all messages */ + FDEVP_TERMINATE = 2000 + + /* Dump all info about this peer in the debug log */ + ,FDEVP_DUMP_ALL + + /* A message was received in the peer */ + ,FDEVP_MSG_INCOMING +}; + +/* Structure to store a sent request */ +struct sentreq { + struct fd_list chain; /* the "o" field points directly to the hop-by-hop of the request (uint32_t *) */ + struct msg *req; /* A request that was sent and not yet answered. */ +}; + +/* Functions */ int fd_peer_init(); -void fd_peer_dump(int details); +void fd_peer_dump_list(int details); int fd_peer_start(); int fd_peer_waitstart(); + + #endif /* _FD_H */
--- a/freeDiameter/fdd.l Fri Sep 25 18:05:06 2009 +0900 +++ b/freeDiameter/fdd.l Mon Sep 28 17:29:25 2009 +0900 @@ -111,10 +111,10 @@ } /* Full words tokens (keywords) */ -(?i:"LocalIdentity") { return LOCALIDENTITY; } -(?i:"LocalRealm") { return LOCALREALM; } -(?i:"LocalPort") { return LOCALPORT; } -(?i:"LocalSecPort") { return LOCALSECPORT; } +(?i:"Identity") { return IDENTITY; } +(?i:"Realm") { return REALM; } +(?i:"Port") { return PORT; } +(?i:"SecPort") { return SECPORT; } (?i:"No_IPv6") { return NOIP6; } (?i:"No_IP") { return NOIP; } (?i:"No_TCP") { return NOTCP; } @@ -127,6 +127,9 @@ (?i:"TwTimer") { return TWTIMER; } (?i:"NoRelay") { return NORELAY; } (?i:"LoadExtension") { return LOADEXT; } +(?i:"ConnectPeer") { return CONNPEER; } +(?i:"ConnectTo") { return CONNTO; } +(?i:"No_TLS") { return NOTLS; } /* Valid single characters for yyparse */
--- a/freeDiameter/fdd.y Fri Sep 25 18:05:06 2009 +0900 +++ b/freeDiameter/fdd.y Mon Sep 28 17:29:25 2009 +0900 @@ -69,12 +69,19 @@ fprintf(stderr, "%s:%d.%d : %s\n", conf->cnf_file, ploc->first_line, ploc->first_column, s); } +int got_peer_noip = 0; +int got_peer_noipv6 = 0; +int got_peer_notcp = 0; +int got_peer_nosctp = 0; + +struct peer_info fddpi; + %} /* Values returned by lex for token */ %union { - char *string; /* The string is allocated by strdup in lex.*/ - int integer; /* Store integer values */ + char *string; /* The string is allocated by strdup in lex.*/ + int integer; /* Store integer values */ } /* In case of error in the lexical analysis */ @@ -83,24 +90,27 @@ %token <string> QSTRING %token <integer> INTEGER -%type <string> extconf +%type <string> extconf -%token LOCALIDENTITY -%token LOCALREALM -%token LOCALPORT -%token LOCALSECPORT +%token IDENTITY +%token REALM +%token PORT +%token SECPORT %token NOIP %token NOIP6 %token NOTCP %token NOSCTP %token PREFERTCP %token OLDTLS +%token NOTLS %token SCTPSTREAMS %token LISTENON %token TCTIMER %token TWTIMER %token NORELAY %token LOADEXT +%token CONNPEER +%token CONNTO /* -------------------------------------- */ @@ -108,12 +118,12 @@ /* The grammar definition - Sections blocs. */ conffile: /* Empty is OK */ - | conffile localidentity - | conffile localrealm + | conffile identity + | conffile realm | conffile tctimer | conffile twtimer - | conffile localport - | conffile localsecport + | conffile port + | conffile secport | conffile sctpstreams | conffile listenon | conffile norelay @@ -124,15 +134,26 @@ | conffile prefertcp | conffile oldtls | conffile loadext + | conffile connpeer + | conffile errors + { + yyerror(&yylloc, conf, "An error occurred while parsing the configuration file"); + return EINVAL; + } ; -localidentity: LOCALIDENTITY '=' QSTRING ';' + /* Lexical or syntax error */ +errors: LEX_ERROR + | error + ; + +identity: IDENTITY '=' QSTRING ';' { conf->cnf_diamid = $3; } ; -localrealm: LOCALREALM '=' QSTRING ';' +realm: REALM '=' QSTRING ';' { conf->cnf_diamrlm = $3; } @@ -154,7 +175,7 @@ } ; -localport: LOCALPORT '=' INTEGER ';' +port: PORT '=' INTEGER ';' { CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16), { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } ); @@ -162,7 +183,7 @@ } ; -localsecport: LOCALSECPORT '=' INTEGER ';' +secport: SECPORT '=' INTEGER ';' { CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16), { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } ); @@ -209,24 +230,54 @@ noip: NOIP ';' { + if (got_peer_noipv6) { + yyerror (&yylloc, conf, "No_IP conflicts with a ConnectPeer directive No_IPv6."); + YYERROR; + } conf->cnf_flags.no_ip4 = 1; } ; noip6: NOIP6 ';' { + if (got_peer_noip) { + yyerror (&yylloc, conf, "No_IP conflicts with a ConnectPeer directive No_IP."); + YYERROR; + } conf->cnf_flags.no_ip6 = 1; } ; notcp: NOTCP ';' { + #ifdef DISABLE_SCTP + yyerror (&yylloc, conf, "No_TCP cannot be specified for daemon compiled with DISABLE_SCTP option."); + YYERROR; + #endif + if (conf->cnf_flags.no_sctp) + { + yyerror (&yylloc, conf, "No_TCP conflicts with No_SCTP directive." ); + YYERROR; + } + if (got_peer_nosctp) { + yyerror (&yylloc, conf, "No_TCP conflicts with a ConnectPeer directive No_SCTP."); + YYERROR; + } conf->cnf_flags.no_tcp = 1; } ; nosctp: NOSCTP ';' { + if (conf->cnf_flags.no_tcp) + { + yyerror (&yylloc, conf, "No_SCTP conflicts with No_TCP directive." ); + YYERROR; + } + if (got_peer_notcp) { + yyerror (&yylloc, conf, "No_SCTP conflicts with a ConnectPeer directive No_TCP."); + YYERROR; + } conf->cnf_flags.no_sctp = 1; } ; @@ -259,3 +310,130 @@ $$ = $2; } ; + +connpeer: { + memset(&fddpi, 0, sizeof(fddpi)); + } + CONNPEER '=' QSTRING peerinfo ';' + { + fddpi.pi_diamid = $4; + CHECK_FCT_DO( fd_peer_add ( &fddpi, conf->cnf_file, NULL, NULL ), + { yyerror (&yylloc, conf, "Error adding ConnectPeer information"); YYERROR; } ); + + /* Now destroy any content in the structure */ + free(fddpi.pi_diamid); + while (!FD_IS_LIST_EMPTY(&fddpi.pi_endpoints)) { + struct fd_list * li = fddpi.pi_endpoints.next; + fd_list_unlink(li); + free(li); + } + } + ; + +peerinfo: /* empty */ + | '{' peerparams '}' + ; + +peerparams: /* empty */ + | peerparams NOIP ';' + { + if ((conf->cnf_flags.no_ip6) || (fddpi.pi_flags.pro3 == PI_P3_IP)) { + yyerror (&yylloc, conf, "No_IP conflicts with a No_IPv6 directive."); + YYERROR; + } + got_peer_noip++; + fddpi.pi_flags.pro3 = PI_P3_IPv6; + } + | peerparams NOIP6 ';' + { + if ((conf->cnf_flags.no_ip4) || (fddpi.pi_flags.pro3 == PI_P3_IPv6)) { + yyerror (&yylloc, conf, "No_IPv6 conflicts with a No_IP directive."); + YYERROR; + } + got_peer_noipv6++; + fddpi.pi_flags.pro3 = PI_P3_IP; + } + | peerparams NOTCP ';' + { + #ifdef DISABLE_SCTP + yyerror (&yylloc, conf, "No_TCP cannot be specified in daemon compiled with DISABLE_SCTP option."); + YYERROR; + #endif + if ((conf->cnf_flags.no_sctp) || (fddpi.pi_flags.pro4 == PI_P4_TCP)) { + yyerror (&yylloc, conf, "No_TCP conflicts with a No_SCTP directive."); + YYERROR; + } + got_peer_notcp++; + fddpi.pi_flags.pro4 = PI_P4_SCTP; + } + | peerparams NOSCTP ';' + { + if ((conf->cnf_flags.no_tcp) || (fddpi.pi_flags.pro4 == PI_P4_SCTP)) { + yyerror (&yylloc, conf, "No_SCTP conflicts with a No_TCP directive."); + YYERROR; + } + got_peer_nosctp++; + fddpi.pi_flags.pro4 = PI_P4_TCP; + } + | peerparams PREFERTCP ';' + { + fddpi.pi_flags.alg = PI_ALGPREF_TCP; + } + | peerparams OLDTLS ';' + { + if (fddpi.pi_flags.sec == PI_SEC_NONE) { + yyerror (&yylloc, conf, "ConnectPeer: TLS_old_method conflicts with No_TLS."); + YYERROR; + } + fddpi.pi_flags.sec = PI_SEC_TLS_OLD; + } + | peerparams NOTLS ';' + { + if (fddpi.pi_flags.sec == PI_SEC_TLS_OLD) { + yyerror (&yylloc, conf, "ConnectPeer: No_TLS conflicts with TLS_old_method."); + YYERROR; + } + fddpi.pi_flags.sec = PI_SEC_NONE; + } + | peerparams PORT '=' INTEGER ';' + { + CHECK_PARAMS_DO( ($4 > 0) && ($4 < 1<<16), + { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } ); + fddpi.pi_port = (uint16_t)$4; + } + | peerparams SCTPSTREAMS '=' INTEGER ';' + { + CHECK_PARAMS_DO( ($4 > 0) && ($4 < 1<<16), + { yyerror (&yylloc, conf, "Invalid value"); YYERROR; } ); + fddpi.pi_streams = (uint16_t)$4; + } + | peerparams TCTIMER '=' INTEGER ';' + { + fddpi.pi_tctimer = $4; + } + | peerparams TWTIMER '=' INTEGER ';' + { + fddpi.pi_twtimer = $4; + } + | peerparams CONNTO '=' QSTRING ';' + { + struct fd_endpoint * ep; + struct addrinfo hints, *ai; + int ret; + + CHECK_MALLOC_DO( ep = malloc(sizeof(struct fd_endpoint)), + { yyerror (&yylloc, conf, "Out of memory"); YYERROR; } ); + memset(ep, 0, sizeof(struct fd_endpoint)); + fd_list_init(&ep->chain, NULL); + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG; + ret = getaddrinfo($4, NULL, &hints, &ai); + if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; } + + memcpy(&ep->ss, ai->ai_addr, ai->ai_addrlen); + free($4); + freeaddrinfo(ai); + fd_list_insert_before(&fddpi.pi_endpoints, &ep->chain); + } + ;
--- a/freeDiameter/main.c Fri Sep 25 18:05:06 2009 +0900 +++ b/freeDiameter/main.c Mon Sep 28 17:29:25 2009 +0900 @@ -116,7 +116,7 @@ break; case FDEV_DUMP_PEERS: - fd_peer_dump(FULL); + fd_peer_dump_list(FULL); break; case FDEV_TERMINATE:
--- a/freeDiameter/peers.c Fri Sep 25 18:05:06 2009 +0900 +++ b/freeDiameter/peers.c Mon Sep 28 17:29:25 2009 +0900 @@ -46,8 +46,6 @@ , "STATE_SUSPECT" , "STATE_REOPEN" }; -#define STATE_STR(state) \ - peer_state_str[ (state) <= STATE_REOPEN ? (state) : 0 ] struct fd_list fd_g_peers; pthread_rwlock_t fd_g_peers_rw; @@ -93,7 +91,7 @@ } /* Dump the list of peers */ -void fd_peer_dump(int details) +void fd_peer_dump_list(int details) { struct fd_list * li; @@ -107,14 +105,21 @@ continue; } - fd_log_debug(" %s %s", np->p_hdr.info.pi_diamid, STATE_STR(np->p_hdr.info.pi_state)); + fd_log_debug(" %s\t%s", STATE_STR(np->p_hdr.info.pi_state), np->p_hdr.info.pi_diamid); if (details > INFO) { - fd_log_debug(" (rlm:%s)", np->p_hdr.info.pi_realm); + fd_log_debug("\t(rlm:%s)", np->p_hdr.info.pi_realm); if (np->p_hdr.info.pi_prodname) - fd_log_debug(" ['%s' %u]", np->p_hdr.info.pi_prodname, np->p_hdr.info.pi_firmrev); + fd_log_debug("\t['%s' %u]", np->p_hdr.info.pi_prodname, np->p_hdr.info.pi_firmrev); + fd_log_debug("\t(from %s)", np->p_dbgorig); } fd_log_debug("\n"); } CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ ); } + +/* Add a new peer entry */ +int fd_peer_add ( struct peer_info * info, char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data ) +{ + return ENOTSUP; +}
--- a/include/freeDiameter/freeDiameter.h Fri Sep 25 18:05:06 2009 +0900 +++ b/include/freeDiameter/freeDiameter.h Mon Sep 28 17:29:25 2009 +0900 @@ -124,12 +124,12 @@ /* Events codespace for fd_g_config->cnf_main_ev */ enum { - FDEV_TERMINATE = 1000, /* request to terminate */ - FDEV_DUMP_DICT, /* Dump the content of the dictionary */ - FDEV_DUMP_EXT, /* Dump state of extensions */ - FDEV_DUMP_QUEUES, /* Dump the message queues */ - FDEV_DUMP_CONFIG, /* Dump the configuration */ - FDEV_DUMP_PEERS /* Dump the list of peers */ + FDEV_TERMINATE = 1000 /* request to terminate */ + ,FDEV_DUMP_DICT /* Dump the content of the dictionary */ + ,FDEV_DUMP_EXT /* Dump state of extensions */ + ,FDEV_DUMP_QUEUES /* Dump the message queues */ + ,FDEV_DUMP_CONFIG /* Dump the configuration */ + ,FDEV_DUMP_PEERS /* Dump the list of peers */ }; @@ -160,32 +160,38 @@ STATE_REOPEN /* Connection has been re-established, waiting for 3 DWR/DWA exchanges before putting back to service */ }; extern const char *peer_state_str[]; +#define STATE_STR(state) \ + peer_state_str[ ((unsigned)(state)) <= STATE_REOPEN ? ((unsigned)(state)) : 0 ] /* Information about a remote peer, used both for query and for creating a new entry */ struct peer_info { - /* This information is always there */ char * pi_diamid; /* UTF-8, \0 terminated. The Diameter Identity of the remote peer */ char * pi_realm; /* idem, its realm. */ - /* Flags */ struct { - #define PI_PROT_DEFAULT 0 /* Use the default algorithm configured for the host */ - #define PI_PROT_TCP 1 - #define PI_PROT_SCTP 2 - unsigned proto :2; + #define PI_P3_DEFAULT 0 /* Use the default L3 protocol configured for the host */ + #define PI_P3_IP 1 /* Use only IP to connect to this peer */ + #define PI_P3_IPv6 2 /* resp, IPv6 */ + unsigned pro3 :2; - #define PI_SEC_DEFAULT 0 /* The default behavior configured for the host */ + #define PI_P4_DEFAULT 0 /* Use the default L4 proto configured for the host */ + #define PI_P4_TCP 1 /* Only use TCP */ + #define PI_P4_SCTP 2 /* Only use SCTP */ + unsigned pro4 :2; + + #define PI_ALGPREF_SCTP 0 /* SCTP is initially attempted */ + #define PI_ALGPREF_TCP 1 /* TCP is initially attempted */ + unsigned alg :1; + + #define PI_SEC_DEFAULT 0 /* New TLS security (dedicated port protecting also CER/CEA) */ #define PI_SEC_NONE 1 /* Transparent security with this peer (IPsec) */ - #define PI_SEC_TLS_NEW 2 /* New TLS security (dedicated port protecting also CER/CEA) */ - #define PI_SEC_TLS_OLD 3 /* Old TLS security (inband on default port) */ + #define PI_SEC_TLS_OLD 2 /* Old TLS security (inband on default port) */ unsigned sec :2; - #define PI_EXP_DEFAULT 0 - #define PI_EXP_NONE 1 /* the peer entry does not expire */ - #define PI_EXP_INACTIVE 2 /* the peer entry expires after pi_lft seconds without activity */ - #define PI_EXP_LIFETIME 3 /* the peer SA information is destroyed after lft seconds (example: DNS timeout) */ - unsigned exp :2; + #define PI_EXP_NONE 0 /* the peer entry does not expire */ + #define PI_EXP_INACTIVE 1 /* the peer entry expires after pi_lft seconds without activity */ + unsigned exp :1; /* Following flags are read-only and received from remote peer */ #define PI_INB_NONE 1 /* Remote peer advertised inband-sec-id 0 (None) */ @@ -231,6 +237,7 @@ * * PARAMETERS: * info : Information to create the peer. + * orig_dbg : A string indicating the origin of the peer information, for debug (ex: conf, redirect, ...) * cb : optional, a callback to call (once) when the peer connection is established or failed * cb_data : opaque data to pass to the callback. * @@ -247,7 +254,7 @@ * (other standard errors may be returned, too, with their standard meaning. Example: * ENOMEM : Memory allocation for the new object element failed.) */ -int fd_peer_add ( struct peer_info * info, void (*cb)(struct peer_info *, void *), void * cb_data ); +int fd_peer_add ( struct peer_info * info, char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data ); /* * FUNCTION: peer_validate_register