arping.lua

#!/usr/bin/env eco

local socket = require 'eco.socket'
local packet = require 'eco.packet'
local link = require 'eco.ip'.link

if #arg < 2 then
    print('Usage:', arg[0], 'device', 'destination')
    os.exit(1)
end

local sock, err = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(socket.ETH_P_ARP))
if not sock then
    error(err)
end

local function send_arp(device, destination)
    local res, err = link.get(device)
    if not res then
        error('get link:' .. err)
    end

    local sender_mac = res.address

    print(sender_mac .. '->ff:ff:ff:ff:ff:ff ARP', 'REQUEST ' .. destination)

    local arp_pkt = packet.arp(socket.ARPOP_REQUEST, sender_mac, nil, nil, destination)
    local eth_pkt = packet.ether(sender_mac, 'ff:ff:ff:ff:ff:ff', socket.ETH_P_ARP, arp_pkt)

    sock:sendto(eth_pkt, { ifname = device })
end

local device = arg[1]
local destination = arg[2]

send_arp(device, destination)

while true do
    local data, addr = sock:recvfrom(4096)
    if not data then
        error(addr)
    end

    local l2 = packet.from_ether(data)
    if l2.proto == socket.ETH_P_ARP then
        local l3 = l2:next()
        if l3 and l3.op == socket.ARPOP_REPLY then
            if l3.sip == destination then
                print(l2, l3)
                break
            end
        end
    end
end
generated by LDoc 1.5.0 Last updated 2026-04-09 14:48:22