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"); } }
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"); } } }