1252265Sjimharris# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
2252265Sjimharris#
3252265Sjimharris# SPDX-License-Identifier: MPL-2.0
4252265Sjimharris#
5252265Sjimharris# This Source Code Form is subject to the terms of the Mozilla Public
6252265Sjimharris# License, v. 2.0.  If a copy of the MPL was not distributed with this
7252265Sjimharris# file, you can obtain one at https://mozilla.org/MPL/2.0/.
8252265Sjimharris#
9252265Sjimharris# See the COPYRIGHT file distributed with this work for additional
10252265Sjimharris# information regarding copyright ownership.
11252265Sjimharris
12252265Sjimharrisimport os
13252265Sjimharrisimport select
14252265Sjimharrisimport signal
15252265Sjimharrisimport socket
16252265Sjimharrisimport sys
17252265Sjimharrisimport time
18252265Sjimharris
19252265Sjimharrisimport dns.flags
20252265Sjimharrisimport dns.message
21252265Sjimharris
22252265Sjimharris
23252265Sjimharrisdef port():
24252265Sjimharris    env_port = os.getenv("PORT")
25252265Sjimharris    if env_port is None:
26252265Sjimharris        env_port = 5300
27252265Sjimharris    else:
28252265Sjimharris        env_port = int(env_port)
29252265Sjimharris
30252265Sjimharris    return env_port
31252265Sjimharris
32252265Sjimharris
33252265Sjimharrisdef udp_listen(port):
34252265Sjimharris    udp = socket.socket(type=socket.SOCK_DGRAM)
35252265Sjimharris    udp.bind(("10.53.0.3", port))
36252265Sjimharris
37252265Sjimharris    return udp
38252265Sjimharris
39252265Sjimharris
40252265Sjimharrisdef tcp_listen(port):
41252265Sjimharris    tcp = socket.socket(type=socket.SOCK_STREAM)
42252265Sjimharris    tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
43252265Sjimharris    tcp.bind(("10.53.0.3", port))
44252265Sjimharris    tcp.listen(100)
45252265Sjimharris
46252265Sjimharris    return tcp
47252265Sjimharris
48252265Sjimharris
49252265Sjimharrisdef udp_tc_once(udp):
50252265Sjimharris    qrybytes, clientaddr = udp.recvfrom(65535)
51252265Sjimharris    qry = dns.message.from_wire(qrybytes)
52252265Sjimharris    answ = dns.message.make_response(qry)
53252265Sjimharris    answ.flags |= dns.flags.TC
54252265Sjimharris    answbytes = answ.to_wire()
55252265Sjimharris    udp.sendto(answbytes, clientaddr)
56252265Sjimharris
57252265Sjimharris
58252265Sjimharrisdef tcp_once(tcp):
59252265Sjimharris    csock, _clientaddr = tcp.accept()
60252265Sjimharris    time.sleep(5)
61252265Sjimharris    csock.close()
62252265Sjimharris
63252265Sjimharris
64252265Sjimharrisdef sigterm(signum, frame):
65252265Sjimharris    os.remove("ans.pid")
66252265Sjimharris    sys.exit(0)
67252265Sjimharris
68252265Sjimharris
69252265Sjimharrisdef write_pid():
70252265Sjimharris    with open("ans.pid", "w") as f:
71252265Sjimharris        pid = os.getpid()
72252265Sjimharris        f.write("{}".format(pid))
73252265Sjimharris
74252265Sjimharris
75252265Sjimharrissignal.signal(signal.SIGTERM, sigterm)
76252265Sjimharriswrite_pid()
77252265Sjimharris
78252265Sjimharrisudp = udp_listen(port())
79252265Sjimharristcp = tcp_listen(port())
80252265Sjimharris
81252270Sjimharrisinput = [udp, tcp]
82252265Sjimharris
83252265Sjimharriswhile True:
84252265Sjimharris    try:
85252265Sjimharris        inputready, outputready, exceptready = select.select(input, [], [])
86252265Sjimharris    except select.error:
87252265Sjimharris        break
88252265Sjimharris    except socket.error:
89252265Sjimharris        break
90252265Sjimharris    except KeyboardInterrupt:
91252265Sjimharris        break
92252265Sjimharris
93252265Sjimharris    for s in inputready:
94252265Sjimharris        if s == udp:
95252265Sjimharris            udp_tc_once(udp)
96252265Sjimharris        if s == tcp:
97252265Sjimharris            tcp_once(tcp)
98252270Sjimharris
99252270Sjimharrissigterm(signal.SIGTERM, 0)
100252265Sjimharris