feat: ports - netsurf with the monkey frontend
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ae69wJS7sueQMUwNxV3nX
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Minimal <arpa/inet.h> for the MontaukOS NetSurf port.
|
||||
*
|
||||
* NetSurf uses inet_pton() only to recognise IP literals in URLs
|
||||
* (content/urldb.c, utils/utils.c) -- it never opens a socket with the result.
|
||||
* A self-contained parser is therefore enough, and keeps this out of the
|
||||
* MontaukOS libc, where a partial implementation would be misleading.
|
||||
*
|
||||
* static inline throughout: these headers are included by a handful of
|
||||
* translation units and NetSurf builds with -Werror, so a non-static
|
||||
* definition would either collide at link time or warn when unused.
|
||||
*/
|
||||
#ifndef _MONTAUK_COMPAT_ARPA_INET_H_
|
||||
#define _MONTAUK_COMPAT_ARPA_INET_H_
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Parse a dotted-quad into 4 network-order bytes. Returns 1 on success. */
|
||||
static inline int montauk_inet_pton4(const char *src, uint8_t *dst)
|
||||
{
|
||||
uint32_t octet = 0;
|
||||
int digits = 0;
|
||||
int seen = 0;
|
||||
uint8_t out[4];
|
||||
|
||||
for (;;) {
|
||||
char c = *src++;
|
||||
|
||||
if (c >= '0' && c <= '9') {
|
||||
if (digits == 3)
|
||||
return 0;
|
||||
/* a leading zero is not accepted (023 is ambiguous) */
|
||||
if (digits == 1 && out[seen] == 0)
|
||||
return 0;
|
||||
octet = octet * 10 + (uint32_t)(c - '0');
|
||||
if (octet > 255)
|
||||
return 0;
|
||||
out[seen] = (uint8_t)octet;
|
||||
digits++;
|
||||
} else if (c == '.' || c == '\0') {
|
||||
if (digits == 0)
|
||||
return 0;
|
||||
if (c == '\0') {
|
||||
if (seen != 3)
|
||||
return 0;
|
||||
memcpy(dst, out, 4);
|
||||
return 1;
|
||||
}
|
||||
if (seen == 3)
|
||||
return 0;
|
||||
seen++;
|
||||
octet = 0;
|
||||
digits = 0;
|
||||
out[seen] = 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse an IPv6 literal, including "::" compression and a trailing
|
||||
* dotted-quad (e.g. ::ffff:192.0.2.1). Returns 1 on success.
|
||||
*/
|
||||
static inline int montauk_inet_pton6(const char *src, uint8_t *dst)
|
||||
{
|
||||
uint8_t out[16];
|
||||
int head = 0; /* bytes written before "::" */
|
||||
int tail = 0; /* bytes buffered after "::" */
|
||||
uint8_t tailbuf[16];
|
||||
int seen_compress = 0;
|
||||
uint8_t *cur = out;
|
||||
int *curlen = &head;
|
||||
|
||||
memset(out, 0, sizeof(out));
|
||||
|
||||
if (src[0] == ':') {
|
||||
if (src[1] != ':')
|
||||
return 0;
|
||||
src += 2;
|
||||
seen_compress = 1;
|
||||
cur = tailbuf;
|
||||
curlen = &tail;
|
||||
if (*src == '\0')
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
uint32_t group = 0;
|
||||
int digits = 0;
|
||||
|
||||
/* a dotted-quad may only appear as the final component */
|
||||
if (strchr(src, '.') != NULL) {
|
||||
const char *p = src;
|
||||
int dots = 0;
|
||||
while (*p != '\0' && *p != ':') {
|
||||
if (*p == '.')
|
||||
dots++;
|
||||
p++;
|
||||
}
|
||||
if (dots == 3 && *p == '\0') {
|
||||
if (*curlen + 4 > 16)
|
||||
return 0;
|
||||
if (montauk_inet_pton4(src, cur + *curlen) == 0)
|
||||
return 0;
|
||||
*curlen += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (*src != '\0' && *src != ':') {
|
||||
char c = *src;
|
||||
uint32_t v;
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
v = (uint32_t)(c - '0');
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
v = (uint32_t)(c - 'a' + 10);
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
v = (uint32_t)(c - 'A' + 10);
|
||||
else
|
||||
return 0;
|
||||
|
||||
group = group * 16 + v;
|
||||
if (++digits > 4)
|
||||
return 0;
|
||||
src++;
|
||||
}
|
||||
|
||||
if (digits == 0)
|
||||
return 0;
|
||||
if (*curlen + 2 > 16)
|
||||
return 0;
|
||||
|
||||
cur[(*curlen)++] = (uint8_t)(group >> 8);
|
||||
cur[(*curlen)++] = (uint8_t)(group & 0xff);
|
||||
|
||||
if (*src == '\0')
|
||||
break;
|
||||
|
||||
src++; /* consume ':' */
|
||||
|
||||
if (*src == ':') {
|
||||
if (seen_compress)
|
||||
return 0;
|
||||
seen_compress = 1;
|
||||
src++;
|
||||
cur = tailbuf;
|
||||
curlen = &tail;
|
||||
if (*src == '\0')
|
||||
break;
|
||||
} else if (*src == '\0') {
|
||||
/* trailing single colon */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (seen_compress) {
|
||||
if (head + tail > 15) /* "::" must stand for >= 1 zero group */
|
||||
return 0;
|
||||
memmove(out + 16 - tail, tailbuf, (size_t)tail);
|
||||
memset(out + head, 0, (size_t)(16 - tail - head));
|
||||
} else if (head != 16) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(dst, out, 16);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* inet_aton(). Returns non-zero on success, as BSD does.
|
||||
*
|
||||
* Only the full dotted-quad form is accepted. Historic inet_aton also takes
|
||||
* "a", "a.b", "a.b.c" and octal/hex octets, but content/urldb.c immediately
|
||||
* rejects anything without three dots (see the comment at its call site), so
|
||||
* the narrower behaviour matches how NetSurf actually uses it -- and refusing
|
||||
* octal-looking octets like "1.2.3.04" is the safer reading for a URL host.
|
||||
*/
|
||||
static inline int inet_aton(const char *cp, struct in_addr *addr)
|
||||
{
|
||||
uint8_t out[4];
|
||||
|
||||
if (cp == NULL || addr == NULL)
|
||||
return 0;
|
||||
if (montauk_inet_pton4(cp, out) != 1)
|
||||
return 0;
|
||||
|
||||
memcpy(&addr->s_addr, out, 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int inet_pton(int af, const char *src, void *dst)
|
||||
{
|
||||
if (src == NULL || dst == NULL)
|
||||
return -1;
|
||||
|
||||
if (af == AF_INET)
|
||||
return montauk_inet_pton4(src, (uint8_t *) dst);
|
||||
if (af == AF_INET6)
|
||||
return montauk_inet_pton6(src, (uint8_t *) dst);
|
||||
|
||||
return -1; /* EAFNOSUPPORT */
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user