#include<stdio.h>
#include<libradius.h>
#include<sys/select.h>
#include<sys/time.h>
#include<libradius.h>
#define RADIUS_COA_SOCKET_PORT 3799
typedef struct radclient_t {
    struct      radclient_t *prev;
    struct      radclient_t *next;

    const char  *filename;
    int     packet_number; /* in the file */
    char        password[256];
    time_t      timestamp;
    RADIUS_PACKET   *request;
    RADIUS_PACKET   *reply;
    int     resend;
    int     tries;
    int     done;
} radclient_t;
static radclient_t *radclient_head = NULL;
static radclient_t *radclient_tail = NULL;
static fr_packet_list_t *pl = NULL;
int main()
{  
   radclient_t *this;
   socklen_t addrsize = 0;
   int fd = socket(AF_INET, SOCK_DGRAM, 0);
   struct sockaddr_in serveraddr, cliaddr;
   memset(&serveraddr, 0, sizeof(struct sockaddr_in));
   memset(&cliaddr, 0, sizeof(struct sockaddr_in));

   serveraddr.sin_family = AF_INET ;

   serveraddr.sin_port = htons(RADIUS_COA_SOCKET_PORT);
   serveraddr.sin_addr.s_addr =htonl(INADDR_ANY);
   addrsize = sizeof(serveraddr);
   bzero(&serveraddr.sin_zero,sizeof(serveraddr.sin_zero));

   // Bind the socket with the server address
   if ((bind(fd, (struct sockaddr *)&serveraddr, addrsize))<0)
   {
       printf("bind failed :: %d\n",errno);
   }
   else
       printf("Radius:: Socket bind successful\n");
   int max_fd = 0;
   struct timeval  tv;
   tv.tv_sec = 1;
   tv.tv_usec = 0;
   int retval;
   radclient_t *radclient;
   RADIUS_PACKET   *reply, **request_p; 
   while(1)
   {
       max_fd = fd + 1;
       fd_set rdset;
       FD_ZERO(&rdset);
       FD_SET(fd, &rdset);  
       retval = select(max_fd, &rdset, NULL, NULL, &tv);
       if (retval == -1) 
            perror("select()");
       else if (retval){
       printf("Data is available now.\n");
       if(FD_ISSET(fd, &rdset))
       {
           RADIUS_PACKET *packet = rad_recv(fd, 0);

           char src_addr[INET_ADDRSTRLEN + 1] = {'\0'};
           char dst_addr[INET_ADDRSTRLEN + 1] = {'\0'};

           inet_ntop(AF_INET, &packet->src_ipaddr.ipaddr, src_addr, INET_ADDRSTRLEN); 
           printf("src_addr : %s\n", src_addr);

           inet_ntop(AF_INET,&packet->dst_ipaddr.ipaddr, dst_addr, INET_ADDRSTRLEN); 
           printf("dst_addr : %s\n", dst_addr);

           printf("src_port : %d\n", packet->src_port);
           printf("dst_port : %d\n", packet->dst_port);

           printf("id: %d\n", packet->id);
           printf("code: %d\n", packet->code);
           printf("hash: %d\n", packet->hash);

           int i = 0;
           for(i = 0; i < AUTH_VECTOR_LEN; i++)
           printf("vector: 0x%x\n ", packet->vector[i]);

           printf("\n");

           printf("data : %s\n", packet->data);
       
           reply = fr_packet_list_recv(pl, &rdset);
           if (!reply) {
                printf( "radclient: received bad packet: %s\n",strerror(errno));
                return -1;  /* bad packet */
            }
           reply->dst_ipaddr = packet->src_ipaddr;

           if (fr_debug_flag > 2) printf("reply: 0x%x\n ", reply);

           request_p = fr_packet_list_find_byreply(pl, reply);
           if (!request_p) {
                fprintf(stderr, "radclient: received response to request we did not send. (id=%d socket %d)\n", reply->id, reply->sockfd);
                rad_free(&reply);
                return -1;  /* got reply to packet we didn't send */
            }
            radclient = fr_packet2myptr(radclient_t, request, request_p);

        /*
        *  Fails the signature validation: not a real reply.
        *  FIXME: Silently drop it and listen for another packet.
        */
        if (rad_verify(reply, radclient->request, "testing123") < 0) {
            fr_perror("rad_verify");
         //   totallost++;
        //    goto packet_done; /* shared secret is incorrect */
        }
  


        }
       else
            printf("Radius:: FD_ISSET Failed\n"); 
        }    
    }
}
