Skip to content

Instantly share code, notes, and snippets.

@cathay4t
Last active August 19, 2020 08:35
Show Gist options
  • Select an option

  • Save cathay4t/56b6a17dc2a3ad1f9ed857e0a516041b to your computer and use it in GitHub Desktop.

Select an option

Save cathay4t/56b6a17dc2a3ad1f9ed857e0a516041b to your computer and use it in GitHub Desktop.
Using glibc `res_ninit()` to query DNS name servers and searches
#!/usr/bin/python3
# Copyright 2020 Red Hat
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author: Gris Ge <fge@redhat.com>
from ctypes import byref
from ctypes import c_char
from ctypes import c_char_p
from ctypes import c_int
from ctypes import c_uint
from ctypes import c_uint16
from ctypes import c_uint32
from ctypes import c_uint8
from ctypes import c_ulong
from ctypes import c_ulonglong
from ctypes import c_ushort
from ctypes import c_void_p
from ctypes import cdll
from ctypes import POINTER
from ctypes import Structure
from ctypes import Union
from ctypes.util import find_library
import ipaddress
MAXNS = 3
SOCKADDR_IN_PAD_LENGTH = 8
MAXDNSRCH = 6
MAXRESOLVSORT = 10
AF_INET = 2
AF_INET6 = 10
class _SortList(Structure):
_fields_ = [("addr", c_uint32), ("mask", c_uint32)]
class _SockaddrIn(Structure):
_fields_ = [
("sin_family", c_ushort),
("sin_port", c_uint16),
("sin_addr", c_uint8 * 4),
("sin_zero", c_uint8 * SOCKADDR_IN_PAD_LENGTH),
]
class _SockaddrIn6(Structure):
_fields_ = [
("sin6_family", c_ushort),
("sin6_port", c_uint16),
("sin6_flowinfo", c_uint32),
("sin6_addr", c_uint8 * 16),
("sin6_scope_id", c_uint32),
]
class _ResStateExt(Structure):
_fields_ = [
("nscount", c_uint16),
("nsmap", c_uint16 * MAXNS),
("nssocks", c_int * MAXNS),
("nscount6", c_uint16),
("nsinit", c_uint16),
("nsaddrs", POINTER(_SockaddrIn6) * MAXNS),
("__glibc_extension_index", c_ulonglong),
]
class _ResStateUnion(Union):
_fields_ = [
("pad", c_char * 52),
("_ext", _ResStateExt),
]
class _ResState(Structure):
_fields_ = [
("retrans", c_int),
("retry", c_int),
("options", c_ulong),
("nscount", c_int),
("nsaddr_list", _SockaddrIn * MAXNS),
("id", c_ushort),
("dnsrch", c_char_p * (MAXDNSRCH + 1)),
("defdname", c_char * 256),
("pfcode", c_ulong),
("ndots", c_uint, 4),
("nsort", c_uint, 4),
("ipv6_unavail", c_uint, 1),
("unused", c_uint, 23),
("sort_list", _SortList * MAXRESOLVSORT),
("__glibc_unused_qhook", c_void_p),
("__glibc_unused_rhook", c_void_p),
("res_h_errno", c_int),
("_vcsock", c_int),
("_flags", c_uint),
("_u", _ResStateUnion),
]
def main():
libc = cdll.LoadLibrary(find_library("c"))
libc.__res_ninit.restype = c_int
libc.__res_ninit.argtypes = (POINTER(_ResState),)
libc.__res_nclose.restype = None
libc.__res_nclose.argtypes = (POINTER(_ResState),)
c_res_state_obj = _ResState()
libc.__res_ninit(byref(c_res_state_obj))
for i in range(0, c_res_state_obj.nscount):
if c_res_state_obj.nsaddr_list[i].sin_family == AF_INET:
sock_addr4 = c_res_state_obj.nsaddr_list[i]
print(ipaddress.IPv4Address(bytes(sock_addr4.sin_addr)))
elif c_res_state_obj._u._ext.nsaddrs:
sock_addr6 = c_res_state_obj._u._ext.nsaddrs[i].contents
if sock_addr6.sin6_family == AF_INET6:
print(ipaddress.IPv6Address(bytes(sock_addr6.sin6_addr)))
for i in range(0, MAXDNSRCH):
if c_res_state_obj.dnsrch[i]:
print(c_res_state_obj.dnsrch[i].decode("utf-8"))
else:
break
libc.__res_nclose(byref(c_res_state_obj))
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment