#include <freeradius-devel/ident.h>
RCSID("$Id$")
#include <string.h>
int RFCNB_errno = 0;
int RFCNB_saved_errno = 0;
#define RFCNB_ERRNO
#include "std-includes.h"
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#endif
#include "rfcnb-priv.h"
#include "rfcnb-util.h"
int RFCNB_Stats[RFCNB_MAX_STATS];
void (*Prot_Print_Routine)() = NULL;
void *RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address,
int port)
{ struct RFCNB_Con *con;
struct in_addr Dest_IP;
int Client;
BOOL redirect; struct redirect_addr *redir_addr;
char *Service_Address;
if (port == 0) port = RFCNB_Default_Port;
if ((con = (struct RFCNB_Con *)malloc(sizeof(struct RFCNB_Con))) == NULL) {
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
return(NULL);
}
con -> fd = -0;
con -> rfc_errno = 0;
con -> timeout = 0;
con -> redirects = 0;
con -> redirect_list = NULL;
Service_Address = Called_Name;
if (strcmp(Called_Address, "") != 0) {
Service_Address = Called_Address;
}
if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) {
return(NULL);
}
redirect = TRUE;
while (redirect) {
redirect = FALSE;
if ((redir_addr = (struct redirect_addr *)malloc(sizeof(struct redirect_addr))) == NULL) {
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
return(NULL);
}
memcpy((char *)&(redir_addr -> ip_addr), (char *)&Dest_IP, sizeof(Dest_IP));
redir_addr -> port = port;
redir_addr -> next = NULL;
if (con -> redirect_list == NULL) {
con -> redirect_list = con -> last_addr = redir_addr;
} else {
con -> last_addr -> next = redir_addr;
con -> last_addr = redir_addr;
}
if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) {
return(NULL);
}
con -> fd = Client;
if ((errno = RFCNB_Session_Req(con,
Called_Name,
Calling_Name,
&redirect, &Dest_IP, &port)) < 0) {
return(NULL);
}
if (redirect) {
(con -> redirects)++;
RFCNB_Close(con -> fd);
}
}
return(con);
}
int RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
{ struct RFCNB_Pkt *pkt; char *hdr;
int len;
pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
if (pkt == NULL) {
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
return(RFCNBE_Bad);
}
pkt -> next = udata;
hdr = pkt -> data;
*(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE;
RFCNB_Put_Pkt_Len(hdr, Length);
#ifdef RFCNB_DEBUG
fprintf(stderr, "Sending packet: ");
#endif
if ((len = RFCNB_Put_Pkt(Con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
return(RFCNBE_Bad);
}
pkt -> next = NULL;
RFCNB_Free_Pkt(pkt);
return(len);
}
int RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
{
struct RFCNB_Pkt *pkt;
int ret_len;
if (con_Handle == NULL){
RFCNB_errno = RFCNBE_BadHandle;
RFCNB_saved_errno = errno;
return(RFCNBE_Bad);
}
pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
if (pkt == NULL) {
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
return(RFCNBE_Bad);
}
pkt -> next = Data;
if ((ret_len = RFCNB_Get_Pkt(con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
#ifdef RFCNB_DEBUG
fprintf(stderr, "Bad packet return in RFCNB_Recv... \n");
#endif
return(RFCNBE_Bad);
}
pkt -> next = NULL;
RFCNB_Free_Pkt(pkt);
return(ret_len);
}
int RFCNB_Hangup(struct RFCNB_Con *con_Handle)
{
if (con_Handle != NULL) {
RFCNB_Close(con_Handle -> fd);
free(con_Handle);
}
return 0;
}
int RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, BOOL yn)
{
return(setsockopt(con_Handle -> fd, IPPROTO_TCP, TCP_NODELAY,
(char *)&yn, sizeof(yn)));
}
void *RFCNB_Listen()
{
}
void RFCNB_Get_Error(char *buffer, int buf_len)
{
if (RFCNB_saved_errno <= 0) {
sprintf(buffer, "%s", RFCNB_Error_Strings[RFCNB_errno]);
}
else {
sprintf(buffer, "%s\n\terrno:%s", RFCNB_Error_Strings[RFCNB_errno],
strerror(RFCNB_saved_errno));
}
}
int RFCNB_Get_Last_Error()
{
return(RFCNB_errno);
}
int RFCNB_Get_Last_Errno()
{
return(RFCNB_saved_errno);
}
int RFCNB_Get_Error_Msg(int code, char *msg_buf, int len)
{
strncpy(msg_buf, RFCNB_Error_Strings[abs(code)], len);
}
void RFCNB_Register_Print_Routine(void (*fn)())
{
Prot_Print_Routine = fn;
}