summaryrefslogtreecommitdiff
path: root/ext/win32/resolv/resolv.c
blob: f19243ccc1877f458fb4f08518d98a215da9a3a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <ruby.h>
#include <ruby/encoding.h>
#include <windows.h>
#ifndef NTDDI_VERSION
#define NTDDI_VERSION 0x06000000
#endif
#include <iphlpapi.h>

static VALUE
w32error_make_error(DWORD e)
{
    VALUE code = ULONG2NUM(e);
    return rb_class_new_instance(1, &code, rb_path2class("Win32::Resolv::Error"));
}

static void
w32error_raise(DWORD e)
{
    rb_exc_raise(w32error_make_error(e));
}

static VALUE
get_dns_server_list(VALUE self)
{
    FIXED_INFO *fixedinfo = NULL;
    ULONG buflen = 0;
    DWORD ret;
    VALUE buf, nameservers = Qnil;

    ret = GetNetworkParams(NULL, &buflen);
    if (ret != NO_ERROR && ret != ERROR_BUFFER_OVERFLOW) {
	w32error_raise(ret);
    }
    fixedinfo = ALLOCV(buf, buflen);
    ret = GetNetworkParams(fixedinfo, &buflen);
    if (ret == NO_ERROR) {
	const IP_ADDR_STRING *ipaddr = &fixedinfo->DnsServerList;
	nameservers = rb_ary_new();
	do {
	    const char *s = ipaddr->IpAddress.String;
	    if (!*s) continue;
	    if (strcmp(s, "0.0.0.0") == 0) continue;
	    rb_ary_push(nameservers, rb_str_new_cstr(s));
	} while ((ipaddr = ipaddr->Next) != NULL);
    }
    ALLOCV_END(buf);
    if (ret != NO_ERROR) w32error_raise(ret);

    return nameservers;
}

void
InitVM_resolv(void)
{
    VALUE mWin32 = rb_define_module("Win32");
    VALUE resolv = rb_define_module_under(mWin32, "Resolv");
    VALUE singl = rb_singleton_class(resolv);
    rb_define_private_method(singl, "get_dns_server_list", get_dns_server_list, 0);
}

void
Init_resolv(void)
{
    InitVM(resolv);
}