| /* |
| * Copyright (c) 2024, Friedt Professional Engineering Services, Inc |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <ctype.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include <zephyr/net/net_if.h> |
| #include <zephyr/posix/arpa/inet.h> |
| #include <zephyr/posix/netinet/in.h> |
| #include <zephyr/posix/net/if.h> |
| |
| in_addr_t inet_addr(const char *cp) |
| { |
| int val = 0; |
| int len = 0; |
| int dots = 0; |
| int digits = 0; |
| |
| /* error checking */ |
| if (cp == NULL) { |
| return -1; |
| } |
| |
| for (int i = 0, subdigits = 0; i <= INET_ADDRSTRLEN; ++i, ++len) { |
| if (subdigits > 3) { |
| return -1; |
| } |
| if (cp[i] == '\0') { |
| break; |
| } else if (cp[i] == '.') { |
| if (subdigits == 0) { |
| return -1; |
| } |
| ++dots; |
| subdigits = 0; |
| continue; |
| } else if (isdigit((int)cp[i])) { |
| ++digits; |
| ++subdigits; |
| continue; |
| } else if (isspace((int)cp[i])) { |
| break; |
| } |
| |
| return -1; |
| } |
| |
| if (dots != 3 || digits < 4) { |
| return -1; |
| } |
| |
| /* conversion */ |
| for (int i = 0, tmp = 0; i < len; ++i, ++cp) { |
| if (*cp != '.') { |
| tmp *= 10; |
| tmp += *cp - '0'; |
| } |
| |
| if (*cp == '.' || i == len - 1) { |
| val <<= 8; |
| val |= tmp; |
| tmp = 0; |
| } |
| } |
| |
| return htonl(val); |
| } |
| |
| char *inet_ntoa(struct in_addr in) |
| { |
| static char buf[INET_ADDRSTRLEN]; |
| unsigned char *bytes = (unsigned char *)&in.s_addr; |
| |
| snprintf(buf, sizeof(buf), "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); |
| |
| return buf; |
| } |
| |
| char *if_indextoname(unsigned int ifindex, char *ifname) |
| { |
| int ret; |
| |
| if (!IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { |
| errno = ENOTSUP; |
| return NULL; |
| } |
| |
| ret = net_if_get_name(net_if_get_by_index(ifindex), ifname, IF_NAMESIZE); |
| if (ret < 0) { |
| errno = ENXIO; |
| return NULL; |
| } |
| |
| return ifname; |
| } |
| |
| void if_freenameindex(struct if_nameindex *ptr) |
| { |
| size_t n; |
| |
| if (ptr == NULL || !IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { |
| return; |
| } |
| |
| NET_IFACE_COUNT(&n); |
| |
| for (size_t i = 0; i < n; ++i) { |
| if (IS_ENABLED(CONFIG_NET_INTERFACE_NAME) && ptr[i].if_name != NULL) { |
| free(ptr[i].if_name); |
| } |
| } |
| |
| free(ptr); |
| } |
| |
| struct if_nameindex *if_nameindex(void) |
| { |
| size_t n; |
| char *name; |
| struct if_nameindex *ni; |
| |
| if (!IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { |
| errno = ENOTSUP; |
| return NULL; |
| } |
| |
| /* FIXME: would be nice to use this without malloc */ |
| NET_IFACE_COUNT(&n); |
| ni = malloc((n + 1) * sizeof(*ni)); |
| if (ni == NULL) { |
| goto return_err; |
| } |
| |
| for (size_t i = 0; i < n; ++i) { |
| ni[i].if_index = i + 1; |
| |
| ni[i].if_name = malloc(IF_NAMESIZE); |
| if (ni[i].if_name == NULL) { |
| goto return_err; |
| } |
| |
| name = if_indextoname(i + 1, ni[i].if_name); |
| __ASSERT_NO_MSG(name != NULL); |
| } |
| |
| ni[n].if_index = 0; |
| ni[n].if_name = NULL; |
| |
| return ni; |
| |
| return_err: |
| if_freenameindex(ni); |
| errno = ENOBUFS; |
| |
| return NULL; |
| } |
| |
| unsigned int if_nametoindex(const char *ifname) |
| { |
| int ret; |
| |
| if (!IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { |
| return 0; |
| } |
| |
| ret = net_if_get_by_name(ifname); |
| if (ret < 0) { |
| return 0; |
| } |
| |
| return ret; |
| } |
| |
| void endhostent(void) |
| { |
| } |
| |
| void endnetent(void) |
| { |
| } |
| |
| void endprotoent(void) |
| { |
| } |
| |
| void endservent(void) |
| { |
| } |
| |
| struct hostent *gethostent(void) |
| { |
| return NULL; |
| } |
| |
| struct netent *getnetbyaddr(uint32_t net, int type) |
| { |
| ARG_UNUSED(net); |
| ARG_UNUSED(type); |
| |
| return NULL; |
| } |
| |
| struct netent *getnetbyname(const char *name) |
| { |
| ARG_UNUSED(name); |
| |
| return NULL; |
| } |
| |
| struct netent *getnetent(void) |
| { |
| return NULL; |
| } |
| |
| struct protoent *getprotobyname(const char *name) |
| { |
| ARG_UNUSED(name); |
| |
| return NULL; |
| } |
| |
| struct protoent *getprotobynumber(int proto) |
| { |
| ARG_UNUSED(proto); |
| |
| return NULL; |
| } |
| |
| struct protoent *getprotoent(void) |
| { |
| return NULL; |
| } |
| |
| struct servent *getservbyname(const char *name, const char *proto) |
| { |
| ARG_UNUSED(name); |
| ARG_UNUSED(proto); |
| |
| return NULL; |
| } |
| |
| struct servent *getservbyport(int port, const char *proto) |
| { |
| ARG_UNUSED(port); |
| ARG_UNUSED(proto); |
| |
| return NULL; |
| } |
| |
| struct servent *getservent(void) |
| { |
| return NULL; |
| } |
| |
| void sethostent(int stayopen) |
| { |
| ARG_UNUSED(stayopen); |
| } |
| |
| void setnetent(int stayopen) |
| { |
| ARG_UNUSED(stayopen); |
| } |
| |
| void setprotoent(int stayopen) |
| { |
| ARG_UNUSED(stayopen); |
| } |
| |
| void setservent(int stayopen) |
| { |
| ARG_UNUSED(stayopen); |
| } |
| |
| int sockatmark(int s) |
| { |
| ARG_UNUSED(s); |
| |
| errno = ENOSYS; |
| return -1; |
| } |