shithub: mc

ref: 073546effee37340cd682778536bb84a77110cad
dir: /libstd/resolve.myr/

View raw version
use "alloc.use"
use "endian.use"
use "error.use"
use "fmt.use"
use "sys.use"
use "types.use"

pkg std =
	type resolveerr = union
		`Badhost
		`Badsrv
		`Badquery
	;;

	type hostinfo = struct
		flags	: uint32
		fam	: sockfam
		stype	: socktype
		proto	: uint32
		addr	: sockaddr[:]
		canon	: byte[:]
		next	: hostinfo#
	;;

	const resolve	: (host : byte[:]	-> hostinfo#)
;;

const resolve = {host : byte[:]
	var hinf

	hinf = zalloc()
	dnsresolve(host)
	-> hinf
}

const dnsresolve = {host : byte[:]
	/*var hosts*/
	var nsrv

	if !valid(host)
		-> `Failure (`Badhost)
	;;
	if (nsrv = dnsconnect()) < 0
		-> `Failure (`Badsrv)
	;;
	if !dnsquery(nsrv, host)
		-> `Failure (`Badquery)
	;;
	-> `Success true
}

const dnsconnect = {
	var sa : sockaddr_in
	var s
	var status
	
	s = socket(Afinet, Sockstream, 0)
	if s < 0
		put("Warning: Failed to open socket: %l\n", s)
		-> -1
	;;
	/* hardcode Google DNS for now */
	sa.fam = Afinet
	sa.port = hosttonet(53)
	sa.addr = 0x08080808
	status = connect(s, (&sa) castto(sockaddr#), sizeof(sockaddr_in))
	if status < 0
		put("Warning: Failed to connect to server: %l\n", status)
		-> -1
	;;
	-> s
}

const dnsquery = {srv, host
	put("Unimplemented query: srv=%z, host=%s\n", srv, host)
	-> false
}

const valid = {host : byte[:]
	var i
	var seglen

	/* maximum length: 255 chars */
	if host.len > 255
		-> false
	;;

	seglen = 0
	for i = 0; i < host.len; i++
		if host[i] == ('.' castto(byte))
			seglen = 0
		;;
		if seglen > 63
			-> false
		;;
		if host[i] & 0x80
			-> false
		;;
	;;

	-> true

}