/**************************************************************************
aim:listen client pc nbns registration (via udp port 137)
author:wujunyong
date:2011-07-21
description: when client pc register it name by broadcast nbns packets, our ap record and send it's ip to logic dhcps module
**************************************************************************/
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include <time.h>
#include <signal.h>
#include <net/if.h>

#define DATAMAX 255
#define UDP_PORT 137
#define FLUSHTIME 120
static char ipcache[2048]={0};

//#define DEBUG 1
#ifdef DEBUG
#define DEBUG_PIRNT(fmt, args...)  printf(fmt, ##args);
#else
#define DEBUG_PIRNT(fmt, args...) 
#endif

static void flushipcache(void)
{
    DEBUG_PIRNT("flush ipcache\n");
    memset(ipcache, 0, sizeof(ipcache));
    alarm(FLUSHTIME);
}


int main(int argc, char *argv[])
{
    int sock;
    struct sockaddr_in NBNSServAddr;
    struct sockaddr_in NBNSClntAddr;
    unsigned int cliAddrLen;
    int NBNSBuffer[DATAMAX];
    unsigned short NBNSServPort=UDP_PORT;
    int recvMsgSize;
    char cmd[64]={0};
    char ip[16]={0};
    char ips[17]={0};
    FILE *fp;
    int i=0;
    struct ifreq interface;
    
    unsigned long ulCurrTime = 0;
    static unsigned long ulPreUpdateTime = 0;   
    printf("attached devices deamon starting...\n");
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_flags = SA_RESTART;

    sa.sa_handler = (void (*)(int)) flushipcache;
		sigaction(SIGALRM, &sa, NULL);

    alarm(FLUSHTIME);

    if((sock=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP))<0)
        {
            DEBUG_PIRNT("socket() failed");
            exit(1);
        }

    /*only for br0*/
    strncpy(interface.ifr_name, "br0", IFNAMSIZ);
    if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &interface, sizeof(interface)) < 0) {
        close(sock);
        return -1;
    }


    memset(&NBNSServAddr, 0 ,sizeof(NBNSServAddr));
    NBNSServAddr.sin_family=AF_INET;
	/* 绑定IP*/
    NBNSServAddr.sin_addr.s_addr=htonl(INADDR_ANY);
/*  绑定端口 */
    NBNSServAddr.sin_port=htons(NBNSServPort);

    if(bind(sock, (struct sockaddr *)&NBNSServAddr, sizeof(NBNSServAddr))<0)
        {
            DEBUG_PIRNT("bind() failed\n");
            exit(1);
        }

    for(;;)
    {
        cliAddrLen=sizeof(NBNSClntAddr);
        if((recvMsgSize=recvfrom(sock, NBNSBuffer, DATAMAX, 0,(struct sockaddr*)&NBNSClntAddr, &cliAddrLen))<0)
            {
                DEBUG_PIRNT("recvfrom() failed\n");
                exit(1);
            }
         
         strcpy(ip, inet_ntoa(NBNSClntAddr.sin_addr));

    /*
      可能多个客户端在大约相同的时间发送NBNS报文
     */
        
         ulCurrTime = time(0);
         strcat(ips, ip);
         strcat(ips, ";");
          DEBUG_PIRNT("ipcache=%s\n", ipcache);
          DEBUG_PIRNT("ips=%s\n", ips);
         if(!strstr(ipcache, ips)) //new ip
         {            
            strcat(ipcache, ip);
            strcat(ipcache, ";");
            
            goto PRINT;
         }
         else
         {
             if ( (ulCurrTime - ulPreUpdateTime) > 10) // old ip but over ten secs
             {                
                goto PRINT;
             }
                
         }
         memset(ips, 0, sizeof(ips));
         continue;
         
         PRINT:
         memset(ips, 0, sizeof(ips));
         ulPreUpdateTime = ulCurrTime; 
         printf("we get nbns packet form %s obtained\n", ip);
     }
}

