~mdw
/
preload-hacks
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
noip.c, noip.1: Add IPv6 support.
[preload-hacks]
/
noip.c
diff --git
a/noip.c
b/noip.c
index
ec66340
..
9c5cd68
100644
(file)
--- a/
noip.c
+++ b/
noip.c
@@
-62,19
+62,21
@@
enum { UNUSED, STALE, USED }; /* Unix socket status values */
enum { WANT_FRESH, WANT_EXISTING }; /* Socket address dispositions */
enum { DENY, ALLOW }; /* ACL verdicts */
enum { WANT_FRESH, WANT_EXISTING }; /* Socket address dispositions */
enum { DENY, ALLOW }; /* ACL verdicts */
-static int address_families[] = { AF_INET, -1 };
+static int address_families[] = { AF_INET,
AF_INET6,
-1 };
#define ADDRBUFSZ 64
/* Address representations. */
typedef union ipaddr {
struct in_addr v4;
#define ADDRBUFSZ 64
/* Address representations. */
typedef union ipaddr {
struct in_addr v4;
+ struct in6_addr v6;
} ipaddr;
/* Convenient socket address hacking. */
typedef union address {
struct sockaddr sa;
struct sockaddr_in sin;
} ipaddr;
/* Convenient socket address hacking. */
typedef union address {
struct sockaddr sa;
struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
} address;
/* Access control list nodes */
} address;
/* Access control list nodes */
@@
-91,7
+93,7
@@
typedef struct full_ipaddr {
int af;
ipaddr addr;
} full_ipaddr;
int af;
ipaddr addr;
} full_ipaddr;
-#define MAX_LOCAL_IPADDRS
16
+#define MAX_LOCAL_IPADDRS
64
static full_ipaddr local_ipaddrs[MAX_LOCAL_IPADDRS];
static int n_local_ipaddrs;
static full_ipaddr local_ipaddrs[MAX_LOCAL_IPADDRS];
static int n_local_ipaddrs;
@@
-144,6
+146,7
@@
static void import(void)
/* Socket address casts */
#define SA(sa) ((struct sockaddr *)(sa))
#define SIN(sa) ((struct sockaddr_in *)(sa))
/* Socket address casts */
#define SA(sa) ((struct sockaddr *)(sa))
#define SIN(sa) ((struct sockaddr_in *)(sa))
+#define SIN6(sa) ((struct sockaddr_in6 *)(sa))
#define SUN(sa) ((struct sockaddr_un *)(sa))
/* Raw bytes */
#define SUN(sa) ((struct sockaddr_un *)(sa))
/* Raw bytes */
@@
-202,6
+205,7
@@
static int family_known_p(int af)
{
switch (af) {
case AF_INET:
{
switch (af) {
case AF_INET:
+ case AF_INET6:
return (1);
default:
return (0);
return (1);
default:
return (0);
@@
-213,6
+217,7
@@
static socklen_t family_socklen(int af)
{
switch (af) {
case AF_INET: return (sizeof(struct sockaddr_in));
{
switch (af) {
case AF_INET: return (sizeof(struct sockaddr_in));
+ case AF_INET6: return (sizeof(struct sockaddr_in6));
default: abort();
}
}
default: abort();
}
}
@@
-222,6
+227,7
@@
static int address_width(int af)
{
switch (af) {
case AF_INET: return 32;
{
switch (af) {
case AF_INET: return 32;
+ case AF_INET6: return 128;
default: abort();
}
}
default: abort();
}
}
@@
-238,6
+244,23
@@
static int common_prefix_length(int af, const ipaddr *a, const ipaddr *b)
if ((aa&m) == 0 && (bb&m) == m) return (32 - simple_mask_length(m));
else return (-1);
} break;
if ((aa&m) == 0 && (bb&m) == m) return (32 - simple_mask_length(m));
else return (-1);
} break;
+ case AF_INET6: {
+ const uint8_t *aa = a->v6.s6_addr, *bb = b->v6.s6_addr;
+ unsigned m;
+ unsigned n;
+ int i;
+
+ for (i = 0; i < 16 && aa[i] == bb[i]; i++);
+ n = 8*i;
+ if (i < 16) {
+ m = aa[i]^bb[i];
+ if ((aa[i]&m) != 0 || (bb[i]&m) != m) return (-1);
+ n += 8 - simple_mask_length(m);
+ for (i++; i < 16; i++)
+ if (aa[i] || bb[i] != 0xff) return (-1);
+ }
+ return (n);
+ } break;
default:
abort();
}
default:
abort();
}
@@
-248,6
+271,7
@@
static int port_from_sockaddr(const struct sockaddr *sa)
{
switch (sa->sa_family) {
case AF_INET: return (ntohs(SIN(sa)->sin_port));
{
switch (sa->sa_family) {
case AF_INET: return (ntohs(SIN(sa)->sin_port));
+ case AF_INET6: return (ntohs(SIN6(sa)->sin6_port));
default: abort();
}
}
default: abort();
}
}
@@
-257,6
+281,7
@@
static void port_to_sockaddr(struct sockaddr *sa, int port)
{
switch (sa->sa_family) {
case AF_INET: SIN(sa)->sin_port = htons(port); break;
{
switch (sa->sa_family) {
case AF_INET: SIN(sa)->sin_port = htons(port); break;
+ case AF_INET6: SIN6(sa)->sin6_port = htons(port); break;
default: abort();
}
}
default: abort();
}
}
@@
-265,6
+290,7
@@
static void ipaddr_from_sockaddr(ipaddr *a, const struct sockaddr *sa)
{
switch (sa->sa_family) {
case AF_INET: a->v4 = SIN(sa)->sin_addr; break;
{
switch (sa->sa_family) {
case AF_INET: a->v4 = SIN(sa)->sin_addr; break;
+ case AF_INET6: a->v6 = SIN6(sa)->sin6_addr; break;
default: abort();
}
}
default: abort();
}
}
@@
-279,6
+305,7
@@
static int ipaddr_equal_p(int af, const ipaddr *a, const ipaddr *b)
{
switch (af) {
case AF_INET: return (a->v4.s_addr == b->v4.s_addr);
{
switch (af) {
case AF_INET: return (a->v4.s_addr == b->v4.s_addr);
+ case AF_INET6: return (memcmp(a->v6.s6_addr, b->v6.s6_addr, 16) == 0);
default: abort();
}
}
default: abort();
}
}
@@
-295,6
+322,19
@@
static int sockaddr_in_range_p(const struct sockaddr *sa,
return (ntohl(a->v4.s_addr) <= addr &&
addr <= ntohl(b->v4.s_addr));
} break;
return (ntohl(a->v4.s_addr) <= addr &&
addr <= ntohl(b->v4.s_addr));
} break;
+ case AF_INET6: {
+ const uint8_t *ss = SIN6(sa)->sin6_addr.s6_addr;
+ const uint8_t *aa = a->v6.s6_addr, *bb = b->v6.s6_addr;
+ int h = 1, l = 1;
+ int i;
+
+ for (i = 0; h && l && i < 16; i++, ss++, aa++, bb++) {
+ if (*ss < *aa || *bb < *ss) return (0);
+ if (*aa < *ss) l = 0;
+ if (*ss < *bb) h = 0;
+ }
+ return (1);
+ } break;
default:
abort();
}
default:
abort();
}
@@
-311,6
+351,15
@@
static void wildcard_address(int af, struct sockaddr *sa)
sin->sin_port = 0;
sin->sin_addr.s_addr = INADDR_ANY;
} break;
sin->sin_port = 0;
sin->sin_addr.s_addr = INADDR_ANY;
} break;
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = SIN6(sa);
+ memset(sin6, 0, sizeof(sin6));
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = 0;
+ sin6->sin6_addr = in6addr_any;
+ sin6->sin6_scope_id = 0;
+ sin6->sin6_flowinfo = 0;
+ } break;
default:
abort();
}
default:
abort();
}
@@
-329,6
+378,16
@@
static void mask_address(int af, ipaddr *a, int plen, int highp)
if (highp) addr |= ~mask;
a->v4.s_addr = htonl(addr & 0xffffffff);
} break;
if (highp) addr |= ~mask;
a->v4.s_addr = htonl(addr & 0xffffffff);
} break;
+ case AF_INET6: {
+ int i = plen/8;
+ unsigned m = (0xff << (8 - plen%8)) & 0xff;
+ unsigned s = highp ? 0xff : 0;
+ if (m) {
+ a->v6.s6_addr[i] = (a->v6.s6_addr[i] & m) | (s & ~m);
+ i++;
+ }
+ for (; i < 16; i++) a->v6.s6_addr[i] = s;
+ } break;
default:
abort();
}
default:
abort();
}
@@
-384,7
+443,7
@@
static char *present_sockaddr(const struct sockaddr *sa, socklen_t len,
}
WANT(1); PUTC(0);
} break;
}
WANT(1); PUTC(0);
} break;
- case AF_INET: {
+ case AF_INET:
case AF_INET6:
{
char addrbuf[NI_MAXHOST], portbuf[NI_MAXSERV];
int err = getnameinfo(sa, len,
addrbuf, sizeof(addrbuf),
char addrbuf[NI_MAXHOST], portbuf[NI_MAXSERV];
int err = getnameinfo(sa, len,
addrbuf, sizeof(addrbuf),
@@
-407,7
+466,7
@@
nospace:
/* Guess the family of a textual socket address. */
static int guess_address_family(const char *p)
/* Guess the family of a textual socket address. */
static int guess_address_family(const char *p)
- { return (AF_INET); }
+ { return (
strchr(p, ':') ? AF_INET6 :
AF_INET); }
/* Parse a socket address P and write the result to SA. */
static int parse_sockaddr(struct sockaddr *sa, const char *p)
/* Parse a socket address P and write the result to SA. */
static int parse_sockaddr(struct sockaddr *sa, const char *p)