2 # VSYS script to configure routes on virtual network interfaces from the root slice
3 # Claudio Freire - 2011/05/19
5 # Gets slice name as argv[1]
6 # Takes routing rules on stdin, one per line
7 # rule := command ' ' target ' gw ' host device
8 # command := 'add' | 'del'
9 # target := host | network
10 # network := host [ '/' netmask ]
12 # host := number '.' number '.' number '.' number
14 # device := ( tun | tap ) slice '-' number
17 # All networks and gateways MUST belong to the virtual
18 # network assigned to the slice (according to the vsys_vnet tag)
22 # add 10.0.0.0/24 gw 10.0.0.1 tap754-0
23 # del 10.0.0.0/24 gw 10.0.0.1 tap754-0
36 vsys_config_dir = "/etc/planetlab/vsys-attributes"
38 if len(sys.argv) != 2: sys.exit(1)
40 # VSYS scripts get slicename as $1
42 sliceid = pwd.getpwnam(slicename).pw_uid
44 netblock_config=os.path.join(vsys_config_dir,slicename,"vsys_vnet")
46 # Read netblock allocation file
51 for netblock in open(netblock_config,'r'):
52 vnet_base, vnet_mask = netblock.split('/')
53 vnet_mask = int(vnet_mask)
55 vnet_base = vnet_mask = None
58 print >>sys.stderr, "Could not find entry for slice %s in netblock config file %s" % (slicename, netblock_config)
61 vnet_int = struct.unpack('!L', socket.inet_aton(vnet_base))[0]
62 vnet_int = (vnet_int >> (32-vnet_mask)) << (32-vnet_mask)
63 mask_int = (0xffffffff >> (32-vnet_mask)) << (32-vnet_mask)
66 rule_re = r"(?P<cmd>add|del)\s+(?P<targetbase>(?:\d{1,3}[.]){3}\d{1,3})(?:/(?P<targetprefix>\d{1,2}))?\s+gw\s+(?P<gw>(?:\d{1,3}[.]){3}\d{1,3}) (?P<dev>(?:tun|tap)%d-\d{1,5})" % (sliceid,)
67 rule_re = re.compile(rule_re)
69 ### Read args from stdin
70 for argline in sys.stdin:
71 argline = argline.strip()
73 # Match rule against the regex,
74 # validating overall structure in the process
75 match = rule_re.match(argline)
77 print >>sys.stderr, "Invalid rule %r" % (argline,)
80 # Validate IPs involved
82 target_ip_int = struct.unpack('!L',
83 socket.inet_aton(match.group('targetbase')))[0]
85 print >>sys.stderr, "Invalid target ip: %s" % (e,)
89 gw_ip_int = struct.unpack('!L',
90 socket.inet_aton(match.group('gw')))[0]
92 print >>sys.stderr, "Invalid target ip: %s" % (e,)
95 if match.group('targetprefix'):
97 target_mask = int(match.group('targetprefix'))
99 print >>sys.stderr, "Invalid target mask: %s" % (e,)
105 ifname = match.group('dev')
107 # Shouldn't happen, but just in case
108 print >>sys.stderr, "Invalid rule %r: Unspecified interface" % (argline,)
111 # Make sure all IPs/networks fall within the assigne vnet
112 if target_mask < vnet_mask:
113 print >>sys.stderr, "Invalid rule %r: target must belong to the %s/%s network" % (argline, vnet_base, vnet_mask)
116 if (target_ip_int & mask_int) != vnet_int:
117 print >>sys.stderr, "Invalid rule %r: target must belong to the %s/%s network" % (argline, vnet_base, vnet_mask)
120 if (gw_ip_int & mask_int) != vnet_int:
121 print >>sys.stderr, "Invalid rule %r: gateway must belong to the %s/%s network" % (argline, vnet_base, vnet_mask)
124 # Revalidate command (just in case)
125 command = match.group("cmd")
126 if command not in ('add','del'):
127 print >>sys.stderr, "Invalid rule %r: invalid command" % (argline,)
131 routeargs = [ "/sbin/route", command ]
133 target_ip_str = socket.inet_ntoa(
134 struct.pack('!L', target_ip_int))
136 gw_ip_str = socket.inet_ntoa(
137 struct.pack('!L', gw_ip_int))
139 if target_mask != 32:
141 "-net", "%s/%d" % (target_ip_str, target_mask)
144 routeargs.append(target_ip_str)
151 proc = subprocess.Popen(routeargs)
153 print >>sys.stderr, "Could not set up route"