/*---------------------------------------------------------- | File : netlib.c | Author : Simon Amor | WWW : http://www.foobar.net/~simon/ | Version : 0.5 | | Description | ~~~~~~~~~~~ | A library which allows users to write network applications | without too much effort. Suggestions for new functions are | always welcome. | *-----------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include /* for sysconf */ #include /* malloc() and free() */ #include /* strcasecmp() */ #include #include /***************************************************************************** * a pointer to a static version id ***/ char *NetVersion = "netlib v0.5 by Simon Amor"; /***************************************************************************** * Closes a socket - 'close(fd)' can also be used if preferred * Returns -1 if error or 0 if successful (just a #define) ***/ #define NetClose(x) close(x) /***************************************************************************** * Returns an address for output - tries to convert to name if possible. * #include ***/ char *NetAddrOut(struct in_addr address) { extern char *inet_ntoa(); struct hostent *he; if ((he=gethostbyaddr((char *)&address.s_addr,sizeof(address.s_addr),AF_INET))!=NULL) return he->h_name; else return (inet_ntoa(address)); } /***************************************************************************** * Accept a new connection from the master socket * returns info about connection in addr & int is * the fd of the new connection ***/ int NetOpenConnection(int mastersocket,struct sockaddr_in *addr) { extern char *inet_ntoa(); int newsock; int addr_len; addr_len=sizeof(struct sockaddr); newsock=accept(mastersocket,(void *)addr,&addr_len); if ((newsock==-1) && (errno==EWOULDBLOCK)) return -1; return newsock; } /***************************************************************************** * Set up master socket and set non blocking * Returns negative number if error, else fd * The port must be >1024 (and usually =<9999) ***/ int NetCreateMasterSocket(int port) { int opensock; int opt=1; struct sockaddr_in server; server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY ; server.sin_port = htons(port); if ((opensock=socket(AF_INET,SOCK_STREAM,0))<0) return -1; if (setsockopt(opensock,SOL_SOCKET,SO_REUSEADDR,(char *) &opt,sizeof(opt))<0) return -2; if (bind(opensock,(struct sockaddr *)&server,sizeof(server))) return -3; if (listen(opensock, 5)<0) return -4; return opensock; } /***************************************************************************** * Set a socket non-blocking * returns -1 on failure, 0 on success ***/ int NetNonBlocking(int socket) { if (fcntl(socket,F_SETFL,O_NDELAY)==-1) return (-1); return (0); } /***************************************************************************** * Send a string to a socket * if failed, returns -1 else returns the number of bytes sent ***/ int NetPutString(int socket, char *format, ...) { va_list ap; char *string = (char *)malloc(4096); int retval; if (string == NULL) return -1; va_start(ap, format); if (!format || !*format) return -1; vsnprintf(string, 4096, format, ap); va_end(ap); retval = send(socket,string,strlen(string),0); free(string); return retval; } /***************************************************************************** * Receive stuff from the socket * if failed, returns -1, else returns bytes received ***/ int NetGetString(int socket,char *buffer,int buffer_size) { int count; if ((count=recv(socket,buffer,buffer_size,0))==-1) { if (errno==EWOULDBLOCK) { buffer[0]='\0'; return 0; } else return -1; } buffer[count]='\0'; return count; } /***************************************************************************** * Receive a single line of data from the socket (up to a '\n' - not '\r') * if failed, returns -1, else returns bytes received ***/ int NetGetLine(int socket,char *buffer,int buffer_size) { int count=0; do { if (recv(socket,&buffer[count],1,0) == -1) { if (errno==EWOULDBLOCK) { buffer[0]='\0'; return 0; } else return -1; } count++; } while (buffer[count-1] != '\n'); buffer[count]='\0'; return count; } /***************************************************************************** * Connects to on port * returns file descriptor attached to the specified port * -1 = no socket, -2 = no host, -3 = no connect ***/ int NetConnectTo(char *host,int port) { struct hostent *he; struct sockaddr_in server; int connect_fd; if ((connect_fd=socket(AF_INET,SOCK_STREAM,0))<0) return (-1); if ((he=gethostbyname(host))==NULL) { close(connect_fd); return (-2); } memcpy(&server.sin_addr,he->h_addr,he->h_length); server.sin_family=AF_INET; server.sin_port=htons(port); if (connect(connect_fd,(struct sockaddr *)&server,sizeof(server))<0) { close(connect_fd); return (-3); } return connect_fd; } /***************************************************************************** * Returns the maximum connections allowed by the hardware ***/ int NetMaxConnections(void) { return (sysconf(_SC_OPEN_MAX)); } /***************************************************************************** * NetGetLogin : returns UID of connection * * If returns a NULL for UID, connection failed, check return value. * Else, UID points to a static buffer containing UID * Return values: * 0 = ok * -1 = socket failure * -2 = unknown host * -3 = information unobtainable - possibly no ident server * -4 = invalid ports specified * -5 = malloc failed * -6 = invalid reply from server ***/ int NetGetLogin(char *RemoteHost, int LocalPort, int RemotePort, char **uid) { int query_fd, params; static char uidBuffer[64]; char *buffer; char reply_type[81], opsys_or_error[81]; char identifier[1024]; *uid = uidBuffer; for (params = 0; params < 64; params++) uidBuffer[params] = '\0'; if ((query_fd = NetConnectTo(RemoteHost, 113))<0) return(query_fd); printf("Hostname: %s\n", RemoteHost); if ((buffer=(char *)malloc(1024)) == NULL) return (-5); sprintf(buffer,"%d, %d\n", LocalPort, RemotePort); if (NetPutString(query_fd, buffer) < 0) { free(buffer); return (-1); } if (NetGetString(query_fd, buffer, 1020) < 0) { free(buffer); return (-1); } NetClose(query_fd); params = sscanf(buffer, " %d , %d : %[^ \t\n\r:] : %[^\t\n\r:] : %[^\n\r]", &LocalPort, &RemotePort, reply_type, opsys_or_error, identifier); printf("Buffer: %s\n", buffer); free(buffer); if (params < 3) return (-3); if ((strcasecmp(reply_type, "ERROR") == 0) && ((strcasecmp(opsys_or_error, "INVALID-PORT") == 0) || (strcasecmp(opsys_or_error, "NO-USER") == 0))) return (-4); if (strcasecmp(reply_type, "USERID") != 0) return (-6); identifier[63]='\0'; strcpy(uidBuffer, identifier); return(0); }