web-dev-qa-db-ja.com

ソケットはバインドされません:そのようなデバイスはありません

だから私はこのPython 3コード:

import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(('eth0', 0))
s.send(eth_packet)

このコードは私のRaspberryPiで機能しますが、外部サーバーでは機能しません。外部サーバーで実行しようとすると、次のようになります。

# Sudo python3 test.py
s.send(eth_packet)
socket.error: [Errno 19] No such device

そして私はネットワークインターフェースの出力をチェックしました(pythonスクリプトを介して):外部サーバー(debian):

['lo [index=1, IPv4=127.0.0.1, IPv6=::1]', 'eth0:0 [index=2, IPv4=xxxxx, IPv6=None]', 'eth0 [index=2, IPv4=yyyyyy, IPv6=zzzzzzz]']

ラズベリーパイ:

['lo [index=1, IPv4=127.0.0.1, IPv6=None]', 'eth0 [index=2, IPv4=rrrrr, IPv6=None]']

誰かが何が起こっているのか説明できますか?手作りのメッセージを送信したいのですが、このエラーが発生し続けます。これはサーバーのドライバーに問題がある可能性がありますか?これはifconfigと同じ結果です。

編集

わかりました、この例ではstraceを使用しました:

#!/usr/bin/env python3

import socket
import binascii
import struct

test= '000a959d6816'
packet= struct.pack("!6s", binascii.unhexlify(bytes(test, 'UTF-8')))
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(('eth0', 0))
s.send(packet)

そしてこれはstraceの重要な部分です:

socket(PF_PACKET, SOCK_RAW, 0)          = 3
ioctl(3, SIOCGIFINDEX, {ifr_name="eth0", ifr_index=2}) = 0
bind(3, {sa_family=AF_PACKET, proto=0000, if2, pkttype=PACKET_Host, addr(0)={0, }, 20) = 0
sendto(3, "\0\n\225\235h\26", 6, 0, NULL, 0) = -1 ENXIO (No such device or address)
open("test.py", O_RDONLY)               = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=247, ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff86c5f090) = -1 ENOTTY (Inappropriate ioctl for device)
fstat(4, {st_mode=S_IFREG|0644, st_size=247, ...}) = 0
lseek(4, 0, SEEK_CUR)                   = 0
dup(4)                                  = 5
fcntl(5, F_GETFL)                       = 0x8000 (flags O_RDONLY|O_LARGEFILE)
fstat(5, {st_mode=S_IFREG|0644, st_size=247, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc1251c2000
lseek(5, 0, SEEK_CUR)                   = 0
read(5, "#!/usr/bin/env python3\n\nimport s"..., 4096) = 247
close(5)                                = 0
munmap(0x7fc1251c2000, 4096)            = 0
lseek(4, 0, SEEK_SET)                   = 0
lseek(4, 0, SEEK_CUR)                   = 0
read(4, "#!/usr/bin/env python3\n\nimport s"..., 4096) = 247
close(4)                                = 0
write(2, "Traceback (most recent call last"..., 143Traceback (most recent call last):
  File "test.py", line 11, in <module>
    s.send(packet)
socket.error: [Errno 6] No such device or address
) = 143
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fc1264050a0}, {0x428787, [], SA_RESTORER, 0x7fc1264050a0}, 8) = 0
close(3)                                = 0
16
user1226868

インターフェイスでRAWソケットをファミリPACKETにバインドする場合、2つのオブジェクトを持つタプルが必要です。

(interfaceName, protoNumber)

または5つのオブジェクト:

(interfaceName, protoNumber, pkttype, hatype, haddr)

ProtoNumberに0を指定しましたが、protoNumber0がシステムに存在しない可能性があります。

パケットファミリに関するドキュメント:packet(7)

sll_protocolは、インクルードファイルで定義されているネットワークバイトオーダーの標準イーサネットプロトコルタイプです。

linux/if_ether.hで正しいプロトコル番号を見つけてください。

5
Figus

外部サーバーがLinuxで実行されていると仮定すると、プログラムを実行できない理由がいくつかあります。

Figusですでに述べたように、実際にはプロトコル番号0を使用していますが、これは定義されていない可能性があります。あなたはより幸運かもしれません:

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, proto)

ここで、protoは、linux/if_ether.hのETH_P_ALLに対応するプロトコル番号です(一部のLinuxボックスでは3)。

だが man packetも言います:有効なUID 0またはCAP_NET_RAW機能を持つプロセスのみがパケットソケットを開くことができます。つまり、コードを実行するには、外部サーバーに対するroot権限が必要です。

1
Serge Ballesta