Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 <stdio.h>
  23. #include <stdlib.h>
  24. #include <dpmi.h>
  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 <dataLenPlus8> - 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 <datalen>
  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(&ethdevinfo, 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 <port>.  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. //=============================================================================
  764.