]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/l_net/l_net_berkley.c
Wrap gtkutil/entry
[xonotic/netradiant.git] / libs / l_net / l_net_berkley.c
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 //===========================================================================
23 //
24 // Name:         l_net_wins.c
25 // Function:     WinSock
26 // Programmer:   MrElusive
27 // Last update:  TTimo: cross-platform version, l_net library
28 // Tab Size:     2
29 // Notes:
30 //===========================================================================
31
32 //#include <windows.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "l_net.h"
37 #include "l_net_wins.h"
38
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/ioctl.h>
42 #include <netinet/in.h>
43 #include <netinet/tcp.h>
44 #include <arpa/inet.h>
45 #include <errno.h>
46 #include <netdb.h>
47 #include <unistd.h>
48 #include <stdarg.h>
49 #include <stdio.h>
50 #define SOCKET_ERROR -1
51 #define INVALID_SOCKET -1
52
53 #define WinError WinPrint
54
55 #define qtrue   1
56 #define qfalse  0
57
58 #define ioctlsocket ioctl
59 #define closesocket close
60
61 int WSAGetLastError(){
62         return errno;
63 }
64
65 /*
66    typedef struct tag_error_struct
67    {
68     int     errnum;
69     LPSTR   errstr;
70    } ERROR_STRUCT;
71  */
72
73 typedef struct tag_error_struct
74 {
75         int errnum;
76         const char *errstr;
77 } ERROR_STRUCT;
78
79 #define NET_NAMELEN         64
80
81 static char my_tcpip_address[NET_NAMELEN];
82
83 #define DEFAULTnet_hostport 26000
84
85 #define MAXHOSTNAMELEN      256
86
87 static int net_acceptsocket = -1;       // socket for fielding new connections
88 static int net_controlsocket;
89 static int net_hostport;                // udp port number for acceptsocket
90 static int net_broadcastsocket = 0;
91 //static qboolean ifbcastinit = qfalse;
92 //static struct sockaddr_s broadcastaddr;
93 static struct sockaddr_s broadcastaddr;
94
95 static unsigned long myAddr;
96
97 ERROR_STRUCT errlist[] = {
98         {EACCES,"EACCES - The address is protected, user is not root"},
99         {EAGAIN,"EAGAIN - Operation on non-blocking socket that cannot return immediatly"},
100         {EBADF, "EBADF - sockfd is not a valid descriptor"},
101         {EFAULT, "EFAULT - The parameter is not in a writable part of the user address space"},
102         {EINVAL,"EINVAL - The socket is already bound to an address"},
103         {ENOBUFS,"ENOBUFS - not enough memory"},
104         {ENOMEM, "ENOMEM - not enough memory"},
105         {ENOTCONN, "ENOTCONN - not connected"},
106         {ENOTSOCK,"ENOTSOCK - Argument is file descriptor not a socket"},
107         {EOPNOTSUPP,"ENOTSUPP - The referenced socket is not of type SOCK_STREAM"},
108         {EPERM, "EPERM - Firewall rules forbid connection"},
109         {-1, NULL}
110 };
111
112 //===========================================================================
113 //
114 // Parameter:                           -
115 // Returns:                                     -
116 // Changes Globals:             -
117 //===========================================================================
118 const char *WINS_ErrorMessage( int error ){
119         int search = 0;
120
121         if ( !error ) {
122                 return "No error occurred";
123         }
124
125         for ( search = 0; errlist[search].errstr; search++ )
126         {
127                 if ( error == errlist[search].errnum ) {
128                         return errlist[search].errstr;
129                 }
130         }  //end for
131
132         return "Unknown error";
133 } //end of the function WINS_ErrorMessage
134 //===========================================================================
135 //
136 // Parameter:                           -
137 // Returns:                                     -
138 // Changes Globals:             -
139 //===========================================================================
140 int WINS_Init( void ){
141         int i;
142         struct hostent *local;
143         char buff[MAXHOSTNAMELEN];
144         struct sockaddr_s addr;
145         char    *p;
146 /*
147    linux doesn't have anything to initialize for the net
148    "Windows .. built for the internet .. the internet .. built with unix"
149  */
150 #if 0
151         WORD wVersionRequested;
152
153         wVersionRequested = MAKEWORD( 2, 2 );
154
155         r = WSAStartup( wVersionRequested, &winsockdata );
156
157         if ( r ) {
158                 WinPrint( "Winsock initialization failed.\n" );
159                 return -1;
160         }
161 #endif
162         /*
163            i = COM_CheckParm ("-udpport");
164            if (i == 0)*/
165         net_hostport = DEFAULTnet_hostport;
166         /*
167            else if (i < com_argc-1)
168             net_hostport = Q_atoi (com_argv[i+1]);
169            else
170             Sys_Error ("WINS_Init: you must specify a number after -udpport");
171          */
172
173         // determine my name & address
174         gethostname( buff, MAXHOSTNAMELEN );
175         local = gethostbyname( buff );
176         if(local && local->h_addr_list && local->h_addr_list[0])
177                 myAddr = *(int *)local->h_addr_list[0];
178         else
179                 myAddr = inet_addr("127.0.0.1");
180
181         // if the quake hostname isn't set, set it to the machine name
182 //      if (Q_strcmp(hostname.string, "UNNAMED") == 0)
183         {
184                 // see if it's a text IP address (well, close enough)
185                 for ( p = buff; *p; p++ )
186                         if ( ( *p < '0' || *p > '9' ) && *p != '.' ) {
187                                 break;
188                         }
189
190                 // if it is a real name, strip off the domain; we only want the host
191                 if ( *p ) {
192                         for ( i = 0; i < 15; i++ )
193                                 if ( buff[i] == '.' ) {
194                                         break;
195                                 }
196                         buff[i] = 0;
197                 }
198 //              Cvar_Set ("hostname", buff);
199         }
200
201         //++timo WTF is that net_controlsocket? it's sole purpose is to retrieve the local IP?
202         if ( ( net_controlsocket = WINS_OpenSocket( 0 ) ) == SOCKET_ERROR ) {
203                 WinError( "WINS_Init: Unable to open control socket\n" );
204         }
205
206         ( (struct sockaddr_in *)&broadcastaddr )->sin_family = AF_INET;
207         ( (struct sockaddr_in *)&broadcastaddr )->sin_addr.s_addr = INADDR_BROADCAST;
208         ( (struct sockaddr_in *)&broadcastaddr )->sin_port = htons( (u_short)net_hostport );
209
210         WINS_GetSocketAddr( net_controlsocket, &addr );
211         strcpy( my_tcpip_address,  WINS_AddrToString( &addr ) );
212         p = strrchr( my_tcpip_address, ':' );
213         if ( p ) {
214                 *p = 0;
215         }
216         WinPrint( "Winsock Initialized\n" );
217
218         return net_controlsocket;
219 } //end of the function WINS_Init
220 //===========================================================================
221 //
222 // Parameter:                           -
223 // Returns:                                     -
224 // Changes Globals:             -
225 //===========================================================================
226 char *WINS_MyAddress( void ){
227         return my_tcpip_address;
228 } //end of the function WINS_MyAddress
229 //===========================================================================
230 //
231 // Parameter:                           -
232 // Returns:                                     -
233 // Changes Globals:             -
234 //===========================================================================
235 void WINS_Shutdown( void ){
236         //WINS_Listen(0);
237         WINS_CloseSocket( net_controlsocket );
238 //      WSACleanup();
239         //
240         //WinPrint("Winsock Shutdown\n");
241 } //end of the function WINS_Shutdown
242 //===========================================================================
243 //
244 // Parameter:                           -
245 // Returns:                                     -
246 // Changes Globals:             -
247 //===========================================================================
248 /*
249    void WINS_Listen(int state)
250    {
251     // enable listening
252     if (state)
253     {
254         if (net_acceptsocket != -1)
255             return;
256         if ((net_acceptsocket = WINS_OpenSocket (net_hostport)) == -1)
257             WinError ("WINS_Listen: Unable to open accept socket\n");
258         return;
259     }
260
261     // disable listening
262     if (net_acceptsocket == -1)
263         return;
264     WINS_CloseSocket (net_acceptsocket);
265     net_acceptsocket = -1;
266    } //end of the function WINS_Listen*/
267 //===========================================================================
268 //
269 // Parameter:                           -
270 // Returns:                                     -
271 // Changes Globals:             -
272 //===========================================================================
273 int WINS_OpenSocket( int port ){
274         int newsocket;
275         struct sockaddr_in address;
276         u_long _true = 1;
277
278         if ( ( newsocket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == SOCKET_ERROR ) {
279                 WinPrint( "WINS_OpenSocket: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
280                 return -1;
281         } //end if
282
283         if ( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
284                 WinPrint( "WINS_OpenSocket: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
285                 closesocket( newsocket );
286                 return -1;
287         } //end if
288
289         memset( (char *) &address, 0, sizeof( address ) );
290         address.sin_family = AF_INET;
291         address.sin_addr.s_addr = INADDR_ANY;
292         address.sin_port = htons( (u_short)port );
293         if ( bind( newsocket, (void *)&address, sizeof( address ) ) == -1 ) {
294                 WinPrint( "WINS_OpenSocket: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
295                 closesocket( newsocket );
296                 return -1;
297         } //end if
298
299         return newsocket;
300 } //end of the function WINS_OpenSocket
301 //===========================================================================
302 //
303 // Parameter:                           -
304 // Returns:                                     -
305 // Changes Globals:             -
306 //===========================================================================
307 int WINS_OpenReliableSocket( int port ){
308         int newsocket;
309         struct sockaddr_in address;
310         qboolean _true = 0xFFFFFFFF;
311
312         //IPPROTO_TCP
313         //
314         if ( ( newsocket = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) {
315                 WinPrint( "WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
316                 return -1;
317         } //end if
318
319         memset( (char *) &address, 0, sizeof( address ) );
320         address.sin_family = AF_INET;
321         address.sin_addr.s_addr = htonl( INADDR_ANY );
322         address.sin_port = htons( (u_short)port );
323         if ( bind( newsocket, (void *)&address, sizeof( address ) ) == -1 ) {
324                 WinPrint( "WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
325                 closesocket( newsocket );
326                 return -1;
327         } //end if
328
329         //
330         if ( setsockopt( newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof( int ) ) == -1 ) {
331                 WinPrint( "WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
332                 WinPrint( "setsockopt error\n" );
333         } //end if
334
335         return newsocket;
336 } //end of the function WINS_OpenReliableSocket
337 //===========================================================================
338 //
339 // Parameter:                           -
340 // Returns:                                     -
341 // Changes Globals:             -
342 //===========================================================================
343 int WINS_Listen( int socket ){
344         u_long _true = 1;
345
346         if ( ioctlsocket( socket, FIONBIO, &_true ) == -1 ) {
347                 WinPrint( "WINS_Listen: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
348                 return -1;
349         } //end if
350         if ( listen( socket, SOMAXCONN ) == SOCKET_ERROR ) {
351                 WinPrint( "WINS_Listen: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
352                 return -1;
353         } //end if
354         return 0;
355 } //end of the function WINS_Listen
356 //===========================================================================
357 //
358 // Parameter:                           -
359 // Returns:                                     -
360 // Changes Globals:             -
361 //===========================================================================
362 int WINS_Accept( int socket, struct sockaddr_s *addr ){
363         socklen_t addrlen = sizeof( struct sockaddr_s );
364         int newsocket;
365         qboolean _true = 1;
366
367         newsocket = accept( socket, (struct sockaddr *)addr, &addrlen );
368         if ( newsocket == INVALID_SOCKET ) {
369                 if ( errno == EAGAIN ) {
370                         return -1;
371                 }
372                 WinPrint( "WINS_Accept: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
373                 return -1;
374         } //end if
375           //
376         if ( setsockopt( newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof( int ) ) == SOCKET_ERROR ) {
377                 WinPrint( "WINS_Accept: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
378                 WinPrint( "setsockopt error\n" );
379         } //end if
380         return newsocket;
381 } //end of the function WINS_Accept
382 //===========================================================================
383 //
384 // Parameter:                           -
385 // Returns:                                     -
386 // Changes Globals:             -
387 //===========================================================================
388 int WINS_CloseSocket( int socket ){
389         /*
390            if (socket == net_broadcastsocket)
391             net_broadcastsocket = 0;
392          */
393 //      shutdown(socket, SD_SEND);
394
395         if ( closesocket( socket ) == SOCKET_ERROR ) {
396                 WinPrint( "WINS_CloseSocket: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
397                 return SOCKET_ERROR;
398         } //end if
399         return 0;
400 } //end of the function WINS_CloseSocket
401 //===========================================================================
402 // this lets you type only as much of the net address as required, using
403 // the local network components to fill in the rest
404 //
405 // Parameter:                           -
406 // Returns:                                     -
407 // Changes Globals:             -
408 //===========================================================================
409 static int PartialIPAddress( char *in, struct sockaddr_s *hostaddr ){
410         char buff[256];
411         char *b;
412         int addr;
413         int num;
414         int mask;
415
416         buff[0] = '.';
417         b = buff;
418         strcpy( buff + 1, in );
419         if ( buff[1] == '.' ) {
420                 b++;
421         }
422
423         addr = 0;
424         mask = -1;
425         while ( *b == '.' )
426         {
427                 num = 0;
428                 if ( *++b < '0' || *b > '9' ) {
429                         return -1;
430                 }
431                 while ( !( *b < '0' || *b > '9' ) )
432                         num = num * 10 + *( b++ ) - '0';
433                 mask <<= 8;
434                 addr = ( addr << 8 ) + num;
435         }
436
437         hostaddr->sa_family = AF_INET;
438         ( (struct sockaddr_in *)hostaddr )->sin_port = htons( (u_short)net_hostport );
439         ( (struct sockaddr_in *)hostaddr )->sin_addr.s_addr = ( myAddr & htonl( mask ) ) | htonl( addr );
440
441         return 0;
442 } //end of the function PartialIPAddress
443 //===========================================================================
444 //
445 // Parameter:                           -
446 // Returns:                                     -
447 // Changes Globals:             -
448 //===========================================================================
449 int WINS_Connect( int socket, struct sockaddr_s *addr ){
450         int ret;
451         u_long _true2 = 0xFFFFFFFF;
452
453         ret = connect( socket, (struct sockaddr *)addr, sizeof( struct sockaddr_s ) );
454         if ( ret == SOCKET_ERROR ) {
455                 WinPrint( "WINS_Connect: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
456                 return -1;
457         } //end if
458         if ( ioctlsocket( socket, FIONBIO, &_true2 ) == -1 ) {
459                 WinPrint( "WINS_Connect: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
460                 return -1;
461         } //end if
462         return 0;
463 } //end of the function WINS_Connect
464 //===========================================================================
465 //
466 // Parameter:                           -
467 // Returns:                                     -
468 // Changes Globals:             -
469 //===========================================================================
470 int WINS_CheckNewConnections( void ){
471         char buf[4];
472
473         if ( net_acceptsocket == -1 ) {
474                 return -1;
475         }
476
477         if ( recvfrom( net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL ) > 0 ) {
478                 return net_acceptsocket;
479         }
480         return -1;
481 } //end of the function WINS_CheckNewConnections
482 //===========================================================================
483 // returns the number of bytes read
484 // 0 if no bytes available
485 // -1 on failure
486 //
487 // Parameter:                           -
488 // Returns:                                     -
489 // Changes Globals:             -
490 //===========================================================================
491 int WINS_Read( int socket, byte *buf, int len, struct sockaddr_s *addr ){
492         socklen_t addrlen = sizeof( struct sockaddr_s );
493         int ret;
494
495         if ( addr ) {
496                 ret = recvfrom( socket, buf, len, 0, (struct sockaddr *)addr, &addrlen );
497                 if ( ret == -1 ) {
498 //                      errno = WSAGetLastError();
499
500                         if ( errno == EAGAIN || errno == ENOTCONN ) {
501                                 return 0;
502                         }
503                 } //end if
504         } //end if
505         else
506         {
507                 ret = recv( socket, buf, len, 0 );
508                 // if there's no data on the socket ret == -1 and errno == EAGAIN
509                 // MSDN states that if ret == 0 the socket has been closed
510                 // man recv doesn't say anything
511                 if ( ret == 0 ) {
512                         return -1;
513                 }
514                 if ( ret == SOCKET_ERROR ) {
515 //                      errno = WSAGetLastError();
516
517                         if ( errno == EAGAIN || errno == ENOTCONN ) {
518                                 return 0;
519                         }
520                 } //end if
521         } //end else
522         if ( ret == SOCKET_ERROR ) {
523                 WinPrint( "WINS_Read: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
524         } //end if
525         return ret;
526 } //end of the function WINS_Read
527 //===========================================================================
528 //
529 // Parameter:                           -
530 // Returns:                                     -
531 // Changes Globals:             -
532 //===========================================================================
533 int WINS_MakeSocketBroadcastCapable( int socket ){
534         int i = 1;
535
536         // make this socket broadcast capable
537         if ( setsockopt( socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof( i ) ) < 0 ) {
538                 return -1;
539         }
540         net_broadcastsocket = socket;
541
542         return 0;
543 } //end of the function WINS_MakeSocketBroadcastCapable
544 //===========================================================================
545 //
546 // Parameter:                           -
547 // Returns:                                     -
548 // Changes Globals:             -
549 //===========================================================================
550 int WINS_Broadcast( int socket, byte *buf, int len ){
551         int ret;
552
553         if ( socket != net_broadcastsocket ) {
554                 if ( net_broadcastsocket != 0 ) {
555                         WinError( "Attempted to use multiple broadcasts sockets\n" );
556                 }
557                 ret = WINS_MakeSocketBroadcastCapable( socket );
558                 if ( ret == -1 ) {
559                         WinPrint( "Unable to make socket broadcast capable\n" );
560                         return ret;
561                 }
562         }
563
564         return WINS_Write( socket, buf, len, &broadcastaddr );
565 } //end of the function WINS_Broadcast
566 //===========================================================================
567 // returns qtrue on success or qfalse on failure
568 //
569 // Parameter:                           -
570 // Returns:                                     -
571 // Changes Globals:             -
572 //===========================================================================
573 int WINS_Write( int socket, byte *buf, int len, struct sockaddr_s *addr ){
574         int ret, written;
575         ret = 0;
576
577         if ( addr ) {
578                 written = 0;
579                 while ( written < len )
580                 {
581                         ret = sendto( socket, &buf[written], len - written, 0, (struct sockaddr *)addr, sizeof( struct sockaddr_s ) );
582                         if ( ret == SOCKET_ERROR ) {
583                                 if ( WSAGetLastError() != EAGAIN ) {
584                                         return qfalse;
585                                 }
586                                 //++timo FIXME: what is this used for?
587 //                              Sleep(1000);
588                         } //end if
589                         else
590                         {
591                                 written += ret;
592                         }
593                 }
594         } //end if
595         else
596         {
597                 written = 0;
598                 while ( written < len )
599                 {
600                         ret = send( socket, buf, len, 0 );
601                         if ( ret == SOCKET_ERROR ) {
602                                 if ( WSAGetLastError() != EAGAIN ) {
603                                         return qfalse;
604                                 }
605                                 //++timo FIXME: what is this used for?
606 //                              Sleep(1000);
607                         } //end if
608                         else
609                         {
610                                 written += ret;
611                         }
612                 }
613         } //end else
614         if ( ret == SOCKET_ERROR ) {
615                 WinPrint( "WINS_Write: %s\n", WINS_ErrorMessage( WSAGetLastError() ) );
616         } //end if
617         return ( ret == len );
618 } //end of the function WINS_Write
619 //===========================================================================
620 //
621 // Parameter:                           -
622 // Returns:                                     -
623 // Changes Globals:             -
624 //===========================================================================
625 char *WINS_AddrToString( struct sockaddr_s *addr ){
626         static char buffer[22];
627         int haddr;
628
629         haddr = ntohl( ( (struct sockaddr_in *)addr )->sin_addr.s_addr );
630         sprintf( buffer, "%d.%d.%d.%d:%d", ( haddr >> 24 ) & 0xff, ( haddr >> 16 ) & 0xff, ( haddr >> 8 ) & 0xff, haddr & 0xff, ntohs( ( (struct sockaddr_in *)addr )->sin_port ) );
631         return buffer;
632 } //end of the function WINS_AddrToString
633 //===========================================================================
634 //
635 // Parameter:                           -
636 // Returns:                                     -
637 // Changes Globals:             -
638 //===========================================================================
639 int WINS_StringToAddr( char *string, struct sockaddr_s *addr ){
640         int ha1, ha2, ha3, ha4, hp;
641         int ipaddr;
642
643         sscanf( string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp );
644         ipaddr = ( ha1 << 24 ) | ( ha2 << 16 ) | ( ha3 << 8 ) | ha4;
645
646         addr->sa_family = AF_INET;
647         ( (struct sockaddr_in *)addr )->sin_addr.s_addr = htonl( ipaddr );
648         ( (struct sockaddr_in *)addr )->sin_port = htons( (u_short)hp );
649         return 0;
650 } //end of the function WINS_StringToAddr
651 //===========================================================================
652 //
653 // Parameter:                           -
654 // Returns:                                     -
655 // Changes Globals:             -
656 //===========================================================================
657 int WINS_GetSocketAddr( int socket, struct sockaddr_s *addr ){
658         socklen_t addrlen = sizeof( struct sockaddr_s );
659         unsigned int a;
660
661         memset( addr, 0, sizeof( struct sockaddr_s ) );
662         getsockname( socket, (struct sockaddr *)addr, &addrlen );
663         a = ( (struct sockaddr_in *)addr )->sin_addr.s_addr;
664         if ( a == 0 || a == inet_addr( "127.0.0.1" ) ) {
665                 ( (struct sockaddr_in *)addr )->sin_addr.s_addr = myAddr;
666         }
667
668         return 0;
669 } //end of the function WINS_GetSocketAddr
670 //===========================================================================
671 //
672 // Parameter:                           -
673 // Returns:                                     -
674 // Changes Globals:             -
675 //===========================================================================
676 int WINS_GetNameFromAddr( struct sockaddr_s *addr, char *name ){
677         struct hostent *hostentry;
678
679         hostentry = gethostbyaddr( (char *)&( (struct sockaddr_in *)addr )->sin_addr, sizeof( struct in_addr ), AF_INET );
680         if ( hostentry ) {
681                 strncpy( name, (char *)hostentry->h_name, NET_NAMELEN - 1 );
682                 return 0;
683         }
684
685         strcpy( name, WINS_AddrToString( addr ) );
686         return 0;
687 } //end of the function WINS_GetNameFromAddr
688 //===========================================================================
689 //
690 // Parameter:                           -
691 // Returns:                                     -
692 // Changes Globals:             -
693 //===========================================================================
694 int WINS_GetAddrFromName( char *name, struct sockaddr_s *addr ){
695         struct hostent *hostentry;
696
697         if ( name[0] >= '0' && name[0] <= '9' ) {
698                 return PartialIPAddress( name, addr );
699         }
700
701         hostentry = gethostbyname( name );
702         if ( !hostentry ) {
703                 return -1;
704         }
705
706         addr->sa_family = AF_INET;
707         ( (struct sockaddr_in *)addr )->sin_port = htons( (u_short)net_hostport );
708         ( (struct sockaddr_in *)addr )->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
709
710         return 0;
711 } //end of the function WINS_GetAddrFromName
712 //===========================================================================
713 //
714 // Parameter:                           -
715 // Returns:                                     -
716 // Changes Globals:             -
717 //===========================================================================
718 int WINS_AddrCompare( struct sockaddr_s *addr1, struct sockaddr_s *addr2 ){
719         if ( addr1->sa_family != addr2->sa_family ) {
720                 return -1;
721         }
722
723         if ( ( (struct sockaddr_in *)addr1 )->sin_addr.s_addr != ( (struct sockaddr_in *)addr2 )->sin_addr.s_addr ) {
724                 return -1;
725         }
726
727         if ( ( (struct sockaddr_in *)addr1 )->sin_port != ( (struct sockaddr_in *)addr2 )->sin_port ) {
728                 return 1;
729         }
730
731         return 0;
732 } //end of the function WINS_AddrCompare
733 //===========================================================================
734 //
735 // Parameter:                           -
736 // Returns:                                     -
737 // Changes Globals:             -
738 //===========================================================================
739 int WINS_GetSocketPort( struct sockaddr_s *addr ){
740         return ntohs( ( (struct sockaddr_in *)addr )->sin_port );
741 } //end of the function WINS_GetSocketPort
742 //===========================================================================
743 //
744 // Parameter:                           -
745 // Returns:                                     -
746 // Changes Globals:             -
747 //===========================================================================
748 int WINS_SetSocketPort( struct sockaddr_s *addr, int port ){
749         ( (struct sockaddr_in *)addr )->sin_port = htons( (u_short)port );
750         return 0;
751 } //end of the function WINS_SetSocketPort