1

私は大学の割り当てに低レベルのネットワークインターフェイスアクセスを持たせるためのミニモジュールに取り組んでいました(明確にするために、これは実際の割り当てではありません)。実際の割り当ては C で行われましたが、その後、ctypes を使って練習することにし、Linux と Python 2.7 をターゲットにして lib を開始しました。

Python 3.3 は、私がカバーしようとした多くの機能を公開していること、およびバージョン 2.3 前後からすでにfcntl.ioctl モジュールがあることを知っています (正確なバージョンは問題ではなく、存在するだけです)。 2.7)、このタスクは学習用でした。

私が遭遇した問題は非常に単純です。C の対応するクラスのレイアウトに基づいて、次のクラスを定義しました (明確にするために、長いスニペットを使用してください)。

class struct_ifmap(Structure):
    _fields_ = [
        ('mem_start', c_ulong),
        ('mem_end', c_ulong),
        ('base_addr', c_ushort),
        ('irq', c_ubyte),
        ('dma', c_ubyte),
        ('port', c_ubyte),]

class union_ifreq_anon(Union):
    _fields_ = [
        ('ifr_addr', struct_sockaddr), 
        ('ifr_dstaddr', struct_sockaddr),
        ('ifr_broadaddr', struct_sockaddr),
        ('ifr_netmask', struct_sockaddr),
        ('ifr_hwaddr', struct_sockaddr),
        ('ifr_flags', c_short),
        ('ifr_ifindex', c_int),
        ('ifr_metric', c_int),
        ('ifr_mtu', c_int),
        ('ifr_map', struct_ifmap),
        ('ifr_slave', c_char),
        ('ifr_newname', c_char),
        ('ifr_data', c_char_p),
        ('raw', c_short * 15),]

class struct_ifreq(Structure):
    __IFNAMSIZ = 16
    _anonymous_ = [
        ('u'),]
    _fields_ = [
        ('ifr_name', c_char * __IFNAMSIZ),
        ('u', union_ifreq_anon),]

そして、次の機能:

def _getfahwdraddr(name):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
        socket.IPPROTO_IP)
    ifr = struct_ifreq()
    ifr.ifr_name = name
    result = _libc.ioctl(sock.fileno(), 0x8927, pointer(ifr))
    if result != 0:
        raise OSError(get_errno())
    return ''.join(['%02x:' % pair for pair in \
ifr.ifr_hwaddr.sa_data[0:6]])[:-1]

これにより得られる出力は -6c:39:-1b:XX:XX:XX であり、実際の MAC、つまり 94:39:e5:XX:XX:XX とは一致しません。1 つの手がかりは、一部の要素が正しいことかもしれませんが、ご覧のとおり、出力は単に間違っています。理由がわかりません。

驚いたことに、SO で同様の質問を見つけましたが、ほぼ同じことを目指していますが、パックされた構造と python 独自の ioctl を使用しています。それだけで機能します: Getting MAC Address . それでも、私の問題は、ctype 構造体を正しく表現して使用する方法です。

4

1 に答える 1

0

あなたは正しい答えを持っています、あなたはそれを正しくフォーマットしていません:

-6c:39:-1b:XX:XX:XX

それは符号付きバイトを表示しています。あなたが望む結果はこれです:

94:39:e5:XX:XX:XX

これは、符号なしバイトとまったく同じ値です。比較:

>>> hex(0x100-0x6c)
'0x94'
>>> hex(0x100-0x1b)
'0xe5'

をどのように定義しているかを示していませんstruct_sockaddrc_uint8 * 14の代わりにunsigned 型を使用するだけで、そこで修正できますc_char * 14

または、フォーマット中にキャストすることもできます。

return ''.join(['%02x:' % c_uint8(pair).value for pair in
                ifr.ifr_hwaddr.sa_data[0:6]])[:-1]

または、同じ問題を解決する他の 30 の方法。

于 2013-02-07T23:34:03.020 に答える