Jump to content

DNS query: Difference between revisions

m
→‎{{header|Phix}}: added syntax colouring, marked p2js incompatible
(Added Wren)
m (→‎{{header|Phix}}: added syntax colouring, marked p2js incompatible)
Line 1,069:
Translated from C/MSDN/several man pages.<br>
<b>NB:</b> may warrant further testing, see output.
<!--<lang Phix>include builtins\cffi.e(notonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span>
 
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">cffi</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
constant AF_UNSPEC = 0,
-- AF_INET = 2,
<span style="color: #008080;">constant</span> <span style="color: #000000;">AF_UNSPEC</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
-- AF_INET6 = 23,
<span style="color: #000080;font-style:italic;">-- AF_INET = 2,
-- SOCK_STREAM = 1,
-- SOCK_DGRAMAF_INET6 = 223,
-- IPPROTO_TCPSOCK_STREAM = 61,</span>
<span style="color: #000000;">SOCK_DGRAM</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span>
NI_MAXHOST = 1025,
<span style="color: #000080;font-style:italic;">-- IPPROTO_TCP = 6,</span>
NI_NUMERICHOST = iff(platform()=LINUX?1:2)
<span style="color: #000000;">NI_MAXHOST</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1025</span><span style="color: #0000FF;">,</span>
 
<span style="color: #000000;">NI_NUMERICHOST</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">LINUX</span><span style="color: #0000FF;">?</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
constant tWAD = """
typedef struct WSAData {
<span style="color: #008080;">constant</span> <span style="color: #000000;">tWAD</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
WORD wVersion;
typedef struct WSAData {
WORD wHighVersion;
char WORD szDescription[257] wVersion;
char WORD szSystemStatus[129] wHighVersion;
char szDescription[257];
unsigned short iMaxSockets;
char szSystemStatus[129];
unsigned short iMaxUdpDg;
unsigned short iMaxSockets;
char *lpVendorInfo;
unsigned short iMaxUdpDg;
} WSADATA, *LPWSADATA;
char *lpVendorInfo;
""",
} WSADATA, *LPWSADATA;
tWAS = """
"""</span><span style="color: #0000FF;">,</span>
int WSAStartup(
<span style="color: #000000;">tWAS</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
_In_ WORD wVersionRequested,
int WSAStartup(
_Out_ LPWSADATA lpWSAData
_In_ WORD wVersionRequested,
);
_Out_ LPWSADATA lpWSAData
""",
);
tWAC = """
"""</span><span style="color: #0000FF;">,</span>
int WSACleanup(void);
<span style="color: #000000;">tWAC</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
""",
int WSACleanup(void);
tAI_W="""
"""</span><span style="color: #0000FF;">,</span>
typedef struct addrinfo {
<span style="color: #000000;">tAI_W</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"""
int ai_flags;
typedef struct addrinfo {
int ai_family;
int ai_socktypeai_flags;
int ai_protocolai_family;
size_t int ai_addrlen ai_socktype;
char int *ai_canonname ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
struct sockaddr *ai_addr;
} ADDRINFOA, *PADDRINFOA;
struct addrinfo *ai_next;
""",
} ADDRINFOA, *PADDRINFOA;
tAI_L="""
"""</span><span style="color: #0000FF;">,</span>
typedef struct addrinfo {
<span style="color: #000000;">tAI_L</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"""
int ai_flags;
typedef struct addrinfo {
int ai_family;
int ai_socktypeai_flags;
int ai_protocolai_family;
int ai_addrlenai_socktype;
int ai_protocol;
struct sockaddr *ai_addr;
char int *ai_canonname ai_addrlen;
struct addrinfosockaddr *ai_nextai_addr;
char *ai_canonname;
};
struct addrinfo *ai_next;
""",
};
tGAI = """
"""</span><span style="color: #0000FF;">,</span>
int getaddrinfo(
<span style="color: #000000;">tGAI</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
_In_opt_ PCSTR pNodeName,
int getaddrinfo(
_In_opt_ PCSTR pServiceName,
_In_opt_ PCSTR pNodeName,
_In_opt_ const ADDRINFOA *pHints,
_In_opt_ PCSTR pServiceName,
_Out_ PADDRINFOA *ppResult
_In_opt_ const ADDRINFOA *pHints,
);
_Out_ PADDRINFOA *ppResult
""",
);
--int getaddrinfo(const char *node, const char *service,
"""</span><span style="color: #0000FF;">,</span>
-- const struct addrinfo *hints,
<span style="color: #000080;font-style:italic;">--int getaddrinfo(const char *node, const char *service,
-- struct addrinfo **res);
-- const struct addrinfo *hints,
tGNI = """
-- struct addrinfo **res);</span>
int getnameinfo(
<span style="color: #000000;">tGNI</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
_In_ sockaddr *sa,
int getnameinfo(
_In_ int salen,
_Out_ _In_ char sockaddr *hostsa,
_In_ DWORDint hostlensalen,
_Out_ char *servhost,
_In_ DWORD servlenhostlen,
_In_ _Out_ intchar flags*serv,
_In_ DWORD servlen,
);
_In_ int flags
""",
);
--int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
"""</span><span style="color: #0000FF;">,</span>
-- char *host, socklen_t hostlen,
<span style="color: #000080;font-style:italic;">--int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
-- char *serv, socklen_t servlen, int flags);
-- char *host, socklen_t hostlen,
tFAI = """
-- char *serv, socklen_t servlen, int flags);</span>
void freeaddrinfo(
<span style="color: #000000;">tFAI</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
_In_ struct addrinfo *ai
void freeaddrinfo(
);
_In_ struct addrinfo *ai
"""
);
--void freeaddrinfo(struct addrinfo *res);
"""</span>
 
<span style="color: #000080;font-style:italic;">--void freeaddrinfo(struct addrinfo *res);</span>
integer xgetaddrinfo = NULL, xgetnameinfo, xfreeaddrinfo, idAI,
xwsastartup, xwsacleanup, error
<span style="color: #004080;">integer</span> <span style="color: #000000;">xgetaddrinfo</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xgetnameinfo</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xfreeaddrinfo</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span>
 
<span style="color: #000000;">xwsastartup</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xwsacleanup</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">error</span>
function get_name_info(string fqdn)
if xgetaddrinfo=NULL then
<span style="color: #008080;">function</span> <span style="color: #000000;">get_name_info</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">fqdn</span><span style="color: #0000FF;">)</span>
atom lib
<span style="color: #008080;">if</span> <span style="color: #000000;">xgetaddrinfo</span><span style="color: #0000FF;">=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span>
if platform()=WINDOWS then
<span style="color: #004080;">atom</span> <span style="color: #000000;">lib</span>
integer idWAD = define_struct(tWAD)
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">WINDOWS</span> <span style="color: #008080;">then</span>
atom pWAD = allocate_struct(idWAD,cleanup:=true)
<span style="color: #004080;">integer</span> <span style="color: #000000;">idWAD</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tWAD</span><span style="color: #0000FF;">)</span>
lib = open_dll("Ws2_32.dll")
<span style="color: #004080;">atom</span> <span style="color: #000000;">pWAD</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">allocate_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idWAD</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cleanup</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
xwsastartup = define_cffi_func(lib,tWAS)
<span style="color: #000000;">lib</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_dll</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Ws2_32.dll"</span><span style="color: #0000FF;">)</span>
xwsacleanup = define_cffi_func(lib,tWAC)
<span style="color: #000000;">xwsastartup</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tWAS</span><span style="color: #0000FF;">)</span>
error = c_func(xwsastartup,{#00020002,pWAD})
<span style="color: #000000;">xwsacleanup</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tWAC</span><span style="color: #0000FF;">)</span>
if error then ?9/0 end if
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xwsastartup</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">#00020002</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pWAD</span><span style="color: #0000FF;">})</span>
idAI = define_struct(tAI_W)
<span style="color: #008080;">if</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
elsif platform()=LINUX then
<span style="color: #000000;">idAI</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tAI_W</span><span style="color: #0000FF;">)</span>
lib = open_dll("libc.so.6")
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">LINUX</span> <span style="color: #008080;">then</span>
idAI = define_struct(tAI_L)
<span style="color: #000000;">lib</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_dll</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"libc.so.6"</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">idAI</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tAI_L</span><span style="color: #0000FF;">)</span>
xgetaddrinfo = define_cffi_func(lib,tGAI)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
xgetnameinfo = define_cffi_func(lib,tGNI)
<span style="color: #000000;">xgetaddrinfo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tGAI</span><span style="color: #0000FF;">)</span>
xfreeaddrinfo = define_cffi_proc(lib,tFAI)
<span style="color: #000000;">xgetnameinfo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tGNI</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">xfreeaddrinfo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_cffi_proc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lib</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tFAI</span><span style="color: #0000FF;">)</span>
atom hints = allocate_struct(idAI,cleanup:=true),
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
res = allocate(machine_word(),cleanup:=true),
<span style="color: #004080;">atom</span> <span style="color: #000000;">hints</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">allocate_struct</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cleanup</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">),</span>
host = allocate(NI_MAXHOST,cleanup:=true)
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">machine_word</span><span style="color: #0000FF;">(),</span><span style="color: #000000;">cleanup</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">),</span>
set_struct_field(idAI,hints,"ai_family",AF_UNSPEC)
<span style="color: #000000;">host</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">NI_MAXHOST</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cleanup</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
-- set_struct_field(idAI,hints,"ai_socktype",SOCK_STREAM)
<span style="color: #000000;">set_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hints</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_family"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">AF_UNSPEC</span><span style="color: #0000FF;">)</span>
set_struct_field(idAI,hints,"ai_socktype",SOCK_DGRAM)
<span style="color: #000080;font-style:italic;">-- set_struct_field(idAI,hints,"ai_socktype",SOCK_STREAM)</span>
error = c_func(xgetaddrinfo,{fqdn,NULL,hints,res})
<span style="color: #000000;">set_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hints</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_socktype"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">SOCK_DGRAM</span><span style="color: #0000FF;">)</span>
if error then ?9/0 end if
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xgetaddrinfo</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">fqdn</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hints</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
res = peekNS(res,machine_word(),false)
<span style="color: #008080;">if</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
atom ptr = res
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peekNS</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">machine_word</span><span style="color: #0000FF;">(),</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
sequence results = {}
<span style="color: #004080;">atom</span> <span style="color: #000000;">ptr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span>
while ptr!=NULL do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">results</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
atom addr = get_struct_field(idAI,ptr,"ai_addr")
<span style="color: #008080;">while</span> <span style="color: #000000;">ptr</span><span style="color: #0000FF;">!=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">do</span>
integer len = get_struct_field(idAI,ptr,"ai_addrlen")
<span style="color: #004080;">atom</span> <span style="color: #000000;">addr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ptr</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_addr"</span><span style="color: #0000FF;">)</span>
error = c_func(xgetnameinfo,{addr, len, host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST})
<span style="color: #004080;">integer</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ptr</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_addrlen"</span><span style="color: #0000FF;">)</span>
if error then ?9/0 end if
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xgetnameinfo</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">addr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">len</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">host</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NI_MAXHOST</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NI_NUMERICHOST</span><span style="color: #0000FF;">})</span>
results = append(results,peek_string(host))
<span style="color: #008080;">if</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
ptr = get_struct_field(idAI,ptr,"ai_next")
<span style="color: #000000;">results</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">results</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">peek_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">host</span><span style="color: #0000FF;">))</span>
end while
<span style="color: #000000;">ptr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_struct_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">idAI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ptr</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ai_next"</span><span style="color: #0000FF;">)</span>
c_proc(xfreeaddrinfo,{res})
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
return results
<span style="color: #7060A8;">c_proc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xfreeaddrinfo</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">results</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure WSACleanup()
if platform()=WINDOWS then
<span style="color: #008080;">procedure</span> <span style="color: #7060A8;">WSACleanup</span><span style="color: #0000FF;">()</span>
error = c_func(xwsacleanup,{})
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">WINDOWS</span> <span style="color: #008080;">then</span>
if error then crash("WSACleanup failed: %d\n",{error}) end if
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xwsacleanup</span><span style="color: #0000FF;">,{})</span>
end if
<span style="color: #008080;">if</span> <span style="color: #000000;">error</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"WSACleanup failed: %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">error</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
?get_name_info("www.kame.net")
WSACleanup()</lang>
<span style="color: #0000FF;">?</span><span style="color: #000000;">get_name_info</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"www.kame.net"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">WSACleanup</span><span style="color: #0000FF;">()</span>
<!--</lang>-->
{{out}}
Note that windows nslookup shows an IPv6 that this does not, whereas
7,805

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.