--- libelwix/src/net.c 2019/09/24 15:49:52 1.20 +++ libelwix/src/net.c 2020/05/27 15:03:28 1.21 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: net.c,v 1.20 2019/09/24 15:49:52 misho Exp $ +* $Id: net.c,v 1.21 2020/05/27 15:03:28 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -12,7 +12,7 @@ terms: All of the documentation and software included in the ELWIX and AITNET Releases is copyrighted by ELWIX - Sofia/Bulgaria -Copyright 2004 - 2019 +Copyright 2004 - 2020 by Michael Pounov . All rights reserved. Redistribution and use in source and binary forms, with or without @@ -778,3 +778,72 @@ e_getlinkbyether(const ether_addr_t * __restrict mac, return a; } #endif + +/* + * e_network() - Get network from address string + * + * @csAddr = Address string with CIDR mask /xx + * @net = Network information structure + * return: -1 error, 1 nothing for return or 0 ok + */ +int +e_network(const char *csAddr, netaddr_t * __restrict net) +{ + int ret = 0; + u_char mask = 0; + inaddr_t a; + char *pos, szAddr[STRSIZ]; + register int i; + + if (!csAddr || !net) + return -1; + else + strlcpy(szAddr, csAddr, sizeof szAddr); + + memset(net, 0, sizeof(netaddr_t)); + + pos = strrchr(szAddr, '/'); + if (pos) { + *pos++ = 0; + mask = (u_char) strtol(pos, NULL, 10); + } else + return 1; + + if (strchr(szAddr, ':')) { + if (mask > 128) + return -1; + else { + for (i = 0; i < 4 && (mask / 32); i++, mask -= 32) + net->mask.in6.__u6_addr.__u6_addr32[i] = 0xFFFFFFFF; + if (mask) + net->mask.in6.__u6_addr.__u6_addr32[i] = E_CIDRMASK(mask % 32); + } + + inet_pton(AF_INET6, szAddr, &a.in6); + +#ifndef __linux__ + net->addr.sin6.sin6_len = sizeof net->addr.sin6; +#endif + for (i = 0; i < 4; i++) + net->addr.sin6.sin6_addr.__u6_addr.__u6_addr32[i] = + a.in6.__u6_addr.__u6_addr32[i] & net->mask.in6.__u6_addr.__u6_addr32[i]; + } else { + if (mask > 32) + return -1; + else { + if (mask == 32) + net->mask.in.s_addr = 0xFFFFFFFF; + else + net->mask.in.s_addr = E_CIDRMASK(mask); + } + + inet_pton(AF_INET, szAddr, &a.in4); + +#ifndef __linux__ + net->addr.sin.sin_len = sizeof net->addr.sin; +#endif + net->addr.sin.sin_addr.s_addr = a.in.s_addr & net->mask.in.s_addr; + } + + return ret; +}