AF_UNIX SEQPACKET/DGRAM, writable /dev overlay, uevent netlink socket; eudev packages
udevd now starts, reads its rules and listens. Still to come: the sysfs device tree and writable uevent files so a trigger has something to replay. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
This commit is contained in:
parent
ed81f9a07a
commit
a9f8cb7e0f
7 changed files with 457 additions and 40 deletions
|
|
@ -164,7 +164,7 @@ SYSCALL_DEFINE(socket)
|
|||
if (type & ~(0xFF | SOCK_CLOEXEC | SOCK_NONBLOCK))
|
||||
return -EINVAL;
|
||||
type &= 0xFF;
|
||||
if (domain == AF_UNIX && type != SOCK_STREAM)
|
||||
if (domain == AF_UNIX && type != SOCK_STREAM && type != SOCK_DGRAM && type != SOCK_SEQPACKET)
|
||||
return -EPROTOTYPE;
|
||||
if (domain == AF_INET && type != SOCK_STREAM && type != SOCK_DGRAM &&
|
||||
type != SOCK_RAW)
|
||||
|
|
@ -185,7 +185,7 @@ SYSCALL_DEFINE(socket)
|
|||
// default rather than departing from it, and programs do write them out:
|
||||
// toybox's `nc` passes IPPROTO_TCP, and refusing it meant "Protocol not
|
||||
// supported" for TCP on a system whose whole network is TCP.
|
||||
if (protocol != 0) {
|
||||
if (protocol != 0 && domain != AF_NETLINK) {
|
||||
int redundant =
|
||||
(domain == AF_INET && type == SOCK_STREAM && protocol == IPPROTO_TCP) ||
|
||||
(domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP);
|
||||
|
|
@ -270,6 +270,16 @@ SYSCALL_DEFINE(bind)
|
|||
return sockbind_in(s, ip, port_from_net(port));
|
||||
}
|
||||
|
||||
// sockaddr_nl: family, pad, port id, groups. Only the groups matter here.
|
||||
if (sock_domain(s) == AF_NETLINK) {
|
||||
uint groups = 0;
|
||||
if (ulen < 12)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&groups, uaddr + 8, 4) < 0)
|
||||
return -EFAULT;
|
||||
return sock_netlink_bind(s, groups);
|
||||
}
|
||||
|
||||
uint64 key;
|
||||
if (sun_abstract(uaddr, ulen, &key))
|
||||
return sockbind_abstract(s, key);
|
||||
|
|
@ -459,15 +469,11 @@ SYSCALL_DEFINE(socketpair)
|
|||
return -EAFNOSUPPORT;
|
||||
int sflags = type & (SOCK_CLOEXEC | SOCK_NONBLOCK);
|
||||
type &= 0xFF;
|
||||
// Datagram and sequenced-packet pairs are carried as a stream. What they
|
||||
// are used for between two processes is passing a descriptor or a status
|
||||
// word -- Rust's process spawning asks for SOCK_SEQPACKET to hear back
|
||||
// from its child -- and one message at a time is all of that. A reader
|
||||
// that sends two and wants them kept apart would see them joined.
|
||||
if (type != SOCK_STREAM && type != 2 /* DGRAM */ && type != 5 /* SEQPACKET */)
|
||||
// Datagram and sequenced-packet pairs keep message boundaries (kernel/net/unix.c).
|
||||
if (type != SOCK_STREAM && type != SOCK_DGRAM && type != SOCK_SEQPACKET)
|
||||
return -EPROTOTYPE;
|
||||
|
||||
if ((r = sockpair(&a, &b)) < 0)
|
||||
if ((r = sockpair_type(&a, &b, type)) < 0)
|
||||
return r;
|
||||
|
||||
if ((fd0 = sock_to_fd(a, sflags)) < 0) {
|
||||
|
|
@ -1076,7 +1082,7 @@ SYSCALL_DEFINE(recvmsg)
|
|||
// one rather than discarding it as Linux would: musl's getifaddrs reads
|
||||
// in chunks, and this whole queue is one "datagram" only by convention.
|
||||
int nlret = -1;
|
||||
if (sock_domain(s) == AF_NETLINK) {
|
||||
if (sock_domain(s) == AF_NETLINK && !sock_is_packet(s)) {
|
||||
uint have = socknl_pending(s);
|
||||
if (have == 0)
|
||||
return -EAGAIN; // never blocks; see sockread
|
||||
|
|
@ -1127,8 +1133,8 @@ SYSCALL_DEFINE(recvmsg)
|
|||
return rd;
|
||||
}
|
||||
got += rd;
|
||||
if (rd < len)
|
||||
break;
|
||||
if (rd < len || sock_is_packet(s))
|
||||
break; // one message per call
|
||||
}
|
||||
|
||||
if (nf > 0) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue