/* SAPMP server - C version. must run as root The 2020 C version of the server does not support error codes 5 and 6 due to lack of built-in data structures for C. */ #include #include #include #include #include #include #include #include #include #include #define SRVPORT 6392 // returns -1 on error, 0 on timeout int readable_timeo(int fd, int sec) { fd_set rset; struct timeval tv; FD_ZERO(&rset); FD_SET(fd,&rset); tv.tv_sec = sec; tv.tv_usec = 0; return (select(fd+1,&rset,NULL,NULL,&tv)); } // readable_timeo // function to convert 4-byte unsigned int to an ip address, writes to s // int should be in network byte order void ipaddr(unsigned int n, char* s) { unsigned char* m = (unsigned char*)&n; sprintf(s,"%d.%d.%d.%d",m[0],m[1],m[2],m[3]); } // argv[1] is external ip of NAT box this server is running on. int main(int argc, char **argv) { int sfd; // server (listening) socket int cfd; // communications socket with client struct sockaddr_in saddr; // info concerning server struct sockaddr_in caddr; // info concerning connecting clients struct in_addr NATADDR; // external addr of NAT box. struct in_addr INADDR; // internal addr struct of host. unsigned int iip; // internal ip of client unsigned short iport; // internal port unsigned short eport; // external port on NAT box unsigned char protocol; // 6=tcp, 17=udp char cmd[512]; // iptables command string int x, y, retval; // some values to play with socklen_t xlen; int ok = 1; // check for integrity unsigned char errs[4]; // up to 4 error codes for(x=0;x<4;x++) errs[x]=0; int erri = 0; // indexes errs array inet_aton(argv[1], &NATADDR); // translate NAT external IP // NATADDR.s_addr contains the unsigned integer. saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); // wildcard saddr.sin_port = htons(SRVPORT); // local port to bind to sfd = socket(AF_INET,SOCK_STREAM,0); // create server socket; bind(sfd,(struct sockaddr*)&saddr,sizeof(saddr)); // reserve server port listen(sfd,16); // set socket queue length while(1) // main server loop { for(x=0;x<4;x++) errs[x]=0; iport = eport = 0; protocol = 0; iip = 0; // wait for client connection: xlen = sizeof(caddr); // in-out parameter to accept: cfd = accept(sfd,(struct sockaddr*)&caddr,&xlen); if (cfd < 0) { perror("socket error\n"); exit(1); } ok = 1; // error check variable if (readable_timeo(cfd,3) <= 0) {ok = 0; errs[erri++%4]=1;} else { // read internal ip, port, eport, protocol: x = 4; y = 0; while (y