Lunatik เป็นกรอบสำหรับการเขียนสคริปต์เคอร์เนล Linux กับ Lua มันแต่งโดยล่าม Lua ที่แก้ไขเพื่อทำงานในเคอร์เนล ไดรเวอร์อุปกรณ์ (เขียนใน lua =)) และเครื่องมือบรรทัดคำสั่งเพื่อโหลดและเรียกใช้สคริปต์และจัดการสภาพแวดล้อมรันไทม์จากพื้นที่ผู้ใช้ A C API เพื่อโหลดและเรียกใช้สคริปต์และจัดการสภาพแวดล้อมรันไทม์จากเคอร์เนล และ Lua APIs สำหรับสิ่งอำนวยความสะดวกเคอร์เนลที่มีผลผูกพันกับสคริปต์ Lua
นี่คือตัวอย่างของไดรเวอร์อุปกรณ์ตัวละครที่เขียนใน Lua โดยใช้ Lunatik เพื่อสร้างอักขระที่พิมพ์ได้ ASCII แบบสุ่ม:
-- /lib/modules/lua/passwd.lua
--
-- implements /dev/passwd for generate passwords
-- usage: $ sudo lunatik run passwd
-- $ head -c <width> /dev/passwd
local device = require ( " device " )
local linux = require ( " linux " )
local function nop () end -- do nothing
local s = linux . stat
local driver = { name = " passwd " , open = nop , release = nop , mode = s . IRUGO }
function driver : read () -- read(2) callback
-- generate random ASCII printable characters
return string.char ( linux . random ( 32 , 126 ))
end
-- creates a new character device
device . new ( driver )ติดตั้งการพึ่งพา (ที่นี่สำหรับ Debian/Ubuntu เพื่อปรับให้เข้ากับการกระจายของคน ๆ หนึ่ง):
sudo apt install git build-essential lua5.4 dwarves clang llvm libelf-dev linux-headers- $( uname -r ) linux-tools-common linux-tools- $( uname -r ) pkg-config libpcap-dev m4 รวบรวมและติดตั้ง lunatik :
LUNATIK_DIR= ~ /lunatik # to be adapted
mkdir " ${LUNATIK_DIR} " ; cd " ${LUNATIK_DIR} "
git clone --depth 1 --recurse-submodules https://github.com/luainkernel/lunatik.git
cd lunatik
make
sudo make install เมื่อเสร็จสิ้นสคริปต์ debian_kernel_postinst_lunatik.sh จากเครื่องมือ/อาจถูกคัดลอกไปยัง /etc/kernel/postinst.d/ : สิ่งนี้ทำให้มั่นใจได้ว่า lunatik (และ xdp ที่ต้องการ libs) จะได้รับการรวบรวมในการอัพเกรดเคอร์เนล
sudo lunatik # execute Lunatik REPL
Lunatik 3.5 Copyright (C) 2023-2024 ring-0 Ltda.
> return 42 -- execute this line in the kernel
42
usage: lunatik [load | unload | reload | status | list] [run | spawn | stop < script > ]load : โหลดโมดูลเคอร์เนล Lunatikunload : โมดูลเคอร์เนล Lunatikreload : โหลดโมดูลเคอร์เนล Lunatikstatus : แสดงโมดูลเคอร์เนล Lunatik ใดในขณะนี้list : แสดงสภาพแวดล้อมรันไทม์ที่กำลังทำงานอยู่ในขณะนี้run : สร้างสภาพแวดล้อมรันไทม์ใหม่เพื่อเรียกใช้สคริปต์ /lib/modules/lua/<script>.luaspawn : สร้างสภาพแวดล้อมรันไทม์ใหม่และวางไข่เธรดเพื่อเรียกใช้สคริปต์ /lib/modules/lua/<script>.luastop : หยุดสภาพแวดล้อมรันไทม์ที่สร้างขึ้นเพื่อเรียกใช้สคริปต์ <script>default เริ่มต้น: เริ่ม REPL (อ่าน - EVAL - PRINT LOOP) Lunatik 3.4 ขึ้นอยู่กับ Lua 5.4 ที่ปรับให้ทำงานในเคอร์เนล
Lunatik ไม่ รองรับเลขคณิตจุดลอยตัวดังนั้นจึง ไม่ รองรับ __div หรือ __pow metamethods และ หมายเลข ประเภทมีเพียง จำนวนเต็ม ย่อยเท่านั้น
Lunatik ไม่ รองรับทั้งไลบรารี IO และ OS และตัวระบุที่กำหนดจากไลบรารีต่อไปนี้:
Lunatik ปรับเปลี่ยนตัว ระบุต่อไปนี้:
"Lua 5.4-kernel""/lib/modules/lua/?.lua;/lib/modules/lua/?/init.lua"Lunatik ไม่ รองรับ lual_stream, lual_execresult, lual_fileresult, luaopen_io และ luaopen_os
Lunatik ปรับเปลี่ยน lual_openlibs เพื่อลบ luaopen_io และ luaopen_os
#include <lunatik.h> int lunatik_runtime ( lunatik_object_t * * pruntime , const char * script , bool sleep ); lunatik_runtime () สร้างสภาพแวดล้อม runtime ใหม่จากนั้นโหลดและเรียกใช้สคริปต์ /lib/modules/lua/<script>.lua เป็นจุดเริ่มต้นสำหรับสภาพแวดล้อมนี้ มัน จะต้อง ถูกเรียกจาก บริบทของกระบวนการ เท่านั้น สภาพแวดล้อม runtime เป็นวัตถุ Lunatik ที่ถือ Lua State วัตถุ Lunatik เป็น Lua UserData พิเศษซึ่งถือประเภทล็อคและตัวนับอ้างอิง หาก sleep เป็น จริง lunatik_runtime () จะใช้ mutex สำหรับการล็อคสภาพแวดล้อม runtime และธง GFP_Kernel สำหรับการจัดสรรหน่วยความจำใหม่ในภายหลังในการโทร lunatik_run () มิฉะนั้นจะใช้สปินล็อคและ gfp_atomic lunatik_runtime () เปิดห้องสมุดมาตรฐาน LUA ที่มีอยู่ใน Lunatik หากประสบความสำเร็จ Lunatik_runtime () ตั้งค่าที่อยู่ที่ชี้ไปที่ pruntime และพื้นที่พิเศษของ Lua พร้อมตัวชี้สำหรับสภาพแวดล้อม runtime ที่สร้างขึ้นใหม่ตั้งค่า ตัวนับอ้างอิง เป็น 1 แล้วส่งคืน 0 มิฉะนั้นจะส่งคืน -ENOMEM หากมีหน่วยความจำไม่เพียงพอ หรือ -EINVAL หากไม่สามารถโหลดหรือเรียกใช้ script
-- /lib/modules/lua/mydevice.lua
function myread ( len , off )
return " 42 "
end static lunatik_object_t * runtime ;
static int __init mydevice_init ( void )
{
return lunatik_runtime ( & runtime , "mydevice" , true);
} int lunatik_stop ( lunatik_object_t * runtime ); lunatik_stop () ปิดสถานะ LUA ที่สร้างขึ้นสำหรับสภาพแวดล้อม runtime นี้และลดตัวนับอ้างอิง เมื่อตัวนับอ้างอิงลดลงเป็นศูนย์ประเภทการล็อคและหน่วยความจำที่จัดสรรสำหรับสภาพแวดล้อม runtime จะถูกปล่อยออกมา หากสภาพแวดล้อม runtime ได้รับการปล่อยตัวจะส่งกลับ 1 ; มิฉะนั้นจะส่งคืน 0
void lunatik_run ( lunatik_object_t * runtime , < inttype > ( * handler )(...), < inttype > & ret , ...); lunatik_run () ล็อคสภาพแวดล้อม runtime และเรียก handler ผ่านสถานะ Lua ที่เกี่ยวข้องเป็นอาร์กิวเมนต์แรกตามด้วยอาร์กิวเมนต์ที่หลากหลาย หากรัฐ Lua ถูกปิดให้ตั้งค่า ret ด้วย -ENXIO ; มิฉะนั้น ret จะถูกตั้งค่าด้วยผลลัพธ์ของ handler(L, ...) การโทร จากนั้นมันจะคืนค่า Lua Stack และปลดล็อกสภาพแวดล้อม runtime มันถูกกำหนดให้เป็นแมโคร
static int l_read ( lua_State * L , char * buf , size_t len , loff_t * off )
{
size_t llen ;
const char * lbuf ;
lua_getglobal ( L , "myread" );
lua_pushinteger ( L , len );
lua_pushinteger ( L , * off );
if ( lua_pcall ( L , 2 , 2 , 0 ) != LUA_OK ) { /* calls myread(len, off) */
pr_err ( "%sn" , lua_tostring ( L , -1 ));
return - ECANCELED ;
}
lbuf = lua_tolstring ( L , -2 , & llen );
llen = min ( len , llen );
if ( copy_to_user ( buf , lbuf , llen ) != 0 )
return - EFAULT ;
* off = ( loff_t ) luaL_optinteger ( L , -1 , * off + llen );
return ( ssize_t ) llen ;
}
static ssize_t mydevice_read ( struct file * f , char * buf , size_t len , loff_t * off )
{
ssize_t ret ;
lunatik_object_t * runtime = ( lunatik_object_t * ) f -> private_data ;
lunatik_run ( runtime , l_read , ret , buf , len , off );
return ret ;
} void lunatik_getobject ( lunatik_object_t * object ); lunatik_getobject () เพิ่มตัวนับอ้างอิงของ object นี้ (เช่นสภาพแวดล้อม runtime )
int lunatik_putobject ( lunatik_object_t * object ); Lunatik_putObject () ลดตัวนับอ้างอิงของ object นี้ (เช่นสภาพแวดล้อม runtime ) หาก object ได้รับการปล่อยตัวจะส่งกลับ 1 ; มิฉะนั้นจะส่งคืน 0
lunatik_object_t * lunatik_toruntime ( lua_State * L ); lunatik_toruntime () ส่งคืนสภาพแวดล้อม runtime ที่อ้างอิงโดยพื้นที่พิเศษของ L
ไลบรารี lunatik ให้การสนับสนุนในการโหลดและเรียกใช้สคริปต์และจัดการสภาพแวดล้อมรันไทม์จาก Lua
lunatik.runtime(script [, sleep]) lunatik.runtime () สร้างสภาพแวดล้อมรันไทม์ใหม่จากนั้นโหลดและเรียกใช้สคริปต์ /lib/modules/lua/<script>.lua เป็นจุดเริ่มต้นสำหรับสภาพแวดล้อมนี้ มันส่งคืนวัตถุ Lunatik ที่เป็นตัวแทนของสภาพแวดล้อม runtime หาก sleep เป็น จริง หรือละเว้นมันจะใช้ mutex และ gfp_kernel; มิฉะนั้นจะใช้สปินล็อคและ gfp_atomic lunatik.runtime () เปิดห้องสมุดมาตรฐาน LUA ที่นำเสนอใน Lunatik
runtime:stop() รันไทม์: หยุด () หยุดสภาพแวดล้อม runtime และล้างข้อมูลอ้างอิงจากวัตถุรันไทม์
runtime:resume([obj1, ...]) รันไทม์: เรซูเม่ () ดำเนินการต่อการดำเนิน runtime ค่า obj1, ... ถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันที่ส่งคืนในการสร้าง runtime หาก runtime ให้ผล resume() รีสตาร์ท ค่า obj1, ... ถูกส่งผ่านเป็นผลลัพธ์จากผลผลิต
ไลบรารี device ให้การสนับสนุนสำหรับการเขียนไดรเวอร์อุปกรณ์ตัวละครใน Lua
device.new(driver) device.new () ส่งคืนวัตถุ device ใหม่และติดตั้ง driver ในระบบ driver จะต้อง กำหนดเป็นตารางที่มีฟิลด์ต่อไปนี้:
name : สตริงที่กำหนดชื่ออุปกรณ์; ใช้สำหรับการสร้างไฟล์อุปกรณ์ (เช่น /dev/<name> ) ตาราง driver อาจเลือกมีฟิลด์ต่อไปนี้:
read : ฟังก์ชั่นการโทรกลับเพื่อจัดการการดำเนินการอ่านบนไฟล์อุปกรณ์ มันได้รับตาราง driver เป็นอาร์กิวเมนต์แรกตามด้วยสองจำนวนเต็ม length ที่จะอ่านและ offset ไฟล์ ควรส่งคืนสตริงและเลือก updated offset หากความยาวของสตริงที่ส่งคืนมากกว่า length ที่ร้องขอสตริงจะถูกแก้ไขตาม length นั้น หาก updated offset ไม่ได้ถูกส่งคืน offset จะได้รับการอัปเดตด้วย offset + lengthwrite : ฟังก์ชั่นการโทรกลับเพื่อจัดการการดำเนินการเขียนบนไฟล์อุปกรณ์ มันได้รับตาราง driver เป็นอาร์กิวเมนต์แรกตามด้วยสตริงที่จะเขียนและจำนวนเต็มเป็นไฟล์ offset มันอาจส่งคืน length ที่เขียนตามด้วย updated offset หากความยาวที่ส่งคืนมากกว่า length ที่ร้องขอความยาวที่ส่งคืนจะได้รับการแก้ไข หาก updated offset ไม่ได้ถูกส่งคืน offset จะได้รับการอัปเดตด้วย offset + lengthopen : ฟังก์ชั่นการโทรกลับเพื่อจัดการการทำงานแบบเปิดบนไฟล์อุปกรณ์ ได้รับตาราง driver และคาดว่าจะไม่กลับมาทำอะไรเลยrelease : ฟังก์ชั่นการโทรกลับเพื่อจัดการการดำเนินการรีลีสบนไฟล์อุปกรณ์ ได้รับตาราง driver และคาดว่าจะไม่กลับมาทำอะไรเลยmode : จำนวนเต็มที่ระบุโหมดไฟล์อุปกรณ์ หากไม่ได้กำหนดการโทรกลับการดำเนินการ device จะส่งกลับ -ENXIO ไปยัง VFS เมื่อเข้าถึงได้
device.stop(dev) , dev:stop() device.top () ลบ driver อุปกรณ์ที่ระบุโดยวัตถุ dev ออกจากระบบ
ไลบรารี linux ให้การสนับสนุนสิ่งอำนวยความสะดวกเคอร์เนล Linux
linux.random([m [, n]])linux.random () เลียนแบบพฤติกรรมของ math.random แต่มีผลผูกพัน <linux/random.h> ของ get_random_u32 () และ get_random_u64 () apis
เมื่อถูกเรียกโดยไม่มีข้อโต้แย้งให้ผลิตจำนวนเต็มที่มีบิตทั้งหมด (หลอก) สุ่ม เมื่อเรียกด้วยจำนวนเต็มสอง m และ n , linux.random () ส่งคืนจำนวนเต็มหลอกสุ่มที่มีการแจกแจงแบบสม่ำเสมอในช่วง [m, n] การโทร math.random(n) สำหรับบวก n เทียบเท่ากับ math.random(1, n)
linux.statLinux.stat เป็นตารางที่ส่งออก <Linux/stat.h> Flag จำนวนเต็มไปยัง Lua
"IRWXUGO" : อนุญาตให้ อ่าน เขียน และ ดำเนินการ สำหรับ ผู้ใช้ กลุ่ม และ อื่น ๆ"IRUGO" : อนุญาตให้ อ่าน สำหรับ ผู้ใช้ กลุ่ม และ อื่น ๆ เท่านั้น"IWUGO" : อนุญาตให้ เขียน สำหรับ ผู้ใช้ กลุ่ม และ อื่น ๆ เท่านั้น"IXUGO" : อนุญาตให้ ดำเนินการ สำหรับ ผู้ใช้ กลุ่ม และ อื่น ๆ เท่านั้น linux.schedule([timeout [, state]]) Linux.schedule () ตั้งค่า state งานปัจจุบันและทำให้ไอทีนอนหลับจนกระทั่งมิลลิวินาทีหมด timeout ผ่านไป หากละเว้นการหมด timeout จะใช้ MAX_SCHEDULE_TIMEOUT หาก state ถูกละเว้นมันจะใช้ task.INTERRUPTIBLE
linux.taskLinux.task เป็นตารางที่ส่งออกสถานะงานสถานะไปยัง Lua
"RUNNING" : งานกำลังดำเนินการกับ CPU หรือรอดำเนินการ"INTERRUPTIBLE" : งานกำลังรอสัญญาณหรือทรัพยากร (นอนหลับ)"UNINTERRUPTIBLE" : ทำตัวเหมือน "ขัดจังหวะ" ยกเว้นว่าสัญญาณจะไม่ปลุกภารกิจ"KILLABLE" : ทำตัวเหมือน "ไม่หยุดยั้ง" ยกเว้นว่าสัญญาณที่ร้ายแรงจะปลุกภารกิจ"IDLE" : ทำตัวเหมือน "ไม่หยุดยั้ง" โดยมีข้อยกเว้นที่หลีกเลี่ยงการบัญชี LoadAVG linux.time()linux.time () ส่งคืนเวลาปัจจุบันในนาโนวินาทีตั้งแต่ยุค
linux.errnoLinux.errno เป็นตารางที่ส่งออก <uapi/asm-generic/errno-base.h> ตั้งค่าสถานะไปยัง Lua
"PERM" : ไม่อนุญาตให้ดำเนินการ"NOENT" : ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว"SRCH" : ไม่มีกระบวนการดังกล่าว"INTR" : การโทรระบบที่ถูกขัดจังหวะ"IO" : I/O ข้อผิดพลาด"NXIO" : ไม่มีอุปกรณ์หรือที่อยู่ดังกล่าว"2BIG" : รายการอาร์กิวเมนต์นานเกินไป"NOEXEC" : ข้อผิดพลาดรูปแบบ EXEC"BADF" : หมายเลขไฟล์ที่ไม่ดี"CHILD" : ไม่มีกระบวนการเด็ก"AGAIN" : ลองอีกครั้ง"NOMEM" : นอกหน่วยความจำ"ACCES" : ปฏิเสธการอนุญาต"FAULT" : ที่อยู่ที่ไม่ดี"NOTBLK" : จำเป็นต้องใช้อุปกรณ์บล็อก"BUSY" : อุปกรณ์หรือทรัพยากรไม่ว่าง"EXIST" : มีไฟล์อยู่"XDEV" : ลิงค์ข้ามอุปกรณ์"NODEV" : ไม่มีอุปกรณ์ดังกล่าว"NOTDIR" : ไม่ใช่ไดเรกทอรี"ISDIR" : เป็นไดเรกทอรี"INVAL" : อาร์กิวเมนต์ที่ไม่ถูกต้อง"NFILE" : ตารางไฟล์ล้น"MFILE" : ไฟล์เปิดมากเกินไป"NOTTY" : ไม่ใช่เครื่องพิมพ์ดีด"TXTBSY" : ไฟล์ข้อความไม่ว่าง"FBIG" : ไฟล์มีขนาดใหญ่เกินไป"NOSPC" : ไม่มีพื้นที่เหลืออยู่บนอุปกรณ์"SPIPE" : ค้นหาที่ผิดกฎหมาย"ROFS" : ระบบไฟล์แบบอ่านอย่างเดียว"MLINK" : มีลิงก์มากเกินไป"PIPE" : ท่อแตก"DOM" : อาร์กิวเมนต์ทางคณิตศาสตร์จากโดเมนของ func"RANGE" : ผลลัพธ์ทางคณิตศาสตร์ไม่สามารถแสดงได้ linux.hton16(num)linux.hton16 () แปลงคำสั่งไบต์โฮสต์เป็นเครือข่ายคำสั่งซื้อไบต์สำหรับจำนวนเต็ม 16 บิต
linux.hton32(num)linux.hton32 () แปลงคำสั่งไบต์โฮสต์เป็นคำสั่งซื้อไบต์สำหรับจำนวนเต็ม 32 บิต
linux.hton64(num)linux.hton64 () แปลงคำสั่งไบต์โฮสต์เป็นคำสั่งซื้อไบต์สำหรับจำนวนเต็ม 64 บิต
linux.ntoh16(num)linux.ntoh16 () แปลงลำดับไบต์เครือข่ายเป็นโฮสต์คำสั่งซื้อไบต์สำหรับจำนวนเต็ม 16 บิต
linux.ntoh32(num)linux.ntoh32 () แปลงลำดับไบต์เครือข่ายเป็นโฮสต์คำสั่งซื้อไบต์สำหรับจำนวนเต็ม 32 บิต
linux.ntoh64(num)linux.ntoh64 () แปลงลำดับไบต์เครือข่ายเป็นโฮสต์คำสั่งซื้อไบต์สำหรับจำนวนเต็ม 64 บิต
linux.htobe16(num)linux.htobe16 () แปลงคำสั่งไบต์โฮสต์เป็นคำสั่งไบต์บิ๊กเอดินสำหรับจำนวนเต็ม 16 บิต
linux.htobe32(num)linux.htobe32 () แปลงคำสั่งไบต์โฮสต์เป็นคำสั่งไบต์บิ๊กเอดินสำหรับจำนวนเต็ม 32 บิต
linux.htobe64(num)linux.htobe64 () แปลงคำสั่งไบต์โฮสต์เป็นคำสั่งไบต์บิ๊กเอดินสำหรับจำนวนเต็ม 64 บิต
linux.be16toh(num)Linux.be16toh () แปลงคำสั่ง Big-Endian Byte เป็นโฮสต์คำสั่งซื้อไบต์สำหรับจำนวนเต็ม 16 บิต
linux.be32toh(num)Linux.be32toh () แปลงคำสั่งไบต์ขนาดใหญ่เพื่อโฮสต์คำสั่งไบต์สำหรับจำนวนเต็ม 32 บิต
linux.be64toh(num)Linux.be64toh () แปลงคำสั่ง Big-Endian Byte เป็นโฮสต์คำสั่งซื้อไบต์สำหรับจำนวนเต็ม 64 บิต
linux.htole16(num)linux.htole16 () แปลงคำสั่งไบต์โฮสต์เป็นคำสั่งไบต์เล็ก ๆ น้อย ๆ สำหรับจำนวนเต็ม 16 บิต
linux.htole32(num)linux.htole32 () แปลงคำสั่งไบต์โฮสต์เป็นคำสั่งไบต์เล็ก ๆ น้อย ๆ สำหรับจำนวนเต็ม 32 บิต
linux.htole64(num)linux.htole64 () แปลงคำสั่งไบต์โฮสต์เป็นคำสั่งไบต์เล็ก ๆ น้อย ๆ สำหรับจำนวนเต็ม 64 บิต
linux.le16toh(num)linux.le16toh () แปลงคำสั่งไบต์เล็ก ๆ น้อย ๆ เพื่อโฮสต์คำสั่งไบต์สำหรับจำนวนเต็ม 16 บิต
linux.le32toh(num)linux.le32toh () แปลงคำสั่งไบต์เล็ก ๆ น้อย ๆ เพื่อโฮสต์คำสั่งไบต์สำหรับจำนวนเต็ม 32 บิต
linux.le64toh(num)linux.le64toh () แปลงคำสั่งไบต์เล็ก ๆ น้อย ๆ เพื่อโฮสต์คำสั่งไบต์สำหรับจำนวนเต็ม 64 บิต
ไลบรารี notifier ให้การสนับสนุนสำหรับเครือข่ายการแจ้งเตือนเคอร์เนล
notifier.keyboard(callback) notifier.keyboard () ส่งคืนวัตถุ notifier แป้นพิมพ์ใหม่และติดตั้งในระบบ ฟังก์ชั่น callback ถูกเรียกเมื่อใดก็ตามที่มีเหตุการณ์คีย์บอร์ดคอนโซลเกิดขึ้น (เช่นคีย์ได้รับการกดหรือเปิดตัว) callback นี้ได้รับอาร์กิวเมนต์ต่อไปนี้:
event : เหตุการณ์ ที่มีอยู่จะถูกกำหนดโดยตาราง notifier.kbddown : true ถ้ากดปุ่ม; false ถ้ามันถูกปล่อยออกมาshift : true ถ้าคีย์ Shift ถูกเก็บไว้; false มิฉะนั้นkey : คีย์ หรือ คีย์มิล ขึ้นอยู่กับ event ฟังก์ชั่น callback อาจส่งคืนค่าที่กำหนดโดยตาราง NOTIFIED
notifier.kbdNotifier.kbd เป็นตารางที่ส่งออก KBD Flags ไปยัง Lua
"KEYCODE" : คีย์บอร์ด คีย์บอร์ด เรียกว่าก่อนอื่นใด"UNBOUND_KEYCODE" : คีย์บอร์ดคีย์บอร์ด ซึ่งไม่ผูกพันกับอื่น ๆ"UNICODE" : คีย์บอร์ด Unicode"KEYSYM" : คีย์บอร์ด คีย์บอร์ด"POST_KEYSYM" : เรียกหลังจากการตีความ คีย์บอร์ด แป้นพิมพ์ notifier.netdevice(callback) Notifier.netDevice () ส่งคืนวัตถุ notifier ใหม่และติดตั้งในระบบ ฟังก์ชั่น callback ถูกเรียกเมื่อมีเหตุการณ์ NetDevice คอนโซลเกิดขึ้น (เช่นอินเทอร์เฟซเครือข่ายได้รับการเชื่อมต่อหรือตัดการเชื่อมต่อ) callback นี้ได้รับอาร์กิวเมนต์ต่อไปนี้:
event : เหตุการณ์ ที่มีอยู่จะถูกกำหนดโดยตาราง Notifier.netDevname : ชื่ออุปกรณ์ ฟังก์ชั่น callback อาจส่งคืนค่าที่กำหนดโดยตาราง NOTIFIED
notifier.netdevNotifier.netdev เป็นตารางที่ส่งออก Netdev ตั้งค่าสถานะไปยัง Lua
notifier.notifyNOTIFIER.Notify เป็นตารางที่ส่งออกแจ้งให้ทราบธงให้ LUA
"DONE" : ไม่สนใจ"OK" : เหมาะกับฉัน"BAD" : การกระทำที่ไม่ดี/ยับยั้ง"STOP" : ทำความสะอาดวิธีกลับจากผู้แจ้งเตือนและหยุดการโทรเพิ่มเติม notfr:delete() NOTFR: ลบ () ลบตัว notifier ที่ระบุโดยวัตถุ notfr ออกจากระบบ
ห้องสมุด socket ให้การสนับสนุนสำหรับการจัดการเครือข่ายเคอร์เนล ห้องสมุดนี้ได้รับแรงบันดาลใจจากโครงการ GSOC ของ Chengzhi Tan
socket.new(family, type, protocol) Socket.new () สร้างวัตถุ socket ใหม่ ฟังก์ชั่นนี้ได้รับอาร์กิวเมนต์ต่อไปนี้:
family : ครอบครัวที่อยู่ ที่มีอยู่จะถูกกำหนดโดยซ็อกเก็ตตารางsock : มี ประเภท ที่มีอยู่ในซ็อกเก็ตตารางprotocol : โปรโตคอล ที่มีอยู่จะถูกกำหนดโดยซ็อกเก็ตตาราง socket.afSocket.af เป็นตารางที่ส่งออกครอบครัว (AF) ไปยัง Lua
"UNSPEC" : ไม่ได้ระบุ"UNIX" : ซ็อกเก็ตโดเมน Unix"LOCAL" : ชื่อ posix สำหรับ AF_UNIX"INET" : Internet IP Protocol"AX25" : Radio Axe.25"IPX" : Novell IPX"APPLETALK" : Appletalk DDP"NETROM" : วิทยุสมัครเล่นสุทธิ/ROM"BRIDGE" : Multiprotocol Bridge"ATMPVC" : ATM PVCS"X25" : สงวนไว้สำหรับโครงการ x.25"INET6" : IP เวอร์ชัน 6"ROSE" : วิทยุสมัครเล่น X.25 Plp"DEC" : สงวนไว้สำหรับโครงการ DECNET"NETBEUI" : สงวนไว้สำหรับโครงการ 802.2LLC"SECURITY" : การโทรกลับ Security Pseudo AF"KEY" : API การจัดการคีย์ PF_KEY"NETLINK" : NetLink"ROUTE" : นามแฝงเพื่อเลียนแบบ 4.4BSD"PACKET" : ตระกูลแพ็คเก็ต"ASH" : Ash"ECONET" : Acorn Econet"ATMSVC" : ATM SVCS"RDS" : ซ็อกเก็ต RDS"SNA" : โครงการ Linux SNA (Nutters!)"IRDA" : ซ็อกเก็ต Irda"PPPOX" : ซ็อกเก็ต PPPOX"WANPIPE" : ซ็อกเก็ต Wanpipe API"LLC" : Linux LLC"IB" : ที่อยู่ infiniband ดั้งเดิม"MPLS" : MPLS"CAN" : เครือข่ายพื้นที่คอนโทรลเลอร์"TIPC" : ซ็อกเก็ต TIPC"BLUETOOTH" : ซ็อกเก็ตบลูทู ธ"IUCV" : ซ็อกเก็ต IUCV"RXRPC" : ซ็อกเก็ต RXRPC"ISDN" : ซ็อกเก็ต MISDN"PHONET" : ซ็อกเก็ต Phonet"IEEE802154" : SOCKETS IEEEE802154"CAIF" : ซ็อกเก็ต CAIF"ALG" : ซ็อกเก็ตอัลกอริทึม"NFC" : ซ็อกเก็ต NFC"VSOCK" : vsockets"KCM" : การเชื่อมต่อเคอร์เนลมัลติเพล็กเตอร์"QIPCRTR" : เราเตอร์ Qualcomm IPC"SMC" : หมายเลขสำรองสำหรับตระกูลโปรโตคอล PF_SMC ที่นำครอบครัว AF_INET มาใช้ใหม่"XDP" : ซ็อกเก็ต XDP"MCTP" : โปรโตคอลการขนส่งส่วนประกอบการจัดการ"MAX" : สูงสุด socket.socksocket.sock เป็นตารางที่ส่งออกประเภทซ็อกเก็ต (ถุงเท้า):
"STREAM" : ซ็อกเก็ตสตรีม (การเชื่อมต่อ)"DGRAM" : ซ็อกเก็ต Datagram (conn.less)"RAW" : ซ็อกเก็ตดิบ"RDM" : ข้อความที่ส่งมาอย่างน่าเชื่อถือ"SEQPACKET" : ซ็อกเก็ตแพ็คเก็ตลำดับ"DCCP" : ซ็อกเก็ตโปรโตคอลควบคุมความแออัดของดาต้าแกรม"PACKET" : วิธีเฉพาะของ Linux ในการรับแพ็กเก็ตในระดับ devและธง (ถุงเท้า):
"CLOEXEC" : N/A"NONBLOCK" : n/a socket.ipprotoSocket.ipproto เป็นตารางที่ส่งออกโปรโตคอล IP (ipproto) ไปยัง Lua
"IP" : Dummy Protocol สำหรับ TCP"ICMP" : โปรโตคอลข้อความควบคุมอินเทอร์เน็ต"IGMP" : โปรโตคอลการจัดการกลุ่มอินเทอร์เน็ต"IPIP" : อุโมงค์ IPIP (อุโมงค์ KA9Q รุ่นเก่าใช้ 94)"TCP" : โปรโตคอลการควบคุมการส่งสัญญาณ"EGP" : โปรโตคอลเกตเวย์ภายนอก"PUP" : PUP Protocol"UDP" : โปรโตคอล DataGram ผู้ใช้"IDP" : โปรโตคอล XNS IDP"TP" : ดังนั้นการขนส่งโปรโตคอลคลาส 4"DCCP" : โปรโตคอลการควบคุมความแออัดของดาต้าแกรม"IPV6" : การขุดอุโมงค์ IPv6-in-IPV4"RSVP" : โปรโตคอล RSVP"GRE" : Cisco GRE Tunnels (RFC 1701,1702)"ESP" : โปรโตคอล Payload Security Security"AH" : โปรโตคอลส่วนหัวการรับรองความถูกต้อง"MTP" : โปรโตคอลการขนส่งแบบมัลติคาสต์"BEETPH" : IP Option Pseudo Header สำหรับบีท"ENCAP" : encapsulation header"PIM" : Protocol Independent Independent"COMP" : โปรโตคอลส่วนหัวการบีบอัด"SCTP" : โปรโตคอลการขนส่งการควบคุมสตรีม"UDPLITE" : UDP-Lite (RFC 3828)"MPLS" : MPLS ใน IP (RFC 4023)"ETHERNET" : Ethernet-Within-IPv6 Encapsulation"RAW" : แพ็คเก็ต IP ดิบ"MPTCP" : Multipath TCP การเชื่อมต่อ sock:close() ถุงเท้า: ปิด () ลบวัตถุ sock ออกจากระบบ
sock:send(message, [addr [, port]]) ถุงเท้า: ส่ง () ส่ง message สตริงผ่าน sock อกเก็ต หากตระกูลที่อยู่ sock เป็น af.INET ก็คาดว่าจะมีข้อโต้แย้งต่อไปนี้:
addr : integer อธิบายที่อยู่ IPv4 ปลายทางport : integer อธิบายพอร์ต IPv4 ปลายทางมิฉะนั้น:
addr : สตริงบรรจุที่อธิบายที่อยู่ปลายทาง sock:receive(length, [flags [, from]]) ถุงเท้า: รับ () ได้รับสตริงที่มี length ไบต์ผ่าน sock อกเก็ต ตารางข้อความ ที่มีอยู่จะถูกกำหนดโดยตาราง socket.msg หาก from เป็น true จะส่งคืนข้อความที่ได้รับตามด้วยที่อยู่ของเพื่อน มิฉะนั้นจะส่งคืนเฉพาะข้อความที่ได้รับ
socket.msgSocket.msg เป็นตารางที่ส่งออกข้อความไปยัง Lua
"OOB" : N/A"PEEK" : N/A"DONTROUTE" : N/A"TRYHARD" : คำพ้องสำหรับ "DONTROUTE" สำหรับ DECNET"CTRUNC" : n/a"PROBE" : อย่าส่ง เฉพาะเส้นทาง Probe Fe สำหรับ MTU"TRUNC" : n/a"DONTWAIT" : Non -Blocking IO"EOR" : สิ้นสุดการบันทึก"WAITALL" : รอคำขอเต็ม"FIN" : N/A"SYN" : n/a"CONFIRM" : ยืนยันความถูกต้องของเส้นทาง"RST" : N/A"ERRQUEUE" : ดึงข้อความจากคิวข้อผิดพลาด"NOSIGNAL" : อย่าสร้าง sigpipe"MORE" : ผู้ส่งจะส่งเพิ่มเติม"WAITFORONE" : RecVMMSG (): บล็อกจนถึง 1+ แพ็คเก็ตพร้อมใช้งาน"SENDPAGE_NOPOLICY" : sendpage () ภายใน: ไม่ใช้นโยบาย"SENDPAGE_NOTLAST" : sendPage () ภายใน: ไม่ใช่หน้าสุดท้าย"BATCH" : sendmmsg (): ข้อความเพิ่มเติมมา"EOF" : N/A"NO_SHARED_FRAGS" : SendPage () ภายใน: FRAGS หน้าไม่แชร์"SENDPAGE_DECRYPTED" : sendpage () ภายใน: หน้าอาจมีข้อความธรรมดาและต้องมีการเข้ารหัส"ZEROCOPY" : ใช้ข้อมูลผู้ใช้ในเส้นทางเคอร์เนล"FASTOPEN" : ส่งข้อมูลใน TCP SYN"CMSG_CLOEXEC" : ตั้งค่า close_on_exec สำหรับตัวอธิบายไฟล์ที่ได้รับผ่าน SCM_RIGHTS sock:bind(addr [, port]) ถุงเท้า: ผูก () ผูก sock ซ็อกเก็ตกับที่อยู่ที่กำหนด หากตระกูลที่อยู่ sock เป็น af.INET ก็คาดว่าจะมีข้อโต้แย้งต่อไปนี้:
addr : integer อธิบายที่อยู่ IPv4 โฮสต์port : integer อธิบายพอร์ต IPv4 โฮสต์มิฉะนั้น:
addr : สตริงบรรจุที่อธิบายที่อยู่โฮสต์ sock:listen([backlog]) ถุงเท้า: ฟัง () ย้าย sock ซ็อกเก็ตไปยังสถานะการฟัง
backlog : รอการเชื่อมต่อขนาดคิว หากละเว้นจะใช้ somaxconn เป็นค่าเริ่มต้น sock:accept([flags]) ถุงเท้า: ยอมรับ () ยอมรับการเชื่อมต่อกับ sock ซ็อกเก็ต มันส่งคืนวัตถุ socket ใหม่ ธง ที่มีอยู่มีอยู่ในซ็อกเก็ตตาราง
sock:connect(addr [, port] [, flags]) ถุงเท้า: เชื่อมต่อ () เชื่อมต่อ sock ซ็อกเก็ตกับที่อยู่ addr หากตระกูลที่อยู่ sock เป็น af.INET ก็คาดว่าจะมีข้อโต้แย้งต่อไปนี้:
addr : integer อธิบายที่อยู่ IPv4 ปลายทางport : integer อธิบายพอร์ต IPv4 ปลายทางมิฉะนั้น:
addr : สตริงบรรจุที่อธิบายที่อยู่ปลายทางธง ที่มีอยู่มีอยู่ในซ็อกเก็ตตาราง
สำหรับซ็อกเก็ต DataGram นั้น addr เป็นที่อยู่ที่ DataGrams ถูกส่งตามค่าเริ่มต้นและที่อยู่เดียวที่ได้รับ DataGrams สำหรับซ็อกเก็ตสตรีมพยายามเชื่อมต่อกับ addr
sock:getsockname() ถุงเท้า: getSockName () รับที่อยู่ที่ sock ซ็อกเก็ตถูกผูกไว้ หากตระกูลที่อยู่ sock เป็น af.INET ก็จะส่งคืนสิ่งต่อไปนี้:
addr : integer อธิบายที่อยู่ IPv4 ที่ถูก จำกัดport : integer อธิบายพอร์ต IPv4 ที่ถูก จำกัดมิฉะนั้น:
addr : สตริงบรรจุที่อธิบายที่อยู่ที่มีขอบเขต sock:getpeername() ถุงเท้า: getpeername () รับที่อยู่ที่เชื่อมต่อ sock ซ็อกเก็ต หากตระกูลที่อยู่ sock เป็น af.INET ก็จะส่งคืนสิ่งต่อไปนี้:
addr : integer อธิบายที่อยู่ IPv4 ของเพียร์port : integer อธิบายพอร์ต IPv4 ของเพียร์มิฉะนั้น:
addr : สตริงบรรจุที่อธิบายที่อยู่ของเพียร์ ไลบรารี socket.inet ให้การสนับสนุนสำหรับซ็อกเก็ต IPv4 ระดับสูง
inet.tcp() inet.tcp () สร้าง socket ใหม่โดยใช้ AF.Inet Address Family, Sock.Stream Type และ ipproto.tcp Protocol มันแทนที่วิธี socket เพื่อใช้ที่อยู่เป็น สัญลักษณ์ตัวเลขและจุด (เช่น "127.0.0.1" ) แทนที่จะเป็นจำนวนเต็ม
inet.udp() inet.udp () สร้าง socket ใหม่โดยใช้ AF.Inet Address Family, Sock.dgram Type และ ipproto.udp Protocol มันแทนที่วิธี socket เพื่อใช้ที่อยู่เป็น สัญลักษณ์ตัวเลขและจุด (เช่น "127.0.0.1" ) แทนที่จะเป็นจำนวนเต็ม
udp:receivefrom(length [, flags]) UDP: รับจาก () เป็นเพียงนามแฝงของ sock:receive(length, flags, true)
ไลบรารี rcu ให้การสนับสนุนกลไกการซิงโครไนซ์การอัปเดตเคอร์เนล (RCU) ห้องสมุดนี้ได้รับแรงบันดาลใจจากโครงการ GSOC ของ Caio Messias
rcu.table([size]) RCU.Table () สร้างวัตถุ rcu.table ใหม่ซึ่งผูกตารางแฮชเคอร์เนลทั่วไป ฟังก์ชั่นนี้ได้รับเป็นอาร์กิวเมนต์จำนวนถังที่ปัดขึ้นไปยังกำลังถัดไปของ 2 ขนาดเริ่มต้นคือ 1024 คีย์ต้องเป็นสตริงและค่าจะต้องเป็นวัตถุ Lunatik หรือไม่มี
ไลบรารี thread ให้การสนับสนุนสำหรับเคอร์เนลด้ายดั้งเดิม
thread.run(runtime, name) thread.run () สร้างวัตถุ thread ใหม่และตื่นขึ้นมา ฟังก์ชั่นนี้ได้รับอาร์กิวเมนต์ต่อไปนี้:
runtime : สภาพแวดล้อมรันไทม์สำหรับการรันงานในเธรดเคอร์เนลที่สร้างขึ้น งานจะต้องระบุโดยการคืนฟังก์ชั่นบนสคริปต์ที่โหลดในสภาพแวดล้อม runtimename : สตริงแสดงชื่อสำหรับเธรด (เช่นดังที่แสดงใน ps ) thread.shouldstop() thread.shouldstop () ส่งคืน true ถ้า thread.stop () ถูกเรียก; มิฉะนั้นจะส่งคืน false
thread.current() Thread.current () ส่งคืนวัตถุ thread ที่แสดงถึงงานปัจจุบัน
thrd:stop() THRD: Stop () ตั้งค่า thread.shouldstop () บนเธรด thrd เพื่อส่งคืนจริงตื่น thrd มาและรอให้มันออก
thrd:task() THRD: task () ส่งคืนตารางที่มีข้อมูลงานของ thread นี้ (เช่น "CPU", "คำสั่ง", "PID" และ "TGID")
ห้องสมุด fib ให้การสนับสนุนฐานข้อมูลการส่งต่อเคอร์เนล
fib.newrule(table, priority)fib.newrule () ผูกเคอร์เนล fib_nl_newrule api; มันสร้างกฎ FIB ใหม่ที่ตรงกับ ตาราง การกำหนดเส้นทางที่ระบุกับ priorioty ที่ระบุ ฟังก์ชั่นนี้คล้ายกับกฎ IP คำสั่งของผู้ใช้พื้นที่ที่เพิ่มโดย iProute2
fib.delrule(table, priority)fib.delrule () ผูกเคอร์เนล fib_nl_delrule api; มันลบกฎ FIB ที่ตรงกับ ตาราง การกำหนดเส้นทางที่ระบุด้วย priorioty ที่ระบุ ฟังก์ชั่นนี้คล้ายกับคำสั่ง uspace-space ip del del ที่จัดทำโดย iProute2
ไลบรารี data ให้การสนับสนุนสำหรับการเชื่อมโยงหน่วยความจำระบบกับ LUA
data.new(size) data.new () สร้างวัตถุ data ใหม่ที่จัดสรร size ไบต์
d:getnumber(offset) D: getNumber () แยก LUA_INTEGER จากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:setnumber(offset, number) D: setNumber () แทรก number LUA_INTEGER ลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:getbyte(offset) D: getByte () แยกไบต์จากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:setbyte(offset, byte) D: setByte () แทรกไบต์ลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:getstring(offset[, length]) D: GetString () แยกสตริงที่มี length ไบต์จากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์ หากละเว้น length มันจะแยกไบต์ทั้งหมดจาก offset ไปยังจุดสิ้นสุดของ data
d:setstring(offset, s) D: setString () แทรกสตริง s ลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:getint8(offset) D: getint8 (D, ออฟเซ็ต) แยกจำนวนเต็ม 8 บิตที่ลงนามจากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:setint8(offset, number) D: setint8 () แทรกหมายเลข 8 บิตที่ลงนามลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:getuint8(offset) D: getuint8 () แยกจำนวนเต็ม 8 บิตที่ไม่ได้ลงชื่อออกจากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:setuint8(offset, number) D: setuint8 () แทรกหมายเลข 8 บิตที่ไม่ได้ลงชื่อลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:getint16(offset) D: getInt16 () แยกจำนวนเต็ม 16 บิตที่ลงนามจากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:setint16(offset, number) D: setint16 () แทรกหมายเลข 16 บิตที่ลงนามลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:getuint16(offset) D: getuint16 () แยกจำนวนเต็ม 16 บิตที่ไม่ได้ลงชื่อออกจากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:setuint16(offset, number) D: setuint16 () แทรกหมายเลข 16 บิตที่ไม่ได้ลงชื่อลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:getint32(offset) D: getInt32 () แยกจำนวนเต็ม 32 บิตที่ลงนามจากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:setint32(offset, number) D: setint32 () แทรกหมายเลข 32 บิตที่ลงนามลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:getuint32(offset) D: getuint32 () แยกจำนวนเต็ม 32 บิตที่ไม่ได้ลงชื่อออกจากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:setuint32(offset, number) D: setuint32 () แทรกหมายเลข 32 บิตที่ไม่ได้ลงชื่อลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:getint64(offset) D: getInt64 () แยกจำนวนเต็ม 64 บิตที่ลงนามจากหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
d:setint64(offset, number) D: SetInt64 () แทรกหมายเลข 64 บิตที่ลงนามลงในหน่วยความจำที่อ้างอิงโดยวัตถุ data และ offset ไบต์เริ่มต้นจากศูนย์
ไลบรารี probe รบให้การสนับสนุนสำหรับโพรบเคอร์เนล
probe.new(symbol|address, handlers) probe.new () ส่งคืนวัตถุ probe รบใหม่สำหรับการตรวจสอบ symbol เคอร์เนล (สตริง) หรือ address (แสง userData) และติดตั้ง handlers ในระบบ handler จะต้อง กำหนดเป็นตารางที่มีฟิลด์ต่อไปนี้:
pre : ฟังก์ชั่นที่จะเรียกก่อนคำสั่งที่ตรวจสอบ ได้รับ symbol หรือ address ตามด้วยการปิดที่อาจถูกเรียกให้แสดงการลงทะเบียน CPU และสแต็กในบันทึกระบบpost : ฟังก์ชั่นที่จะเรียกหลังจากคำสั่งที่ตรวจสอบ ได้รับ symbol หรือ address ตามด้วยการปิดที่อาจถูกเรียกให้แสดงการลงทะเบียน CPU และสแต็กในบันทึกระบบ p:stop() P: หยุด () ลบตัวจัดการ probe ออกจากระบบ
p:enable(bool) P: เปิดใช้งาน () เปิดใช้งานหรือปิดการใช้งานตัวจัดการ probe รบตามด้วย bool
ไลบรารี syscall ให้การสนับสนุนสำหรับที่อยู่และหมายเลขการโทรของระบบ
syscall.address(number) syscall.address () ส่งคืนที่อยู่การโทรระบบ (Light UserData) ที่อ้างอิงโดย number ที่กำหนด
syscall.number(name) syscall.number () ส่งคืนหมายเลขการโทรของระบบที่อ้างอิงโดย name ที่กำหนด
ไลบรารี syscall.table ให้การสนับสนุนสำหรับการแปลชื่อการโทรของระบบไปยังที่อยู่ (Light UserData)
ไลบรารี xdp ให้การสนับสนุนระบบย่อย Data Path (XDP) Kernel Express ห้องสมุดนี้ได้รับแรงบันดาลใจจากโครงการ GSOC ของ Victor Nogueira
xdp.attach(callback) XDP.ATTACH () ลงทะเบียนฟังก์ชั่น callback ไปยัง runtime ปัจจุบันที่จะเรียกจากโปรแกรม XDP/EBPF เมื่อใดก็ตามที่เรียก BPF_LUAXDP_RUN KFUNC callback นี้ได้รับอาร์กิวเมนต์ต่อไปนี้:
buffer : วัตถุ data ที่แสดงถึงบัฟเฟอร์เครือข่ายargument : วัตถุ data ที่มีอาร์กิวเมนต์ที่ส่งผ่านโดยโปรแกรม XDP/EBPF ฟังก์ชั่น callback อาจส่งคืนค่าที่กำหนดโดยตารางการดำเนินการ xDP
xdp.detach() xdp.detach () ยกเลิกการลงทะเบียน callback ที่เกี่ยวข้องกับ runtime ปัจจุบันถ้ามี
xdp.actionXDP.Action เป็นตารางที่ส่งออก XDP_ACTION FLAGS ไปยัง LUA
"ABORTED" : ระบุว่าโปรแกรม XDP ถูกยกเลิกโดยทั่วไปเนื่องจากข้อผิดพลาด"DROP" : ระบุว่าควรทิ้งแพ็คเก็ตทิ้งไว้ทั้งหมด"PASS" : อนุญาตให้แพ็กเก็ตผ่านไปยังสแต็กเครือข่าย Linux"TX" : ส่งแพ็คเก็ตกลับออกไปในอินเทอร์เฟซเดียวกันกับที่ได้รับ"REDIRECT" : เปลี่ยนเส้นทางแพ็กเก็ตไปยังอินเทอร์เฟซอื่นหรือบริบทการประมวลผล ไลบรารี xtable ให้การสนับสนุนสำหรับการพัฒนาส่วนขยาย NetFilter Xtable
xtable.match(opts)xtable.match () ส่งคืนวัตถุ Xtable ใหม่สำหรับการขยายการจับคู่ ฟังก์ชั่นนี้ได้รับอาร์กิวเมนต์ต่อไปนี้:
opts : ตารางที่มีฟิลด์ต่อไปนี้:name : สตริงแทนชื่อส่วนขยาย xtablerevision : จำนวนเต็มแสดงถึงการแก้ไขส่วนขยาย xtablefamily : ที่อยู่ครอบครัวหนึ่งใน NetFilter ครอบครัวproto : หมายเลขโปรโตคอลหนึ่งในซ็อกเก็ต.hooks : ขอเชื่อมต่อส่วนขยายเข้ากับค่าหนึ่งจากตาราง hooks - netfilter.inet_hooks, netfilter.bridge_hooks และ netfilter.arp_hooks (หมายเหตุ: netfilter.netdev_hooks ไม่สามารถใช้งานได้สำหรับมรดก X_Tables) (เช่น - 1 << inet_hooks.LOCAL_OUT )match : ฟังก์ชั่นที่จะเรียกใช้สำหรับแพ็คเก็ตจับคู่ ได้รับข้อโต้แย้งต่อไปนี้:skb (อ่านอย่างง่าย): วัตถุ data ที่แสดงถึงบัฟเฟอร์ซ็อกเก็ตpar : ตารางที่มี hotdrop , thoff (การชดเชยส่วนหัวการขนส่ง) และฟิลด์ fragoff (Fragment Offset)userargs : สตริง LUA ที่ส่งผ่านจากโมดูล userpace xtabletrue ถ้าแพ็กเก็ตตรงกับส่วนขยาย; มิฉะนั้นจะต้องส่งคืน falsecheckentry : ฟังก์ชั่นที่จะเรียกร้องให้ตรวจสอบรายการ ฟังก์ชั่นนี้ได้รับ userargs เป็นอาร์กิวเมนต์destroy : ฟังก์ชั่นที่จะเรียกว่าทำลายการขยาย Xtable ฟังก์ชั่นนี้ได้รับ userargs เป็นอาร์กิวเมนต์ xtable.target(opts)xtable.target () ส่งคืนวัตถุ Xtable ใหม่สำหรับการขยายเป้าหมาย ฟังก์ชั่นนี้ได้รับอาร์กิวเมนต์ต่อไปนี้:
opts : ตารางที่มีฟิลด์ต่อไปนี้:name : สตริงแทนชื่อส่วนขยาย xtablerevision : จำนวนเต็มแสดงถึงการแก้ไขส่วนขยาย xtablefamily : ที่อยู่ครอบครัวหนึ่งใน NetFilter ครอบครัวproto : หมายเลขโปรโตคอลหนึ่งในซ็อกเก็ต.hooks : ขอเชื่อมต่อส่วนขยายเข้ากับค่าหนึ่งจากตาราง hooks - netfilter.inet_hooks, netfilter.bridge_hooks และ netfilter.arp_hooks (หมายเหตุ: netfilter.netdev_hooks ไม่สามารถใช้งานได้สำหรับมรดก X_Tables) (เช่น - 1 << inet_hooks.LOCAL_OUT )target : ฟังก์ชั่นที่จะเรียกใช้สำหรับการกำหนดเป้าหมายแพ็คเก็ต ได้รับข้อโต้แย้งต่อไปนี้:skb : วัตถุ data ที่แสดงถึงบัฟเฟอร์ซ็อกเก็ตpar (อ่านอย่างง่าย): ตารางที่มี hotdrop , thoff (การชดเชยส่วนหัวการขนส่ง) และฟิลด์ fragoff (Fragment Offset)userargs : สตริง LUA ที่ส่งผ่านจากโมดูล userpace xtablecheckentry : ฟังก์ชั่นที่จะเรียกร้องให้ตรวจสอบรายการ ฟังก์ชั่นนี้ได้รับ userargs เป็นอาร์กิวเมนต์destroy : ฟังก์ชั่นที่จะเรียกว่าทำลายการขยาย Xtable ฟังก์ชั่นนี้ได้รับ userargs เป็นอาร์กิวเมนต์ ไลบรารี netfilter ให้การสนับสนุนระบบ NetFilter Hook ใหม่
netfilter.register(ops) NetFilter.register () ลงทะเบียนตะขอ NetFilter ใหม่พร้อมตาราง ops ที่กำหนด ฟังก์ชั่นนี้ได้รับอาร์กิวเมนต์ต่อไปนี้:
ops : ตารางที่มีฟิลด์ต่อไปนี้:pf : ตระกูลโปรโตคอลหนึ่งใน netfilter ครอบครัวhooknum : ขอเชื่อมต่อตัวกรองกับหนึ่งค่าจากตาราง hooks ทั้งสอง - netfilter.inet_hooks, netfilter.bridge_hooks, netfilter.arp_hooks และ netfilter.netdev_hooks (เช่น - inet_hooks.LOCAL_OUT + 11 )priority : ลำดับความสำคัญของเบ็ด หนึ่งในค่าจากตาราง netfilter.ip_priority หรือ netfilter.bridge_priorityhook : ฟังก์ชั่นที่จะเรียกใช้สำหรับเบ็ด ได้รับข้อโต้แย้งต่อไปนี้:skb : a data object representing the socket buffer.netfilter.familynetfilter.family is a table that exports address families to Lua.
"UNSPEC" : Unspecified."INET" : Internet Protocol version 4."IPV4" : Internet Protocol version 4."IPV6" : Internet Protocol version 6."ARP" : Address Resolution Protocol."NETDEV" : Device ingress and egress path"BRIDGE" : Ethernet Bridge. netfilter.actionnetfilter.action is a table that exports netfilter actions to Lua.
"DROP" : NF_DROP . The packet is dropped. It is not forwarded, processed, or seen by any other network layer."ACCEPT" : NF_ACCEPT . The packet is accepted and passed to the next step in the network processing chain."STOLEN" : NF_STOLEN . The packet is taken by the handler, and processing stops."QUEUE" : NF_QUEUE . The packet is queued for user-space processing."REPEAT" : NF_REPEAT . The packet is sent through the hook chain again."STOP" : NF_STOP . Processing of the packet stops."CONTINUE" : XT_CONTINUE . Return the packet should continue traversing the rules within the same table."RETURN" : XT_RETURN . Return the packet to the previous chain. netfilter.inet_hooksnetfilter.inet_hooks is a table that exports inet netfilter hooks to Lua.
"PRE_ROUTING" : NF_INET_PRE_ROUTING . The packet is received by the network stack."LOCAL_IN" : NF_INET_LOCAL_IN . The packet is destined for the local system."FORWARD" : NF_INET_FORWARD . The packet is to be forwarded to another host."LOCAL_OUT" : NF_INET_LOCAL_OUT . The packet is generated by the local system."POST_ROUTING" : NF_INET_POST_ROUTING . The packet is about to be sent out. netfilter.bridge_hooksnetfilter.bridge_hooks is a table that exports bridge netfilter hooks to Lua.
"PRE_ROUTING" : NF_BR_PRE_ROUTING . First hook invoked, runs before forward database is consulted."LOCAL_IN" : NF_BR_LOCAL_IN . Invoked for packets destined for the machine where the bridge was configured on."FORWARD" : NF_BR_FORWARD . Called for frames that are bridged to a different port of the same logical bridge device."LOCAL_OUT" : NF_BR_LOCAL_OUT . Called for locally originating packets that will be transmitted via the bridge."POST_ROUTING" : NF_BR_POST_ROUTING . Called for all locally generated packets and all bridged packets netfilter.arp_hooksnetfilter.arp_hooks is a table that exports arp netfilter hooks to Lua.
"IN" : NF_ARP_IN . The packet is received by the network stack."OUT" : NF_ARP_OUT . The packet is generated by the local system."FORWARD" : NF_ARP_FORWARD . The packet is to be forwarded to another host. netfilter.netdev_hooksnetfilter.netdev_hooks is a table that exports netdev netfilter hooks to Lua.
"INGRESS" : NF_NETDEV_INGRESS . The packet is received by the network stack."EGRESS" : NF_NETDEV_EGRESS . The packet is generated by the local system. netfilter.ip_prioritynetfilter.ip_priority is a table that exports netfilter IPv4/IPv6 priority levels to Lua.
"FIRST" : NF_IP_PRI_FIRST"RAW_BEFORE_DEFRAG" : NF_IP_PRI_RAW_BEFORE_DEFRAG"CONNTRACK_DEFRAG" : NF_IP_PRI_CONNTRACK_DEFRAG"RAW" : NF_IP_PRI_RAW"SELINUX_FIRST" : NF_IP_PRI_SELINUX_FIRST"CONNTRACK" : NF_IP_PRI_CONNTRACK"MANGLE" : NF_IP_PRI_MANGLE"NAT_DST" : NF_IP_PRI_NAT_DST"FILTER" : NF_IP_PRI_FILTER"SECURITY" : NF_IP_PRI_SECURITY"NAT_SRC" : NF_IP_PRI_NAT_SRC"SELINUX_LAST" : NF_IP_PRI_SELINUX_LAST"CONNTRACK_HELPER" : NF_IP_PRI_CONNTRACK_HELPER"LAST" : NF_IP_PRI_LAST netfilter.bridge_prioritynetfilter.bridge_priority is a table that exports netfilter bridge priority levels to Lua.
"FIRST" : NF_BR_PRI_FIRST"NAT_DST_BRIDGED" : NF_BR_PRI_NAT_DST_BRIDGED"FILTER_BRIDGED" : NF_BR_PRI_FILTER_BRIDGED"BRNF" : NF_BR_PRI_BRNF"NAT_DST_OTHER" : NF_BR_PRI_NAT_DST_OTHER"FILTER_OTHER" : NF_BR_PRI_FILTER_OTHER"NAT_SRC" : NF_BR_PRI_NAT_SRC"LAST" : NF_BR_PRI_LAST The luaxt userspace library provides support for generating userspace code for xtable extensions.
To build the library, the following steps are required:
usr/lib/xtable and create a libxt_<ext_name>.lua file.luaxt ) in the created file.LUAXTABLE_MODULE=<ext_name> make to build the extension and LUAXTABLE_MODULE=<ext_name> make install (as root) to install the userspace plugin to the system. Now load the extension normally using iptables .
luaxt.match(opts)luaxt.match() returns a new luaxt object for match extensions. This function receives the following arguments:
opts : a table containing the following fields:revision : integer representing the xtable extension revision ( must be same as used in corresponding kernel extension).family : address family, one of luaxt.familyhelp : function to be called for displaying help message for the extension.init : function to be called for initializing the extension. This function receives an par table that can be used to set userargs . ( par.userargs = "mydata" )print : function to be called for printing the arguments. This function recevies userargs set by the init or parse function.save : function to be called for saving the arguments. This function recevies userargs set by the init or parse function.parse : function to be called for parsing the command line arguments. This function receives an par table that can be used to set userargs and flags . ( par.userargs = "mydata" )final_check : function to be called for final checking of the arguments. This function receives flags set by the parse function. luaxt.target(opts)luaxt.target() returns a new luaxt object for target extensions. This function receives the following arguments:
opts : a table containing the following fields:revision : integer representing the xtable extension revision ( must be same as used in corresponding kernel extension).family : address family, one of luaxt.familyhelp : function to be called for displaying help message for the extension.init : function to be called for initializing the extension. This function receives an par table that can be used to set userargs . ( par.userargs = "mydata" )print : function to be called for printing the arguments. This function recevies userargs set by the init or parse function.save : function to be called for saving the arguments. This function recevies userargs set by the init or parse function.parse : function to be called for parsing the command line arguments. This function receives an par table that can be used to set userargs and flags . ( par.userargs = "mydata" )final_check : function to be called for final checking of the arguments. This function receives flags set by the parse function. luaxt.familyluaxt.family is a table that exports address families to Lua.
"UNSPEC" : Unspecified."INET" : Internet Protocol version 4."IPV4" : Internet Protocol version 4."IPV6" : Internet Protocol version 6."ARP" : Address Resolution Protocol."NETDEV" : Device ingress and egress path"BRIDGE" : Ethernet Bridge.completion The completion library provides support for the kernel completion primitives.
Task completion is a synchronization mechanism used to coordinate the execution of multiple threads, similar to pthread_barrier , it allows threads to wait for a specific event to occur before proceeding, ensuring certain tasks are complete in a race-free manner.
completion.new() completion.new() creates a new completion object.
c:complete()c:complete() signals a single thread waiting on this completion.
c:wait([timeout]) c:wait() waits for completion of a task until the specified timeout expires. The timeout is specified in milliseconds. If the timeout parameter is omitted, it waits indefinitely. Passing a timeout value less than zero results in undefined behavior. Threads waiting for events can be interrupted by signals, for example, such as when thread.stop is invoked. Therefore, this function can return in three ways:
truenil, "timeout"nil, "interrupt" spyglass is a kernel script that implements a keylogger inspired by the spy kernel module. This kernel script logs the keysym of the pressed keys in a device ( /dev/spyglass ). If the keysym is a printable character, spyglass logs the keysym itself; otherwise, it logs a mnemonic of the ASCII code, (eg, <del> stands for 127 ).
sudo make examples_install # installs examples
sudo lunatik run examples/spyglass # runs spyglass
sudo tail -f /dev/spyglass # prints the key log
sudo sh -c "echo 'enable=false' > /dev/spyglass" # disable the key logging
sudo sh -c "echo 'enable=true' > /dev/spyglass" # enable the key logging
sudo sh -c "echo 'net=127.0.0.1:1337' > /dev/spyglass" # enable network support
nc -lu 127.0.0.1 1337 & # listen to UDP 127.0.0.1:1337
sudo tail -f /dev/spyglass # sends the key log through the network
keylocker is a kernel script that implements Konami Code for locking and unlocking the console keyboard. When the user types ↑ ↑ ↓ ↓ ← → ← → LCTRL LALT , the keyboard will be locked ; that is, the system will stop processing any key pressed until the user types the same key sequence again.
sudo make examples_install # installs examples
sudo lunatik run examples/keylocker # runs keylocker
<↑> <↑> <↓> <↓> <←> <→> <←> <→> <LCTRL> <LALT> # locks keyboard
<↑> <↑> <↓> <↓> <←> <→> <←> <→> <LCTRL> <LALT> # unlocks keyboard
tap 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.
sudo make examples_install # installs examples
sudo lunatik run examples/tap # runs tap
cat /dev/tap
shared is a kernel script that implements an in-memory key-value store using rcu, data, socket and thread.
sudo make examples_install # installs examples
sudo lunatik spawn examples/shared # spawns shared
nc 127.0.0.1 90 # connects to shared
foo=bar # assigns "bar" to foo
foo # retrieves foo
bar
^C # finishes the connection
echod is an echo server implemented as kernel scripts.
sudo make examples_install # installs examples
sudo lunatik spawn examples/echod/daemon # runs echod
nc 127.0.0.1 1337
hello kernel!
hello kernel!
systrack is a kernel script that implements a device driver to monitor system calls. It prints the amount of times each system call was called since the driver has been installed.
sudo make examples_install # installs examples
sudo lunatik run examples/systrack # runs systracker
cat /dev/systrack
writev: 0
close: 1927
write: 1085
openat: 2036
read: 4131
readv: 0
filter is a kernel extension composed by a XDP/eBPF program to filter HTTPS sessions and a Lua kernel script to filter SNI TLS extension. This kernel extension drops any HTTPS request destinated to a blacklisted server.
Compile and install libbpf , libxdp and xdp-loader :
mkdir -p " ${LUNATIK_DIR} " ; cd " ${LUNATIK_DIR} " # LUNATIK_DIR must be set to the same value as above (Setup section)
git clone --depth 1 --recurse-submodules https://github.com/xdp-project/xdp-tools.git
cd xdp-tools/lib/libbpf/src
make
sudo DESTDIR=/ make install
cd ../../../
make libxdp
cd xdp-loader
make
sudo make installCome back to this repository, install and load the filter:
cd ${LUNATIK_DIR} /lunatik # cf. above
sudo make btf_install # needed to export the 'bpf_luaxdp_run' kfunc
sudo make examples_install # installs examples
make ebpf # builds the XDP/eBPF program
sudo make ebpf_install # installs the XDP/eBPF program
sudo lunatik run examples/filter/sni false # runs the Lua kernel script
sudo xdp-loader load -m skb < ifname > https.o # loads the XDP/eBPF programFor example, testing is easy thanks to docker. Assuming docker is installed and running:
sudo xdp-loader load -m skb docker0 https.o
sudo journalctl -ft kerneldocker run --rm -it alpine/curl https://ebpf.io The system logs (in the first terminal) should display filter_sni: ebpf.io DROP , and the docker run… should return curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to ebpf.io:443 .
This other sni filter uses netfilter api.
dnsblock is a kernel script that uses the lunatik xtable library to filter DNS packets. This script drops any outbound DNS packet with question matching the blacklist provided by the user.
sudo make examples_install # installs examples
cd examples/dnsblock
make # builds the userspace extension for netfilter
sudo make install # installs the extension to Xtables directory
sudo lunatik run examples/dnsblock/dnsblock false # runs the Lua kernel script
sudo iptables -A OUTPUT -m dnsblock -j DROP # this initiates the netfilter framework to load our extension
sudo make examples_install # installs examples
sudo lunatik run examples/dnsblock/nf_dnsblock false # runs the Lua kernel script
dnsdoctor is a kernel script that uses the lunatik xtable library to change the DNS response from Public IP to a Private IP if the destination IP matches the one provided by the user. For example, if the user wants to change the DNS response from 192.168.10.1 to 10.1.2.3 for the domain lunatik.com if the query is being sent to 10.1.1.2 (a private client), this script can be used.
sudo make examples_install # installs examples
cd examples/dnsdoctor
setup.sh # sets up the environment
# test the setup, a response with IP 192.168.10.1 should be returned
dig lunatik.com
# run the Lua kernel script
sudo lunatik run examples/dnsdoctor/dnsdoctor false
# build and install the userspace extension for netfilter
make
sudo make install
# add rule to the mangle table
sudo iptables -t mangle -A PREROUTING -p udp --sport 53 -j dnsdoctor
# test the setup, a response with IP 10.1.2.3 should be returned
dig lunatik.com
# cleanup
sudo iptables -t mangle -D PREROUTING -p udp --sport 53 -j dnsdoctor # remove the rule
sudo lunatik unload
cleanup.sh
sudo make examples_install # installs examples
examples/dnsdoctor/setup.sh # sets up the environment
# test the setup, a response with IP 192.168.10.1 should be returned
dig lunatik.com
# run the Lua kernel script
sudo lunatik run examples/dnsdoctor/nf_dnsdoctor false
# test the setup, a response with IP 10.1.2.3 should be returned
dig lunatik.com
# cleanup
sudo lunatik unload
examples/dnsdoctor/cleanup.sh
Lunatik is dual-licensed under MIT or GPL-2.0-only.
Lua submodule is licensed under MIT. For more details, see its Copyright Notice.
Klibc submodule is dual-licensed under BSD 3-Clause or GPL-2.0-only. For more details, see its LICENCE file.