Ejemplo n.º 1
0
    def HandleDhcpDiscover(self, packet):
        self.app.logger.info('DISCOVER from %s', packet.str_mac)
        self.app.logger.debug(packet.str())

        node = Node.query.get(packet.str_mac)

        if node is None:
            self.app.logger.info('Node %s has not listen in database', packet.str_mac)
            events.PyBootstrapperEventDhcpUnknownHost.register(packet.str_mac)
            return

        offer = DhcpPacket()
        offer.CreateDhcpOfferPacketFrom(packet)
        yiaddr = node.offer(self.icmp_test_alive)

        if packet.str_user_class == 'gPXE':
            options = node.gpxe_options
        else:
            options = node.pxe_options

        for opt in options:
            offer.SetOption(opt.option, opt.binary)

        offer.SetOption("yiaddr", yiaddr.words)
        offer.SetOption("siaddr", self.listen_on_ip.list())

        self.app.logger.debug(offer.str())

        if self.SendDhcpPacketTo(offer, self.broadcast, self.emit_port) <= 0:
            self.app.logger.error('Could not send DHCP offer to %s', packet.str_mac)
Ejemplo n.º 2
0
    def __init__(self):
        DhcpPacket.__init__(self)

        self.SetOption("htype",[1])
        self.SetOption("hlen",[6])
        self.SetOption("xid",[0x34,0x87,0x11,0x31])
        self.SetOption("host_name", strlist("xyang-test").list())
Ejemplo n.º 3
0
	def ap_func( self ):
		global selfmac
		def sendlan( o ):
			o.dst = gwmac
			o.src = selfmac
			print "发送出去"
			print `o`
			print "发送结束"
			#lancap.send( o )
			#self.send_s.sendto(str(o),0,(gwip,53) )
			print "结果:", wincap.sendto( self.send_s, str(o), (gwip,53)  )
		
		print "开始AP线程."
		lancap = getcap( lanid )
		apcap  = getcap( apid  )
		for a, b in apcap:
			d = dpkt.ethernet.Ethernet( b )
			#d.dst = gwmac
			if isinstance ( d.data, dpkt.ip6.IP6): continue
			print `d`
			ip = d.data
			if isinstance( d.data, dpkt.arp.ARP ):
				print "ARP包"
				#sendlan( d )
				continue
			if ip.dst == "\xff" * 6:
				# 广播包,直接转
				print "广播包"
				d.src = selfmac
				lancap.send( d )
			if isinstance( d.data.data, dpkt.udp.UDP ):
				if not selfmac: selfmac = d.dst
				udp = ip.data
				print "UDP 包",tip(ip.src),ip.data.sport,"==>", tip(ip.dst),udp.dport
				if udp.dport == 67:
					print "DHCP"
					pak = DhcpPacket()
					pak.DecodePacket( udp.data )
					print pak.str()
					if pak.GetOption("dhcp_message_type")
					continue
				p = self.up.handleOut( ip.src, ip.data.sport, ip.dst, ip.data.dport )
				d.data.src = selfip
				if( ip.data.dport == 53 ):
					d.data.dst = dnsip
				d.data.sum = 0
				d.data.id = 0
			#	sendlan( d )
			
	def lan_func(self ):
		lancap = getcap( lanid )
		apcap = getcap( apid )
		lancap.setfilter(  )
Ejemplo n.º 4
0
    def HandleDhcpRequest(self, packet):

        self.app.logger.info('REQUEST from %s', packet.str_mac)
        self.app.logger.debug(packet.str())

        node = Node.query.get(packet.str_mac)

        renew_ip = self._list2long(packet.GetOption("ciaddr"))
        new_ip = self._list2long(packet.GetOption('request_ip_address'))

        server_id = self._list2long(packet.GetOption('server_identifier'))

        lease = None

        if not server_id:  # INIT-REBOOT
            lease = node.lease(new_ip)

        elif ipv4(server_id) == self.listen_on_ip:  # SELECT
            request_ip_address = renew_ip or new_ip
            if not request_ip_address:
                self.app.logger.error('Got DHCP REQUEST from %s with empty request_ip_address and ciaddr', packet.str_mac)
            else:
                lease = node.lease(request_ip_address, existen=renew_ip)

        else:
            self.app.logger.info('Node %s has accept offer from another server', packet.str_mac)
            node.cleanup_offers()
            return

        if not lease:
            self.nack(packet)
            return

        ack = DhcpPacket()
        ack.CreateDhcpAckPacketFrom(packet)

        if packet.str_user_class in ['gPXE', 'iPXE']:
            options = node.gpxe_options
        else:
            options = node.pxe_options

        for opt in options:
            ack.SetOption(opt.option, opt.binary)

        ack.SetOption("yiaddr", lease.yiaddr.words)
        ack.SetOption("siaddr", self.listen_on_ip.list())

        events.PyBootstrapperEventDhcpLeasing.register(packet.str_mac, lease.yiaddr)
        node.commit_lease(lease)

        self.app.logger.debug(ack.str())
        if self.SendDhcpPacketTo(ack, self.broadcast, self.emit_port) <= 0:
            self.app.logger.error('Could not send DHCP ACK to %s', packet.str_mac)
Ejemplo n.º 5
0
    def recieve_next_dhcp_packet(self, timeout=30):
        print "Here"
        while True:
            data = select.select([self._socket], [], [], timeout)[0]

            if not len(data):
                return None

            packet_data, source_address = self._socket.recvfrom(2048)
            if packet_data:
                packet = DhcpPacket()
                packet.source_address = source_address
                packet.DecodePacket(packet_data)
                return packet
Ejemplo n.º 6
0
    def handle_dhcp_ack(self, packet: DhcpPacket) -> None:
        """Called by the requestor as soon as a DHCP ACK packet is received for
        our XID.

        In case the packet matches what we currently expect, the packet is
        parsed and the success handler called.

        The request instance (self) is removed from the requestor and will
        therefore be destroyed soon.
        """
        if self._state != self.AR_REQUEST:
            return
        self._log.debug("Received ACK")
        if not self._valid_source_address(packet):
            return
        if self._timeout_obj:
            self._timeout_mgr.del_timeout_object(self._timeout_obj)
        self._requestor.del_request(self)
        result = {}  # type: Dict[str, Any]
        result['domain'] = packet.GetOption('domain_name').decode("ascii")

        translate_ips = {
            'yiaddr': 'ip_address',
            'subnet_mask': 'subnet_mask',
            'router': 'gateway',
        }
        for opt_name in translate_ips:
            if not packet.IsOption(opt_name):
                continue
            val = packet.GetOption(opt_name)
            if len(val) == 4:
                result[translate_ips[opt_name]] = str(IPv4Address(val))

        dns = []  # type: List[str]
        result['dns'] = dns
        dns_list = packet.GetOption('domain_name_server')
        while len(dns_list) >= 4:
            dns.append(str(IPv4Address(dns_list[:4])))
            dns_list = dns_list[4:]

        if packet.IsOption('classless_static_route'):
            static_routes = parse_classless_static_routes(
                list(packet.GetOption('classless_static_route'))
            )
            if static_routes is not None:
                if 'gateway' in result:
                    # We MUST ignore a regular default route if static routes
                    # are sent.
                    del result['gateway']
                # Find and filter out default route (if any).  And set it as
                # the new gateway parameter.
                result['static_routes'] = []
                for network, netmask, gateway in static_routes:
                    if network == '0.0.0.0' and netmask == '0.0.0.0':
                        result['gateway'] = gateway
                    else:
                        result['static_routes'].append((network, netmask, gateway))
            del static_routes

        # Calculate lease timeouts (with RFC T1/T2 if not found in packet)
        lease_delta = int.from_bytes(packet.GetOption('ip_address_lease_time'), "big")
        result['lease_timeout'] = self._start_time + lease_delta
        if packet.IsOption('renewal_time_value'):
            renewal_delta = int.from_bytes(
                packet.GetOption('renewal_time_value'), "big"
            )
        else:
            renewal_delta = int(lease_delta * 0.5) + random.randint(-5, 5)
        result['renewal_timeout'] = self._start_time + renewal_delta
        if packet.IsOption('rebinding_time_value'):
            rebinding_delta = int.from_bytes(
                packet.GetOption('rebinding_time_value'), "big"
            )
        else:
            rebinding_delta = int(lease_delta * 0.875) + random.randint(-5, 5)
        result['rebinding_timeout'] = self._start_time + rebinding_delta

        self._success_handler(result)
Ejemplo n.º 7
0
 def _set_lease_time(self, packet: DhcpPacket) -> None:
     if self._lease_time is None:
         return
     packet.SetOption('ip_address_lease_time', self._lease_time.to_bytes(4, "big"))
Ejemplo n.º 8
0
#!/usr/bin/python

from pydhcplib.dhcp_packet import DhcpPacket
from pydhcplib.type_strlist import strlist
from pydhcplib.type_ipv4 import ipv4

packet = DhcpPacket()

packet.SetOption("op", [1])
packet.SetOption("domain_name", strlist("anemon.org").list())
packet.SetOption("router", ipv4("192.168.0.1").list() + [6, 4, 2, 1])
packet.SetOption("time_server", [100, 100, 100, 7, 6, 4, 2, 1])
packet.SetOption("yiaddr", [192, 168, 0, 18])

print packet.str()
Ejemplo n.º 9
0
def preparePacket(xid=None,
                  giaddr='0.0.0.0',
                  chaddr='00:00:00:00:00:00',
                  ciaddr='0.0.0.0',
                  yiaddr='0.0.0.0',
                  msgtype='discover',
                  required_opts=[]):
    req = DhcpPacket()
    req.SetOption('op', [1])
    req.SetOption('htype', [1])
    req.SetOption('hlen', [6])
    req.SetOption('hops', [0])
    if not xid:
        xid = genxid()
    req.SetOption('xid', xid)
    req.SetOption('giaddr', ipv4(giaddr).list())
    req.SetOption('chaddr', hwmac(chaddr).list() + [0] * 10)
    req.SetOption('ciaddr', ipv4(ciaddr).list())
    if msgtype == 'request':
        mt = 3
    elif msgtype == 'release':
        mt = 7
    else:
        mt = 1
    if mt == 3:
        req.SetOption('yiaddr', ipv4(yiaddr).list())
        req.SetOption('request_ip_address', ipv4(yiaddr).list())
    req.SetOption('dhcp_message_type', [mt])
    return req
Ejemplo n.º 10
0
#!/usr/bin/python

from pydhcplib.dhcp_packet import DhcpPacket
from pydhcplib.type_strlist import strlist
from pydhcplib.type_ipv4 import ipv4


packet = DhcpPacket()

packet.SetOption("op",[1])
packet.SetOption("domain_name",strlist("anemon.org").list())
packet.SetOption("router",ipv4("192.168.0.1").list()+[6,4,2,1])
packet.SetOption("time_server",[100,100,100,7,6,4,2,1])
packet.SetOption("yiaddr",[192,168,0,18])

print(packet.str())
Ejemplo n.º 11
0
#!/usr/bin/python

from pydhcplib.dhcp_packet import DhcpPacket
from pydhcplib.type_strlist import strlist
from pydhcplib.type_ipv4 import ipv4


packet = DhcpPacket()

packet.SetOption("op",[1])
packet.SetOption("domain_name",strlist("anemon.org").list())
packet.SetOption("router",ipv4("192.168.0.1").list()+[6,4,2,1])
packet.SetOption("time_server",[100,100,100,7,6,4,2,1])
packet.SetOption("yiaddr",[192,168,0,18])

print packet.str()
Ejemplo n.º 12
0
	def getselfip( self):
		
		pak = DhcpPacket()
		pak.SetOption("op", [1] )
		#pak.SetOption("time_server", [100,100,100,7,6,4,2,1])
		pak.SetOption("yiaddr", [0,0,0,0])
		pak.SetOption("giaddr", [0,0,0,0])
		pak.SetOption("ciaddr", [0,0,0,0])
		pak.SetOption("dhcp_message_type",[1])
		pak.SetOption("hlen",[6])
		pak.SetOption("flags",[1<<7,0] )
#		pak.SetOption("chaddr",[1,2,3,4,5,6,0,0,0,0,0,0,0,0,0,0] )
		pak.SetOption("chaddr",[0, 0x24, 0x2c, 0xf2, 0x01, 0xe2 ] + [ 0 for x in range(10)] )
		pak.SetOption("xid",genxid( ))
		pak.SetOption("htype",[1])
		pak.SetOption("host_name",[ 0x28, 0x27,0x29])
		
		pak.SetOption("request_ip_address", [1,1,1,111] )
		pak.SetOption("parameter_request_list",[1,28,2,3,15,6,12,40,41,42])
		
		#d = dpkt.dhcp.DHCP( chaddr = selfmac, xid=00332,op=dpkt.dhcp.DHCPDISCOVER, opts=( (dpkt.dhcp.DHCP_OPT_REQ_IP,""),) )
		d = pak.EncodePacket()
	
		i = 300  - len(d)
		u = dpkt.udp.UDP( dport=67, sport=68, data=d + "\x00" * i)
		u.ulen = len(u)
		i = dpkt.ip.IP( dst="\xff"*4, src="\x00"*4, data = u, p=dpkt.ip.IP_PROTO_UDP, ttl=128, tos = 0x10 )
		i.len = len(i)
		e = dpkt.ethernet.Ethernet( dst="\xff" * 6, src=macaddr, data = i )
		print `e`
		cap = getcap( lanid )
		p = "ffffffffffff00242ce7f885080045100148000000001011a99600000000ffffffff0044004301343cda0101060087ee9dc00000800000000000000000000000000000000000000c29f201e2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006382536332040101016f350101370a011c02030f060c28292aff0000000000000000000000000000000000000000000000000000000000000000000000000000"
		ps = ""
		for s in range( len(p)/ 2 ):
			ps += eval("'\\x"+p[s*2]+p[s*2+1]+"'") 
		ps = e
		cap.send( str(ps) )
Ejemplo n.º 13
0
def prepare_packet(giaddr='0.0.0.0',
                   chaddr='00:00:00:00:00:00',
                   ciaddr='0.0.0.0',
                   hostname=None):
    req = DhcpPacket()
    req.SetOption('op', [1])
    req.SetOption('htype', [1])
    req.SetOption('hlen', [6])
    req.SetOption('hops', [0])
    req.SetOption('xid', genxid())
    req.SetOption('giaddr', ipv4(giaddr).list())
    req.SetOption('chaddr', hwmac(chaddr).list() + [0] * 10)
    req.SetOption('ciaddr', ipv4('0.0.0.0').list())
    req.SetOption('dhcp_message_type', [3])  # request
    req.SetOption('request_ip_address', ipv4(ciaddr).list())
    if hostname:
        req.SetOption('host_name', strlist(hostname).list())
    return req
Ejemplo n.º 14
0
#!/usr/bin/python

from pydhcplib.dhcp_packet import DhcpPacket
from pydhcplib.type_strlist import strlist
from pydhcplib.type_ipv4 import ipv4


packet = DhcpPacket()

packet.SetOption("domain_name",strlist("anemon.org").list())
packet.SetOption("router",[192,168,0,1])
packet.SetOption("time_server",[192,168,1,50,192,168,1,51])
packet.SetOption("yiaddr",[192,168,0,18])
packet.SetOption("op", )

print packet.str()
Ejemplo n.º 15
0
def ack(packet, defaultnbi, msgtype):
    """
        The ack function constructs either a BSDP[LIST] or BSDP[SELECT] ACK
        DhcpPacket(), determined by the given msgtype, 'list' or 'select'.
        It calls the previously defined getSysIdEntitlement() and parseOptions()
        functions for either msgtype.
    """

    bsdpack = DhcpPacket()

    try:
        # Get the requesting client's clientsysid and MAC address from the
        # BSDP options
        clientsysid = \
        str(strlist(packet.GetOption('vendor_class_identifier'))).split('/')[2]

        clientmacaddr = chaddr_to_mac(packet.GetOption('chaddr'))

        # Decode and parse the BSDP options from vendor_encapsulated_options
        bsdpoptions = \
            parseOptions(packet.GetOption('vendor_encapsulated_options'))

        # Figure out the NBIs this clientsysid is entitled to
        enablednbis = getSysIdEntitlement(nbiimages, clientsysid,
                                          clientmacaddr, msgtype)

        # The Startup Disk preference panel in OS X uses a randomized reply port
        #   instead of the standard port 68. We check for the existence of that
        #   option in the bsdpoptions dict and if found set replyport to it.
        if 'reply_port' in bsdpoptions:
            replyport = int(
                str(
                    format(bsdpoptions['reply_port'][0], 'x') +
                    format(bsdpoptions['reply_port'][1], 'x')), 16)
        else:
            replyport = 68

        # Get the client's IP address, a standard DHCP option
        clientip = ipv4(packet.GetOption('ciaddr'))
        if str(clientip) == '0.0.0.0':
            clientip = ipv4(packet.GetOption('request_ip_address'))
            logging.debug(
                "Did not get a valid clientip, using request_ip_address %s instead"
                % (str(clientip), ))
    except:
        logging.debug("Unexpected error: ack() common %s" % sys.exc_info()[1])
        raise

    #print 'Configuring common BSDP packet options'

    # We construct the rest of our common BSDP reply parameters according to
    #   Apple's spec. The only noteworthy parameter here is sname, a zero-padded
    #   64 byte string list containing the BSDP server's hostname.
    bsdpack.SetOption("op", [2])
    bsdpack.SetOption("htype", packet.GetOption('htype'))
    bsdpack.SetOption("hlen", packet.GetOption('hlen'))
    bsdpack.SetOption("xid", packet.GetOption('xid'))
    bsdpack.SetOption("ciaddr", packet.GetOption('ciaddr'))
    bsdpack.SetOption("siaddr", serverip)
    bsdpack.SetOption("yiaddr", [0, 0, 0, 0])
    bsdpack.SetOption("sname",
                      strlist(serverhostname.ljust(64, '\x00')).list())
    bsdpack.SetOption("chaddr", packet.GetOption('chaddr'))
    bsdpack.SetOption("dhcp_message_type", [5])
    bsdpack.SetOption("server_identifier", serverip)
    bsdpack.SetOption("vendor_class_identifier", strlist('AAPLBSDPC').list())

    # Process BSDP[LIST] requests
    if msgtype == 'list':
        #print 'Creating LIST packet'
        try:
            nameslength = 0
            n = 2

            # First calculate the total length of the names of all combined
            #   NBIs, a required parameter that is part of the BSDP
            #   vendor_encapsulated_options.
            for i in enablednbis:
                nameslength += i['length']

            # Next calculate the total length of all enabled NBIs
            totallength = len(enablednbis) * 5 + nameslength

            # The bsdpimagelist var is inserted into vendor_encapsulated_options
            #   and comprises of the option code (9), total length of options,
            #   the IDs and names of all NBIs and the 4 byte string list that
            #   contains the default NBI ID. Promise, all of this is part of
            #   the BSDP spec, go look it up.
            bsdpimagelist = [9, totallength]
            bsdpimagelist += imagenameslist
            defaultnbi = '%04X' % defaultnbi

            # Encode the default NBI option (7) its standard length (4) and the
            #   16 bit string list representation of defaultnbi
            defaultnbi = [7,4,129,0] + \
            [int(defaultnbi[i:i+n], 16) for i in range(0, len(defaultnbi), n)]

            if int(defaultnbi[-1:][0]) == 0:
                hasnulldefault = True
            else:
                hasnulldefault = False

            # To prevent sending a default image ID of 0 (zero) to the client
            #   after the initial INFORM[LIST] request we test for 0 and if
            #   so, skip inserting the defaultnbi BSDP option. Since it is
            #   optional anyway we won't confuse the client.
            compiledlistpacket = strlist([1, 1, 1, 4, 2, 128, 128]).list()
            if not hasnulldefault:
                compiledlistpacket += strlist(defaultnbi).list()
            compiledlistpacket += strlist(bsdpimagelist).list()

            # And finally, once we have all the image list encoding taken care
            #   of, we plug them into the vendor_encapsulated_options DHCP
            #   option after the option header:
            #   - [1,1,1] = BSDP message type (1), length (1), value (1 = list)
            #   - [4,2,255,255] = Server priority message type 4, length 2,
            #       value 0xffff (65535 - Highest)
            #   - defaultnbi (option 7) - Optional, not sent if '0'
            #   - List of all available Image IDs (option 9)

            bsdpack.SetOption("vendor_encapsulated_options",
                              compiledlistpacket)

            # Some debugging to stdout
            logging.debug('-=========================================-')
            logging.debug("Return ACK[LIST] to " + str(clientip) + ' on ' +
                          str(replyport))
            if hasnulldefault is False:
                logging.debug("Default boot image ID: " + str(defaultnbi[2:]))
        except:
            logging.debug("Unexpected error ack() list: %s" %
                          sys.exc_info()[1])
            raise

    # Process BSDP[SELECT] requests
    elif msgtype == 'select':
        #print 'Creating SELECT packet'
        # Get the value of selected_boot_image as sent by the client and convert
        #   the value for later use.
        try:
            imageid = int(
                '%02X' % bsdpoptions['selected_boot_image'][2] +
                '%02X' % bsdpoptions['selected_boot_image'][3], 16)
        except:
            logging.debug("Unexpected error ack() select: imageid %s" %
                          sys.exc_info()[1])
            raise

        # Initialize variables for the booter file (kernel) and the dmg path
        booterfile = ''
        rootpath = ''
        selectedimage = ''
        if nbiurl.hostname[0].isalpha():
            basedmgpath = getBaseDmgPath(nbiurl)

        # Iterate over enablednbis and retrieve the kernel and boot DMG for each
        try:
            for nbidict in enablednbis:
                if nbidict['id'] == imageid:
                    booterfile = nbidict['booter']
                    rootpath = basedmgpath + nbidict['dmg']
                    # logging.debug('-->> Using boot image URI: ' + str(rootpath))
                    selectedimage = bsdpoptions['selected_boot_image']
                    # logging.debug('ACK[SELECT] image ID: ' + str(selectedimage))
        except:
            logging.debug("Unexpected error ack() selectedimage: %s" %
                          sys.exc_info()[1])
            raise

        # Generate the rest of the BSDP[SELECT] ACK packet by encoding the
        #   name of the kernel (file), the TFTP path and the vendor encapsulated
        #   options:
        #   - [1,1,2] = BSDP message type (1), length (1), value (2 = select)
        #   - [8,4] = BSDP selected_image (8), length (4), encoded image ID
        try:
            bsdpack.SetOption("file",
                              strlist(booterfile.ljust(128, '\x00')).list())
            bsdpack.SetOption("root_path", strlist(rootpath).list())
            bsdpack.SetOption("vendor_encapsulated_options",
                              strlist([1, 1, 2, 8, 4] + selectedimage).list())
        except:
            logging.debug("Unexpected error ack() select SetOption: %s" %
                          sys.exc_info()[1])
            raise

        try:
            # Some debugging to stdout
            logging.debug('-=========================================-')
            logging.debug("Return ACK[SELECT] to " + str(clientip) + ' on ' +
                          str(replyport))
            logging.debug(
                "--> TFTP path: %s\n-->Boot image URI: %s" %
                (str(strlist(bsdpack.GetOption("file"))), str(rootpath)))
        except:
            logging.debug("Unexpected error ack() select print debug: %s" %
                          sys.exc_info()[1])
            raise

    # Return the finished packet, client IP and reply port back to the caller
    return bsdpack, clientip, replyport