diff --git a/kernel-src/include/kernel/abi.h b/kernel-src/include/kernel/abi.h index e8a4ed84..7a77f997 100644 --- a/kernel-src/include/kernel/abi.h +++ b/kernel-src/include/kernel/abi.h @@ -88,6 +88,7 @@ typedef struct { #define AF_LOCAL 1 #define AF_INET 2 +#define AF_PACKET 17 #define SOCK_STREAM 1 #define SOCK_DGRAM 2 @@ -155,6 +156,16 @@ typedef struct { char sun_path[ABISOCKADDR_UN_MAX]; } unaddr_t; +typedef struct { + uint16_t sll_family; + uint16_t sll_protocol; + int32_t sll_ifindex; + uint16_t sll_hatype; + uint8_t sll_pkttype; + uint8_t sll_halen; + uint8_t sll_addr[8]; +} sockaddr_ll_t; + typedef struct { void *addr; socklen_t addrlen; diff --git a/kernel-src/include/kernel/sock.h b/kernel-src/include/kernel/sock.h index 49535220..4aab531c 100644 --- a/kernel-src/include/kernel/sock.h +++ b/kernel-src/include/kernel/sock.h @@ -175,8 +175,8 @@ static inline int socket_send(socket_t *socket, void *buffer, size_t size, uintm return e; } -static inline int sock_convertaddress(sockaddr_t *sockaddr, abisockaddr_t *abisockaddr) { - switch (abisockaddr->type) { +static inline int sock_convertaddress(sockaddr_t *sockaddr, void *abisockaddr) { + switch (((abisockaddr_t *)abisockaddr)->type) { case AF_INET: inaddr_t *inaddr = (inaddr_t *)abisockaddr; sockaddr->ipv4addr.addr = be_to_cpu_d(inaddr->sin_addr); @@ -190,6 +190,18 @@ static inline int sock_convertaddress(sockaddr_t *sockaddr, abisockaddr_t *abiso memcpy(sockaddr->path, unaddr->sun_path, length + 1); break; + case AF_PACKET: { + sockaddr_ll_t lladdr; + memcpy(&lladdr, abisockaddr, sizeof(lladdr)); + if (lladdr.sll_ifindex < 0 || lladdr.sll_ifindex > 0xffff) + return EINVAL; + + sockaddr->raw.netdev = lladdr.sll_ifindex; + sockaddr->raw.proto = be_to_cpu_w(lladdr.sll_protocol); + memset(sockaddr->raw.mac, 0, sizeof(sockaddr->raw.mac)); + memcpy(sockaddr->raw.mac, lladdr.sll_addr, min((size_t)lladdr.sll_halen, sizeof(sockaddr->raw.mac))); + break; + } default: return EINVAL; } @@ -197,21 +209,33 @@ static inline int sock_convertaddress(sockaddr_t *sockaddr, abisockaddr_t *abiso return 0; } -static inline int sock_addrtoabiaddr(int socktype, sockaddr_t *sockaddr, abisockaddr_t *abisockaddr) { +static inline int sock_addrtoabiaddr(int socktype, sockaddr_t *sockaddr, void *abisockaddr) { switch (socktype) { case SOCKET_TYPE_UDP: case SOCKET_TYPE_TCP: - abisockaddr->type = AF_INET; + ((abisockaddr_t *)abisockaddr)->type = AF_INET; inaddr_t *inaddr = (inaddr_t *)abisockaddr; inaddr->sin_addr = cpu_to_be_d(sockaddr->ipv4addr.addr); inaddr->sin_port = cpu_to_be_w(sockaddr->ipv4addr.port); break; case SOCKET_TYPE_LOCAL: case SOCKET_TYPE_LOCAL_SEQPACKET: - abisockaddr->type = AF_LOCAL; + ((abisockaddr_t *)abisockaddr)->type = AF_LOCAL; unaddr_t *unaddr = (unaddr_t *)abisockaddr; strcpy(unaddr->sun_path, sockaddr->path); break; + case SOCKET_TYPE_RAW_STRIPPED: { + sockaddr_ll_t lladdr = { + .sll_family = AF_PACKET, + .sll_protocol = cpu_to_be_w(sockaddr->raw.proto), + .sll_ifindex = sockaddr->raw.netdev, + .sll_hatype = ARPHRD_ETHER, + .sll_halen = sizeof(sockaddr->raw.mac) + }; + memcpy(lladdr.sll_addr, sockaddr->raw.mac, sizeof(sockaddr->raw.mac)); + memcpy(abisockaddr, &lladdr, sizeof(lladdr)); + break; + } default: return EINVAL; } @@ -253,6 +277,13 @@ static inline int sock_copy_addr_to_user(int socktype, sockaddr_t *sockaddr, voi return 0; } + case SOCKET_TYPE_RAW_STRIPPED: { + sockaddr_ll_t lladdr = {0}; + sock_addrtoabiaddr(socktype, sockaddr, &lladdr); + + *actual_len = sizeof(lladdr); + return usercopy_touser(uaddr, &lladdr, min(uaddrlen, sizeof(lladdr))); + } default: return EINVAL; } diff --git a/kernel-src/sys/syscalls/socket.c b/kernel-src/sys/syscalls/socket.c index 44812a7e..37ed1223 100644 --- a/kernel-src/sys/syscalls/socket.c +++ b/kernel-src/sys/syscalls/socket.c @@ -36,6 +36,11 @@ syscallret_t syscall_socket(context_t *, int domain, int type, int protocol) { socktype = SOCKET_TYPE_LOCAL; if (type == SOCK_SEQPACKET) socktype = SOCKET_TYPE_LOCAL_SEQPACKET; + break; + case AF_PACKET: + if (type == SOCK_DGRAM) + socktype = SOCKET_TYPE_RAW_STRIPPED; + break; } if (socktype == -1) {