28,8 → 28,8 |
mov [mem.realloc], ecx |
mov [dll.load], edx |
mov [DNSrequestID], 1 |
stdcall edx, @IMPORT |
ret 4 |
xor eax, eax |
ret |
|
;;===========================================================================;; |
;; in_addr_t __stdcall inet_addr(__in const char* hostname); ;; |
257,7 → 257,7 |
ret |
|
struct __gai_reqdata |
socket dd ? |
socketnum dd ? |
; external code should not look on rest of this structure, |
; it is internal for getaddrinfo_start/process/abort |
reqid dw ? ; DNS request ID |
279,7 → 279,7 |
;;---------------------------------------------------------------------------;; |
;> first parameter (optional) = host name ;; |
;> second parameter (optional) = service name (decimal number for now) ;; |
;> third parameter (optional) = hints for socket type ;; |
;> third parameter (optional) = hints for socketnum type ;; |
;> fourth parameter = pointer to result (head of L1-list) ;; |
;;---------------------------------------------------------------------------;; |
;< eax = 0 on success / one of EAI_ codes on error ;; |
425,14 → 425,14 |
jecxz @f |
cmp [ecx+addrinfo.ai_family], edi |
jz @f |
cmp [ecx+addrinfo.ai_family], PF_INET |
cmp [ecx+addrinfo.ai_family], AF_INET4 |
jnz .ret |
@@: |
; 1e. Valid combinations for ai_socktype/ai_protocol: 0/0 for any or |
; SOCK_STREAM/IPPROTO_TCP, SOCK_DGRAM/IPPROTO_UDP |
; (raw sockets are not yet supported by the kernel) |
; (raw socketnums are not yet supported by the kernel) |
xor edx, edx ; assume 0=any if no hints |
jecxz .socket_type_ok |
jecxz .socketnum_type_ok |
mov edx, [ecx+addrinfo.ai_socktype] |
mov esi, [ecx+addrinfo.ai_protocol] |
; 1f. Test for ai_socktype=0 and ai_protocol=0. |
439,16 → 439,16 |
test edx, edx |
jnz .check_socktype |
test esi, esi |
jz .socket_type_ok |
jz .socketnum_type_ok |
; 1g. ai_socktype=0, ai_protocol is nonzero. |
push EAI_SERVICE |
pop eax |
inc edx ; edx = SOCK_STREAM |
cmp esi, IPPROTO_TCP |
jz .socket_type_ok |
jz .socketnum_type_ok |
inc edx ; edx = SOCK_DGRAM |
cmp esi, IPPROTO_UDP |
jz .socket_type_ok |
jz .socketnum_type_ok |
.ret: |
; Restore saved registers, destroy stack frame and return. |
mov esp, ebp |
464,16 → 464,16 |
cmp edx, SOCK_DGRAM |
jnz .ret |
test esi, esi |
jz .socket_type_ok |
jz .socketnum_type_ok |
cmp esi, IPPROTO_UDP |
jz .socket_type_ok |
jz .socketnum_type_ok |
jmp .ret |
.check_tcp: |
test esi, esi |
jz .socket_type_ok |
jz .socketnum_type_ok |
cmp esi, IPPROTO_TCP |
jnz .ret |
.socket_type_ok: |
.socketnum_type_ok: |
mov [ebx+__gai_reqdata.socktype], dl |
; 2. Resolve service. |
; 2a. If no name is given, remember value -1. |
513,7 → 513,7 |
; 3. Process host name. |
mov esi, [.hostname] |
; 3a. If hostname is not given, |
; use localhost for active sockets and INADDR_ANY for passive sockets. |
; use localhost for active socketnums and INADDR_ANY for passive socketnums. |
mov eax, 0x0100007F ; 127.0.0.1 in network byte order |
test byte [ebx+__gai_reqdata.flags], AI_PASSIVE |
jz @f |
675,25 → 675,43 |
mov eax, 0x01000100 |
stosd |
; 7. Get DNS server address. |
mcall 52, 13 |
xchg esi, eax ; put server address to esi |
; 8. Open UDP socket to DNS server, port 53. |
mcall 53, 0, 0, 53 |
mcall 76, API_IPv4 + 4 ; protocol IP=0, device number=0, function=get DNS address |
cmp eax, -1 |
je .ret.dnserr |
mov esi, eax ; put server address to esi |
; 8. Open UDP socketnum to DNS server, port 53. |
; 8a. Create new socketnum. |
mcall 75, 0, AF_INET4, SOCK_DGRAM |
cmp eax, -1 ; error? |
jz .ret.dnserr |
xchg ecx, eax ; put socket handle to ecx |
mov ecx, eax ; put socketnum handle to ecx |
; 8b. Create sockaddr structure on the stack. |
push 0 |
push 0 ; sin_zero |
push esi ; sin_addr |
push AF_INET4 + (53 shl 24) |
; sin_family and sin_port in network byte order |
; 8c. Connect. |
mcall 75, 4, , esp, sizeof.sockaddr_in |
; 8d. Restore the stack, undo 8b. |
add esp, esi |
; 8e. Check result. |
cmp eax, -1 |
jz .ret.close |
; 9. Send DNS request packet. |
sub edi, esp ; get packet length |
mcall 53, 4, , edi, esp |
mov esi, edi |
xor edi, edi |
mcall 75, 6, , esp |
cmp eax, -1 |
jz .ret.close |
mov eax, [.reqdata] |
mov [eax+__gai_reqdata.socket], ecx |
mov [eax+__gai_reqdata.socketnum], ecx |
push -1 |
pop eax ; return status: more processing required |
jmp .ret.dns |
.ret.close: |
mcall 53, 1 |
mcall 75, 1 |
.ret.dnserr: |
push EAI_AGAIN |
pop eax |
741,9 → 759,11 |
push ebx esi edi |
mov edi, [.reqdata] |
; 2. Read UDP datagram. |
mov ecx, [edi+__gai_reqdata.socket] |
mcall 53, 11, , , 512 |
; 3. Ignore events for other sockets (return if no data read) |
mov ecx, [edi+__gai_reqdata.socketnum] |
push edi |
mcall 75, 7, , , 512, 0 |
pop edi |
; 3. Ignore events for other socketnums (return if no data read) |
test eax, eax |
jz .ret.more_processing_required |
; 4. Sanity check: discard too short packets. |
898,11 → 918,11 |
@@: |
pop eax |
.ret.close: |
; 15. Close socket. |
; 15. Close socketnum. |
push eax |
mov ecx, [.reqdata] |
mov ecx, [ecx+__gai_reqdata.socket] |
mcall 53, 1 |
mov ecx, [ecx+__gai_reqdata.socketnum] |
mcall 75, 1 |
pop eax |
; 16. Restore used registers, destroy stack frame and return. |
.ret: |
1150,13 → 1170,12 |
; 4. Fill struct addrinfo. |
mov eax, [ebx+__gai_reqdata.flags] |
mov [edi+addrinfo.ai_flags], eax |
mov byte [edi+addrinfo.ai_family], PF_INET |
mov byte [edi+addrinfo.ai_family], AF_INET4 |
mov byte [edi+addrinfo.ai_addrlen], sizeof.sockaddr_in |
lea ecx, [edi+sizeof.addrinfo] |
mov [edi+addrinfo.ai_addr], ecx |
; 5. Fill struct sockaddr_in. |
mov byte [ecx+sockaddr_in.sin_len], sizeof.sockaddr_in |
mov byte [ecx+sockaddr_in.sin_family], PF_INET |
mov byte [ecx+sockaddr_in.sin_family], AF_INET4 |
pop eax |
mov [ecx+sockaddr_in.sin_addr], eax |
; 6. Append new item to the list. |
1170,7 → 1189,7 |
ret |
|
.set_socktype: |
; Set ai_socktype and ai_protocol fields by given socket type. |
; Set ai_socktype and ai_protocol fields by given socketnum type. |
mov byte [edi+addrinfo.ai_socktype], cl |
dec cl |
jnz .set_udp |
1185,7 → 1204,7 |
; Just copy port from input __gai_reqdata to output addrinfo. |
push edx |
mov edx, [ebx+__gai_reqdata.service] |
xchg dl, dh ; convert to network byte order |
xchg dl, dh ; convert to network byte order ;;;;; CHECKME |
mov [edi+sizeof.addrinfo+sockaddr_in.sin_port], dx |
pop edx |
ret |
1200,10 → 1219,10 |
;;===========================================================================;; |
; 0. Save used registers for __stdcall. |
push ebx |
; 1. Allocated resources: only socket, so close it and return. |
; 1. Allocated resources: only socketnum, so close it and return. |
mov eax, [esp+8] |
mov ecx, [eax+__gai_reqdata.socket] |
mcall 53, 1 |
mov ecx, [eax+__gai_reqdata.socketnum] |
mcall 75, 1 |
; 2. Restore used registers and return. |
pop ebx |
ret 4 |
1264,16 → 1283,6 |
getaddrinfo_abort , 'getaddrinfo_abort' , \ |
freeaddrinfo , 'freeaddrinfo' |
|
; import from libini |
align 4 |
@IMPORT: |
|
library libini, 'libini.obj' |
import libini, \ |
ini.get_str, 'ini_get_str', \ |
ini.get_int, 'ini_get_int' |
|
|
section '.data' data readable writable align 16 |
; uninitialized data |
mem.alloc dd ? |