1f9c4cfa7SFilip Tehlar#/usr/bin/env python
2f9c4cfa7SFilip Tehlar
3f9c4cfa7SFilip Tehlar# Simple map resolver
4f9c4cfa7SFilip Tehlar#
5f9c4cfa7SFilip Tehlar# This script creates an UDP socket and starts listening on it.
6f9c4cfa7SFilip Tehlar# When a map-request is received nonce is extracted from the request and
7f9c4cfa7SFilip Tehlar# used in map-reply.
8f9c4cfa7SFilip Tehlar#
9f9c4cfa7SFilip Tehlar# Notes:
10f9c4cfa7SFilip Tehlar# * works only with ipv4 in both under/over-lays.
11f9c4cfa7SFilip Tehlar# * exact address matching is done while looking for a mapping
12f9c4cfa7SFilip Tehlar#
13f9c4cfa7SFilip Tehlar# Usage:
14f9c4cfa7SFilip Tehlar#   ./dummy_mr <bind-ip> <port>
15f9c4cfa7SFilip Tehlar#
16f9c4cfa7SFilip Tehlar
17f9c4cfa7SFilip Tehlarimport sys
18f9c4cfa7SFilip Tehlarimport socket
19f9c4cfa7SFilip Tehlar
20f9c4cfa7SFilip Tehlar# mapping between EIDs and RLOCs
21f9c4cfa7SFilip Tehlarmappings = {
22f9c4cfa7SFilip Tehlar  b'\x06\x00\x02\x02' : (b'\x06\x00\x03\x02', ),
23f9c4cfa7SFilip Tehlar  b'\x06\x00\x01\x02' : (b'\x06\x00\x03\x01', )
24f9c4cfa7SFilip Tehlar}
25f9c4cfa7SFilip Tehlar
26f9c4cfa7SFilip Tehlar# LISP map-reply message
27f9c4cfa7SFilip Tehlarreply_data = (b'\x20\x00\x00\x01'   # type, PES, reserved, record count
28f9c4cfa7SFilip Tehlar             + '\x00\x00\x00\x00'   # nonce
29f9c4cfa7SFilip Tehlar             + '\x00\x00\x00\x00'   # nonce
30f9c4cfa7SFilip Tehlar             + '\x00\x00\x05\xa0'   # record TTL
31f9c4cfa7SFilip Tehlar             + '\x01\x18\x10\x00'   # loc-count, EID-len, ACT
32f9c4cfa7SFilip Tehlar             + '\x00\x00\x00\x01'   # rsvd, map-version, EID-AFI=ipv4
33f9c4cfa7SFilip Tehlar             + '\x06\x00\x02\x00'   # EID prefix
34f9c4cfa7SFilip Tehlar             + '\x01\x01\xff\x00'   # prio, weight, mprio, mweight
35f9c4cfa7SFilip Tehlar             + '\x00\x05\x00\x01'   # unused, LpR, Loc-AFI
36f9c4cfa7SFilip Tehlar             + '\x06\x00\x03\x02')  # locator
37f9c4cfa7SFilip Tehlar
38f9c4cfa7SFilip Tehlarrequest_nonce_offset = 36
39f9c4cfa7SFilip Tehlarreply_nonce_offset = 4
40f9c4cfa7SFilip Tehlar
41f9c4cfa7SFilip Tehlarrequest_eid_offset = 60
42f9c4cfa7SFilip Tehlarreply_eid_offset = 24
43f9c4cfa7SFilip Tehlar
44f9c4cfa7SFilip Tehlarreply_rloc_offset = 36
45f9c4cfa7SFilip Tehlar
46f9c4cfa7SFilip Tehlar
47f9c4cfa7SFilip Tehlardef build_reply(nonce, deid):
48f9c4cfa7SFilip Tehlar  if deid not in mappings:
49f9c4cfa7SFilip Tehlar    raise Exception('No mapping found for eid {}!'.format(repr(deid)))
50f9c4cfa7SFilip Tehlar  m = mappings[deid]
51f9c4cfa7SFilip Tehlar
52f9c4cfa7SFilip Tehlar  # prepare reply data
53f9c4cfa7SFilip Tehlar  reply = bytearray(reply_data)
54f9c4cfa7SFilip Tehlar
55f9c4cfa7SFilip Tehlar  # update rloc field in reply message
56f9c4cfa7SFilip Tehlar  rloc = bytearray(m[0])
57f9c4cfa7SFilip Tehlar
58f9c4cfa7SFilip Tehlar  for i in range(0, 4):
59f9c4cfa7SFilip Tehlar    reply[reply_rloc_offset + i] = rloc[i]
60f9c4cfa7SFilip Tehlar
61f9c4cfa7SFilip Tehlar  # update eid prefix field
62f9c4cfa7SFilip Tehlar  for i in range(0, 4):
63f9c4cfa7SFilip Tehlar    reply[reply_eid_offset + i] = deid[i]
64f9c4cfa7SFilip Tehlar
65f9c4cfa7SFilip Tehlar  # update nonce
66f9c4cfa7SFilip Tehlar  for i in range(0, 8):
67f9c4cfa7SFilip Tehlar    reply[reply_nonce_offset + i] = nonce[i]
68f9c4cfa7SFilip Tehlar
69f9c4cfa7SFilip Tehlar  return reply
70f9c4cfa7SFilip Tehlar
71f9c4cfa7SFilip Tehlar
72f9c4cfa7SFilip Tehlardef run(host, port):
73f9c4cfa7SFilip Tehlar  sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
74f9c4cfa7SFilip Tehlar  server_address = (host, int(port))
75f9c4cfa7SFilip Tehlar  sock.bind(server_address)
76f9c4cfa7SFilip Tehlar
77f9c4cfa7SFilip Tehlar  while True:
78f9c4cfa7SFilip Tehlar    data, address = sock.recvfrom(4096)
79f9c4cfa7SFilip Tehlar
80f9c4cfa7SFilip Tehlar    # extract nonce from request
81f9c4cfa7SFilip Tehlar    nonce = data[request_nonce_offset:request_nonce_offset+8]
82f9c4cfa7SFilip Tehlar
83f9c4cfa7SFilip Tehlar    # extract deid
84f9c4cfa7SFilip Tehlar    deid = data[request_eid_offset:request_eid_offset+4]
85f9c4cfa7SFilip Tehlar
86f9c4cfa7SFilip Tehlar    rp = build_reply(nonce, deid)
87f9c4cfa7SFilip Tehlar    sock.sendto(rp, address)
88f9c4cfa7SFilip Tehlar
89f9c4cfa7SFilip Tehlar
90f9c4cfa7SFilip Tehlarif __name__ == "__main__":
91f9c4cfa7SFilip Tehlar  if len(sys.argv) < 2:
92f9c4cfa7SFilip Tehlar    raise Exception('IP and port expected')
93f9c4cfa7SFilip Tehlar
94f9c4cfa7SFilip Tehlar  run(sys.argv[1], sys.argv[2])