Skip to content

Commit

Permalink
add support for AF_PACKET
Browse files Browse the repository at this point in the history
  • Loading branch information
lneto committed May 25, 2023
1 parent fda2a9b commit 5c115bc
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 9 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,20 @@ sudo lunatik run examples/keylocker # runs keylocker
<↑> <↑> <↓> <↓> <←> <→> <←> <→> <LCTRL> <LALT> # unlocks keyboard
```
### tap
[tap](examples/tap.lua)
is a kernel script that implements a _sniffer_ using `AF_PACKET` socket.
It prints destination and source MAC addresses followed by Ethernet type and the frame size.
#### Usage
```
sudo make examples_install # installs examples
sudo lunatik run examples/tap # runs tap
cat /dev/tap
```
## References
* [Scriptables Operating Systems with Lua](https://www.netbsd.org/~lneto/dls14.pdf)
Expand Down
48 changes: 48 additions & 0 deletions examples/tap.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
--
-- Copyright (c) 2023 ring-0 Ltda.
--
-- Permission is hereby granted, free of charge, to any person obtaining
-- a copy of this software and associated documentation files (the
-- "Software"), to deal in the Software without restriction, including
-- without limitation the rights to use, copy, modify, merge, publish,
-- distribute, sublicense, and/or sell copies of the Software, and to
-- permit persons to whom the Software is furnished to do so, subject to
-- the following conditions:
--
-- The above copyright notice and this permission notice shall be
-- included in all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--

local device = require("device")
local socket = require("socket")
local linux = require("linux")

local PACKET = socket.af.PACKET
local RAW = socket.sock.RAW
local ETH_P_ALL = 0x0003
local MTU = 1500

local function nop() end

local s = linux.stat
local tap = {name = "tap", open = nop, release = nop, mode = s.IRUGO}

local socket = socket.new(PACKET, RAW, ETH_P_ALL)
socket:bind(string.pack(">I2", ETH_P_ALL))

function tap:read()
local frame = socket:receive(MTU)
local dst, src, ethtype = string.unpack(">I6I6I2", frame)
return string.format("%X\t%X\t%X\t%d\n", dst, src, ethtype, #frame)
end

device.new(tap)

27 changes: 18 additions & 9 deletions lib/luasocket.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,27 @@ do { \
msg.msg_name = &addr; \
} while(0)

static void luasocket_checkaddr(lua_State *L, struct socket *socket, struct sockaddr *addr, int ix)
#define LUASOCKET_SOCKADDR(addr) (struct sockaddr *)&addr, sizeof(addr)

#define LUASOCKET_ADDRMAX (sizeof(struct sockaddr_ll)) /* AF_PACKET */
#define LUASOCKET_ADDRLEN (LUASOCKET_ADDRMAX - sizeof(unsigned short))
typedef struct luasocket_addr_s {
unsigned short family;
unsigned char data[LUASOCKET_ADDRLEN];
} luasocket_addr_t;

static void luasocket_checkaddr(lua_State *L, struct socket *socket, luasocket_addr_t *addr, int ix)
{
addr->sa_family = socket->sk->sk_family;
if (addr->sa_family == AF_INET) {
addr->family = socket->sk->sk_family;
if (addr->family == AF_INET) {
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
addr_in->sin_addr.s_addr = htonl((u32)luaL_checkinteger(L, ix));
addr_in->sin_port = htons((u16)luaL_checkinteger(L, ix + 1));
}
else {
size_t len;
const char *addr_data = luaL_checklstring(L, ix, &len);
memcpy(addr->sa_data, addr_data, min(sizeof(addr->sa_data), len));
memcpy(addr->data, addr_data, min(LUASOCKET_ADDRLEN, len));
}
}

Expand Down Expand Up @@ -131,7 +140,7 @@ static int luasocket_send(lua_State *L)
vec.iov_len = len;

if (unlikely(nargs >= 3)) {
struct sockaddr addr;
luasocket_addr_t addr;
luasocket_checkaddr(L, socket, &addr, 3);
luasocket_msgaddr(msg, addr);
}
Expand Down Expand Up @@ -168,10 +177,10 @@ static int luasocket_receive(lua_State *L)
static int luasocket_bind(lua_State *L)
{
struct socket *socket = luasocket_checksocket(L, 1);
struct sockaddr addr;
luasocket_addr_t addr;

luasocket_checkaddr(L, socket, &addr, 2);
luasocket_try(L, kernel_bind, socket, &addr, sizeof(addr));
luasocket_try(L, kernel_bind, socket, LUASOCKET_SOCKADDR(addr));
return 0;
}

Expand Down Expand Up @@ -200,14 +209,14 @@ static int luasocket_accept(lua_State *L)
static int luasocket_connect(lua_State *L)
{
struct socket *socket = luasocket_checksocket(L, 1);
struct sockaddr addr;
luasocket_addr_t addr;
int nargs = lua_gettop(L);
int flags;

luasocket_checkaddr(L, socket, &addr, 2);
flags = luaL_optinteger(L, nargs, 0);

luasocket_try(L, kernel_connect, socket, &addr, sizeof(addr), flags);
luasocket_try(L, kernel_connect, socket, LUASOCKET_SOCKADDR(addr), flags);
return 0;
}

Expand Down

0 comments on commit 5c115bc

Please sign in to comment.