Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
/*
2
Copyright (C) 1996-1997 Id Software, Inc.
3
 
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
 
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
 
13
See the GNU General Public License for more details.
14
 
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
 
19
*/
20
// net_bw.c
21
 
22
#include 
23
#include 
24
#include 
25
 
26
#include "quakedef.h"
27
#include "dosisms.h"
28
 
29
 
30
// this section is general Unix stuff that we need
31
 
32
#define	EIO		 		5	/* I/O error */
33
#define EBADS			9
34
#define EWOULDBLOCK		35	/* function would block */
35
#define EMSGSIZE		40	/* message to big for buffers */
36
#define	EPROTONOSUPPORT	43	/* Protocol not supported */
37
#define	ESOCKTNOSUPPORT	44	/* Socket type not supported */
38
#define	EPFNOSUPPORT	46	/* Protocol family not supported */
39
#define EAFNOSUPPORT	47	/* Address family not supported */
40
#define ECONNABORTED	53	/* User requested hangup */
41
#define ENOBUFS 		55	/* No buffers available */
42
#define EISCONN 		56	/* Socket has closed */
43
#define ENOTCONN		57	/* Socket is not connected */
44
#define ESHUTDOWN		58	/* Socket is closed */
45
#define ETOOMANYREFS	59	/* Too many sockets open */
46
#define ETIMEDOUT		60	/* Connection timed out */
47
#define ECONNREFUSED	61	/* Connection refused */
48
 
49
#define AF_INET 		2	/* internet */
50
 
51
#define PF_INET			AF_INET
52
 
53
#define SOCK_STREAM		1		/* stream */
54
#define SOCK_DGRAM		2		/* datagram */
55
 
56
#define IPPROTO_TCP		6
57
#define IPPROTO_UDP		17
58
 
59
#define INADDR_ANY		0
60
 
61
#define SIOCDONE		0x7300
62
#define FIONREAD		0x667f
63
#define FIONBIO 		0x667e
64
#define FIONWIN 		0x1000
65
#define FIONTIN 		0x2000
66
 
67
#define BRDINIT 		0
68
#define BRDADDR 		10
69
 
70
#define MAXHOSTNAMELEN	256
71
 
72
#define SOL_SOCKET		0xffff		/* options for socket level */
73
 
74
/*
75
 * Option flags per-socket.
76
 */
77
#define SO_DEBUG		0x0001		/* turn on debugging info recording */
78
#define SO_ACCEPTCONN	0x0002		/* socket has had listen() */
79
#define SO_REUSEADDR	0x0004		/* allow local address reuse */
80
#define SO_KEEPALIVE	0x0008		/* keep connections alive */
81
#define SO_DONTROUTE	0x0010		/* just use interface addresses */
82
#define SO_BROADCAST	0x0020		/* permit sending of broadcast msgs */
83
#define SO_USELOOPBACK	0x0040		/* bypass hardware when possible */
84
#define SO_LINGER		0x0080		/* linger on close if data present */
85
#define SO_OOBINLINE	0x0100		/* leave received OOB data in line */
86
#define SO_USEPRIV		0x4000		/* allocate from privileged port area */
87
#define SO_CANTSIG		0x8000		/* prevent SIGPIPE on SS_CANTSENDMORE */
88
 
89
/*
90
 * Additional options, not kept in so_options.
91
 */
92
#define SO_SNDBUF		0x1001		/* send buffer size */
93
#define SO_RCVBUF		0x1002		/* receive buffer size */
94
#define SO_SNDLOWAT		0x1003		/* send low-water mark */
95
#define SO_RCVLOWAT		0x1004		/* receive low-water mark */
96
#define SO_SNDTIMEO		0x1005		/* send timeout */
97
#define SO_RCVTIMEO		0x1006		/* receive timeout */
98
#define SO_ERROR		0x1007		/* get error status and clear */
99
#define SO_TYPE			0x1008		/* get socket type */
100
 
101
 
102
struct in_addr
103
{
104
	union
105
	{
106
		struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
107
		struct { unsigned short s_w1,s_w2; } S_un_w;
108
		unsigned long S_addr;
109
	} S_un;
110
};
111
#define	s_addr	S_un.S_addr	/* can be used for most tcp & ip code */
112
#define	s_host	S_un.S_un_b.s_b2	/* host on imp */
113
#define	s_net	S_un.S_un_b.s_b1	/* network */
114
#define	s_imp	S_un.S_un_w.s_w2	/* imp */
115
#define	s_impno	S_un.S_un_b.s_b4	/* imp # */
116
#define	s_lh	S_un.S_un_b.s_b3	/* logical host */
117
 
118
struct sockaddr_in
119
{
120
    short			sin_family;
121
    unsigned short	sin_port;
122
	struct in_addr	sin_addr;
123
    char			sin_zero[8];
124
};
125
 
126
struct	hostent {
127
	char	*h_name;	/* official name of host */
128
	char	**h_aliases;	/* alias list */
129
	int	h_addrtype;	/* host address type */
130
	int	h_length;	/* length of address */
131
	char	**h_addr_list;	/* list of addresses from name server */
132
#define	h_addr	h_addr_list[0]	/* address, for backward compatiblity */
133
};
134
 
135
char *inet_ntoa(struct in_addr in);
136
 
137
 
138
// this section is B&W specific constants & structures
139
 
140
#define BW_IOCTL_BIND			0
141
#define BW_IOCTL_CLEAROPTIONS	5
142
#define BW_IOCTL_SETOPTIONS		6
143
#define BW_IOCTL_PEEK			7
144
#define BW_IOCTL_SETWINMASK		8
145
 
146
#define BW_OPTION_BLOCKING		0x01
147
#define BW_OPTION_REUSEBUFFERS	0x80
148
 
149
#define BW_ERR_USR_HANGUP		50
150
#define BW_ERR_HANGUP			51
151
#define BW_ERR_NET_ERR			52
152
#define BW_ERR_IS_CLOSED		53
153
#define BW_ERR_TIME_OUT			54
154
#define BW_ERR_RESET			55
155
#define BW_ERR_FULL				56
156
#define BW_ERR_BLOCK			57
157
#define BW_ERR_SHUTDOWN			58
158
 
159
#pragma pack(1)
160
 
161
typedef struct
162
{
163
	char			state;			// always 1
164
	short			localPort;
165
	struct in_addr	localAddr;
166
	char			reason;			// always 0
167
	char			options;
168
	short			dataAvailable;
169
} BW_UDPinfo_t;
170
 
171
typedef struct
172
{
173
	char			reserved1 [6];
174
	unsigned short	info2Offset;
175
	char			reserved2 [18];
176
	struct in_addr	remoteAddr;
177
} BW_UDPreadInfo1_t;
178
 
179
typedef struct
180
{
181
	short			remotePort;
182
	char			reserved1 [2];
183
	unsigned short	dataLenPlus8;
184
	char			reserved2 [2];
185
	char			data[1];			// actual size is  - 8
186
} BW_UDPreadInfo2_t;
187
 
188
typedef struct
189
{
190
	char			reserved1 [2];
191
	short			remotePort;
192
	unsigned short	dataLen;
193
	struct in_addr	remoteAddr;
194
	char			reserved2 [42];
195
	char			data[1];			// actual size is 
196
} BW_writeInfo_t;
197
 
198
typedef struct
199
{
200
	short	ioport;
201
	byte	dma;
202
	byte	vector;
203
	byte	irq;
204
	short	bufferSize;
205
	short	maxWindow;
206
	short	timeZone;
207
	byte	myType;
208
	int		inetAddr;
209
	short	value;
210
	byte	subnetMask;
211
	short	etherPointer;
212
	short	logserverPointer;
213
	short	nameserverPointer;
214
	short	printserverPointer;
215
	short	timeserverPointer;
216
	short	gatewayPointer;
217
	short	driverSegment;
218
	byte	transferSize;
219
	char	cardName [9];
220
} BW_ethdevinfo_t;
221
 
222
#pragma pack()
223
 
224
#define LOWMEM_SIZE	4096
225
 
226
static unsigned char *lowmem_buffer;
227
static int lowmem_bufseg;
228
static int lowmem_bufoff;
229
static BW_ethdevinfo_t ethdevinfo;
230
static int netmask;
231
static struct in_addr bcastaddr;
232
 
233
extern regs_t regs;
234
 
235
static int net_acceptsocket = -1;		// socket for fielding new connections
236
static int net_controlsocket = 0;
237
 
238
#include "net_bw.h"
239
 
240
//=============================================================================
241
 
242
static int BW_ioctl(int s, char *msg, int msglen)
243
{
244
	Q_memcpy(lowmem_buffer, msg, msglen);
245
 
246
	regs.x.ax = 0x4403;
247
	regs.x.bx = s;
248
	regs.x.cx = msglen;
249
	regs.x.dx = lowmem_bufoff;
250
	regs.x.ds = lowmem_bufseg;
251
	if (dos_int86(0x21))
252
		return regs.x.ax;
253
	return 0;
254
}
255
 
256
//=============================================================================
257
 
258
static int BW_TranslateError(int error)
259
{
260
	switch(error)
261
	{
262
		case BW_ERR_USR_HANGUP:	return ECONNABORTED;
263
		case BW_ERR_HANGUP:		return EISCONN;
264
		case BW_ERR_NET_ERR:	return ENOTCONN;
265
		case BW_ERR_IS_CLOSED:	return ENOTCONN;
266
		case BW_ERR_TIME_OUT:	return ETIMEDOUT;
267
		case BW_ERR_RESET:		return ECONNREFUSED;
268
		case BW_ERR_FULL:		return ETOOMANYREFS;
269
		case BW_ERR_BLOCK:		return EWOULDBLOCK;
270
		case BW_ERR_SHUTDOWN:	return ESHUTDOWN;
271
	}
272
	return EIO;
273
}
274
 
275
//=============================================================================
276
 
277
static int GetEthdevinfo(void)
278
{
279
	int fd;
280
 
281
	Q_strcpy((char *)lowmem_buffer, "ETHDEV27");
282
	regs.x.ax = 0x3d42;
283
	regs.x.ds = lowmem_bufseg;
284
	regs.x.dx = lowmem_bufoff;
285
	if (dos_int86(0x21))
286
		return -1;
287
	fd = regs.x.ax;
288
 
289
	regs.x.ax = 0x4401;
290
	regs.x.bx = fd;
291
	regs.x.dx = 0x60;
292
	dos_int86(0x21);
293
 
294
	regs.h.ah = 0x3f;
295
	regs.x.cx = sizeof(ethdevinfo);
296
	regs.x.es = regs.x.ds = lowmem_bufseg;
297
	regs.x.dx = lowmem_bufoff;
298
	regs.x.bx = fd;
299
	if (dos_int86(0x21))
300
		return -1;
301
	Q_memcpy(ðdevinfo, lowmem_buffer, regs.x.ax);
302
 
303
	regs.h.ah = 0x3e;
304
	regs.x.bx = fd;
305
	dos_int86(0x21);
306
 
307
	return 0;
308
}
309
 
310
//=============================================================================
311
 
312
int BW_Init(void)
313
{
314
	struct qsockaddr addr;
315
	char *colon;
316
 
317
	if (COM_CheckParm ("-noudp"))
318
		return -1;
319
 
320
	lowmem_buffer = dos_getmemory(LOWMEM_SIZE);
321
	if (!lowmem_buffer)
322
		Sys_Error("not enough low memory\n");
323
	lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
324
	lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;
325
 
326
	if (GetEthdevinfo())
327
	{
328
		Con_DPrintf("Beame & Whiteside TCP/IP not detected\n");
329
		dos_freememory(lowmem_buffer);
330
		return -1;
331
	}
332
	netmask = 0xffffffff >> (32 - ethdevinfo.subnetMask);
333
	bcastaddr.s_addr = (ethdevinfo.inetAddr & netmask) | (~netmask);
334
 
335
	if ((net_controlsocket = BW_OpenSocket (0)) == -1)
336
	{
337
		dos_freememory(lowmem_buffer);
338
		Con_DPrintf ("BW_Init unable to open control socket; disabled\n");
339
		return -1;
340
	}
341
 
342
	BW_GetSocketAddr (net_controlsocket, &addr);
343
	Q_strcpy(my_tcpip_address,  BW_AddrToString (&addr));
344
	colon = Q_strrchr (my_tcpip_address, ':');
345
	if (colon)
346
		*colon = 0;
347
 
348
	Con_Printf("BW_Init: UDP initialized\n");
349
	tcpipAvailable = true;
350
 
351
	return net_controlsocket;
352
}
353
 
354
//=============================================================================
355
 
356
void BW_Shutdown(void)
357
{
358
	BW_Listen (false);
359
	BW_CloseSocket (net_controlsocket);
360
	dos_freememory(lowmem_buffer);
361
}
362
 
363
//=============================================================================
364
 
365
void BW_Listen (qboolean state)
366
{
367
	// enable listening
368
	if (state)
369
	{
370
		if (net_acceptsocket != -1)
371
			return;
372
		if ((net_acceptsocket = BW_OpenSocket (net_hostport)) == -1)
373
			Sys_Error ("BW_Listen: Unable to open accept socket\n");
374
		return;
375
	}
376
 
377
	// disable listening
378
	if (net_acceptsocket == -1)
379
		return;
380
	BW_CloseSocket (net_acceptsocket);
381
	net_acceptsocket = -1;
382
}
383
 
384
 
385
//=============================================================================
386
 
387
/*
388
OpenSocket returns a handle to a network socket that has been opened,
389
set to nonblocking, and bound to .  Additional socket options
390
should be set here if they are needed.  -1 is returned on failure.
391
*/
392
 
393
int BW_OpenSocket(int port)
394
{
395
	int s;
396
	int ret;
397
	int deadman = 3 * 1024;
398
	static int dynamic = 1024;
399
	static char reuse_msg[2] = {BW_IOCTL_SETOPTIONS, BW_OPTION_REUSEBUFFERS};
400
	static char bind_msg[3] = {BW_IOCTL_BIND, 0, 0};
401
	static char nonblock_msg[2] = {BW_IOCTL_CLEAROPTIONS, BW_OPTION_BLOCKING};
402
 
403
	// allocate a UDP socket
404
	Q_strcpy((char *)lowmem_buffer, "UDP-IP10");
405
	regs.x.ax = 0x3d42;
406
	regs.x.ds = lowmem_bufseg;
407
	regs.x.dx = lowmem_bufoff;
408
	if (dos_int86(0x21))
409
	{
410
		Con_Printf("BW_OpenSocket failed: %u\n", BW_TranslateError(regs.x.ax));
411
		return -1;
412
	}
413
	s = regs.x.ax;
414
 
415
	// set file descriptor to raw mode
416
	regs.x.ax = 0x4401;
417
	regs.x.bx = s;
418
	regs.x.dx = 0x60;
419
	dos_int86(0x21);
420
 
421
	if (BW_ioctl(s, reuse_msg, 2))
422
	{
423
		Con_Printf("BW_OpenSocket ioctl(reuse) failed\n");
424
		return -1;
425
	}
426
 
427
	if (BW_ioctl(s, nonblock_msg, 2))
428
	{
429
		Con_Printf("BW_OpenSocket ioctl(nonblocking) failed\n");
430
		return -1;
431
	}
432
 
433
	// if a socket was specified, bind to it and return
434
	if (port)
435
	{
436
		*(short *)&bind_msg[1] = port;
437
		if (BW_ioctl(s, bind_msg, 3))
438
		{
439
			BW_CloseSocket(s);
440
			return -1;
441
		}
442
		return s;
443
	}
444
 
445
	// B&W does NOT do dynamic allocation, so if port == 0 we must fake it
446
	do
447
	{
448
		port = dynamic++;
449
		if (dynamic == 4096)
450
			dynamic = 1024;
451
		deadman--;
452
		*(short *)&bind_msg[1] = port;
453
		ret = BW_ioctl(s, bind_msg, 3);
454
	}
455
	while (ret && deadman);
456
	if (ret)
457
		return -1;
458
	return s;
459
}
460
 
461
//=============================================================================
462
 
463
int BW_CloseSocket(int socket)
464
{
465
	regs.h.ah = 0x3e;
466
	regs.x.bx = socket;
467
	if(dos_int86(0x21))
468
		{
469
			Con_Printf("BW_CloseSocket %u failed: %u\n", socket, BW_TranslateError(regs.x.ax));
470
			return -1;
471
		}
472
	return 0;
473
}
474
 
475
//=============================================================================
476
 
477
int BW_Connect (int socket, struct qsockaddr *hostaddr)
478
{
479
	return 0;
480
}
481
 
482
//=============================================================================
483
 
484
int BW_CheckNewConnections(void)
485
{
486
	if (net_acceptsocket == 0)
487
		return -1;
488
 
489
	// see if there's anything waiting
490
	regs.x.ax = 0x4406;
491
	regs.x.bx = net_acceptsocket;
492
	dos_int86(0x21);
493
	if (regs.x.ax == 0)
494
		return -1;
495
	return net_acceptsocket;
496
}
497
 
498
//=============================================================================
499
 
500
int BW_Read(int s, byte *buf, int len, struct qsockaddr *from)
501
{
502
	BW_UDPreadInfo1_t *info1;
503
	BW_UDPreadInfo2_t *info2;
504
 
505
	// ask if there's anything waiting
506
	regs.x.ax = 0x4406;
507
	regs.x.bx = s;
508
	dos_int86(0x21);
509
	if (regs.x.ax == 0)
510
		return 0;
511
 
512
	// there was, so let's get it
513
	regs.h.ah = 0x3f;
514
	regs.x.cx = /* len + 53 */ LOWMEM_SIZE;
515
	regs.x.es = regs.x.ds = lowmem_bufseg;
516
	regs.x.dx = lowmem_bufoff;
517
	regs.x.bx = s;
518
	if (dos_int86(0x21))
519
	{
520
		Con_Printf("BW UDP read error: %u\n", BW_TranslateError(regs.x.ax));
521
		return -1;
522
	}
523
 
524
	info1 = (BW_UDPreadInfo1_t *)lowmem_buffer;
525
	info2 = (BW_UDPreadInfo2_t *)(lowmem_buffer + info1->info2Offset);
526
 
527
	if (from)
528
	{
529
		from->sa_family = AF_INET;
530
		((struct sockaddr_in *)from)->sin_addr = info1->remoteAddr;
531
		((struct sockaddr_in *)from)->sin_port = htons(info2->remotePort);
532
	}
533
 
534
	len = info2->dataLenPlus8 - 8;
535
	if (len > NET_DATAGRAMSIZE)
536
	{
537
		Con_Printf("BW UDP read packet too large: %u\n", len);
538
		return -1;
539
	}
540
	Q_memcpy(buf, info2->data, len);
541
 
542
	return len;
543
}
544
 
545
//=============================================================================
546
 
547
int BW_Broadcast(int s, byte *msg, int len)
548
{
549
	BW_writeInfo_t *writeInfo;
550
 
551
	// ask if we're clear to send
552
	regs.x.ax = 0x4407;
553
	regs.x.bx = s;
554
	dos_int86(0x21);
555
	if (regs.x.ax == 0)
556
		return 0;
557
 
558
	// yes, let's do it
559
	writeInfo = (BW_writeInfo_t *)lowmem_buffer;
560
	writeInfo->remoteAddr = bcastaddr;
561
	writeInfo->remotePort = net_hostport;
562
	writeInfo->dataLen = len;
563
	if (len > NET_DATAGRAMSIZE)
564
		Sys_Error("BW UDP write packet too large: %u\n", len);
565
	Q_memcpy(writeInfo->data, msg, len);
566
	writeInfo->data[len] = 0;
567
	regs.h.ah = 0x40;
568
	regs.x.bx = s;
569
	regs.x.cx = len + sizeof(BW_writeInfo_t);
570
	regs.x.es = regs.x.ds = lowmem_bufseg;
571
	regs.x.dx = lowmem_bufoff;
572
	if (dos_int86(0x21))
573
	{
574
		Con_Printf("BW_Broadcast failed: %u\n", BW_TranslateError(regs.x.ax));
575
		return -1;
576
	}
577
 
578
	return len;
579
}
580
 
581
//=============================================================================
582
 
583
int BW_Write(int s, byte *msg, int len, struct qsockaddr *to)
584
{
585
	BW_writeInfo_t *writeInfo;
586
 
587
	// ask if we're clear to send
588
	regs.x.ax = 0x4407;
589
	regs.x.bx = s;
590
	dos_int86(0x21);
591
	if (regs.x.ax == 0)
592
		return 0;
593
 
594
	// yes, let's do it
595
	writeInfo = (BW_writeInfo_t *)lowmem_buffer;
596
	writeInfo->remoteAddr = ((struct sockaddr_in *)to)->sin_addr;
597
	writeInfo->remotePort = ntohs(((struct sockaddr_in *)to)->sin_port);
598
	writeInfo->dataLen = len;
599
	if (len > NET_DATAGRAMSIZE)
600
		Sys_Error("BW UDP write packet too large: %u\n", len);
601
	Q_memcpy(writeInfo->data, msg, len);
602
	writeInfo->data[len] = 0;
603
	regs.h.ah = 0x40;
604
	regs.x.bx = s;
605
	regs.x.cx = len + sizeof(BW_writeInfo_t);
606
	regs.x.es = regs.x.ds = lowmem_bufseg;
607
	regs.x.dx = lowmem_bufoff;
608
	if (dos_int86(0x21))
609
	{
610
		Con_Printf("BW_Write failed: %u\n", BW_TranslateError(regs.x.ax));
611
		return -1;
612
	}
613
 
614
	return len;
615
}
616
 
617
//=============================================================================
618
 
619
 
620
char *BW_AddrToString (struct qsockaddr *addr)
621
{
622
	static char buffer[22];
623
 
624
	sprintf(buffer, "%d.%d.%d.%d:%d",
625
		((struct sockaddr_in *)addr)->sin_addr.s_net,
626
		((struct sockaddr_in *)addr)->sin_addr.s_host,
627
		((struct sockaddr_in *)addr)->sin_addr.s_lh,
628
		((struct sockaddr_in *)addr)->sin_addr.s_impno,
629
		ntohs(((struct sockaddr_in *)addr)->sin_port)
630
		);
631
	return buffer;
632
}
633
 
634
//=============================================================================
635
 
636
int BW_StringToAddr (char *string, struct qsockaddr *addr)
637
{
638
	int ha1, ha2, ha3, ha4, hp;
639
	int ipaddr;
640
 
641
	sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
642
	ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
643
 
644
	addr->sa_family = AF_INET;
645
	((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
646
	((struct sockaddr_in *)addr)->sin_port = htons((short)hp);
647
	return 0;
648
}
649
 
650
//=============================================================================
651
 
652
int BW_GetSocketAddr (int socket, struct qsockaddr *addr)
653
{
654
	regs.x.ax = 0x4402;
655
	regs.x.bx = socket;
656
	regs.x.cx = sizeof(BW_UDPinfo_t);
657
	regs.x.dx = lowmem_bufoff;
658
	regs.x.ds = lowmem_bufseg;
659
	dos_int86(0x21);
660
 
661
	addr->sa_family = AF_INET;
662
	((struct sockaddr_in *)addr)->sin_addr.s_addr = ((BW_UDPinfo_t *)lowmem_buffer)->localAddr.s_addr;
663
	((struct sockaddr_in *)addr)->sin_port = htons(((BW_UDPinfo_t *)lowmem_buffer)->localPort);
664
 
665
	return 0;
666
}
667
 
668
//=============================================================================
669
 
670
int BW_GetNameFromAddr (struct qsockaddr *addr, char *name)
671
{
672
	Q_strcpy(name, BW_AddrToString(addr));
673
	return 0;
674
}
675
 
676
///=============================================================================
677
 
678
int BW_GetAddrFromName (char *name, struct qsockaddr *hostaddr)
679
{
680
	char buff[MAXHOSTNAMELEN];
681
	char *b;
682
	int addr;
683
	int num;
684
	int mask;
685
	int run;
686
	int port;
687
 
688
	if (name[0] < '0' || name[0] > '9')
689
		return -1;
690
 
691
	buff[0] = '.';
692
	b = buff;
693
	Q_strcpy(buff+1, name);
694
	if (buff[1] == '.')
695
		b++;
696
 
697
	addr = 0;
698
	mask = -1;
699
	while (*b == '.')
700
	{
701
		b++;
702
		num = 0;
703
		run = 0;
704
		while (!( *b < '0' || *b > '9'))
705
		{
706
		  num = num*10 + *b++ - '0';
707
		  if (++run > 3)
708
		  	return -1;
709
		}
710
		if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
711
			return -1;
712
		if (num < 0 || num > 255)
713
			return -1;
714
		mask<<=8;
715
		addr = (addr<<8) + num;
716
	}
717
	addr = htonl(addr);
718
	mask = htonl(mask);
719
 
720
	if (*b++ == ':')
721
		port = Q_atoi(b);
722
	else
723
		port = net_hostport;
724
 
725
	hostaddr->sa_family = AF_INET;
726
	((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
727
	((struct sockaddr_in *)hostaddr)->sin_addr.s_addr =
728
	((ethdevinfo.inetAddr & mask) | addr);
729
 
730
	return 0;
731
}
732
 
733
//=============================================================================
734
 
735
int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
736
{
737
	if (addr1->sa_family != addr2->sa_family)
738
		return -1;
739
 
740
	if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
741
		return -1;
742
 
743
	if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
744
		return 1;
745
 
746
	return 0;
747
}
748
 
749
//=============================================================================
750
 
751
int BW_GetSocketPort (struct qsockaddr *addr)
752
{
753
	return ntohs(((struct sockaddr_in *)addr)->sin_port);
754
}
755
 
756
 
757
int BW_SetSocketPort (struct qsockaddr *addr, int port)
758
{
759
	((struct sockaddr_in *)addr)->sin_port = htons(port);
760
	return 0;
761
}
762
 
763
//=============================================================================