radiusload
Snebjørn Andersen
sanderse at bellesystems.com
Fri May 26 07:08:19 EDT 2000
--
Snebjørn Andersen
Software Developer, Software Development
Belle Systems A/S
Tel.: +45 5944 2500
E-mail: sanderse at bellesystems.com
Web: http://www.bellesystems.com
Defining the Future of IP Services
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <inttypes.h>
#include <netdb.h>
#include "main.h"
#include "md5.h"
#include "config.h"
#define DEFAULT_CONFIG_FILE "radiusload.cfg"
#define SUCCESS 0
#define FAILED -1
#define VENDOR_SPECIFIC 26
#define VENDOR_CISCO 9
#define CISCO_VSA_CONNECTION_ID 24
#define CISCO_VSA_SETUP_TIME 25
#define CISCO_VSA_CALL_ORIGIN 26
#define CISCO_VSA_CALL_TYPE 27
#define CISCO_VSA_CONNECT_TIME 28
#define CISCO_VSA_DISCONNECT_TIME 29
#define CISCO_VSA_DISCONNECT_CAUSE 30
#define CISCO_VSA_VOICE_QUALITY 31
#define CISCO_VSA_GW_ID 33
unsigned char * addVendorAttribute(uint32_t vendor_id, unsigned char vendor_type, const char *value, unsigned char *ptr);
struct attribute_type_struct attributeType[] =
{
{AT_USER_NAME, VT_STRING }, /* 1 */
{AT_USER_PASSWORD, VT_STRING }, /* 2 */
{AT_CHAP_PASSWORD, VT_STRING }, /* 3 */
{AT_NAS_IP_ADDRESS, VT_ADDRESS }, /* 4 */
{AT_NAS_PORT, VT_INTEGER }, /* 5 */
{AT_SERVICE_TYPE, VT_INTEGER }, /* 6 */
{AT_FRAMED_PROTOCOL, VT_INTEGER }, /* 7 */
{AT_FRAMED_ADDRESS, VT_ADDRESS}, /* 8 */
{AT_CLASS, VT_STRING}, /* 25 */
{AT_CALLED_STATION_ID, VT_STRING }, /* 30 */
{AT_CALLING_STATION_ID, VT_STRING }, /* 31 */
{AT_NAS_IDENTIFIER, VT_STRING }, /* 32 */
{AT_ACCT_STATUS_TYPE, VT_INTEGER }, /* 40 */
{AT_ACCT_INPUT_OCTETS, VT_INTEGER}, /* 42 */
{AT_ACCT_OUTPUT_OCTETS, VT_INTEGER}, /* 43 */
{AT_ACCT_SESSION_ID, VT_STRING}, /* 44 */
{AT_ACCT_AUTHENTIC, VT_INTEGER}, /* 45 */
{AT_ACCT_SESSION_TIME, VT_INTEGER}, /* 46 */
{AT_ACCT_INPUT_PACKETS, VT_INTEGER}, /* 47 */
{AT_ACCT_OUTPUT_PACKETS, VT_INTEGER}, /* 48 */
{AT_NAS_PORT_ID, VT_INTEGER }, /* 61 */
{0, 0}
};
unsigned long auth_reqs_sent = 0;
unsigned long acct_reqs_sent = 0;
unsigned long auth_rejects = 0;
unsigned long auth_accepts = 0;
unsigned long curr_online = 0;
unsigned long pending_reqs = 0;
unsigned long lost_auth_resps = 0;
unsigned long lost_acct_resps = 0;
unsigned long out_of_ids = 0;
unsigned long ip_addr = 0;
double logon_time = 0;
int scroll_stats = 1;
unsigned long stat_lines = 0;
unsigned long from_num;
unsigned long to_num;
unsigned long rate;
unsigned long duration;
unsigned long session_id;
char prefix[64];
char user_password[16];
char shared_secret[32];
unsigned long shared_secret_len;
unsigned long dead_timeout;
unsigned long nas_ip_adr;
time_t start_time;
unsigned long current_user_num;
static unsigned char net_buffer[1500]; /* MTU SIZE */
static unsigned char tmp_buffer[1500];
char config_file_name[100];
unsigned char global_identifier;
unsigned h323_conf_id_sequencer = 0;
unsigned h323_conf_id_semiunique = 0;
int auth_sock_fd;
int acct_sock_fd;
static struct sockaddr dest_auth_addr;
static struct sockaddr dest_acct_addr;
struct pending_request pending_req[256];
struct logged_on_user *user_top = NULL, *user_bottom = NULL;
extern struct config cfg;
static unsigned long nextUserNum();
int my_32bit_rand();
int main(int argc, char *argv[])
{
int rc, i, max_fd;
fd_set read_set, tmp_read_set;
struct timeval timeout;
time_t now, uniq;
if( argc < 2 )
{
strcpy(config_file_name, DEFAULT_CONFIG_FILE);
}
else
{
strcpy(config_file_name, argv[1]);
}
rc = read_config(config_file_name);
if(rc == -1)
{
return 0;
}
nas_ip_adr=string2ip(cfg.nas_ip_addr);
FD_ZERO( &read_set );
for( i = 0 ; i < 256 ; i++ )
{
pending_req[i].active = 0;
}
srand( time(NULL) );
start_time = time(NULL);
from_num = cfg.from_num;
to_num = cfg.to_num;
rate = cfg.rate;
duration = cfg.duration;
global_identifier = 0;
ip_addr = cfg.ip_prefix << 24;
dead_timeout = cfg.dead_timeout;
strcpy(prefix, cfg.prefix);
strcpy(shared_secret, cfg.shared_secret);
strcpy(user_password, cfg.password);
shared_secret_len = strlen(shared_secret);
session_id = 0;
current_user_num = from_num;
if( getRadiusSocket( &dest_auth_addr, cfg.auth_ip_addr, cfg.auth_port) != 1 )
{
fprintf(stderr, "main: getRadiusSocket() AUTH\n");
exit(0);
}
if( getRadiusSocket( &dest_acct_addr, cfg.acct_ip_addr, cfg.acct_port ) != 1 )
{
fprintf(stderr, "main: getRadiusSocket() ACCT\n");
exit(0);
}
auth_sock_fd = openUDPSocket();
acct_sock_fd = openUDPSocket();
FD_SET( auth_sock_fd, &read_set );
FD_SET( acct_sock_fd, &read_set );
max_fd = acct_sock_fd + 1;
uniq = start_time;
setbuf(stdout, NULL);
printf("RADIUS work-loader v2000c (c) Belle Systems A/S 2000\n");
printf("Compiled: " __DATE__ " " __TIME__ "\n");
printf("Special why-do-i-not-logg-off-the-users-after-some-time version\n");
if(!scroll_stats)
{
printf("\nReqs Acpts Rjcts CurOL Pend LstRs1 LstRs2 LstRq LogTm\n");
printf("--------------------------------------------------------------\n");
printf(" ");
}
for(;;)
{
tmp_read_set = read_set;
timeout.tv_sec = 0;
timeout.tv_usec = 100000; /* 0.1 sec */
rc = select( max_fd, &tmp_read_set, NULL, NULL, &timeout);
switch( rc )
{
case -1: /* ERROR */
break;
case 0: /* TIME OUT */
break;
default:
if( FD_ISSET( auth_sock_fd, &tmp_read_set ) )
{
handleAuthResponse(auth_sock_fd);
}
if( FD_ISSET( acct_sock_fd, &tmp_read_set ) )
{
handleAcctResponse(acct_sock_fd);
}
break;
}
now = time(NULL);
if( now != uniq )
{
uniq = now;
if(scroll_stats)
{
if( stat_lines % 10 == 0)
{
printf("\nReqs Acpts Rjcts CurOL Pend LstRs1 LstRs2 LstRq LogTm\n");
printf("--------------------------------------------------------------\n");
}
}
else
{
printf("\r");
}
printf("%05ld %05ld %05ld %05ld %04ld %05ld %05ld %05ld %02.3f",
(long)cfg.send_auth?auth_reqs_sent:acct_reqs_sent,
(long)auth_accepts,
(long)auth_rejects,
(long)curr_online,
(long)pending_reqs,
(long)lost_auth_resps,
(long)lost_acct_resps,
(long)out_of_ids,
logon_time/auth_accepts
);
if(scroll_stats)
{
printf("\n");
}
stat_lines++;
}
checkForLostResponses();
if(cfg.send_auth)
{
if( (auth_reqs_sent < (unsigned long)cfg.no_requests)||(cfg.no_requests == 0) )
{
while( ( now - start_time ) * rate > auth_reqs_sent )
{
/* Time to send new requests */
sendAuthRequest();
auth_reqs_sent++;
if(auth_reqs_sent%16==0) {
/*sleep for 5 microseconds so the radius server has time to recv() the packets*/
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 500000;
/*nanosleep(&ts,NULL);*/
}
}
}
}
else if(cfg.send_acct_start)
{
if((acct_reqs_sent<(unsigned long)cfg.no_requests) || (cfg.no_requests==0))
{
while((now-start_time)*rate > acct_reqs_sent)
{
sendUnauthenticatedAcctStartRequest();
acct_reqs_sent++;
if(acct_reqs_sent%16==0) {
//sleep for 5 microseconds so the radius server has time to recv() the packets
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 500000;
//nanosleep(&ts,NULL);
}
}
}
}
else
{
if((acct_reqs_sent<(unsigned long)cfg.no_requests) || (cfg.no_requests==0))
{
while((now-start_time)*rate > acct_reqs_sent)
{
sendUnauthenticatedAcctStopRequest();
acct_reqs_sent++;
if(acct_reqs_sent%16==0) {
//sleep for 5 microseconds so the radius server has time to recv() the packets
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 500000;
//nanosleep(&ts,NULL);
}
}
}
}
checkForAcctStopRequests();
}
}
void checkForLostResponses()
{
int i;
time_t now;
now = time(NULL);
for( i = 0 ; i < 256 ; i++ )
{
if( ((now - pending_req[i].timestamp) > (time_t)dead_timeout) && pending_req[i].active )
{
if(pending_req[i].code!=4)
lost_auth_resps++;
else
lost_acct_resps++;
pending_reqs--;
pending_req[i].active = 0;
}
}
}
void checkForAcctStopRequests()
{
struct logged_on_user *ptr=NULL;
time_t now;
now = time(NULL);
if (user_top==NULL && user_bottom!=NULL)
//if ((user_top==NULL) != (user_bottom!=NULL))
{
fprintf(stderr, "Listen er smadret [online %d]\n",(int)curr_online);
if (user_top==NULL) fprintf(stderr, "user_top=NULL\n");
if (user_bottom==NULL) fprintf(stderr, "botton=NULL\n");
abort();
exit(1);
}
//printf("user_top pointer = %p\n", user_top);
//printf("ptr pointer = %p\n", ptr);
ptr = user_top;
while( ptr && ptr->timestamp<now )
{
struct logged_on_user *tmp_ptr=NULL;
sendAcctStopRequest(ptr->port, ptr->username,
ptr->session_id,ptr->class_attr,
ptr->framed_ip_addr);
fprintf(stderr, "Loggin user off [%p]\n", ptr);
//printf("tmp pointer = %p\n", tmp_ptr);
//printf("ptr pointer = %p\n", ptr);
tmp_ptr = ptr;
ptr = ptr->next;
free(tmp_ptr);
}
user_top = ptr;
printf("Users = %ld\n", (long)curr_online);
if (curr_online==0) sleep(100);
//debug code:
if(curr_online > 2000) {
fprintf(stderr,"=========== Suspecious many online users ==========\n");
fprintf(stderr,"curr_online = %d\n",(int)curr_online);
fprintf(stderr,"now = %d\n", (int)now);
fprintf(stderr,"duration = %ld\n",(long)duration);
fprintf(stderr,"rate = %d\n", (int)rate);
fprintf(stderr,"from=%d, to=%d\n", (int)from_num, (int)to_num);
fprintf(stderr,"Dumping first 200 online users:\n");
int i=0;
for(ptr = user_top; ptr && i<200; i++) {
fprintf(stderr,
"%d: timestamp=%d, port=%d, username='%s' \n",
i,
(int)ptr->timestamp,
(int)ptr->port,
ptr->username
);
ptr=ptr->next;
}
fprintf(stderr,"========= Dont scroll! Or the lemmings will eat you! ==============\n");
exit(1);
}
}
void cpyStrAttribute( struct radius_header *resp_header,
int attr_type,
char *output)
{
unsigned short packet_len;
unsigned char *attr_ptr;
packet_len = ntohs(resp_header->length);
attr_ptr = (unsigned char *)resp_header->data;
while( (attr_ptr - net_buffer) < packet_len )
{
if( *attr_ptr == attr_type )
{
memcpy( output, attr_ptr + 2, *(attr_ptr + 1) - 2);
break;
}
attr_ptr += *(attr_ptr + 1);
}
}
void cpyIPAddrAttribute( struct radius_header *resp_header,
int attr_type,
uint32_t *output)
{
unsigned short packet_len;
unsigned char *attr_ptr;
packet_len = ntohs(resp_header->length);
attr_ptr = (unsigned char *)resp_header->data;
while( (attr_ptr - net_buffer) < packet_len )
{
if( *attr_ptr == attr_type )
{
uint32_t ip;
memcpy( &ip, attr_ptr + 2, 4);
*output = (uint32_t) ntohl(ip);
break;
}
attr_ptr += *(attr_ptr + 1);
}
}
void handleAuthResponse(int auth_fd)
{
int rc;
struct sockaddr incoming_addr;
#ifdef linux
socklen_t incoming_addr_len = sizeof(incoming_addr);
#else
int incoming_addr_len = sizeof(incoming_addr);
#endif
struct radius_header *header;
char class_attr[254];
uint32_t framed_ip_addr=0;
unsigned char tmp_id;
header = (struct radius_header *)net_buffer;
/* LOOP? */
rc = recvfrom(auth_fd,
(char*)net_buffer,
sizeof(net_buffer),
0,
&incoming_addr,
&incoming_addr_len );
tmp_id = header->identifier;
if( pending_req[header->identifier].active &&
pending_req[header->identifier].code == 1)
{
if(header->code == 2)
{
/* Accepted */
logon_time += get_precise_time() - pending_req[header->identifier].precise_ts;
auth_accepts++;
curr_online++;
class_attr[0]='\0';
if(cfg.remember_class_attr)
{
cpyStrAttribute(header, AT_CLASS, class_attr);
}
if(cfg.remember_framed_ip_addr)
{
cpyIPAddrAttribute(header, AT_FRAMED_ADDRESS, &framed_ip_addr );
}
sendAcctStartRequest( pending_req[header->identifier].port,
pending_req[header->identifier].username,
class_attr,
framed_ip_addr);
}
else
{
auth_rejects++;
/* Rejected */
}
pending_req[tmp_id].active = 0;
pending_reqs--;
}
}
void handleAcctResponse(int acct_fd)
{
int rc;
struct sockaddr incoming_addr;
#ifdef linux
socklen_t incoming_addr_len=sizeof(incoming_addr);
#else
int incoming_addr_len=sizeof(incoming_addr);
#endif
struct radius_header *header;
header = (struct radius_header *)net_buffer;
rc = recvfrom(acct_fd,
(char*)net_buffer,
1500,
0,
&incoming_addr,
&incoming_addr_len );
if(pending_req[header->identifier].active &&
pending_req[header->identifier].code == 4)
{
if(header->code==5)
{
/*acct_accepts++*/
}
else
{
/*acct_rejects++*/
}
pending_req[header->identifier].active = 0;
pending_reqs--;
}
return;
}
void sendAcctStartRequest(unsigned long port, const char *username, char *class_attr, uint32_t framed_ip_addr)
{
unsigned char id, *buffer, md5_digest[16];
int rc;
struct radius_header *req_header;
char session_id_str[10];
unsigned long value;
unsigned short packet_len;
if(!cfg.send_acct_start)
{
return;
}
rc = findFreeIdentifier(&id);
if( rc != SUCCESS )
{
return;
}
session_id++;
insertUser( port, username, session_id, class_attr, framed_ip_addr );
pending_req[id].code = 4;
pending_req[id].acct_type = 1;
pending_req[id].port = port;
strcpy(pending_req[id].username, username);
pending_req[id].timestamp = time(NULL);
/* Send Accounting Start Request */
req_header = (struct radius_header *)net_buffer;
req_header->code = 4;
req_header->identifier = id;
buffer = (unsigned char*)req_header->data;
value = 0xc0a801aa;
buffer = addAttribute(AT_NAS_IP_ADDRESS, &nas_ip_adr, buffer);
buffer = addAttribute(AT_NAS_PORT, &port, buffer);
value = 0; /* Async */
buffer = addAttribute(AT_NAS_PORT_ID, &value, buffer);
buffer = addAttribute(AT_USER_NAME, username, buffer);
if(cfg.called_lineid[0]) buffer = addAttribute(AT_CALLED_STATION_ID, cfg.called_lineid, buffer);
if(cfg.calling_lineid[0]) buffer = addAttribute(AT_CALLING_STATION_ID, cfg.calling_lineid, buffer);
value = 1; /* Start */
buffer = addAttribute(AT_ACCT_STATUS_TYPE, &value, buffer);
if(class_attr && class_attr[0])
{
buffer = addAttribute(AT_CLASS, class_attr, buffer);
}
value = 1;
buffer = addAttribute(AT_ACCT_AUTHENTIC, &value, buffer);
value = 2;
buffer = addAttribute(AT_SERVICE_TYPE, &value, buffer);
sprintf(session_id_str, "%09ld", (long)session_id);
buffer = addAttribute(AT_ACCT_SESSION_ID, session_id_str, buffer);
value = 1;
buffer = addAttribute(AT_FRAMED_PROTOCOL, &value, buffer);
if(!cfg.remember_framed_ip_addr)
{
value = session_id + ip_addr;
}
else
{
value = framed_ip_addr;
}
buffer = addAttribute(AT_FRAMED_ADDRESS, &value, buffer);
memset(req_header->authenticator, 0, AUTHENTICATOR_LENGTH);
randomVector(buffer);
packet_len = buffer - net_buffer;
req_header->length = htons(packet_len);
md5_calc(md5_digest, net_buffer, packet_len + AUTHENTICATOR_LENGTH);
memcpy(req_header->authenticator, md5_digest, AUTHENTICATOR_LENGTH );
rc = sendto(acct_sock_fd,(char*)net_buffer, (size_t)packet_len, (int)0,
&dest_acct_addr,
sizeof(struct sockaddr));
if( rc != packet_len )
{
fprintf(stderr, "sendAcctStartRequest: sendto() failed\n");
}
{
static int i=0;
if((i++)%16==0) {
/*sleep for 5 microseconds so the radius server has time to recv() the packets*/
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 500000;
/*nanosleep(&ts,NULL);*/
}
}
}
void sendAcctStopRequest(unsigned long port, const char *username,
unsigned long acct_session_id, const char *class_attr, uint32_t framed_ip_addr)
{
unsigned char id, *buffer, md5_digest[16];
int rc;
struct radius_header *req_header;
unsigned long value;
unsigned short packet_len;
char session_id_str[20];
char str_value[128];
if(!cfg.send_acct_stop)
{
return;
}
rc = findFreeIdentifier(&id);
if( rc != SUCCESS )
{
return;
}
pending_req[id].code = 4;
pending_req[id].acct_type = 1;
pending_req[id].port = port;
strcpy(pending_req[id].username, username);
pending_req[id].timestamp = time(NULL);
curr_online--;
/* Send Accounting Stop Request */
req_header = (struct radius_header *)net_buffer;
req_header->code = 4;
req_header->identifier = id;
buffer = req_header->data;
value = 0xc0a801aa;
buffer = addAttribute(AT_NAS_IP_ADDRESS, &nas_ip_adr, buffer);
buffer = addAttribute(AT_NAS_PORT, &port, buffer);
value = 0; /* Async */
buffer = addAttribute(AT_NAS_PORT_ID, &value, buffer);
buffer = addAttribute(AT_USER_NAME, username, buffer);
if(cfg.called_lineid[0]) buffer = addAttribute(AT_CALLED_STATION_ID, cfg.called_lineid, buffer);
if(cfg.calling_lineid[0]) buffer = addAttribute(AT_CALLING_STATION_ID, cfg.calling_lineid, buffer);
value = 2; /* Stop */
buffer = addAttribute(AT_ACCT_STATUS_TYPE, &value, buffer);
if(class_attr && class_attr[0])
{
buffer = addAttribute(AT_CLASS, class_attr, buffer);
}
else if(!cfg.send_auth)
{
//fabricate a class attribute
char fabricated_class_attr[256];
sprintf(fabricated_class_attr,"BSC1:%ld_%d_1_%d_%d_1_2_-1_1_N_-1",
(long)time(0)-duration,
(int)port,
2504,
2504
);
buffer = addAttribute(AT_CLASS, fabricated_class_attr, buffer);
}
value = 1;
buffer = addAttribute(AT_ACCT_AUTHENTIC, &value, buffer);
value = 2;
buffer = addAttribute(AT_SERVICE_TYPE, &value, buffer);
sprintf(session_id_str, "%09ld", (long)acct_session_id);
buffer = addAttribute(AT_ACCT_SESSION_ID, session_id_str, buffer);
value = 1;
buffer = addAttribute(AT_FRAMED_PROTOCOL, &value, buffer);
if(cfg.remember_framed_ip_addr==0)
{
value = acct_session_id + ip_addr;
}
else
{
value = framed_ip_addr;
}
buffer = addAttribute(AT_FRAMED_ADDRESS, &value, buffer);
value = 8000;
buffer = addAttribute(AT_ACCT_INPUT_OCTETS, &value, buffer);
value = 800;
buffer = addAttribute(AT_ACCT_OUTPUT_OCTETS, &value, buffer);
value = 100;
buffer = addAttribute(AT_ACCT_INPUT_PACKETS, &value, buffer);
value = 10;
buffer = addAttribute(AT_ACCT_OUTPUT_PACKETS, &value, buffer);
buffer = addAttribute(AT_ACCT_SESSION_TIME, &duration, buffer);
if ( cfg.use_voip_accounting )
{
char val[9];
char valid_chars[] = {"01234567890abcdef"};
if(h323_conf_id_semiunique==0) {
struct sockaddr_in my_address;
#ifdef linux
socklen_t sl = sizeof(my_address);
#else
int sl = sizeof(my_address);
#endif
getsockname(acct_sock_fd, (struct sockaddr*)&my_address, &sl);
h323_conf_id_semiunique = (getpid()<<16) | my_address.sin_port;
}
sprintf(str_value, "h323-conf-id=01234567 %8x %8x ", h323_conf_id_sequencer++, h323_conf_id_semiunique);
for (int i=0; i <= 7; i++)
val[i] = valid_chars[rand() % 16];
val[8] = 0;
strcat(str_value, val);
buffer = addVendorAttribute(VENDOR_CISCO, CISCO_VSA_CONNECTION_ID,
str_value, buffer);
buffer = addVendorAttribute(VENDOR_CISCO, CISCO_VSA_SETUP_TIME,
"h323-setup-time=09:30:00.000 UTC Fri Dec 10 1999", buffer);
buffer = addVendorAttribute(VENDOR_CISCO, CISCO_VSA_CONNECT_TIME,
"h323-connect-time=09:30:00.000 UTC Fri Dec 10 1999", buffer);
buffer = addVendorAttribute(VENDOR_CISCO, CISCO_VSA_DISCONNECT_TIME,
"h323-disconnect-time=09:30:50.000 UTC Fri Dec 10 1999", buffer);
buffer = addVendorAttribute(VENDOR_CISCO, CISCO_VSA_GW_ID,
"h323-gw-id=192.168.1.149", buffer);
buffer = addVendorAttribute(VENDOR_CISCO, CISCO_VSA_CALL_ORIGIN,
"h323-call-origin=originate", buffer);
buffer = addVendorAttribute(VENDOR_CISCO, CISCO_VSA_CALL_TYPE,
"h323-call-type=VoIP", buffer);
buffer = addVendorAttribute(VENDOR_CISCO, CISCO_VSA_DISCONNECT_CAUSE,
"h323-disconnect-cause=10", buffer);
buffer = addVendorAttribute(VENDOR_CISCO, CISCO_VSA_VOICE_QUALITY,
"h323-voice-quality=0", buffer);
}
bzero(req_header->authenticator, AUTHENTICATOR_LENGTH);
randomVector(buffer);
packet_len = buffer - net_buffer;
req_header->length = htons(packet_len);
md5_calc(md5_digest, net_buffer, packet_len + AUTHENTICATOR_LENGTH);
memcpy(req_header->authenticator, md5_digest, AUTHENTICATOR_LENGTH );
char hex_str[2048];
bintohex((char*)net_buffer, packet_len, hex_str);
/* printf("Accounting stop packet:%s\n\n", hex_str);
*/
rc = sendto(acct_sock_fd,
(char*)net_buffer,
packet_len,
0,
&dest_acct_addr,
sizeof(struct sockaddr));
if( rc != packet_len )
{
fprintf(stderr, "sendAcctStopRequest: sendto() failed\n");
}
}
void sendUnauthenticatedAcctStopRequest()
{
unsigned long port;
char username[64];
uint32_t framed_ip_addr;
unsigned long acct_session_id;
unsigned long user_num = nextUserNum();
// sprintf(username,"%s%010d", prefix, current_user_num);
if(cfg.username_digits==0)
sprintf(username,"%s%ld", prefix, (long)user_num);
else
sprintf(username,"%s%0*ld", prefix, cfg.username_digits, (long)user_num);
port = user_num;
framed_ip_addr = ::ip_addr + user_num;
acct_session_id = user_num;
sendAcctStopRequest(port, username, acct_session_id, NULL, framed_ip_addr);
curr_online--;
}
void sendAuthRequest()
{
unsigned char id;
char username[64];
int rc, i;
struct radius_header *req_header;
unsigned char md5_digest[16], *password_ptr, *buffer;
unsigned long value, port;
unsigned short packet_len;
unsigned long user_num = nextUserNum();
rc = findFreeIdentifier(&id);
if( rc != SUCCESS )
{
return;
}
// sprintf( username, "%s%010d", prefix, current_user_num);
if(cfg.username_digits==0)
sprintf(username,"%s%ld", prefix, (long)user_num);
else
sprintf(username,"%s%0*ld", prefix, cfg.username_digits, (long)user_num);
port = user_num;
pending_req[id].code = 1;
pending_req[id].port = port;
strcpy( pending_req[id].username, username);
/* Send Authentication Request */
req_header = (struct radius_header *)net_buffer;
req_header->code = 1;
req_header->identifier = id;
buffer = req_header->data;
value = 0xc0a801aa;
buffer = addAttribute(AT_NAS_IP_ADDRESS, &nas_ip_adr, buffer);
buffer = addAttribute(AT_NAS_PORT, &port, buffer);
value = 0; /* Async */
buffer = addAttribute(AT_NAS_PORT_ID, &value, buffer);
buffer = addAttribute(AT_USER_NAME, username, buffer);
if(cfg.called_lineid[0]) buffer = addAttribute(AT_CALLED_STATION_ID, cfg.called_lineid, buffer);
if(cfg.calling_lineid[0]) buffer = addAttribute(AT_CALLING_STATION_ID, cfg.calling_lineid, buffer);
/* Save position of password attribute */
password_ptr = buffer;
buffer = addAttribute(AT_USER_PASSWORD, user_password, buffer);
value = 2;
buffer = addAttribute(AT_SERVICE_TYPE, &value, buffer);
value = 1;
buffer = addAttribute(AT_FRAMED_PROTOCOL, &value, buffer);
randomVector(req_header->authenticator);
packet_len = buffer - net_buffer;
req_header->length = htons(packet_len);
/* Encrypt password attribute value */
memcpy(tmp_buffer + shared_secret_len,
req_header->authenticator,
AUTHENTICATOR_LENGTH );
memcpy(tmp_buffer, shared_secret, shared_secret_len);
md5_calc(md5_digest, tmp_buffer, shared_secret_len + AUTHENTICATOR_LENGTH );
for( i = 0 ; i < 16 ; i++ )
{
password_ptr[2 + i] ^= md5_digest[i];
}
rc = sendto(auth_sock_fd,
(char*)net_buffer,
packet_len,
0,
&dest_auth_addr,
sizeof(struct sockaddr));
if( rc != packet_len )
{
fprintf(stderr, "sendAuthRequest: sendto() failed\n");
}
}
void sendUnauthenticatedAcctStartRequest() {
//Send a acct-start packet without any preceding authentication
unsigned long port;
char username[64];
uint32_t framed_ip_addr;
unsigned long user_num = nextUserNum();
// sprintf(username,"%s%010d", prefix, current_user_num);
if(cfg.username_digits==0)
sprintf(username,"%s%ld", prefix, (long)user_num);
else
sprintf(username,"%s%0*ld", prefix, cfg.username_digits, (long)user_num);
port = user_num;
framed_ip_addr = ::ip_addr + user_num;
sendAcctStartRequest(port, username, NULL, framed_ip_addr);
curr_online++;
}
int findFreeIdentifier(unsigned char *new_id)
{
int i;
for( i = 0 ; i <= 256 ; i++ )
{
global_identifier++;
if( !pending_req[global_identifier].active )
{
pending_req[global_identifier].active = 1;
pending_req[global_identifier].timestamp = time(NULL);
pending_req[global_identifier].precise_ts = get_precise_time();
*new_id = global_identifier;
pending_reqs++;
return SUCCESS;
}
}
out_of_ids++;
return FAILED;
}
int openUDPSocket()
{
int fd, result;
struct sockaddr salocal;
struct sockaddr_in *sin;
fd = socket (AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
(void) perror ("socket");
return -1;
}
sin = (struct sockaddr_in *) & salocal;
memset ((char *) sin, '\0', sizeof (salocal));
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = htons(0);
result = bind (fd, & salocal, sizeof (*sin));
if (result < 0)
{
(void) perror ("bind");
return -1;
}
return fd;
}
int getRadiusSocket(struct sockaddr *saradius, char *ip, int port)
{
struct sockaddr_in *sin;
sin = (struct sockaddr_in *) saradius;
memset ((char *) sin, '\0', sizeof (struct sockaddr));
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = 0;
if( (sin->sin_addr.s_addr = string2ip(ip)) == 0 )
{
(void) perror ("radius ip address");
return 0;
}
sin->sin_port = htons(port);
return 1;
}
void randomVector(unsigned char *vector)
{
int randno;
int i;
for( i = 0 ; i < AUTHENTICATOR_LENGTH ; )
{
randno = rand();
memcpy(vector, &randno, sizeof(int));
vector += sizeof(int);
i += sizeof(int);
}
}
void insertUser(unsigned long port, const char *username,
unsigned long acct_session_id, const char *class_attr, uint32_t framed_ip_addr)
{
struct logged_on_user *ptr;
ptr = (struct logged_on_user *)malloc(sizeof(struct logged_on_user));
ptr->port = port;
ptr->session_id = acct_session_id;
strcpy( ptr->username, username);
if(class_attr)
{
strcpy( ptr->class_attr, class_attr);
}
else
{
ptr->class_attr[0]='\0';
}
ptr->framed_ip_addr = framed_ip_addr;
ptr->timestamp = time(NULL) + duration;
ptr->next = NULL;
if( user_bottom == NULL )
{
fprintf(stderr, "First time: adding user to list\n");
printf("user top [%p]\n", ptr);
user_top = ptr;
}
else
{
fprintf(stderr, "Adding user to list [%p]\n", ptr);
user_bottom->next = ptr;
}
user_bottom = ptr;
if (user_top->next != NULL && user_top==NULL)
{
fprintf(stderr, "top Something is really wrong!");
}
if (user_bottom->next != NULL && user_bottom==NULL)
{
fprintf(stderr, "bottom Something is really wrong!");
}
}
unsigned char *addAttribute(unsigned char type, const void *value, unsigned char *ptr)
{
int i;
unsigned char *start_ptr;
for( i = 0 ; attributeType[i].type != 0 ; i++ )
{
if( attributeType[i].type == type )
{
start_ptr = ptr;
*ptr++ = type;
switch( attributeType[i].value_type )
{
case VT_STRING:
if( type != AT_USER_PASSWORD )
{
*ptr++ = strlen((char*)value) + 2;
memcpy(ptr, (char*)value, strlen((char*)value));
ptr += strlen((char*)value);
}
else
{
*ptr++ = 18;
memset(ptr, 0, 18);
memcpy(ptr, (char*)value, strlen((char*)value));
ptr += 16;
}
break;
case VT_ADDRESS:
case VT_TIME:
case VT_INTEGER: {
uint32_t nvalue;
*ptr++ = sizeof(long) + 2;
nvalue = htonl( *((long*)value) );
memcpy(ptr, &nvalue, 4);
ptr += 4;
break;
}
default:
printf("Unknown attribute!\n");
return 0;
}
}
}
return ptr;
}
unsigned char * addVendorAttribute(uint32_t vendor_id, unsigned char vendor_type, const char *value, unsigned char *ptr)
{
int value_len = strlen(value);
/* set the attribute type to vendor specific */
*ptr++ = VENDOR_SPECIFIC;
/* set the total length of the attribute */
*ptr++ = 2 + 4 + 1 + 1 + value_len;
/* set the vendor ID (4 bytes) */
vendor_id = htonl(vendor_id);
memcpy(ptr, &vendor_id, 4);
ptr+=4;
/* set the vendor attribute type */
*ptr++ = vendor_type;
/* set the vendor attribute length */
*ptr++ = value_len + 2;
/* copy the attribute value */
memcpy(ptr, (char*)value, value_len);
ptr += value_len;
return ptr;
}
double get_precise_time()
{
#ifdef linux
struct timeval tv;
struct timezone tz;
tz.tz_minuteswest = 120;
gettimeofday(&tv, &tz);
return (tv.tv_sec + (double)tv.tv_usec/1000000);
#else
struct timespec mytime;
clock_gettime(0, &mytime);
return(mytime.tv_sec + (double)mytime.tv_nsec/NANOSEC);
#endif
}
long string2ip(const char *s) {
struct hostent *he;
he = gethostbyname((char*)s);
if(!he) return 0;
uint32_t ip;
memcpy(&ip,he->h_addr_list[0],4);
return ip;
}
static unsigned long nextUserNum() {
unsigned long user_num;
if(cfg.username_distribution==sequential_mode)
{
user_num = current_user_num;
if(current_user_num==(unsigned long)cfg.to_num)
current_user_num = cfg.from_num;
else
current_user_num++;
}
else
{
user_num = from_num + my_32bit_rand()%(cfg.to_num-cfg.from_num);
}
return user_num;
}
int my_32bit_rand() {
static int l=0;
int r = rand();
l = ((l<<5) ^ r)&0x7fffffff;
return l;
}
More information about the Python-list
mailing list