net_bw.c 18 KB

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