Python 解包缓冲数据

5

我正在使用radius中的rlm_python模块,并从coovachilli获取DHCP位置option82,其以十六进制或二进制格式呈现。

将其捕获为字符串会显示此值:\001\027\002\025\001+\001\024,但是Python显示的值被截断了,因为option82包含在TLVs-type,length,values中编码的suboptions,这意味着该字段以类型0x01(circuit ID, per RFC 3046)开头,后跟一个字节长度。

你有什么办法可以正确捕获并解包选项?

我已经使用了struct.unpack来解包该字符串,但它没有意义...因为它没有告诉我关于option82字段中打包的suboptions

Python 2.4.3 (#1, May  5 2011, 16:39:10) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from struct import *
>>> unpack('=hhl',"\001\027\002\025\001+\001\024" )
(5889, 5378, 335620865)

有什么想法吗?

更新:

Coovachilli编译时使用--locationopt82选项,并将位置作为属性发送,类似于以下内容...

rad_recv: Accounting-Request packet from host 10.66.53.49 port 53178, id=101, length=342
        ChilliSpot-Version = "1.3.0"
        ChilliSpot-Acct-View-Point = ChilliSpot-Client-View-Point
        Event-Timestamp = "Apr 18 2013 11:59:16 BST"
        User-Name = "3C-D0-F8-4A-05-68"
        Acct-Input-Octets = 0
        Acct-Output-Octets = 22851
        Acct-Input-Gigawords = 0
        Acct-Output-Gigawords = 0
        Acct-Input-Packets = 0
        Acct-Output-Packets = 370
        Acct-Session-Time = 5401
        ChilliSpot-Session-State = Authorized
        Acct-Status-Type = Interim-Update
        Acct-Session-Id = "516fbceb00000002"
        Framed-IP-Address = 10.75.33.46
        NAS-Port-Type = Wireless-802.11
        NAS-Port = 2
        NAS-Port-Id = "00000002"
        Calling-Station-Id = "3C-D0-F8-4A-05-68"
        Called-Station-Id = "00-50-56-B7-66-00"
        NAS-IP-Address = 10.75.32.7
        ChilliSpot-Location = "\001\030\002\026\001+\001\024"
        ChilliSpot-Location-Change-Count = 15
        NAS-Identifier = "VLAN299-REGENT"
        WISPr-Location-ID = "isocc=GR,cc=44,ac=01200,network=mywifi,my_Network_regent"
        WISPr-Location-Name = "REGENT"

FreeRADIUS有rlm_python模块,该模块寻找会计请求。

def accounting(p):
    file = open("/tmp/test.log","a")
    username = None
    chillilocation = None
    output = StringIO.StringIO()

    for t in p:
        if t[0] == 'User-Name':
            username = t[1]
        elif t[0] == 'ChilliSpot-Location':
            chillilocation = t[1]a
             output.write(t[1])


    content = output.getvalue()


    file.write("I am being called in radius accouting section as %s and location is %s \n" % (username,content))
    file.close()
    print "---Accounting---"
    radiusd.radlog(radiusd.L_INFO, '*** radlog call in accounting (0) ***')
    print
    print p
    return radiusd.RLM_MODULE_OK

我尝试将ChilliSpot-Location存储在stringstringIO中,并使用struct进行解包,但是没有成功。看起来它是以TLV格式存储的... 有什么想法可以将其剥离出来吗?

如何使用rlm_python和coovachilli将值捕获为字符串? - RedBaron
我已经在上面进行了更新。 - krisdigitx
不确定整个内容,但 ChilliSpot-Location 应该是一个可读的字符串。请参见规格示例(向下浏览到中间某个位置,看到 RADIUS Access-Request from CoovaChilli)。 - RedBaron
1个回答

0

unpack()函数不能将值解包为“有意义”的值。它将字符串解包为一系列数字字段,因此每个字段的大小由格式字符串中的每个字符指定(字母前面的数字是乘数)。

难道unpack()不应该使用八位字节大小的字段吗?

>>> unpack('=8B',"\001\027\002\025\001+\001\024")
(1, 23, 2, 21, 1, 43, 1, 20)
# 或者'+'是分隔符(43):
>>> unpack('=6Bh',"\001\027\002\025\001+\001\024")
(1, 23, 2, 21, 1, 43, 5121)

第一个字节可能是电路子选项代码(unpack()[0]==1),大小异常地高达23,这意味着我们没有得到整个子选项值。但我们也可能只有大小为10或8个字节的子选项包含的值。

我不确定选项82是否应该包含可读的字符串,尽管"ChilliSpot-Location"确实包含。 RFC3046指出电路子选项应包含诸如"路由器接口编号"、端口号和其他数值等内容。但是,rad_recv的这个属性真的来自于82选项吗?


感谢回复,根据Coova的说法,它来自DHCP数据包中的Option 82字段。如果解包只显示大小,那么实际内容在哪里呢?显然它代表着某些东西... - krisdigitx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接