From 7a393c06fe66ef7c47870d6397ee90a063943f1b Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sat, 20 Feb 2021 22:52:46 -0800 Subject: [PATCH] Add IP address conversion helpers Fixes #47 --- libc/sock/inet_addr.c | 32 +++++++++++++++ libc/sock/inet_aton.c | 69 +++++++++++++++++++++++++++++++++ libc/sock/inet_ntoa.c | 36 +++++++++++++++++ libc/sock/sock.h | 5 ++- test/libc/sock/inet_ntoa_test.c | 26 +++++++++++++ 5 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 libc/sock/inet_addr.c create mode 100644 libc/sock/inet_aton.c create mode 100644 libc/sock/inet_ntoa.c create mode 100644 test/libc/sock/inet_ntoa_test.c diff --git a/libc/sock/inet_addr.c b/libc/sock/inet_addr.c new file mode 100644 index 000000000..1bc7455a4 --- /dev/null +++ b/libc/sock/inet_addr.c @@ -0,0 +1,32 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/sock/sock.h" + +/** + * Converts dotted IPv4 address string to network order binary. + * @see inet_aton() + */ +uint32_t inet_addr(const char *s) { + struct in_addr in; + if (inet_aton(s, &in)) { + return in.s_addr; + } else { + return -1; + } +} diff --git a/libc/sock/inet_aton.c b/libc/sock/inet_aton.c new file mode 100644 index 000000000..9345350cb --- /dev/null +++ b/libc/sock/inet_aton.c @@ -0,0 +1,69 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╚──────────────────────────────────────────────────────────────────────────────╝ +│ │ +│ Musl Libc │ +│ Copyright © 2005-2014 Rich Felker, et al. │ +│ │ +│ Permission is hereby granted, free of charge, to any person obtaining │ +│ a copy of this software and associated documentation files (the │ +│ "Software"), to deal in the Software without restriction, including │ +│ without limitation the rights to use, copy, modify, merge, publish, │ +│ distribute, sublicense, and/or sell copies of the Software, and to │ +│ permit persons to whom the Software is furnished to do so, subject to │ +│ the following conditions: │ +│ │ +│ The above copyright notice and this permission notice shall be │ +│ included in all copies or substantial portions of the Software. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ +│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ +│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ +│ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ +│ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ +│ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE │ +│ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ +│ │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/conv.h" +#include "libc/sock/sock.h" +#include "libc/str/str.h" + +asm(".ident\t\"\\n\\n\ +Musl libc (MIT License)\\n\ +Copyright 2005-2014 Rich Felker, et. al.\""); +asm(".include \"libc/disclaimer.inc\""); + +/** + * Converts dotted IPv4 address string to network order binary. + */ +int inet_aton(const char *s0, struct in_addr *dest) { + const char *s = s0; + unsigned char *d = (void *)dest; + unsigned long a[4] = {0}; + char *z; + int i; + for (i = 0; i < 4; i++) { + a[i] = strtoul(s, &z, 0); + if (z == s || (*z && *z != '.') || !isdigit(*s)) return 0; + if (!*z) break; + s = z + 1; + } + if (i == 4) return 0; + switch (i) { + case 0: + a[1] = a[0] & 0xffffff; + a[0] >>= 24; + case 1: + a[2] = a[1] & 0xffff; + a[1] >>= 16; + case 2: + a[3] = a[2] & 0xff; + a[2] >>= 8; + } + for (i = 0; i < 4; i++) { + if (a[i] > 255) return 0; + d[i] = a[i]; + } + return 1; +} diff --git a/libc/sock/inet_ntoa.c b/libc/sock/inet_ntoa.c new file mode 100644 index 000000000..cd6c0d8b1 --- /dev/null +++ b/libc/sock/inet_ntoa.c @@ -0,0 +1,36 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/fmt/itoa.h" +#include "libc/sock/sock.h" + +/** + * Converts IPv4 network address to array. + */ +char *inet_ntoa(struct in_addr in) { + static char buf[16]; + char *p = buf; + p += int64toarray_radix10((in.s_addr >> 000) & 255, p); + *p++ = '.'; + p += int64toarray_radix10((in.s_addr >> 010) & 255, p); + *p++ = '.'; + p += int64toarray_radix10((in.s_addr >> 020) & 255, p); + *p++ = '.'; + p += int64toarray_radix10((in.s_addr >> 030) & 255, p); + return buf; +} diff --git a/libc/sock/sock.h b/libc/sock/sock.h index 226e4b617..ec1f013be 100644 --- a/libc/sock/sock.h +++ b/libc/sock/sock.h @@ -65,7 +65,10 @@ struct msghdr { /* Linux+NT ABI */ }; const char *inet_ntop(int, const void *, char *, uint32_t); -int inet_pton(int af, const char *, void *); +int inet_aton(const char *, struct in_addr *); +int inet_pton(int, const char *, void *); +uint32_t inet_addr(const char *); +char *inet_ntoa(struct in_addr); int parseport(const char *); int socket(int, int, int) nodiscard; diff --git a/test/libc/sock/inet_ntoa_test.c b/test/libc/sock/inet_ntoa_test.c new file mode 100644 index 000000000..025137c2c --- /dev/null +++ b/test/libc/sock/inet_ntoa_test.c @@ -0,0 +1,26 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/sock/sock.h" +#include "libc/testlib/testlib.h" + +TEST(inet_ntoa, test) { + struct in_addr s; + EXPECT_EQ(0x04030201, (s.s_addr = inet_addr("1.2.3.4"))); + EXPECT_STREQ("1.2.3.4", inet_ntoa(s)); +}