55
66/***
77* Low-level Lua interface for kernel networking sockets.
8- * This library provides support for creating and managing various types of
9- * sockets within the Linux kernel, enabling network communication directly
10- * from Lua scripts running in kernel space. It is inspired by
11- * [Chengzhi Tan](https://github.com/tcz717)'s
8+ * Inspired by [Chengzhi Tan](https://github.com/tcz717)'s
129* [GSoC project](https://summerofcode.withgoogle.com/archive/2018/projects/5993341447569408).
1310*
14- * It allows operations such as creating sockets, binding, listening, connecting,
15- * sending, and receiving data. The library also exposes constants for address
16- * families, socket types, IP protocols, and message flags.
17- *
18- * For higher-level IPv4 TCP/UDP socket operations with string-based IP addresses
19- * (e.g., "127.0.0.1"), consider using the `socket.inet` library.
11+ * For higher-level IPv4 TCP/UDP socket operations, consider using the `socket.inet` library.
2012*
2113* @module socket
2214* @see socket.inet
@@ -70,7 +62,7 @@ static size_t luasocket_checkaddr(lua_State *L, struct socket *socket, struct so
7062 else if (addr -> ss_family == AF_PACKET ) {
7163 struct sockaddr_ll * addr_ll = (struct sockaddr_ll * )addr ;
7264 addr_ll -> sll_protocol = htons ((u16 )lunatik_checkinteger (L , ix , 0 , U16_MAX ));
73- addr_ll -> sll_ifindex = (int )lunatik_checkinteger (L , ix + 1 , 0 , INT_MAX );;
65+ addr_ll -> sll_ifindex = (int )lunatik_checkinteger (L , ix + 1 , 0 , INT_MAX );
7466 return sizeof (struct sockaddr_ll );
7567 }
7668 else {
@@ -84,25 +76,21 @@ static size_t luasocket_checkaddr(lua_State *L, struct socket *socket, struct so
8476
8577static int luasocket_pushaddr (lua_State * L , struct sockaddr_storage * addr )
8678{
87- int n ;
8879 if (addr -> ss_family == AF_INET ) {
8980 struct sockaddr_in * addr_in = (struct sockaddr_in * )addr ;
9081 lua_pushinteger (L , (lua_Integer )ntohl (addr_in -> sin_addr .s_addr ));
9182 lua_pushinteger (L , (lua_Integer )ntohs (addr_in -> sin_port ));
92- n = 2 ;
83+ return 2 ;
9384 }
9485#ifdef CONFIG_UNIX
9586 else if (LUASOCKET_ISUNIX (addr -> ss_family )) {
9687 struct sockaddr_un * addr_un = (struct sockaddr_un * )addr ;
9788 lua_pushstring (L , addr_un -> sun_path );
98- n = 1 ;
89+ return 1 ;
9990 }
10091#endif
101- else {
102- lua_pushlstring (L , (const char * )addr -> __data , LUASOCKET_ADDRMAX );
103- n = 1 ;
104- }
105- return n ;
92+ lua_pushlstring (L , (const char * )addr -> __data , LUASOCKET_ADDRMAX );
93+ return 1 ;
10694}
10795
10896LUNATIK_PRIVATECHECKER (luasocket_check , struct socket * );
@@ -112,33 +100,17 @@ LUNATIK_PRIVATECHECKER(luasocket_check, struct socket *);
112100/***
113101* Sends a message through the socket.
114102*
115- * For connection-oriented sockets (`SOCK_STREAM`), `addr` and `port` are usually omitted
116- * as the connection is already established.
117- * For connectionless sockets (`SOCK_DGRAM`), `addr` and `port` (if applicable for the
118- * address family) specify the destination.
119- *
120103* @function send
121104* @tparam string|data message The message to send; a data object avoids string allocation.
122- * @tparam[opt] integer|string addr The destination address.
123- *
124- * - For `AF_INET` (IPv4) sockets: An integer representing the IPv4 address (e.g., from `net.aton()`).
125- * - For other address families (e.g., `AF_PACKET`): A packed string representing the destination address
126- * (e.g., MAC address for `AF_PACKET`). The exact format depends on the family.
127- * @tparam[opt] integer port The destination port number (required if `addr` is an IPv4 address for `AF_INET`).
105+ * @tparam[opt] integer|string addr Destination address (family-dependent).
106+ * @tparam[opt] integer port Destination port (required for `AF_INET`).
128107* @treturn integer The number of bytes sent.
129- * @raise Error if the send operation fails or if address parameters are incorrect for the socket type.
130- * @usage
131- * -- For a connected TCP socket:
132- * local bytes_sent = tcp_conn_sock:send("Hello, server!")
133- *
134- * -- For a UDP socket (sending to 192.168.1.100, port 1234):
135- * local bytes_sent = udp_sock:send("UDP packet", net.aton("192.168.1.100"), 1234)
108+ * @raise Error if the send operation fails.
136109* @see net.aton
137110*/
138111static int luasocket_send (lua_State * L )
139112{
140113 struct socket * socket = luasocket_check (L , 1 );
141- size_t len ;
142114 struct kvec vec ;
143115 struct msghdr msg ;
144116 struct sockaddr_storage addr ;
@@ -151,18 +123,20 @@ static int luasocket_send(lua_State *L)
151123 luadata_t * data = lunatik_checkclass (L , 2 , "data" , LUNATIK_OPT_SINGLE )-> private ;
152124 lunatik_argchecknull (L , data -> ptr , 2 );
153125 vec .iov_base = data -> ptr ;
154- len = data -> size ;
126+ vec . iov_len = data -> size ;
155127 }
156- else
128+ else {
129+ size_t len ;
157130 vec .iov_base = (void * )luaL_checklstring (L , 2 , & len );
158- vec .iov_len = len ;
131+ vec .iov_len = len ;
132+ }
159133
160134 if (unlikely (nargs >= 3 )) {
161135 size_t size = luasocket_checkaddr (L , socket , & addr , 3 );
162136 luasocket_msgaddr (msg , addr , size );
163137 }
164138
165- lunatik_tryret (L , ret , kernel_sendmsg , socket , & msg , & vec , 1 , len );
139+ lunatik_tryret (L , ret , kernel_sendmsg , socket , & msg , & vec , 1 , vec . iov_len );
166140 lua_pushinteger (L , ret );
167141 return 1 ;
168142}
@@ -185,7 +159,6 @@ static int luasocket_receive(lua_State *L)
185159{
186160 struct socket * socket = luasocket_check (L , 1 );
187161 int isdata = lua_isuserdata (L , 2 );
188- size_t len ;
189162 luaL_Buffer B ;
190163 struct kvec vec ;
191164 struct msghdr msg ;
@@ -200,51 +173,31 @@ static int luasocket_receive(lua_State *L)
200173 luadata_t * data = lunatik_checkclass (L , 2 , "data" , LUNATIK_OPT_SINGLE )-> private ;
201174 lunatik_argchecknull (L , data -> ptr , 2 );
202175 vec .iov_base = data -> ptr ;
203- len = data -> size ;
176+ vec . iov_len = data -> size ;
204177 }
205178 else {
206- len = (size_t )luaL_checkinteger (L , 2 );
179+ size_t len = (size_t )luaL_checkinteger (L , 2 );
207180 vec .iov_base = (void * )luaL_buffinitsize (L , & B , len );
181+ vec .iov_len = len ;
208182 }
209- vec .iov_len = len ;
210183
211184 if (unlikely (from ))
212185 luasocket_msgaddr (msg , addr , sizeof (addr ));
213186
214- lunatik_tryret (L , ret , kernel_recvmsg , socket , & msg , & vec , 1 , len , flags );
187+ lunatik_tryret (L , ret , kernel_recvmsg , socket , & msg , & vec , 1 , vec . iov_len , flags );
215188 isdata ? lua_pushinteger (L , ret ) : luaL_pushresultsize (& B , ret );
216189
217190 return unlikely (from ) ? luasocket_pushaddr (L , (struct sockaddr_storage * )msg .msg_name ) + 1 : 1 ;
218191}
219192
220193/***
221194* Binds the socket to a local address.
222- * This is typically used on the server side before calling `listen()` or on
223- * connectionless sockets to specify a local port/interface for receiving.
224195*
225196* @function bind
226- * @tparam integer|string addr The local address to bind to. The interpretation depends on `socket.sk.sk_family`:
227- *
228- * - `AF_INET` (IPv4): An integer representing the IPv4 address (e.g., from `net.aton()`).
229- * Use `0` (or `net.aton("0.0.0.0")`) to bind to all available interfaces.
230- * The `port` argument is also required.
231- * - `AF_PACKET`: An integer representing the ethernet protocol in host byte order
232- * (e.g., `0x0003` for `ETH_P_ALL`, `0x88CC` for `ETH_P_LLDP`)
233- * The `port` argument is also required.
234- * - Other families: A packed string directly representing parts of the family-specific address structure.
235- *
236- * @tparam[opt] integer port The local port or interface index.
237- * - `AF_INET`: TCP/UDP port number.
238- * - `AF_PACKET`: Network interface index (e.g., from `linux.ifindex("eth0")`).
239- *
197+ * @tparam integer|string addr Local address to bind to (family-dependent).
198+ * @tparam[opt] integer port Local port or interface index (family-dependent).
240199* @treturn nil
241- * @raise Error if the bind operation fails (e.g., address already in use, invalid address).
242- * @usage
243- * -- Bind TCP/IPv4 socket to localhost, port 8080
244- * tcp_server_sock:bind(net.aton("127.0.0.1"), 8080)
245- *
246- * -- Bind AF_PACKET socket to protocol `ETH_P_LLDP` on a specific interface
247- * af_packet_sock:bind(0x88CC, linux.ifindex("eth0"))
200+ * @raise Error if the bind operation fails.
248201* @see net.aton
249202* @see linux.ifindex
250203*/
@@ -263,16 +216,11 @@ static int luasocket_bind(lua_State *L)
263216
264217/***
265218* Puts a connection-oriented socket into the listening state.
266- * This is required for server sockets (e.g., `SOCK_STREAM`) to be able to
267- * accept incoming connections.
268219*
269220* @function listen
270- * @tparam[opt] integer backlog The maximum length of the queue for pending connections.
271- * If omitted, a system-dependent default (e.g., `SOMAXCONN`) is used.
221+ * @tparam[opt] integer backlog Maximum pending connection queue length (default: `SOMAXCONN`).
272222* @treturn nil
273- * @raise Error if the listen operation fails (e.g., socket not bound, invalid state).
274- * @usage
275- * tcp_server_sock:listen(10)
223+ * @raise Error if the listen operation fails.
276224*/
277225static int luasocket_listen (lua_State * L )
278226{
@@ -285,23 +233,13 @@ static int luasocket_listen(lua_State *L)
285233
286234/***
287235* Initiates a connection on a socket.
288- * This is typically used by client sockets to establish a connection to a server.
289- * For datagram sockets, this sets the default destination address for `send` and
290- * the only address from which datagrams are received.
291236*
292237* @function connect
293- * @tparam integer|string addr The destination address to connect to.
294- * Interpretation depends on `socket.sk.sk_family`:
295- *
296- * - `AF_INET` (IPv4): An integer representing the IPv4 address (e.g., from `net.aton()`).
297- * The `port` argument is also required.
298- * - Other families: A packed string representing the family-specific destination address.
299- * @tparam[opt] integer port The destination port number (required and used only if the family is `AF_INET`).
300- * @tparam[opt=0] integer flags Optional connection flags.
238+ * @tparam integer|string addr Destination address (family-dependent).
239+ * @tparam[opt] integer port Destination port (required for `AF_INET`).
240+ * @tparam[opt=0] integer flags Connection flags.
301241* @treturn nil
302- * @raise Error if the connect operation fails (e.g., connection refused, host unreachable).
303- * @usage
304- * tcp_client_sock:connect(net.aton("192.168.1.100"), 80)
242+ * @raise Error if the connect operation fails.
305243*/
306244static int luasocket_connect (lua_State * L )
307245{
@@ -332,43 +270,25 @@ static int luasocket_get##what(lua_State *L) \
332270* Gets the local address to which the socket is bound.
333271*
334272* @function getsockname
335- * @treturn integer|string addr The local address.
336- *
337- * - For `AF_INET`: An integer representing the IPv4 address (can be converted with `net.ntoa()`).
338- * - For other families: A packed string representing the local address.
339- * @treturn[opt] integer port If the family is `AF_INET`, the local port number.
273+ * @treturn integer|string addr Local address (family-dependent).
274+ * @treturn[opt] integer port Local port for `AF_INET`.
340275* @raise Error if the operation fails.
341- * @usage
342- * local local_ip_int, local_port = my_socket:getsockname()
343- * if my_socket.sk.sk_family == socket.af.INET then print("Bound to " .. net.ntoa(local_ip_int) .. ":" .. local_port) end
344276*/
345277LUASOCKET_NEWGETTER (sockname );
346278
347279/***
348280* Gets the address of the peer to which the socket is connected.
349- * This is typically used with connection-oriented sockets after a connection
350- * has been established, or with connectionless sockets after `connect()` has
351- * been called to set a default peer.
352281*
353282* @function getpeername
354- * @treturn integer|string addr The peer's address.
355- *
356- * - For `AF_INET`: An integer representing the IPv4 address (can be converted with `net.ntoa()`).
357- * - For other families: A packed string representing the peer's address.
358- * @treturn[opt] integer port If the family is `AF_INET`, the peer's port number.
359- * @raise Error if the operation fails (e.g., socket not connected).
360- * @usage
361- * local peer_ip_int, peer_port = connected_socket:getpeername()
362- * if connected_socket.sk.sk_family == socket.af.INET then print("Connected to " .. net.ntoa(peer_ip_int) .. ":" .. peer_port) end
283+ * @treturn integer|string addr Peer address (family-dependent).
284+ * @treturn[opt] integer port Peer port for `AF_INET`.
285+ * @raise Error if the operation fails.
363286*/
364287LUASOCKET_NEWGETTER (peername );
365288
366289/***
367- * Closes the socket.
368- * This shuts down the socket for both reading and writing and releases
369- * associated kernel resources.
370- * This method is also called automatically when the socket object is garbage collected
371- * or via Lua 5.4's to-be-closed mechanism.
290+ * Closes the socket, shutting it down and releasing kernel resources.
291+ * Also called on garbage collection or via Lua 5.4's to-be-closed mechanism.
372292*
373293* @function close
374294* @treturn nil
@@ -704,13 +624,9 @@ static const lunatik_class_t luasocket_class = {
704624
705625/***
706626* Accepts a connection on a listening socket.
707- * This function is used with connection-oriented sockets (e.g., `SOCK_STREAM`)
708- * that have been put into the listening state by `sock:listen()`.
709627*
710628* @function accept
711- * @tparam socket self The listening socket object.
712- * @tparam[opt=0] integer flags Optional flags to apply to the newly accepted socket
713- * (e.g., `socket.sock.NONBLOCK`, `socket.sock.CLOEXEC`).
629+ * @tparam[opt=0] integer flags Flags for the new socket (e.g., `socket.sock.NONBLOCK`).
714630* @treturn socket A new socket object representing the accepted connection.
715631* @raise Error if the accept operation fails.
716632*/
@@ -726,19 +642,13 @@ static int luasocket_accept(lua_State *L)
726642
727643/***
728644* Creates a new socket object.
729- * This function is the primary way to create a socket.
730645*
731646* @function new
732- * @tparam integer family The address family for the socket (e.g., `socket.af.INET`).
733- * @tparam integer type The type of the socket (e.g., `socket.sock.STREAM`).
734- * @tparam integer protocol The protocol to be used (e.g., `socket.ipproto.TCP`).
735- * For `AF_PACKET` sockets, `protocol` is typically an `ETH_P_*` value in network byte order
736- * (e.g., `linux.hton16(0x0003)` for `ETH_P_ALL`).
647+ * @tparam integer family Address family (e.g., `socket.af.INET`).
648+ * @tparam integer type Socket type (e.g., `socket.sock.STREAM`).
649+ * @tparam integer protocol Protocol (e.g., `socket.ipproto.TCP`).
737650* @treturn socket A new socket object.
738651* @raise Error if socket creation fails.
739- * @usage
740- * -- TCP/IPv4 socket
741- * local tcp_sock = socket.new(socket.af.INET, socket.sock.STREAM, socket.ipproto.TCP)
742652* @see socket.af
743653* @see socket.sock
744654* @see socket.ipproto
0 commit comments