Beispiel #1
0
int server(char *backing_file,int size,int foregroundMode)
{
  
  struct sockaddr_in bind_addr;
  
  /* Get backing store */
  if (!backing_file)
    {
      /* transitory storage of HLR data, so just malloc() the memory */
      hlr=calloc(size,1);
      if (!hlr) exit(setReason("Failed to calloc() HLR database."));
      if (debug) fprintf(stderr,"Allocated %d byte temporary HLR store\n",size);
    }
  else
    {
      unsigned char zero[8192];
      FILE *f=fopen(backing_file,"r+");
      if (!f) f=fopen(backing_file,"w+");
      if (!f) exit(setReason("Could not open backing file."));
      bzero(&zero[0],8192);
      fseek(f,0,SEEK_END);
      errno=0;
      while(ftell(f)<size)
	{
	  int r;
	  fseek(f,0,SEEK_END);
	  if ((r=fwrite(zero,8192,1,f))!=1)
	    {
	      perror("fwrite");
	      exit(setReason("Could not enlarge backing file to requested size (short write)"));
	    }
	  fseek(f,0,SEEK_END);
	}
      
      if (errno) perror("fseek");
      if (fwrite("",1,1,f)!=1)
	{
	  fprintf(stderr,"Failed to set backing file size.\n");
	  perror("fwrite");
	}
      hlr=(unsigned char *)mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_NORESERVE,fileno(f),0);
      if (hlr==MAP_FAILED) {
	perror("mmap");
	exit(setReason("Memory mapping of HLR backing file failed."));
      }
      if (debug) fprintf(stderr,"Allocated %d byte HLR store backed by file `%s'\n",
			 size,backing_file);
    }
  hlr_size=size;


  sock=socket(PF_INET,SOCK_DGRAM,0);
  if (sock<0) {
    fprintf(stderr,"Could not create UDP socket.\n");
    perror("socket");
    exit(-3);
  }

  bind_addr.sin_family = AF_INET;
  bind_addr.sin_port = htons( PORT_DNA );
  bind_addr.sin_addr.s_addr = htonl( INADDR_ANY );
  if(bind(sock,(struct sockaddr *)&bind_addr,sizeof(bind_addr))) {
    fprintf(stderr,"MP HLR server could not bind to UDP port %d\n", PORT_DNA);
    perror("bind");
    exit(-3);
  }

  /* Detach from the console */
  if (!foregroundMode) daemon(0,0);

  while(1) {
    unsigned char buffer[16384];
    socklen_t recvaddrlen=sizeof(recvaddr);
    struct pollfd fds;
    int len;

    bzero((void *)&recvaddr,sizeof(recvaddr));
    fds.fd=sock; fds.events=POLLIN;
    
    /* Wait patiently for packets to arrive */
    while (poll(&fds,1,1000)<1)	sleep(0);

    len=recvfrom(sock,buffer,sizeof(buffer),0,&recvaddr,&recvaddrlen);

    client_port=((struct sockaddr_in*)&recvaddr)->sin_port;
    client_addr=((struct sockaddr_in*)&recvaddr)->sin_addr;

    if (debug) fprintf(stderr,"Received packet from %s (len=%d).\n",inet_ntoa(client_addr),len);
    if (debug>1) dump("recvaddr",(unsigned char *)&recvaddr,recvaddrlen);
    if (debug>3) dump("packet",(unsigned char *)buffer,len);
    if (dropPacketP(len)) {
      if (debug) fprintf(stderr,"Simulation mode: Dropped packet due to simulated link parameters.\n");
      continue;
    }
    if (!packetOk(buffer,len,NULL)) process_packet(buffer,len,&recvaddr,recvaddrlen);
    else {
      if (debug) setReason("Ignoring invalid packet");
    }
    if (debug>1) fprintf(stderr,"Finished processing packet, waiting for next one.\n");
  }  
}
Beispiel #2
0
int getReplyPackets(int method,int peer,int batchP,
		    struct response_set *responses,
		    unsigned char *transaction_id,int timeout)
{
  /* set timeout alarm */
  
  /* get packets until timeout, or until we get a packet from the specified peer
     if method==REQ_SERIAL.  If REQ_SERIAL we also reject packets from other 
     senders as they must be spoofs.
  */
  struct timeval t;
  int timeout_secs;
  int timeout_usecs;
  int to=timeout;

  if (debug>1) printf("getReplyPackets(policy=%d)\n",method);

  /* Work out when the timeout will expire */
  gettimeofday(&t,NULL); 
  timeout_secs=t.tv_sec; timeout_usecs=t.tv_usec;
  if (to>1000) { timeout_secs+=(to/1000); to=to%1000; }
  timeout_usecs+=to*1000; if (timeout_usecs>1000000) { timeout_secs++; timeout_usecs-=1000000; }
  
  while(1) {
    unsigned char buffer[16384];
    socklen_t recvaddrlen=sizeof(recvaddr);
    struct pollfd fds;
    client_port=((struct sockaddr_in*)&recvaddr)->sin_port;
    bzero((void *)&recvaddr,sizeof(recvaddr));
    fds.fd=sock; fds.events=POLLIN;
    while (poll(&fds,1,10 /* wait for 10ms at a time */)<1)
      {
	gettimeofday(&t,NULL);
	if (t.tv_sec>timeout_secs) return 1;
	if (t.tv_sec==timeout_secs&&t.tv_usec>=timeout_usecs) return 1;
      }
    client_port=((struct sockaddr_in*)&recvaddr)->sin_port;
    int len=recvfrom(sock,buffer,sizeof(buffer),0,&recvaddr,&recvaddrlen);
    client_addr=((struct sockaddr_in*)&recvaddr)->sin_addr;
    if (debug) fprintf(stderr,"Received reply from %s (len=%d).\n",inet_ntoa(client_addr),len);
    if (debug>1) dump("recvaddr",(unsigned char *)&recvaddr,recvaddrlen);
    if (debug>2) dump("packet",(unsigned char *)buffer,len);
    if (dropPacketP(len)) {
      if (debug) fprintf(stderr,"Simulation mode: Dropped packet due to simulated link parameters.\n");
      continue;
    }
    if (!packetOk(buffer,len,transaction_id)) {
      /* Packet passes tests - extract responses and append them to the end of the response list */
      if (extractResponses(client_addr,buffer,len,responses)) 
	return setReason("Problem extracting response fields from reply packets");
      if (method==REQ_SERIAL||method==REQ_FIRSTREPLY) {
	if (!batchP) return 0;
	/* In batch mode we need ACTION_DONE to mark end of transmission. 
	   While it gets sent last, out-of-order delivery means we can't rely on
	   such a nice arrangement. */
	{
	  /* XXX inefficient for long lists.
	     XXX can be made better by working backwards from end using double-linked list and 
	     remembering the previous length of the list */
	  struct response *r=responses->responses;
	  while(r)
	    {
	      if (r->code==ACTION_DONE) return 0;
	      r=r->next;
	    }
	}
      }
      else {
	if (debug>1) printf("Waiting for more packets, since called with policy %d\n",method);
      }
    } else {
      if (debug) setReason("Ignoring invalid packet");
    }      
  }
}