You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by pa...@apache.org on 2017/08/28 18:01:16 UTC

[trafficserver] branch master updated (b4128c5 -> eb601a3)

This is an automated email from the ASF dual-hosted git repository.

paziz pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git.


    from b4128c5  Coverity 1379933:  Control flow issues  (DEADCODE)
     new a197ef5  microDNS
     new eb601a3  update README.md

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 tests/tools/microDNS/README.md            |  46 ++++++++
 tests/tools/microDNS/sample_zonefile.json |   9 ++
 tests/tools/microDNS/uDNS.py              | 175 ++++++++++++++++++++++++++++++
 3 files changed, 230 insertions(+)
 create mode 100644 tests/tools/microDNS/README.md
 create mode 100644 tests/tools/microDNS/sample_zonefile.json
 create mode 100644 tests/tools/microDNS/uDNS.py

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].

[trafficserver] 02/02: update README.md

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paziz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit eb601a386cade900976bfd16c75bb94562766fe8
Author: Syeda Persia Aziz <pe...@yahoo.com>
AuthorDate: Fri Aug 25 14:54:34 2017 -0500

    update README.md
---
 tests/tools/microDNS/README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/tools/microDNS/README.md b/tests/tools/microDNS/README.md
index e655d31..d6b533e 100644
--- a/tests/tools/microDNS/README.md
+++ b/tests/tools/microDNS/README.md
@@ -34,13 +34,13 @@ A DNS request for `host1.example.com` could return the A-record associated with
 
 Running
 ------
-`python3 uDNS.py port zone_file [--rr]`
+`python3 uDNS.py ip_addr port zone_file [--rr]`
 
 For a detailed description of flags, see `python3 uDNS.py -h`
 
 
 Use with Apache Traffic Server
 ------
-1. In `records.config`, add configuration lines: `CONFIG proxy.config.dns.nameservers STRING 127.0.0.1:PORT` and `CONFIG proxy.config.dns.round_robin_nameservers INT 0`, where `PORT` is whatever port you want uDNS to serve on.
-2. Run uDNS on `PORT`
+1. In `records.config`, add configuration lines: `CONFIG proxy.config.dns.nameservers STRING ip_address:PORT` and `CONFIG proxy.config.dns.round_robin_nameservers INT 0`, where `PORT` is whatever port you want uDNS to serve on.
+2. Run uDNS on `Ip_addr`:`PORT`
 3. Now all domains mapped in the uDNS JSON config file should be mapped by ATS as well

-- 
To stop receiving notification emails like this one, please contact
"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>.

[trafficserver] 01/02: microDNS

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paziz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit a197ef5989b11e3e52ea099dec2ee5e3ad9fda5b
Author: Persia Aziz <pe...@yahoo-inc.com>
AuthorDate: Fri Aug 25 13:59:29 2017 -0500

    microDNS
---
 tests/tools/microDNS/README.md            |  46 ++++++++
 tests/tools/microDNS/sample_zonefile.json |   9 ++
 tests/tools/microDNS/uDNS.py              | 175 ++++++++++++++++++++++++++++++
 3 files changed, 230 insertions(+)

diff --git a/tests/tools/microDNS/README.md b/tests/tools/microDNS/README.md
new file mode 100644
index 0000000..e655d31
--- /dev/null
+++ b/tests/tools/microDNS/README.md
@@ -0,0 +1,46 @@
+uDNS
+=====
+
+uDNS is a small DNS server that takes in a pre-defined set of domain names and the IPs that each domain name maps to. The mappings should be inputted with a JSON file in a format described below.
+
+uDNS runs on localhost and serves whatever port is specified in the command line arguments. uDNS serves both UDP and TCP connections.
+
+If uDNS does not find the requested domain in the explicitly mapped section of the JSON, uDNS will respond with the IPs given in the `otherwise` section of the JSON. The `otherwise` section is mandatory.
+
+
+JSON format
+------
+```json
+{
+  "mappings": [
+    {"domain1": ["ip1", "ip2", "etc"]},
+    {"domain2": ["ip3", "ip4", "etc"]},
+    {"domain3": ["ip5"]},
+  ],
+
+  "otherwise": ["defaultip1", "defaultip2", "etc"]
+}
+```
+
+An example can be found in `sample_zonefile.json`
+
+
+Caveat
+------
+You should not include any two records like this: `host1.example.com` and `example.com`
+
+A DNS request for `host1.example.com` could return the A-record associated with `host1.example.com` or `example.com`, depending on your luck.
+
+
+Running
+------
+`python3 uDNS.py port zone_file [--rr]`
+
+For a detailed description of flags, see `python3 uDNS.py -h`
+
+
+Use with Apache Traffic Server
+------
+1. In `records.config`, add configuration lines: `CONFIG proxy.config.dns.nameservers STRING 127.0.0.1:PORT` and `CONFIG proxy.config.dns.round_robin_nameservers INT 0`, where `PORT` is whatever port you want uDNS to serve on.
+2. Run uDNS on `PORT`
+3. Now all domains mapped in the uDNS JSON config file should be mapped by ATS as well
diff --git a/tests/tools/microDNS/sample_zonefile.json b/tests/tools/microDNS/sample_zonefile.json
new file mode 100644
index 0000000..e4c8282
--- /dev/null
+++ b/tests/tools/microDNS/sample_zonefile.json
@@ -0,0 +1,9 @@
+{ 
+  "mappings": [
+    {"abc.xyz.com.": ["127.0.0.1","127.0.1.1"]},
+    {"yahoo.com.": ["128.0.0.1", "128.0.1.0"]},
+    {"yelp.com.": ["34.35.166.23", "129.0.0.1"]}
+  ],
+
+  "otherwise": ["127.0.0.1", "127.1.1.1"]
+}
diff --git a/tests/tools/microDNS/uDNS.py b/tests/tools/microDNS/uDNS.py
new file mode 100644
index 0000000..f82d48e
--- /dev/null
+++ b/tests/tools/microDNS/uDNS.py
@@ -0,0 +1,175 @@
+# coding=utf-8
+
+#  
+#  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.
+
+import datetime
+import sys
+import time
+import threading
+import traceback
+import socketserver
+import argparse
+import codecs
+import json
+from dnslib import *
+
+TTL = 60 * 5  # completely arbitrary TTL value
+round_robin = False
+default_records = list()
+records = dict()
+
+class DomainName(str):
+    def __getattr__(self, item):
+        return DomainName(item + '.' + self)
+
+class BaseRequestHandler(socketserver.BaseRequestHandler):
+
+    def get_data(self):
+        raise NotImplementedError
+
+    def send_data(self, data):
+        raise NotImplementedError
+
+    def handle(self):
+        now = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')
+        print("\n\n%s request %s (%s %s):" % (self.__class__.__name__[:3], now, self.client_address[0],
+                                               self.client_address[1]))
+        try:
+            data = self.get_data()
+            self.send_data(dns_response(data))
+        except Exception:
+            traceback.print_exc(file=sys.stderr)
+
+
+class TCPRequestHandler(BaseRequestHandler):
+
+    def get_data(self):
+        data = self.request.recv(8192).strip()
+        sz = int(codecs.encode(data[:2], 'hex'), 16)
+        if sz < len(data) - 2:
+            raise Exception("Wrong size of TCP packet")
+        elif sz > len(data) - 2:
+            raise Exception("Too big TCP packet")
+        return data[2:]
+
+    def send_data(self, data):
+        sz = codecs.decode(hex(len(data))[2:].zfill(4), 'hex')
+        return self.request.sendall(sz + data)
+
+
+class UDPRequestHandler(BaseRequestHandler):
+
+    def get_data(self):
+        return self.request[0].strip()
+
+    def send_data(self, data):
+        return self.request[1].sendto(data, self.client_address)
+
+def build_domain_mappings(path):
+    with open(path) as f:
+        zone_file = json.load(f)
+
+    for domain in zone_file['mappings']:
+        for d in iter(domain.keys()):
+            # this loop only runs once, kind of a hack to access the only key in the dict
+            domain_name = DomainName(d)            
+            print("Domain name:",domain_name)
+            records[domain_name] = [A(x) for x in domain[domain_name]]
+            print(records[domain_name])
+
+    default_records.extend([A(d) for d in zone_file['otherwise']])
+
+def add_authoritative_records(reply, domain):
+    # ns1 and ns1 are hardcoded in, change if necessary
+    reply.add_auth(RR(rname=domain, rtype=QTYPE.NS, rclass=1, ttl=TTL, rdata=NS(domain.ns1)))
+    reply.add_auth(RR(rname=domain, rtype=QTYPE.NS, rclass=1, ttl=TTL, rdata=NS(domain.ns2)))
+
+def dns_response(data):
+    ''' dns_response takes in the raw bytes from the socket and does all the logic behind what 
+        RRs get returned as the response '''
+    global default_records, records, TTL, round_robin
+
+    request = DNSRecord.parse(data)
+    print(request)
+
+    reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q)
+    qname = request.q.qname
+    qn = str(qname)
+    qtype = request.q.qtype
+    qt = QTYPE[qtype]
+    found_specific = False
+
+    # first look for a specific mapping
+    for domain, rrs in records.items():
+        if domain == qn or qn.endswith('.' + domain):
+        # we are the authoritative name server for this domain and all subdomains
+            for rdata in rrs:
+                # only include requested record types (ie. A, MX, etc)
+                rqt = rdata.__class__.__name__
+                if qt in ['*', rqt]:  
+                    found_specific = True
+                    reply.add_answer(RR(rname=qname, rtype=getattr(QTYPE, str(rqt)), rclass=1, ttl=TTL, rdata=rdata))
+
+            # rotate the A entries if round robin is on
+            if round_robin:
+                a_records = [x for x in rrs if type(x) == A]
+                records[domain] = a_records[1:] + a_records[:1]  # rotate list
+            break
+
+    # else if a specific mapping is not found, return default A-records
+    if not found_specific:
+        for a in default_records:
+            reply.add_answer(RR(rname=qname, rtype=QTYPE.A, rclass=1, ttl=TTL, rdata=a))
+
+        if round_robin:
+            default_records = default_records[1:] + default_records[:1]
+    print("---- Reply: ----\n", reply)
+    return reply.pack()
+
+
+if __name__ == '__main__':
+    # handle cmd line args
+    parser = argparse.ArgumentParser()    
+    parser.add_argument("ip_addr",type=str, help="Interface",default="127.0.0.1")
+    parser.add_argument("port", type=int, help="port uDNS should listen on")
+    parser.add_argument("zone_file", help="path to zone file")
+    parser.add_argument("--rr", action='store_true', help='round robin load balances if multiple IP addresses are present for 1 domain')
+    args = parser.parse_args()
+
+    if args.rr:
+        round_robin = True
+    build_domain_mappings(args.zone_file)
+
+    servers = [
+        socketserver.ThreadingUDPServer((args.ip_addr, args.port), UDPRequestHandler),
+        socketserver.ThreadingTCPServer((args.ip_addr, args.port), TCPRequestHandler),
+    ]
+
+    print("Starting DNS...")
+    for s in servers:
+        thread = threading.Thread(target=s.serve_forever)  # that thread will start one more thread for each request
+        thread.daemon = True  # exit the server thread when the main thread terminates
+        thread.start()
+
+    try:
+        while 1:
+            time.sleep(1)
+            sys.stderr.flush()
+            sys.stdout.flush()
+
+    except KeyboardInterrupt:
+        pass
+    finally:
+        for s in servers:
+            s.shutdown()

-- 
To stop receiving notification emails like this one, please contact
"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>.