/**************************************************
OpengateM - MAC address authentication system 
 module to control udp client 

 As the address permission check is time consuming procedure, 
 checked addresses are cached in the memory of daemons.

 When the address registration is updated by the management program,
 it is is reported to daemons via UDP, where the management program 
 plays as UDP client and the daemon as UDP server.
 Addresses of UDP servers and trusted UDP clients are in conf file.
 When Daemons receive the UDP, clear the cache of the reported 
 address and recheck the address permission.
 If UDP is failed, the recheck is delayed to the cache timeout. 

Copyright (C) 2011 Opengate Project Team
Written by Yoshiaki Watanabe

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Email: watanaby@is.saga-u.ac.jp
**************************************************/

#include "opengatemmng.h"

/***********************************************************/
/* send mac address to plural daemons via UDP at db update */
/* UDP server(=daemon) addresses are defined in conf file  */
/***********************************************************/
int putMacAddressToServers(char* macAddress){
  char udpServerAddr[ADDRMAXLN];
  char udpServerPort[WORDMAXLN];
  char* udpServer;

  udpServer=GetFirstConfValue("UdpServer");
  if(isNull(udpServer)){
    err_msg("ERR at %s#%d: no udp server in conf",__FILE__,__LINE__);
    return FALSE;
  }
  while(!isNull(udpServer)){
    if(sscanf(udpServer, "%s %s", udpServerAddr, udpServerPort)!=2){
      err_msg("ERR at %s#%d: abnormal udp servers in conf",__FILE__,__LINE__);
      continue;
    }
    PutDataToUdpPort(udpServerAddr, udpServerPort, macAddress);
    udpServer=GetNextConfValue();
  }
  return TRUE;
}

/**************************************/
/* put data to udp port of a server   */
/**************************************/
int putDataToUdpPort(char* udpServerAddr, char* udpServerPort, char* buff){

  int sockfd;
  struct addrinfo hints, *servinfo, *p;
  int ret;
  int numbytes;
  
  /* if no buffer return error */
  if (buff==NULL||*buff=='\0') return FALSE;

  /* prepare address hints */ 
  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC; /* IPv4/IPv6 dual */
  hints.ai_socktype = SOCK_DGRAM; /* UDP */

  if ((ret = getaddrinfo(udpServerAddr, udpServerPort, &hints, &servinfo))!= 0) {
    err_msg("ERR at %s#%d: getaddrinfo: %s",__FILE__,__LINE__, 
	    gai_strerror(ret));
    return FALSE;
  }
  
  /* loop through addresses */
  for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype,
			 p->ai_protocol)) == -1) {
      err_msg("ERR at %s#%d: socket error: %s",__FILE__,__LINE__,
	      strerror(errno));
      continue;
    }
    break;
  }
  if (p == NULL) {
    err_msg("ERR at %s#%d: failed to bind socket",__FILE__,__LINE__);
    return FALSE;
  }
  
  /* send data to server */
  if ((numbytes = sendto(sockfd, buff, strlen(buff), 0,
			 p->ai_addr, p->ai_addrlen)) == -1) {
    err_msg("ERR at %s#%d: sendto error: %s",__FILE__,__LINE__,
	    strerror(errno));
    err_msg("ERR at %s#%d: Check firewall/daemon on [%s] to get udp[%d] packet"
	    "from here", 
	    __FILE__,__LINE__,udpServerAddr,udpServerPort);
    return FALSE;
  }
  
  /* finalize */
  freeaddrinfo(servinfo);
  close(sockfd);
  
  return TRUE;
}

/**********************************
**********************************/
int PutDataToUdpPort(char* udpServerAddr, char* udpServerPort,char* buff){
  int ret;
  if(debug>1) err_msg("DEBUG:=>putDataToUdpPort(%s)",udpServerAddr, udpServerPort,buff);
  ret = putDataToUdpPort(udpServerAddr, udpServerPort,buff);
  if(debug>1) err_msg("DEBUG:(%d)<=putDateToUdpPort( )",ret);
  return ret;
}


int PutMacAddressToServers(char* macAddress){
  int ret;
  if(debug>1) err_msg("DEBUG:=>putMacAddressToServers(%s)",macAddress);
  ret = putMacAddressToServers(macAddress);
  if(debug>1) err_msg("DEBUG:(%d)<=putMacAddressToServers( )",ret);
  return ret;
}


