- if (inet_pton(AF_INET6, address, &address_in6) > 0)
- {
- if (inet_pton(AF_INET6, mask, &mask_in6) > 0)
- {
- memcpy(&addr_raw, &address_in6.s6_addr, 16);
- memcpy(&mask_raw, &mask_in6.s6_addr, 16);
-
- if (bits > 128)
- bits = 128;
- }
- else
- {
- /* The address was valid ipv6, but the mask
- * that goes with it wasnt.
- */
- free(mask);
- return false;
- }
- }
- else
-#endif
- if (inet_pton(AF_INET, address, &address_in4) > 0)
- {
- if (inet_pton(AF_INET, mask, &mask_in4) > 0)
- {
- memcpy(&addr_raw, &address_in4.s_addr, 4);
- memcpy(&mask_raw, &mask_in4.s_addr, 4);
-
- if (bits > 32)
- bits = 32;
- }
- else
- {
- /* The address was valid ipv4,
- * but the mask that went with it wasnt.
- */
- free(mask);
- return false;
- }
- }
- else
- {
- /* The address was neither ipv4 or ipv6 */
- free(mask);
- return false;
- }
-
- /* Low-level-match the bits in the raw data */
- free(mask);
- return MatchCIDRBits(addr_raw, mask_raw, bits);
-}
-
-void irc::sockets::Blocking(int s)
-{
- int flags = fcntl(s, F_GETFL, 0);
- fcntl(s, F_SETFL, flags ^ O_NONBLOCK);
-}
-
-void irc::sockets::NonBlocking(int s)
-{
- int flags = fcntl(s, F_GETFL, 0);
- fcntl(s, F_SETFL, flags | O_NONBLOCK);
-}
-
-/** This will bind a socket to a port. It works for UDP/TCP.
- * It can only bind to IP addresses, if you wish to bind to hostnames
- * you should first resolve them using class 'Resolver'.
- */
-bool InspIRCd::BindSocket(int sockfd, int port, char* addr, bool dolisten)
-{
- /* We allocate 2 of these, because sockaddr_in6 is larger than sockaddr (ugh, hax) */
- sockaddr* server = new sockaddr[2];
- memset(server,0,sizeof(sockaddr)*2);
-
- int ret, size;
-
- if (*addr == '*')
- *addr = 0;
-
-#ifdef IPV6
- if (*addr)
- {
- /* There is an address here. Is it ipv6? */
- if (strchr(addr,':'))
- {
- /* Yes it is */
- in6_addr addy;
- if (inet_pton(AF_INET6, addr, &addy) < 1)
- {
- delete[] server;
- return false;
- }
-
- ((sockaddr_in6*)server)->sin6_family = AF_INET6;
- memcpy(&(((sockaddr_in6*)server)->sin6_addr), &addy, sizeof(in6_addr));
- ((sockaddr_in6*)server)->sin6_port = htons(port);
- size = sizeof(sockaddr_in6);
- }
- else
- {
- /* No, its not */
- in_addr addy;
- if (inet_pton(AF_INET, addr, &addy) < 1)
- {
- delete[] server;
- return false;
- }
-
- ((sockaddr_in*)server)->sin_family = AF_INET;
- ((sockaddr_in*)server)->sin_addr = addy;
- ((sockaddr_in*)server)->sin_port = htons(port);
- size = sizeof(sockaddr_in);
- }
- }
- else
- {
- if (port == -1)
- {
- /* Port -1: Means UDP IPV4 port binding - Special case
- * used by DNS engine.
- */
- ((sockaddr_in*)server)->sin_family = AF_INET;
- ((sockaddr_in*)server)->sin_addr.s_addr = htonl(INADDR_ANY);
- ((sockaddr_in*)server)->sin_port = 0;
- size = sizeof(sockaddr_in);
- }
- else
- {
- /* Theres no address here, default to ipv6 bind to all */
- ((sockaddr_in6*)server)->sin6_family = AF_INET6;
- memset(&(((sockaddr_in6*)server)->sin6_addr), 0, sizeof(in6_addr));
- ((sockaddr_in6*)server)->sin6_port = htons(port);
- size = sizeof(sockaddr_in6);
- }
- }
-#else
- /* If we aren't built with ipv6, the choice becomes simple */
- ((sockaddr_in*)server)->sin_family = AF_INET;
- if (*addr)
- {
- /* There is an address here. */
- in_addr addy;
- if (inet_pton(AF_INET, addr, &addy) < 1)
- {
- delete[] server;
- return false;
- }
- ((sockaddr_in*)server)->sin_addr = addy;
- }
- else
- {
- /* Bind ipv4 to all */
- ((sockaddr_in*)server)->sin_addr.s_addr = htonl(INADDR_ANY);
- }
- /* Bind ipv4 port number */
- ((sockaddr_in*)server)->sin_port = htons(port);
- size = sizeof(sockaddr_in);
-#endif
- ret = bind(sockfd, server, size);
- delete[] server;