Exemplo n.º 1
0
def subnet_equ(prf_a=None, prf_b=None, mask_a=None, mask_b=None):
    if prf_a is None or prf_b is None or mask_a is None or mask_b is None:
        return False
    if mask_a != mask_b:
        return False

    a = ip_to_bin(prf_a) & ip_to_bin(masklen2netmask(mask_a))
    b = ip_to_bin(prf_b) & ip_to_bin(masklen2netmask(mask_b))

    if a == b:
        return True
    else:
        return False
Exemplo n.º 2
0
    def action(self, packet):
	targetip = utils.bin_to_ip(packet.data.src)
	targetport = 137
	nbns_response = packet.data.data.data
	nbns_response.op = 0x8500
	# For each question, add an answer
	for query in nbns_response.qd:
	    name = decode_name(query.name).rstrip()
	    address = self.getAddress(name)
	    if not address:
		out.debug("%s: Skipped Query from %s for %s" % (self.getName(), targetip, name), 0)
		continue
	    answer = NS.RR()
	    answer.name = query.name # We reinsert in encoded format
	    answer.type = query.type
	    answer.cls = query.cls
	    answer.ttl = 120 # Not very long TTL
	    answer.rlen = 6
	    answer.rdata = '\x00\x00' + utils.ip_to_bin(address) # 0x0000 is flags for Unique name + B-Node
	    nbns_response.an.append(answer)
	nbns_response.qd = []

	if len(nbns_response.an) == 0:
	    return False
	# Response is a UDP packet with 137 source port and Query's IP+Port as destination
	sock = socket(AF_INET, SOCK_DGRAM)
	sock.bind(('0.0.0.0', targetport))
	sock.sendto(str(nbns_response), (targetip, packet.data.data.sport))
	sock.close()
	for answer in nbns_response.an:
	    out.verbose("%s: \tResponse: %s - %s" % (self.getName(), decode_name(answer.name).rstrip(), utils.bin_to_ip(answer.rdata[2:])))
	return True
Exemplo n.º 3
0
    def parseData(self, data):
	packet = dpkt.ethernet.Ethernet(data)
	# Skip packets sent from our machine
	if packet.dst == get_mac(self.interface[0]):
		return None
	# ARP
	if packet.type == dpkt.ethernet.ETH_TYPE_ARP:
	    packet.data = dpkt.arp.ARP(str(packet.data))
	# IPv4
	elif packet.type == dpkt.ethernet.ETH_TYPE_IP:
	    packet.data = dpkt.ip.IP(str(packet.data))
	    # UDP
	    if packet.data.p == dpkt.ip.IP_PROTO_UDP:
		packet.data.data = dpkt.udp.UDP(str(packet.data.data))
		# LLMNR (224.0.0.252:5355), same packet format as DNS
		if packet.data.dst == ip_to_bin("224.0.0.252") and packet.data.data.dport == 5355:
		    packet.data.data.data = dpkt.dns.DNS(str(packet.data.data.data))
		# Netbios Name Service (from 137 UDP to 137 UDP)
		if packet.data.data.dport == 137 and packet.data.data.dport == 137:
		    packet.data.data.data = dpkt.netbios.NS(str(packet.data.data.data))
		    
	    # TCP
	    elif packet.data.p == dpkt.ip.IP_PROTO_TCP:
		packet.data.data = dpkt.tcp.TCP(str(packet.data.data))

	return packet
Exemplo n.º 4
0
    def condition(self, packet):
	# Should be an IPv4 packet
	if packet.type != dpkt.ethernet.ETH_TYPE_IP:
	    return False
	# Should be a UDP packet
	if packet.data.p != dpkt.ip.IP_PROTO_UDP:
	    return False
	# Should have a 224.0.0.252:5355 destination
	if packet.data.dst != utils.ip_to_bin("224.0.0.252"):
	    return False
	if packet.data.data.dport != 5355:
	    return False
	# And is a LLMNR Request
	if packet.data.data.data.op & 0x8000 != 0:
	    return False
	out.verbose("%s: LLMNR request from %s" % (self.getName(), utils.bin_to_ip(packet.data.src)))
	out.verbose("%s: \tQueries: %s" % (self.getName(), ' '.join([x.name for x in packet.data.data.data.qd])))
	return True
Exemplo n.º 5
0
    def action(self, packet):
	targetip = utils.bin_to_ip(packet.data.src)
	targetport = 5355
	llmnr_response = packet.data.data.data
	llmnr_response.op = 0x8000
	# For each question, add an answer
	for query in llmnr_response.qd:
	    address = self.getAddress(query.name, query.type)
	    if not address:
		out.debug("%s: Skipped query from %s for %s" % (self.getName(), targetip, query.name), 0)
		continue
	    answer = dpkt.dns.DNS.RR()
	    answer.name = query.name
	    answer.type = query.type
	    answer.cls = query.cls
	    answer.ttl = 30
	    if answer.type == dpkt.dns.DNS_A:
		answer.rlen = 4
		answer.rdata = utils.ip_to_bin(address)
	    elif answer.type == dpkt.dns.DNS_AAAA:
		answer.rlen = 16
		answer.rdata = utils.ip6_to_bin(address)
	    llmnr_response.an.append(answer)

	if len(llmnr_response.an) == 0:
	    return False
	# Response is a UDP packet with 5355 source port and Query's source port
	# as destination port.
	sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	sock.bind(('0.0.0.0', targetport))
	sock.sendto(str(llmnr_response), (targetip, packet.data.data.sport))
	sock.close()
	for answer in llmnr_response.an:
	    if answer.type == dpkt.dns.DNS_A:
		out.verbose("%s: \tResponse: %s - %s" % (self.getName(), answer.name, utils.bin_to_ip(answer.rdata)))
	    elif answer.type == dpkt.dns.DNS_AAAA:
		out.verbose("%s: \tResponse: %s - %s" % (self.getName(), answer.name, utils.bin_to_ip6(answer.rdata)))
	return True
Exemplo n.º 6
0
def subnet_create_api():
    """
    Implementation Notes
      Creates a subnet on a network.

    Response Class (Status 201)
      Subnet {
        subnetId (string, optional): Subnet uuid.
        subnetName (string, optional): Subnet name, a user readable name.
        networkId (string, optional): Network uuid.
        cidr (string, optional): The CIDR of subnet.
        allocation_pools (Array[inline_model], optional):
          The start and end addresses for the allocation pools.
        gatewayIp (string, required): The gateway IP address.
        dnsNameservers (Array[string], optional):
          A list of DNS name servers for the subnet.
      }
      inline_model {
        start (string, optional): Start IP address. ,
        end (string, optional): End IP address.
      }

    Parameters
      Subnet (body, required): Subnet description
    """
    try:
        req = models.Subnet(request.json)
        req.validate()
    except Exception as e:
        return err_return('Parameter Invalid', 'ParameterInvalid', '',
                          HTTP_BAD_REQUEST)
    try:
        if not req.network_id:
            return err_return('networkid is required', 'ParameterInvalid', '',
                              HTTP_BAD_REQUEST)
        if not req.subnet_id:
            req_id = str(uuid.uuid4())
        else:
            req_id = req.subnet_id
            sb_name = subnet_db_get_one('name', id=req_id)
            if sb_name:
                return err_return('id(%s) in use by %s' % (req_id, sb_name),
                                  'ParameterInvalid', '', HTTP_BAD_REQUEST)
        if req.subnet_name:
            if len(req.subnet_name) > NAME_MAX_LEN:
                return err_return('Length of name must be less than 255',
                                  'ParameterInvalid', '', HTTP_BAD_REQUEST)
        else:
            req.subnet_name = ''

        external = network_db_get_one('external', id=req.network_id)
        if external is None:
            return err_return("networkid does not exist", "ParameterInvalid",
                              "", HTTP_BAD_REQUEST)
        if not req.dns_nameservers:
            req.dns_nameservers = []
        if not req.allocation_pools:
            req.allocation_pools = []
        allocation_pools = []
        for all_pool in req.allocation_pools:
            allocation_pools.append(all_pool.to_primitive())
        req.allocation_pools = allocation_pools
        for pool in req.allocation_pools:
            if ip_to_bin(pool['start']) > ip_to_bin(pool['end']):
                return err_return("end_ip must be more than start_ip",
                                  "IPRangeError", "", HTTP_BAD_REQUEST)

        if external == 0:
            if not req.cidr:
                return err_return('cidr is required', 'ParameterInvalid', '',
                                  HTTP_BAD_REQUEST)
            if not validate_cidr(req.cidr):
                return err_return('cidr invalid', 'ParameterInvalid', '',
                                  HTTP_BAD_REQUEST)
            if not req.gateway_ip:
                return err_return('gateway ip is required', 'ParameterInvalid',
                                  '', HTTP_BAD_REQUEST)
            vl2lcid = yynetworkid_to_lcvl2id(req.network_id)
            log.debug('vl2lcid=%s' % vl2lcid)
            nets = [{
                "prefix": VFW_TOR_LINK_NET_PRE,
                "netmask": VFW_TOR_LINK_NET_MASK
            }]
            cidr = str(req.cidr).split('/')
            new_prf = cidr[0]
            new_mask = int(cidr[1])
            subnets = get_subnets_by_network(req.network_id)
            for subnet in subnets:
                cidr = subnet['cidr'].split('/')
                old_prf = cidr[0]
                old_mask = int(cidr[1])
                if subnet_equ(new_prf, old_prf, new_mask, old_mask):
                    log.error('cidr is the same')
                    return err_return('subnet already exist',
                                      'ParameterInvalid', '', HTTP_BAD_REQUEST)
                nets.append({"prefix": old_prf, "netmask": old_mask})
            nets.append({"prefix": new_prf, "netmask": new_mask})
            log.debug('nets=%s' % nets)
            nw_name = network_db_get_one('name', id=req.network_id)
            payload = json.dumps({"name": nw_name, "nets": nets})
            r = lcapi.patch(conf.livecloud_url + '/v1/vl2s/%s' % vl2lcid,
                            data=payload)
            if r.status_code != HTTP_OK:
                return Response(json.dumps(NEUTRON_400)), HTTP_NOT_FOUND
            nets = r.json()['DATA']['NETS']
            for net in nets:
                if subnet_equ(net['PREFIX'], new_prf, net['NETMASK'],
                              new_mask):
                    sb_lcuuid = net['LCUUID']
                    sb_idx = net['NET_INDEX']
                    break
            else:
                log.error('sb_lcuuid no found')
                sb_lcuuid = 'sb_lcuuid no found'
                sb_idx = -1
        else:
            subnetid = subnet_db_get_one('id', network_id=req.network_id)
            if subnetid:
                return err_return('subnet(%s) already exists' % subnetid,
                                  'Fail', '', HTTP_BAD_REQUEST)
            # ISP
            if not req.allocation_pools:
                return err_return('allocation_pools can not be empty',
                                  'ParameterInvalid', '', HTTP_BAD_REQUEST)
            id = subnet_db_get_one('id', network_id=req.network_id)
            if id:
                return subnet_get(subnetid=id)
            lcuuid = network_db_get_one('lcuuid', id=req.network_id)
            isp = lc_vl2_db_get_one('isp', lcuuid=lcuuid)
            items = lc_ip_res_db_get_all(req='ip, netmask, gateway, userid',
                                         isp=isp)
            if not items:
                return err_return("No ISP IP found", "BadRequest",
                                  "Please add ISP IP to system first",
                                  HTTP_BAD_REQUEST)
            req.gateway_ip = items[0]['gateway']
            req.cidr = ip_mask_to_cidr(items[0]['ip'], items[0]['netmask'])
            isp_all_ips = []
            ip_to_userid = {}
            for it in items:
                isp_all_ips.append(it['ip'])
                ip_to_userid[it['ip']] = it['userid']
            req_ips = alloc_pools_to_ip_list(req.allocation_pools)
            for req_ip in req_ips:
                if req_ip not in isp_all_ips:
                    return err_return("%s does not exist" % req_ip,
                                      "IPInvalid", "", HTTP_BAD_REQUEST)
                if ip_to_userid[req_ip] != 0:
                    return err_return("%s in use" % req_ip, "IPInUse", "",
                                      HTTP_BAD_REQUEST)
            sb_lcuuid = str(uuid.uuid4())
            sb_idx = -1

        sql = ("INSERT INTO neutron_subnets "
               "VALUES('%s','%s','%s','%s','%s','%s','%s','%s',%d)" %
               (req_id, req.subnet_name, req.network_id, req.cidr,
                json.dumps(req.allocation_pools), req.gateway_ip,
                json.dumps(req.dns_nameservers), sb_lcuuid, sb_idx))
        log.debug('add subnet sql=%s' % sql)
        with MySQLdb.connect(**DB_INFO) as cursor:
            cursor.execute(sql)
        if external:
            sql = "UPDATE ip_resource_v2_2 SET userid=%s WHERE ip in ('-1',"
            for req_ip in req_ips:
                sql += "'%s'," % req_ip
            sql = sql[:-1]
            sql += ")"
            log.debug('sql=%s' % sql)
            with MySQLdb.connect(**LCDB_INFO) as cursor:
                cursor.execute(sql, conf.livecloud_userid)

        resp, code = subnet_get(subnetid=req_id)
        return resp, HTTP_CREATED

    except Exception as e:
        log.error(e)
        return Response(json.dumps(NEUTRON_500)), HTTP_INTERNAL_SERVER_ERROR
Exemplo n.º 7
0
def subnet_put_api(subnetid=None):
    """
    Implementation Notes
      Updates existing subnet.

    Response Class (Status 200)
      Subnet {
        subnetId (string, optional): Subnet uuid.
        subnetName (string, optional): Subnet name, a user readable name.
        networkId (string, optional): Network uuid.
        cidr (string, optional): The CIDR of subnet.
        allocation_pools (Array[inline_model], optional):
          The start and end addresses for the allocation pools.
        gatewayIp (string, optional): The gateway IP address.
        dnsNameservers (Array[string], optional):
          A list of DNS name servers for the subnet.
      }
      inline_model {
        start (string, optional): Start IP address. ,
        end (string, optional): End IP address.
      }

    Parameters
      subnetId (string, optional): The subnet uuid to act on
      Subnet (body, required): Subnet description
    """
    try:
        if not subnetid:
            return err_return('subnetId is required', "ParameterInvalid", "",
                              HTTP_BAD_REQUEST)
        db_subnet = subnet_db_get_one('*', id=subnetid)
        if not db_subnet:
            return err_return('subnetId does not exist', "ParameterInvalid",
                              "", HTTP_NOT_FOUND)
        cidr = db_subnet['cidr']
        try:
            req = models.Subnet(request.json)
            req.validate()
        except Exception as e:
            log.error(e)
            return err_return('Parameter Invalid', "ParameterInvalid", "",
                              HTTP_BAD_REQUEST)
        with MySQLdb.connect(**DB_INFO) as cursor:
            if req.subnet_name is not None:
                if len(req.subnet_name) > NAME_MAX_LEN:
                    return err_return('Length of name must be less than 255',
                                      'ParameterInvalid', '', HTTP_BAD_REQUEST)
                sql = "UPDATE neutron_subnets SET name=%s WHERE id=%s"
                cursor.execute(sql, (req.subnet_name, subnetid))
            if req.dns_nameservers is not None:
                sql = ("UPDATE neutron_subnets SET "
                       "dns_nameservers=%s WHERE id=%s")
                cursor.execute(sql,
                               (json.dumps(req.dns_nameservers), subnetid))
        if req.allocation_pools is not None:
            allocation_pools = []
            for all_pool in req.allocation_pools:
                allocation_pools.append(all_pool.to_primitive())
            req.allocation_pools = allocation_pools
            for pool in req.allocation_pools:
                if ip_to_bin(pool['start']) > ip_to_bin(pool['end']):
                    return err_return("end_ip must be more than start_ip",
                                      "IPRangeError", "", HTTP_BAD_REQUEST)
        networkid = subnetid_to_networkid(subnetid)
        db_network = network_db_get_one('*', id=networkid)
        external = db_network['external']
        log.debug('external=%s' % external)
        if external:
            if req.allocation_pools is not None:
                old_alloc_pools = json.loads(db_subnet['allocation_pools'])
                old_alloc_ips = alloc_pools_to_ip_list(old_alloc_pools)
                new_alloc_ips = alloc_pools_to_ip_list(req.allocation_pools)
                tmp_nips = copy.deepcopy(new_alloc_ips)
                for new_ip in tmp_nips:
                    if new_ip in old_alloc_ips:
                        new_alloc_ips.remove(new_ip)
                        old_alloc_ips.remove(new_ip)
                isp = lc_vl2_db_get_one('isp', lcuuid=db_network['lcuuid'])
                items = lc_ip_res_db_get_all(req='ip, userid, vifid', isp=isp)
                isp_all_ips = []
                ip_to_userid = {}
                ip_to_vifid = {}
                for it in items:
                    isp_all_ips.append(it['ip'])
                    ip_to_userid[it['ip']] = it['userid']
                    ip_to_vifid[it['ip']] = it['vifid']
                for new_alloc_ip in new_alloc_ips:
                    if new_alloc_ip not in isp_all_ips:
                        return err_return("%s invalid" % new_alloc_ip,
                                          "IPInvalid", "", HTTP_BAD_REQUEST)
                    if ip_to_userid[new_alloc_ip] != 0:
                        return err_return("%s in use" % new_alloc_ip,
                                          "IPInUse", "", HTTP_BAD_REQUEST)
                for old_alloc_ip in old_alloc_ips:
                    if ip_to_vifid[old_alloc_ip] != 0:
                        return err_return("%s in use" % old_alloc_ip,
                                          "IPInUse", "", HTTP_BAD_REQUEST)
                sql = ("UPDATE neutron_subnets SET allocation_pools='%s' "
                       "WHERE id='%s'" %
                       (json.dumps(req.allocation_pools), subnetid))
                with MySQLdb.connect(**DB_INFO) as cursor:
                    cursor.execute(sql)
                sql = ("UPDATE ip_resource_v2_2 SET userid=0 "
                       "WHERE ip in ('-1',")
                for ip in old_alloc_ips:
                    sql += "'%s'," % ip
                sql = sql[:-1]
                sql += ")"
                sql2 = ("UPDATE ip_resource_v2_2 SET userid=%s "
                        "WHERE ip in ('-1',")
                for ip in new_alloc_ips:
                    sql2 += "'%s'," % ip
                sql2 = sql2[:-1]
                sql2 += ")"
                with MySQLdb.connect(**LCDB_INFO) as cursor:
                    cursor.execute(sql)
                    cursor.execute(sql2, conf.livecloud_userid)
            return subnet_get(subnetid=subnetid)

        if req.gateway_ip is not None:
            with MySQLdb.connect(**DB_INFO) as cursor:
                sql = "UPDATE neutron_subnets SET gateway_ip=%s WHERE id=%s"
                cursor.execute(sql, (req.gateway_ip, subnetid))
        log.debug('old_cidr=%s, new_cidr=%s' % (cidr, req.cidr))
        if req.cidr and cidr != req.cidr:
            vl2lcid = yynetworkid_to_lcvl2id(networkid)
            nets = [{
                "prefix": VFW_TOR_LINK_NET_PRE,
                "netmask": VFW_TOR_LINK_NET_MASK
            }]
            subnets = get_subnets_by_network(networkid)
            for subnet in subnets:
                if str(subnet['id']) == subnetid:
                    continue
                cidr = subnet['cidr'].split('/')
                nets.append({"prefix": cidr[0], "netmask": int(cidr[1])})
            cidr = str(req.cidr).split('/')
            log.debug('netmask=%s' % cidr[1])
            nets.append({"prefix": cidr[0], "netmask": int(cidr[1])})
            nw_name = network_db_get_one('name', id=networkid)
            payload = json.dumps({"name": nw_name, "nets": nets})
            log.debug('patch vl2 data=%s' % payload)
            r = lcapi.patch(conf.livecloud_url + '/v1/vl2s/%s' % vl2lcid,
                            data=payload)
            if r.status_code != HTTP_OK:
                err = r.json()['DESCRIPTION']
                log.error(err)
                return err_return(err, 'Fail', '', HTTP_BAD_REQUEST)
            nets = r.json()['DATA']['NETS']
            for net in nets:
                if subnet_equ(net['PREFIX'], cidr[0], net['NETMASK'],
                              int(cidr[1])):
                    sb_lcuuid = net['LCUUID']
                    sb_idx = net['NET_INDEX']
                    break
            else:
                log.error('sb_lcuuid no found')
                return Response(json.dumps(NEUTRON_500)), \
                    HTTP_INTERNAL_SERVER_ERROR
            if req.allocation_pools is None:
                req.allocation_pools = []
        else:
            req.cidr = db_subnet['cidr']
            sb_lcuuid = db_subnet['lcuuid']
            sb_idx = db_subnet['net_idx']
            if req.allocation_pools is None:
                return subnet_get(subnetid=subnetid)
            new_alloc_ips = alloc_pools_to_ip_list(req.allocation_pools)
            vl2id = lc_vl2_db_get_one('id', lcuuid=sb_lcuuid)
            used_ips = lc_vif_ip_db_get_all('ip',
                                            vl2id=vl2id,
                                            net_index=sb_idx)
            for used_ip in used_ips:
                ip = used_ip['ip']
                if ip not in new_alloc_ips:
                    return err_return('used ip(%s) not in alloc pool' % ip,
                                      'ParameterInvalid', '', HTTP_BAD_REQUEST)

        sql = ("UPDATE neutron_subnets SET cidr='%s', "
               "allocation_pools='%s', lcuuid='%s', net_idx=%s "
               "WHERE id='%s'" % (req.cidr, json.dumps(
                   req.allocation_pools), sb_lcuuid, sb_idx, subnetid))
        log.debug('sql=%s' % sql)
        with MySQLdb.connect(**DB_INFO) as cursor:
            cursor.execute(sql)
        return subnet_get(subnetid=subnetid)
    except Exception as e:
        log.error(e)
        return Response(json.dumps(NEUTRON_500)), HTTP_INTERNAL_SERVER_ERROR