diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2014-07-25 16:23:20 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2014-07-25 16:23:20 +0000 |
commit | d8f8cd4cfe005df3e0b4ede47f7396b70caf2500 (patch) | |
tree | 7be3292cc399443181be05cee4680e8ebe0fca6e /usr.sbin/httpd/httpd.c | |
parent | 60fdc24783f4efe5869ee41bb5ff93ddd8254293 (diff) |
Add support for "virtual hosts" aka. server blocks aka. multiple
servers with the same or "overlapping" IP address but a different name.
ok beck@
Diffstat (limited to 'usr.sbin/httpd/httpd.c')
-rw-r--r-- | usr.sbin/httpd/httpd.c | 98 |
1 files changed, 97 insertions, 1 deletions
diff --git a/usr.sbin/httpd/httpd.c b/usr.sbin/httpd/httpd.c index d38b4d9e41c..22ae5f9a445 100644 --- a/usr.sbin/httpd/httpd.c +++ b/usr.sbin/httpd/httpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: httpd.c,v 1.7 2014/07/24 08:32:36 reyk Exp $ */ +/* $OpenBSD: httpd.c,v 1.8 2014/07/25 16:23:19 reyk Exp $ */ /* * Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org> @@ -580,6 +580,102 @@ get_data(u_int8_t *ptr, size_t len) } int +sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen) +{ + struct sockaddr_in *a4, *b4; + struct sockaddr_in6 *a6, *b6; + u_int32_t av[4], bv[4], mv[4]; + + if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC) + return (0); + else if (a->sa_family > b->sa_family) + return (1); + else if (a->sa_family < b->sa_family) + return (-1); + + if (prefixlen == -1) + memset(&mv, 0xff, sizeof(mv)); + + switch (a->sa_family) { + case AF_INET: + a4 = (struct sockaddr_in *)a; + b4 = (struct sockaddr_in *)b; + + av[0] = a4->sin_addr.s_addr; + bv[0] = b4->sin_addr.s_addr; + if (prefixlen != -1) + mv[0] = prefixlen2mask(prefixlen); + + if ((av[0] & mv[0]) > (bv[0] & mv[0])) + return (1); + if ((av[0] & mv[0]) < (bv[0] & mv[0])) + return (-1); + break; + case AF_INET6: + a6 = (struct sockaddr_in6 *)a; + b6 = (struct sockaddr_in6 *)b; + + memcpy(&av, &a6->sin6_addr.s6_addr, 16); + memcpy(&bv, &b6->sin6_addr.s6_addr, 16); + if (prefixlen != -1) + prefixlen2mask6(prefixlen, mv); + + if ((av[3] & mv[3]) > (bv[3] & mv[3])) + return (1); + if ((av[3] & mv[3]) < (bv[3] & mv[3])) + return (-1); + if ((av[2] & mv[2]) > (bv[2] & mv[2])) + return (1); + if ((av[2] & mv[2]) < (bv[2] & mv[2])) + return (-1); + if ((av[1] & mv[1]) > (bv[1] & mv[1])) + return (1); + if ((av[1] & mv[1]) < (bv[1] & mv[1])) + return (-1); + if ((av[0] & mv[0]) > (bv[0] & mv[0])) + return (1); + if ((av[0] & mv[0]) < (bv[0] & mv[0])) + return (-1); + break; + } + + return (0); +} + +u_int32_t +prefixlen2mask(u_int8_t prefixlen) +{ + if (prefixlen == 0) + return (0); + + if (prefixlen > 32) + prefixlen = 32; + + return (htonl(0xffffffff << (32 - prefixlen))); +} + +struct in6_addr * +prefixlen2mask6(u_int8_t prefixlen, u_int32_t *mask) +{ + static struct in6_addr s6; + int i; + + if (prefixlen > 128) + prefixlen = 128; + + bzero(&s6, sizeof(s6)); + for (i = 0; i < prefixlen / 8; i++) + s6.s6_addr[i] = 0xff; + i = prefixlen % 8; + if (i) + s6.s6_addr[prefixlen / 8] = 0xff00 >> i; + + memcpy(mask, &s6, sizeof(s6)); + + return (&s6); +} + +int accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int reserve, volatile int *counter) { |