|
|
1.1 ! root 1: // net_ipx.c ! 2: ! 3: #include <stdio.h> ! 4: #include <stdlib.h> ! 5: #include <dpmi.h> ! 6: ! 7: #include "quakedef.h" ! 8: #include "dosisms.h" ! 9: #include "net_ipx.h" ! 10: ! 11: #define EIO 5 /* I/O error */ ! 12: ! 13: #define AF_NETWARE 64 ! 14: ! 15: #define IPX_OPEN 0 ! 16: #define IPX_CLOSE 1 ! 17: #define IPX_GETROUTE 2 ! 18: #define IPX_SEND 3 ! 19: #define IPX_LISTEN 4 ! 20: #define IPX_SCHEDULEEVENT 5 ! 21: #define IPX_CANCEL 6 ! 22: #define IPX_SCHEDULESPECIALEVENT 7 ! 23: #define IPX_GETINTERVALMARKER 8 ! 24: #define IPX_GETADDRESS 9 ! 25: #define IPX_RELINQUISH 10 ! 26: ! 27: #define PTYPE_UNKNOWN 0 ! 28: #define PTYPE_RIP 1 ! 29: #define PTYPE_ECHO 2 ! 30: #define PTYPE_ERROR 3 ! 31: #define PTYPE_IPX 4 ! 32: #define PTYPE_SPX 5 ! 33: ! 34: #pragma pack(1) ! 35: ! 36: typedef struct ! 37: { ! 38: byte network[4]; ! 39: byte node[6]; ! 40: short socket; ! 41: } IPXaddr; ! 42: ! 43: struct sockaddr_ipx ! 44: { ! 45: short sipx_family; ! 46: IPXaddr sipx_addr; ! 47: char sipx_zero[2]; ! 48: }; ! 49: #define sipx_port sipx_addr.socket ! 50: ! 51: typedef struct ! 52: { ! 53: short checkSum; ! 54: short length; ! 55: byte transportControl; ! 56: byte type; ! 57: IPXaddr destination; ! 58: IPXaddr source; ! 59: } IPXheader; ! 60: ! 61: typedef struct ECBStructure ! 62: { ! 63: struct ECBStructure *link; ! 64: unsigned short ESR_off; ! 65: unsigned short ESR_seg; ! 66: byte inUse; ! 67: byte completionCode; ! 68: short socket; ! 69: byte IPXWorkspace[4]; ! 70: byte driverWorkspace[12]; ! 71: byte immediateAddress[6]; ! 72: short fragCount; ! 73: short fragOff; ! 74: short fragSeg; ! 75: short fragSize; ! 76: } ECB; ! 77: ! 78: #pragma pack() ! 79: ! 80: typedef struct ! 81: { ! 82: ECB ecb; ! 83: IPXheader header; ! 84: int sequence; ! 85: char data[NET_DATAGRAMSIZE]; ! 86: } ipx_lowmem_buffer_t; ! 87: ! 88: #define LOWMEMSIZE (100 * 1024) ! 89: #define LOWMEMSAVE 256 ! 90: #define IPXBUFFERS ((LOWMEMSIZE - LOWMEMSAVE)/ sizeof(ipx_lowmem_buffer_t)) ! 91: #define IPXSOCKBUFFERS 5 ! 92: #define IPXSOCKETS (IPXBUFFERS / IPXSOCKBUFFERS) ! 93: ! 94: // each socket's socketbuffer 0 is used for sending, the others for listening ! 95: ! 96: typedef struct ! 97: { ! 98: char reserved[LOWMEMSAVE]; ! 99: ipx_lowmem_buffer_t socketbuffer[IPXSOCKETS][IPXSOCKBUFFERS]; ! 100: } ipx_lowmem_area_t; ! 101: ! 102: ! 103: static int ipxsocket[IPXSOCKETS]; ! 104: static ECB *readlist[IPXSOCKETS]; ! 105: static int sequence[IPXSOCKETS]; ! 106: static int handlesInUse; ! 107: static ipx_lowmem_area_t *lma; ! 108: static char *lowmem_buffer; ! 109: static int lowmem_bufseg; ! 110: static int lowmem_bufoff; ! 111: static unsigned short ipx_cs; ! 112: static unsigned short ipx_ip; ! 113: static int net_acceptsocket = -1; ! 114: static int net_controlsocket; ! 115: ! 116: static void IPX_PollProcedure(void); ! 117: static PollProcedure pollProcedure = {NULL, 0.0, IPX_PollProcedure}; ! 118: ! 119: //============================================================================= ! 120: ! 121: static void IPX_GetLocalAddress(IPXaddr *addr) ! 122: { ! 123: regs.x.cs = ipx_cs; ! 124: regs.x.ip = ipx_ip; ! 125: regs.x.bx = IPX_GETADDRESS; ! 126: regs.x.es = lowmem_bufseg; ! 127: regs.x.si = lowmem_bufoff; ! 128: __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); ! 129: Q_memcpy(addr, lowmem_buffer, 10); ! 130: } ! 131: ! 132: //============================================================================= ! 133: ! 134: static int IPX_GetLocalTarget(IPXaddr *addr, byte *localTarget) ! 135: { ! 136: regs.x.cs = ipx_cs; ! 137: regs.x.ip = ipx_ip; ! 138: regs.x.bx = IPX_GETROUTE; ! 139: regs.x.es = lowmem_bufseg; ! 140: regs.x.si = lowmem_bufoff; ! 141: regs.x.di = lowmem_bufoff + sizeof(IPXaddr); ! 142: Q_memcpy(lowmem_buffer, addr, sizeof(IPXaddr)); ! 143: __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); ! 144: if (regs.h.al) ! 145: return -1; ! 146: Q_memcpy(localTarget, lowmem_buffer + sizeof(IPXaddr), 6); ! 147: return 0; ! 148: } ! 149: ! 150: //============================================================================= ! 151: ! 152: static void IPX_ListenForPacket(ECB *ecb) ! 153: { ! 154: regs.x.cs = ipx_cs; ! 155: regs.x.ip = ipx_ip; ! 156: regs.x.bx = IPX_LISTEN; ! 157: regs.x.es = ptr2real(ecb) >> 4; ! 158: regs.x.si = ptr2real(ecb) & 0xf; ! 159: __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); ! 160: } ! 161: ! 162: //============================================================================= ! 163: ! 164: static void IPX_RelinquishControl(void) ! 165: { ! 166: regs.x.cs = ipx_cs; ! 167: regs.x.ip = ipx_ip; ! 168: regs.x.bx = IPX_RELINQUISH; ! 169: __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); ! 170: } ! 171: ! 172: ! 173: void IPX_PollProcedure(void) ! 174: { ! 175: IPX_RelinquishControl(); ! 176: SchedulePollProcedure(&pollProcedure, 0.01); ! 177: } ! 178: ! 179: //============================================================================= ! 180: ! 181: static void ProcessReadyList(int s) ! 182: { ! 183: int n; ! 184: ECB *ecb; ! 185: ECB *prev; ! 186: ! 187: for (n = 1; n < IPXSOCKBUFFERS; n++) ! 188: { ! 189: if (lma->socketbuffer[s][n].ecb.inUse == 0) ! 190: { ! 191: for (ecb = readlist[s], prev = NULL; ecb; ecb = ecb->link) ! 192: { ! 193: if (lma->socketbuffer[s][n].sequence < ((ipx_lowmem_buffer_t *) ecb)->sequence) ! 194: break; ! 195: prev = ecb; ! 196: } ! 197: if (ecb) ! 198: lma->socketbuffer[s][n].ecb.link = ecb; ! 199: else ! 200: lma->socketbuffer[s][n].ecb.link = NULL; ! 201: if (prev) ! 202: prev->link = &lma->socketbuffer[s][n].ecb; ! 203: else ! 204: readlist[s] = &lma->socketbuffer[s][n].ecb; ! 205: lma->socketbuffer[s][n].ecb.inUse = 0xff; ! 206: } ! 207: } ! 208: } ! 209: ! 210: //============================================================================= ! 211: ! 212: int IPX_Init(void) ! 213: { ! 214: int s; ! 215: int n; ! 216: struct qsockaddr addr; ! 217: char *colon; ! 218: ! 219: if (COM_CheckParm ("-noipx")) ! 220: return -1; ! 221: ! 222: // find the IPX far call entry point ! 223: regs.x.ax = 0x7a00; ! 224: __dpmi_simulate_real_mode_interrupt (0x2f, (__dpmi_regs *)®s); ! 225: if (regs.h.al != 0xff) ! 226: { ! 227: Con_Printf("IPX not detected\n"); ! 228: return -1; ! 229: } ! 230: ipx_cs = regs.x.es; ! 231: ipx_ip = regs.x.di; ! 232: ! 233: // grab a chunk of memory down in DOS land ! 234: lowmem_buffer = dos_getmemory(LOWMEMSIZE); ! 235: if (!lowmem_buffer) ! 236: { ! 237: Con_Printf("IPX_Init: Not enough low memory\n"); ! 238: return -1; ! 239: } ! 240: lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf; ! 241: lowmem_bufseg = ptr2real(lowmem_buffer) >> 4; ! 242: ! 243: // init socket handles & buffers ! 244: handlesInUse = 0; ! 245: lma = (ipx_lowmem_area_t *)lowmem_buffer; ! 246: for (s = 0; s < IPXSOCKETS; s++) ! 247: { ! 248: ipxsocket[s] = 0; ! 249: for (n = 0; n < IPXSOCKBUFFERS; n++) ! 250: { ! 251: lma->socketbuffer[s][n].ecb.link = NULL; ! 252: lma->socketbuffer[s][n].ecb.ESR_off = 0; ! 253: lma->socketbuffer[s][n].ecb.ESR_seg = 0; ! 254: lma->socketbuffer[s][n].ecb.socket = 0; ! 255: lma->socketbuffer[s][n].ecb.inUse = 0xff; ! 256: lma->socketbuffer[s][n].ecb.completionCode = 0; ! 257: lma->socketbuffer[s][n].ecb.fragCount = 1; ! 258: lma->socketbuffer[s][n].ecb.fragOff = ptr2real(&lma->socketbuffer[s][n].header) & 0xf; ! 259: lma->socketbuffer[s][n].ecb.fragSeg = ptr2real(&lma->socketbuffer[s][n].header) >> 4; ! 260: lma->socketbuffer[s][n].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE; ! 261: } ! 262: } ! 263: ! 264: if ((net_controlsocket = IPX_OpenSocket (0)) == -1) ! 265: { ! 266: dos_freememory(lowmem_buffer); ! 267: Con_DPrintf ("IPX_Init: Unable to open control socket\n"); ! 268: return -1; ! 269: } ! 270: ! 271: SchedulePollProcedure(&pollProcedure, 0.01); ! 272: ! 273: IPX_GetSocketAddr (net_controlsocket, &addr); ! 274: Q_strcpy(my_ipx_address, IPX_AddrToString (&addr)); ! 275: colon = Q_strrchr (my_ipx_address, ':'); ! 276: if (colon) ! 277: *colon = 0; ! 278: ! 279: Con_Printf("IPX initialized\n"); ! 280: ipxAvailable = true; ! 281: return net_controlsocket; ! 282: } ! 283: ! 284: //============================================================================= ! 285: ! 286: void IPX_Shutdown(void) ! 287: { ! 288: IPX_Listen (false); ! 289: IPX_CloseSocket (net_controlsocket); ! 290: dos_freememory(lowmem_buffer); ! 291: } ! 292: ! 293: //============================================================================= ! 294: ! 295: void IPX_Listen (qboolean state) ! 296: { ! 297: // enable listening ! 298: if (state) ! 299: { ! 300: if (net_acceptsocket != -1) ! 301: return; ! 302: if ((net_acceptsocket = IPX_OpenSocket (net_hostport)) == -1) ! 303: Sys_Error ("IPX_Listen: Unable to open accept socket\n"); ! 304: return; ! 305: } ! 306: ! 307: // disable listening ! 308: if (net_acceptsocket == -1) ! 309: return; ! 310: IPX_CloseSocket (net_acceptsocket); ! 311: net_acceptsocket = -1; ! 312: } ! 313: ! 314: //============================================================================= ! 315: ! 316: int IPX_OpenSocket(int port) ! 317: { ! 318: int handle; ! 319: int n; ! 320: unsigned short socket; ! 321: ! 322: if (handlesInUse == IPXSOCKETS) ! 323: return -1; ! 324: ! 325: // open the IPX socket ! 326: regs.x.cs = ipx_cs; ! 327: regs.x.ip = ipx_ip; ! 328: regs.x.bx = IPX_OPEN; ! 329: regs.h.al = 0; ! 330: regs.x.dx = htons(port); ! 331: __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); ! 332: if (regs.h.al == 0xfe) ! 333: { ! 334: Con_DPrintf("IPX_OpenSocket: all sockets in use\n"); ! 335: return -1; ! 336: } ! 337: if (regs.h.al == 0xff) ! 338: { ! 339: Con_DPrintf("IPX_OpenSocket: socket already open\n"); ! 340: return -1; ! 341: } ! 342: if (regs.h.al != 0) ! 343: { ! 344: Con_DPrintf("IPX_OpenSocket: error %02x\n", regs.h.al); ! 345: return -1; ! 346: } ! 347: socket = regs.x.dx; ! 348: ! 349: // grab a handle; fill in the ECBs, and get them listening ! 350: for (handle = 0; handle < IPXSOCKETS; handle++) ! 351: { ! 352: if (ipxsocket[handle] == 0) ! 353: { ! 354: ipxsocket[handle] = socket; ! 355: readlist[handle] = NULL; ! 356: sequence[handle] = 0; ! 357: for (n = 0; n < IPXSOCKBUFFERS; n ++) ! 358: { ! 359: lma->socketbuffer[handle][n].ecb.socket = socket; ! 360: lma->socketbuffer[handle][n].ecb.inUse = 0; ! 361: if (n) ! 362: IPX_ListenForPacket(&lma->socketbuffer[handle][n].ecb); ! 363: } ! 364: handlesInUse++; ! 365: return handle; ! 366: } ! 367: } ! 368: ! 369: // "this will NEVER happen" ! 370: Sys_Error("IPX_OpenSocket: handle allocation failed\n"); ! 371: return -1; ! 372: } ! 373: ! 374: //============================================================================= ! 375: ! 376: int IPX_CloseSocket(int handle) ! 377: { ! 378: // if there's a send in progress, give it one last chance ! 379: if (lma->socketbuffer[handle][0].ecb.inUse != 0) ! 380: IPX_RelinquishControl(); ! 381: ! 382: // close the socket (all pending sends/received are cancelled) ! 383: regs.x.cs = ipx_cs; ! 384: regs.x.ip = ipx_ip; ! 385: regs.x.bx = IPX_CLOSE; ! 386: regs.x.dx = ipxsocket[handle]; ! 387: __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); ! 388: ! 389: ipxsocket[handle] = 0; ! 390: handlesInUse--; ! 391: ! 392: return 0; ! 393: } ! 394: ! 395: //============================================================================= ! 396: ! 397: int IPX_Connect (int handle, struct qsockaddr *addr) ! 398: { ! 399: IPXaddr ipxaddr; ! 400: ! 401: Q_memcpy(&ipxaddr, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr)); ! 402: if (IPX_GetLocalTarget(&ipxaddr, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0) ! 403: { ! 404: Con_Printf("Get Local Target failed\n"); ! 405: return -1; ! 406: } ! 407: ! 408: return 0; ! 409: } ! 410: ! 411: //============================================================================= ! 412: ! 413: int IPX_CheckNewConnections (void) ! 414: { ! 415: int n; ! 416: ! 417: if (net_acceptsocket == -1) ! 418: return -1; ! 419: ! 420: for (n = 1; n < IPXSOCKBUFFERS; n ++) ! 421: if (lma->socketbuffer[net_acceptsocket][n].ecb.inUse == 0) ! 422: return net_acceptsocket; ! 423: return -1; ! 424: } ! 425: ! 426: //============================================================================= ! 427: ! 428: int IPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr) ! 429: { ! 430: ECB *ecb; ! 431: ipx_lowmem_buffer_t *rcvbuf; ! 432: int copylen; ! 433: ! 434: ProcessReadyList(handle); ! 435: tryagain: ! 436: if (readlist[handle] == NULL) ! 437: return 0; ! 438: ecb = readlist[handle]; ! 439: readlist[handle] = ecb->link; ! 440: ! 441: if (ecb->completionCode != 0) ! 442: { ! 443: Con_Printf("Warning: IPX_Read error %02x\n", ecb->completionCode); ! 444: ecb->fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE; ! 445: IPX_ListenForPacket(ecb); ! 446: goto tryagain; ! 447: } ! 448: ! 449: rcvbuf = (ipx_lowmem_buffer_t *)ecb; ! 450: ! 451: // copy the data up to the buffer ! 452: copylen = ntohs(rcvbuf->header.length) - (sizeof(int) + sizeof(IPXheader)); ! 453: if (len < copylen) ! 454: Sys_Error("IPX_Read: buffer too small (%d vs %d)\n", len, copylen); ! 455: Q_memcpy(buf, rcvbuf->data, copylen); ! 456: ! 457: // fill in the addr if they want it ! 458: if (addr) ! 459: { ! 460: ((struct sockaddr_ipx *)addr)->sipx_family = AF_NETWARE; ! 461: Q_memcpy(&((struct sockaddr_ipx *)addr)->sipx_addr, rcvbuf->header.source.network, sizeof(IPXaddr)); ! 462: ((struct sockaddr_ipx *)addr)->sipx_zero[0] = 0; ! 463: ((struct sockaddr_ipx *)addr)->sipx_zero[1] = 0; ! 464: } ! 465: ! 466: // update the send ecb's immediate address ! 467: Q_memcpy(lma->socketbuffer[handle][0].ecb.immediateAddress, rcvbuf->ecb.immediateAddress, 6); ! 468: ! 469: // get this ecb listening again ! 470: rcvbuf->ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE; ! 471: IPX_ListenForPacket(&rcvbuf->ecb); ! 472: return copylen; ! 473: } ! 474: ! 475: //============================================================================= ! 476: ! 477: int IPX_Broadcast (int handle, byte *buf, int len) ! 478: { ! 479: struct sockaddr_ipx addr; ! 480: int ret; ! 481: ! 482: Q_memset(addr.sipx_addr.network, 0x00, 4); ! 483: Q_memset(addr.sipx_addr.node, 0xff, 6); ! 484: addr.sipx_port = htons(net_hostport); ! 485: Q_memset(lma->socketbuffer[handle][0].ecb.immediateAddress, 0xff, 6); ! 486: ret = IPX_Write (handle, buf, len, (struct qsockaddr *)&addr); ! 487: return ret; ! 488: } ! 489: ! 490: //============================================================================= ! 491: ! 492: int IPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr) ! 493: { ! 494: // has the previous send completed? ! 495: while (lma->socketbuffer[handle][0].ecb.inUse != 0) ! 496: IPX_RelinquishControl(); ! 497: ! 498: switch (lma->socketbuffer[handle][0].ecb.completionCode) ! 499: { ! 500: case 0x00: // success ! 501: case 0xfc: // request cancelled ! 502: break; ! 503: ! 504: case 0xfd: // malformed packet ! 505: default: ! 506: Con_Printf("IPX driver send failure: %02x\n", lma->socketbuffer[handle][0].ecb.completionCode); ! 507: break; ! 508: ! 509: case 0xfe: // packet undeliverable ! 510: case 0xff: // unable to send packet ! 511: Con_Printf("IPX lost route, trying to re-establish\n"); ! 512: ! 513: // look for a new route ! 514: if (IPX_GetLocalTarget (&lma->socketbuffer[handle][0].header.destination, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0) ! 515: return -1; ! 516: ! 517: // re-send the one that failed ! 518: regs.x.cs = ipx_cs; ! 519: regs.x.ip = ipx_ip; ! 520: regs.x.bx = IPX_SEND; ! 521: regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4; ! 522: regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf; ! 523: __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); ! 524: ! 525: // report that we did not send the current one ! 526: return 0; ! 527: } ! 528: ! 529: // ecb : length ! 530: lma->socketbuffer[handle][0].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + len; ! 531: ! 532: // ipx header : type ! 533: lma->socketbuffer[handle][0].header.type = PTYPE_IPX; ! 534: ! 535: // ipx header : destination ! 536: Q_memcpy(&lma->socketbuffer[handle][0].header.destination, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr)); ! 537: ! 538: // sequence number ! 539: lma->socketbuffer[handle][0].sequence = sequence[handle]; ! 540: sequence[handle]++; ! 541: ! 542: // copy down the data ! 543: Q_memcpy(lma->socketbuffer[handle][0].data, buf, len); ! 544: ! 545: regs.x.cs = ipx_cs; ! 546: regs.x.ip = ipx_ip; ! 547: regs.x.bx = IPX_SEND; ! 548: regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4; ! 549: regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf; ! 550: __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); ! 551: ! 552: return len; ! 553: } ! 554: ! 555: //============================================================================= ! 556: ! 557: char *IPX_AddrToString (struct qsockaddr *addr) ! 558: { ! 559: static char buf[28]; ! 560: ! 561: sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u", ! 562: ((struct sockaddr_ipx *)addr)->sipx_addr.network[0], ! 563: ((struct sockaddr_ipx *)addr)->sipx_addr.network[1], ! 564: ((struct sockaddr_ipx *)addr)->sipx_addr.network[2], ! 565: ((struct sockaddr_ipx *)addr)->sipx_addr.network[3], ! 566: ((struct sockaddr_ipx *)addr)->sipx_addr.node[0], ! 567: ((struct sockaddr_ipx *)addr)->sipx_addr.node[1], ! 568: ((struct sockaddr_ipx *)addr)->sipx_addr.node[2], ! 569: ((struct sockaddr_ipx *)addr)->sipx_addr.node[3], ! 570: ((struct sockaddr_ipx *)addr)->sipx_addr.node[4], ! 571: ((struct sockaddr_ipx *)addr)->sipx_addr.node[5], ! 572: ntohs(((struct sockaddr_ipx *)addr)->sipx_port) ! 573: ); ! 574: return buf; ! 575: } ! 576: ! 577: //============================================================================= ! 578: ! 579: int IPX_StringToAddr (char *string, struct qsockaddr *addr) ! 580: { ! 581: int val; ! 582: char buf[3]; ! 583: ! 584: buf[2] = 0; ! 585: Q_memset(addr, 0, sizeof(struct qsockaddr)); ! 586: addr->sa_family = AF_NETWARE; ! 587: ! 588: #define DO(src,dest) \ ! 589: buf[0] = string[src]; \ ! 590: buf[1] = string[src + 1]; \ ! 591: if (sscanf (buf, "%x", &val) != 1) \ ! 592: return -1; \ ! 593: ((struct sockaddr_ipx *)addr)->sipx_addr.dest = val ! 594: ! 595: DO(0, network[0]); ! 596: DO(2, network[1]); ! 597: DO(4, network[2]); ! 598: DO(6, network[3]); ! 599: DO(9, node[0]); ! 600: DO(11, node[1]); ! 601: DO(13, node[2]); ! 602: DO(15, node[3]); ! 603: DO(17, node[4]); ! 604: DO(19, node[5]); ! 605: #undef DO ! 606: ! 607: sscanf (&string[22], "%u", &val); ! 608: ((struct sockaddr_ipx *)addr)->sipx_port = htons(val); ! 609: ! 610: return 0; ! 611: } ! 612: ! 613: //============================================================================= ! 614: ! 615: int IPX_GetSocketAddr (int handle, struct qsockaddr *addr) ! 616: { ! 617: Q_memset(addr, 0, sizeof(struct qsockaddr)); ! 618: addr->sa_family = AF_NETWARE; ! 619: IPX_GetLocalAddress(&((struct sockaddr_ipx *)addr)->sipx_addr); ! 620: ((struct sockaddr_ipx *)addr)->sipx_port = ipxsocket[handle]; ! 621: return 0; ! 622: } ! 623: ! 624: //============================================================================= ! 625: ! 626: int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name) ! 627: { ! 628: Q_strcpy(name, IPX_AddrToString(addr)); ! 629: return 0; ! 630: } ! 631: ! 632: //============================================================================= ! 633: ! 634: int IPX_GetAddrFromName (char *name, struct qsockaddr *addr) ! 635: { ! 636: int n; ! 637: char buf[32]; ! 638: ! 639: n = Q_strlen(name); ! 640: ! 641: if (n == 12) ! 642: { ! 643: sprintf(buf, "00000000:%s:%u", name, net_hostport); ! 644: return IPX_StringToAddr (buf, addr); ! 645: } ! 646: if (n == 21) ! 647: { ! 648: sprintf(buf, "%s:%u", name, net_hostport); ! 649: return IPX_StringToAddr (buf, addr); ! 650: } ! 651: if (n > 21 && n <= 27) ! 652: return IPX_StringToAddr (name, addr); ! 653: ! 654: return -1; ! 655: } ! 656: ! 657: //============================================================================= ! 658: ! 659: int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) ! 660: { ! 661: if (addr1->sa_family != addr2->sa_family) ! 662: return -1; ! 663: ! 664: if(Q_memcmp(&((struct sockaddr_ipx *)addr1)->sipx_addr, &((struct sockaddr_ipx *)addr2)->sipx_addr, 10)) ! 665: return -1; ! 666: ! 667: if (((struct sockaddr_ipx *)addr1)->sipx_port != ((struct sockaddr_ipx *)addr2)->sipx_port) ! 668: return 1; ! 669: ! 670: return 0; ! 671: } ! 672: ! 673: //============================================================================= ! 674: ! 675: int IPX_GetSocketPort (struct qsockaddr *addr) ! 676: { ! 677: return ntohs(((struct sockaddr_ipx *)addr)->sipx_port); ! 678: } ! 679: ! 680: ! 681: int IPX_SetSocketPort (struct qsockaddr *addr, int port) ! 682: { ! 683: ((struct sockaddr_ipx *)addr)->sipx_port = htons(port); ! 684: return 0; ! 685: } ! 686: ! 687: //=============================================================================
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.