diff --git a/include/zlibs/sys/socket.h b/include/zlibs/sys/socket.h index 6983e180..19b10d8a 100755 --- a/include/zlibs/sys/socket.h +++ b/include/zlibs/sys/socket.h @@ -31,6 +31,7 @@ #define IPPROTO_UDP 17 #define MSG_PEEK (1 << 0) +#define MSG_DONTWAIT (1 << 1) typedef uint32_t socklen_t; typedef uint16_t sa_family_t; diff --git a/kernel/kpart/minilib.c b/kernel/kpart/minilib.c index 8fc7e015..ba3133af 100644 --- a/kernel/kpart/minilib.c +++ b/kernel/kpart/minilib.c @@ -171,6 +171,11 @@ void *malloc(uint32_t size) { } void *realloc(void *ptr, uint32_t size) { + if (size == 0) { + free(ptr); + return NULL; + } + void *new_addr = mem_alloc(size, SNOW_KERNEL, 0); if (new_addr == NULL) diff --git a/zlibs/modules/socket/arp.c b/zlibs/modules/socket/arp.c new file mode 100644 index 00000000..cfade87e --- /dev/null +++ b/zlibs/modules/socket/arp.c @@ -0,0 +1,74 @@ +/*****************************************************************************\ +| === arp.c : 2026 === | +| | +| Implementation for the ARP automatic reponse by socket .pi0iq. | +| d" . `'b | +| This file is part of profanOS and is released under q. /|\ " | +| the terms of the GNU General Public License `// \\ | +| // \\ | +| === elydre : https://github.com/elydre/profanOS === ####### \\ | +\*****************************************************************************/ + +#include "arp.h" +#include + +static void respond(arp_packet_t *packet) { + if (packet->htype != 1 || packet->ptype != 0x0800) + return ; + if (packet->plen != 4 || packet->hlen != 6) + return ; + if (packet->op != 1) + return ; + + eth_info_t info; + eth_get_info(0, &info); + if (info.ip != packet->t_paddr) + return ; + + uint8_t response[6 + 6 + 2 + 28]; + mem_copy(response, packet->s_haddr, 6); + mem_copy(&response[6], info.mac, 6); + response[12] = 0x08; + response[13] = 0x06; + + uint8_t *arp = &response[14]; + // htype + arp[0] = 0; + arp[1] = 1; + + // ptype + arp[2] = 0x08; + arp[3] = 0; + + //hlen/plen + arp[4] = 6; + arp[5] = 4; + + //op + arp[6] = 0; + arp[7] = 2; + + mem_copy(&arp[8], info.mac, 6); + mem_copy(&arp[14], &info.ip, 4); + mem_copy(&arp[18], packet->s_haddr, 6); + mem_copy(&arp[24], &packet->s_paddr, 4); + eth_send(response, 6 + 6 + 2 + 28); +} + +void socket_on_recv_arp(int len, uint8_t *packet) { + if (len < 28) + return ; + arp_packet_t arp; + + arp.htype = (((uint16_t)packet[0]) << 8) | (packet[1]); + arp.ptype = (((uint16_t)packet[2]) << 8) | (packet[3]); + arp.hlen = packet[4]; + arp.plen = packet[5]; + arp.op = (((uint16_t)packet[6]) << 8) | (packet[7]); + mem_copy(arp.s_haddr, &packet[8], 6); + mem_copy(&arp.s_paddr, &packet[14], 4); + mem_copy(arp.t_haddr, &packet[18], 6); + mem_copy(&arp.t_paddr, &packet[24], 4); + + respond(&arp); +} diff --git a/zlibs/modules/socket/include/arp.h b/zlibs/modules/socket/include/arp.h new file mode 100644 index 00000000..d34ddd84 --- /dev/null +++ b/zlibs/modules/socket/include/arp.h @@ -0,0 +1,33 @@ +/*****************************************************************************\ +| === arp.h : 2026 === | +| | +| Header for the Address Resolution Procotol (ARP) .pi0iq. | +| d" . `'b | +| This file is part of profanOS and is released under q. /|\ " | +| the terms of the GNU General Public License `// \\ | +| // \\ | +| === elydre : https://github.com/elydre/profanOS === ####### \\ | +\*****************************************************************************/ + +#ifndef ARP_H +#define ARP_H + +#include "utils.h" +#include +#include + +typedef struct { + uint16_t htype; + uint16_t ptype; + uint8_t hlen; + uint8_t plen; + uint16_t op; + uint8_t s_haddr[6]; + uint32_t s_paddr; + uint8_t t_haddr[6]; + uint32_t t_paddr; +} arp_packet_t; + +void socket_on_recv_arp(int len, uint8_t *packet); + +#endif diff --git a/zlibs/modules/socket/ip/on_send.c b/zlibs/modules/socket/ip/on_send.c index 53a801c5..de4acdab 100644 --- a/zlibs/modules/socket/ip/on_send.c +++ b/zlibs/modules/socket/ip/on_send.c @@ -57,6 +57,7 @@ void socket_on_send_ip(uint32_t src_ip, uint32_t dest_ip, uint8_t protocol, uint eth_info_t info; eth_get_info(0, &info); + mem_copy(ð_buffer[6], &info.mac, 6); if ((src_ip & info.net_mask) == (dest_ip & info.net_mask)) mem_copy(eth_buffer, "\xff\xff\xff\xff\xff\xff", 6); diff --git a/zlibs/modules/socket/tick.c b/zlibs/modules/socket/tick.c index be1fa097..aeccb9a7 100644 --- a/zlibs/modules/socket/tick.c +++ b/zlibs/modules/socket/tick.c @@ -15,8 +15,10 @@ #include "udp.h" #include "ip.h" +#include "arp.h" #define ETHER_IP4 0x0800 +#define ETHER_ARP 0x0806 void socket_tick(int len, uint8_t *packet) { for (int i = 0; i < sockets_len; i++) { @@ -44,6 +46,9 @@ void socket_tick(int len, uint8_t *packet) { case ETHER_IP4: socket_on_recv_ip(len, packet); break; + case ETHER_ARP: + socket_on_recv_arp(len, packet); + break; default: break; } diff --git a/zlibs/modules/socket/udp/recvfrom.c b/zlibs/modules/socket/udp/recvfrom.c index 7bdc987d..5c7a48ad 100644 --- a/zlibs/modules/socket/udp/recvfrom.c +++ b/zlibs/modules/socket/udp/recvfrom.c @@ -18,8 +18,10 @@ ssize_t socket_udp_recvfrom(socket_t *sock, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { udp_t *data = sock->data; + if (flags & MSG_DONTWAIT && data->recv_len == 0) + return -EAGAIN; while (data->recv_len == 0) - process_sleep(process_get_pid(), 10); + process_sleep(process_get_pid(), 5); if ((size_t)data->recv[0].len < len) len = data->recv[0].len; @@ -31,8 +33,10 @@ ssize_t socket_udp_recvfrom(socket_t *sock, void *buf, size_t len, int flags, addr2->sin_addr.s_addr = data->recv[0].src_ip; *addrlen = sizeof(struct sockaddr_in); } - mem_copy(data->recv, &data->recv[1], sizeof(udp_packet_t) * (data->recv_len - 1)); - if (!(flags & MSG_PEEK)) + if (!(flags & MSG_PEEK)) { + free(data->recv[0].data); + mem_copy(data->recv, &data->recv[1], sizeof(udp_packet_t) * (data->recv_len - 1)); data->recv_len--; + } return (ssize_t) len; } diff --git a/zlibs/modules/socket/udp/sendto.c b/zlibs/modules/socket/udp/sendto.c index 38e51bbb..504174f1 100644 --- a/zlibs/modules/socket/udp/sendto.c +++ b/zlibs/modules/socket/udp/sendto.c @@ -10,15 +10,18 @@ \*****************************************************************************/ #include +#include #include #include "udp.h" -ssize_t socket_udp_send(socket_t *sock, const uint8_t *buffer, size_t len, uint32_t dip, uint16_t dport) { +ssize_t socket_udp_send(socket_t *sock, const uint8_t *buffer, size_t len, uint32_t dip, uint16_t dport, int flags) { udp_t *data = sock->data; if (len > 1450) return -EMSGSIZE; - if (data->send_len == 64) - return -ENOMEM; + if (data->send_len == 64 && (flags & MSG_DONTWAIT)) + return -EAGAIN; + while (data->send_len == 64) + process_sleep(process_get_pid(), 1); udp_packet_t *packet = &data->send[data->send_len]; if (dip == 0) { if (!data->is_connected) @@ -57,7 +60,7 @@ ssize_t socket_udp_sendto(socket_t *sock, const void *buf, size_t len, int flags const struct sockaddr *dest_addr, socklen_t addrlen) { if (!dest_addr && addrlen == 0) - return socket_udp_send(sock, buf, len, 0, 0); + return socket_udp_send(sock, buf, len, 0, 0, 0); if (addrlen != sizeof(struct sockaddr_in)) return -EINVAL; @@ -66,5 +69,5 @@ ssize_t socket_udp_sendto(socket_t *sock, const void *buf, size_t len, int flags return -EINVAL; if (addr2->sin_port == 0) return -EINVAL; - return socket_udp_send(sock, buf, len, addr2->sin_addr.s_addr, addr2->sin_port); + return socket_udp_send(sock, buf, len, addr2->sin_addr.s_addr, addr2->sin_port, flags); } diff --git a/zlibs/modules/socket/udp/udp.c b/zlibs/modules/socket/udp/udp.c index 4e89f0e7..aca0ed11 100644 --- a/zlibs/modules/socket/udp/udp.c +++ b/zlibs/modules/socket/udp/udp.c @@ -50,7 +50,8 @@ void socket_udp_tick(socket_t *sock) { } if (!info->send_len) return ; + socket_on_send_udp(&info->send[0]); + free(info->send[0].data); info->send_len--; - socket_on_send_udp(&info->send[info->send_len]); - free(info->send[info->send_len].data); + mem_copy(info->send, &info->send[1], sizeof(udp_packet_t) * info->send_len); }