/*
 * convertToIPv4NetAddr
 * This function converts an IPv4-mapped IPv6 address to an IPv4 address.
 * ::FFFF:X:X (32 are non zeros) or 
 * ::X:X (32 are non zeros and rest are 0's) but NOT loopback address(::1)
 * Input : PRNetAddr * src_v6addr IPv6 address
 * Output : PRNetAddr * dst_v4addr IPv4 address
 */
static void convertToIPv4NetAddr(const PRNetAddr *src_v6addr,
                                 PRNetAddr *dst_v4addr)
{
    PR_ASSERT(PR_AF_INET6 == src_v6addr->ipv6.family);

    // ::FFFF:X:X
    if (PR_IsNetAddrType(src_v6addr, PR_IpAddrV4Mapped)) {
        // IPv6 address is a union of 16*PRUint8 each of 1 byte (8 bits)
        // copy last 32 bits src_v6addr->ipv6.ip.pr_s6_addr32[3] or
        // copy last 4, 8 bits(1 byte).
        const PRUint8 *srcp = src_v6addr->ipv6.ip.pr_s6_addr;
        memcpy((char *)&dst_v4addr->inet.ip, srcp + 12, 4);
        dst_v4addr->inet.family = PR_AF_INET;
        dst_v4addr->raw.family = PR_AF_INET;
    } else if (!PR_IsNetAddrType(src_v6addr, PR_IpAddrLoopback) && 
               (src_v6addr->ipv6.ip.pr_s6_addr32[0] == 0 &&
               src_v6addr->ipv6.ip.pr_s6_addr32[1] == 0 &&
               src_v6addr->ipv6.ip.pr_s6_addr32[2] == 0 &&
               src_v6addr->ipv6.ip.pr_s6_addr32[3] != 0)) {
        // ::X:X (32 are non zeros and rest are 0's)
        dst_v4addr->inet.ip = src_v6addr->ipv6.ip.pr_s6_addr32[3];
        dst_v4addr->inet.family = PR_AF_INET;
        dst_v4addr->raw.family = PR_AF_INET;
   }
}
static PRStatus
nsSOCKSIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime to)
{
    PRStatus status;
    PRNetAddr dst;

    nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
    if (info == NULL) return PR_FAILURE;

    if (PR_NetAddrFamily(addr) == PR_AF_INET6 &&
        PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
        const uint8_t *srcp;

        LOGDEBUG(("socks: converting ipv4-mapped ipv6 address to ipv4"));

        // copied from _PR_ConvertToIpv4NetAddr()
        PR_InitializeNetAddr(PR_IpAddrAny, 0, &dst);
        srcp = addr->ipv6.ip.pr_s6_addr;
        memcpy(&dst.inet.ip, srcp + 12, 4);
        dst.inet.family = PR_AF_INET;
        dst.inet.port = addr->ipv6.port;
    } else {
        memcpy(&dst, addr, sizeof(dst));
    }

    info->SetDestinationAddr(&dst);
    info->SetConnectTimeout(to);

    do {
        status = info->DoHandshake(fd, -1);
    } while (status == PR_SUCCESS && !info->IsConnected());

    return status;
}
void
nsServerSocket::IsLocal(bool *aIsLocal)
{
#if defined(XP_UNIX)
  // Unix-domain sockets are always local.
  if (mAddr.raw.family == PR_AF_LOCAL)
  {
    *aIsLocal = true;
    return;
  }
#endif

  // If bound to loopback, this server socket only accepts local connections.
  *aIsLocal = PR_IsNetAddrType(&mAddr, PR_IpAddrLoopback);
}
NS_IMETHODIMP
nsLDAPConnection::OnLookupComplete(nsICancelable *aRequest,
                                   nsIDNSRecord  *aRecord,
                                   nsresult       aStatus)
{    
    nsresult rv = NS_OK;

    if (aRecord) {
        // Build mResolvedIP list
        //
        mResolvedIP.Truncate();

        PRInt32 index = 0;
        char addrbuf[64];
        PRNetAddr addr;

        while (NS_SUCCEEDED(aRecord->GetNextAddr(0, &addr))) {
            // We can only use v4 addresses
            //
            PRBool v4mapped = PR_FALSE;
            if (addr.raw.family == PR_AF_INET6)
                v4mapped = PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped);
            if (addr.raw.family == PR_AF_INET || v4mapped) {
                // If there are more IPs in the list, we separate them with
                // a space, as supported/used by the LDAP C-SDK.
                //
                if (index++)
                    mResolvedIP.Append(' ');

                // Convert the IPv4 address to a string, and append it to our
                // list of IPs.  Strip leading '::FFFF:' (the IPv4-mapped-IPv6 
                // indicator) if present.
                //
                PR_NetAddrToString(&addr, addrbuf, sizeof(addrbuf));
                if ((addrbuf[0] == ':') && (strlen(addrbuf) > 7))
                    mResolvedIP.Append(addrbuf+7);
                else
                    mResolvedIP.Append(addrbuf);
            }
        }
    }

    if (NS_FAILED(aStatus)) {
        // The DNS service failed, lets pass something reasonable
        // back to the listener.
        //
        switch (aStatus) {
        case NS_ERROR_OUT_OF_MEMORY:
        case NS_ERROR_UNKNOWN_HOST:
        case NS_ERROR_FAILURE:
        case NS_ERROR_OFFLINE:
            rv = aStatus;
            break;

        default:
            rv = NS_ERROR_UNEXPECTED;
            break;
        }
    } else if (!mResolvedIP.Length()) {
        // We have no host resolved, that is very bad, and should most
        // likely have been caught earlier.
        //
        NS_ERROR("nsLDAPConnection::OnStopLookup(): the resolved IP "
                 "string is empty.\n");
        
        rv = NS_ERROR_UNKNOWN_HOST;
    } else {
        // We've got the IP(s) for the hostname, now lets setup the
        // LDAP connection using this information. Note that if the
        // LDAP server returns a referral, the C-SDK will perform a
        // new, synchronous DNS lookup, which might hang (but hopefully
        // if we've come this far, DNS is working properly).
        //
        mConnectionHandle = ldap_init(mResolvedIP.get(),
                                      mPort == -1 ? LDAP_PORT : mPort);
        // Check that we got a proper connection, and if so, setup the
        // threading functions for this connection.
        //
        if ( !mConnectionHandle ) {
            rv = NS_ERROR_FAILURE;  // LDAP C SDK API gives no useful error
        } else {
#if defined(DEBUG_dmose) || defined(DEBUG_bienvenu)
            const int lDebug = 0;
            ldap_set_option(mConnectionHandle, LDAP_OPT_DEBUG_LEVEL, &lDebug);
#endif

            // the C SDK currently defaults to v2.  if we're to use v3, 
            // tell it so.
            //
            int version;
            switch (mVersion) {
            case 2:
                break;
            case 3:
                version = LDAP_VERSION3;
                ldap_set_option(mConnectionHandle, LDAP_OPT_PROTOCOL_VERSION, 
                                &version);
		break;
            default:
                NS_ERROR("nsLDAPConnection::OnLookupComplete(): mVersion"
                         " invalid");
            }

#ifdef MOZ_PSM
            // This code sets up the current connection to use PSM for SSL
            // functionality.  Making this use libssldap instead for
            // non-browser user shouldn't be hard.

            extern nsresult nsLDAPInstallSSL(LDAP *ld, const char *aHostName);

            if (mSSL) {
                if (ldap_set_option(mConnectionHandle, LDAP_OPT_SSL,
                                    LDAP_OPT_ON) != LDAP_SUCCESS ) {
                    NS_ERROR("nsLDAPConnection::OnStopLookup(): Error"
                             " configuring connection to use SSL");
                    rv = NS_ERROR_UNEXPECTED;
                }

                rv = nsLDAPInstallSSL(mConnectionHandle, mDNSHost.get());
                if (NS_FAILED(rv)) {
                    NS_ERROR("nsLDAPConnection::OnStopLookup(): Error"
                             " installing secure LDAP routines for"
                             " connection");
                }
            }
#endif
        }

        // Create a new runnable object, and increment the refcnt. The
        // thread will also hold a strong ref to the runnable, but we need
        // to make sure it doesn't get destructed until we are done with
        // all locking etc. in nsLDAPConnection::Release().
        //
        mRunnable = new nsLDAPConnectionLoop();
        NS_IF_ADDREF(mRunnable);
        if (!mRunnable || NS_FAILED(mRunnable->Init())) {
            rv = NS_ERROR_OUT_OF_MEMORY;
        } else {
            // Here we keep a weak reference in the runnable object to the
            // nsLDAPConnection ("this"). This avoids the problem where a
            // connection can't get destructed because of the new thread
            // keeping a strong reference to it. It also helps us know when
            // we need to exit the new thread: when we can't convert the weak
            // reference to a strong ref, we know that the nsLDAPConnection
            // object is gone, and we need to stop the thread running.
            //
            nsCOMPtr<nsILDAPConnection> conn =
                static_cast<nsILDAPConnection *>(this);

            mRunnable->mWeakConn = do_GetWeakReference(conn);

            // kick off a thread for result listening and marshalling
            //
            rv = NS_NewThread(getter_AddRefs(mThread), mRunnable);
            if (NS_FAILED(rv)) {
                rv = NS_ERROR_NOT_AVAILABLE;
            }
            // XXX(darin): We need to shutdown this thread at some point.
            //             Otherwise, it will stick around until shutdown.
        }
    }

    // Drop the DNS request object, we no longer need it, and set the flag
    // indicating that DNS has finished.
    //
    mDNSRequest = 0;
    mDNSHost.Truncate();

    // Call the listener, and then we can release our reference to it.
    //
    mInitListener->OnLDAPInit(this, rv);
    mInitListener = 0;

    return rv;
}
Exemple #5
0
int main(int argc, char **argv)
#endif
{
    const char *hostName = DEFAULT_HOST_NAME;
    PRHostEnt he, reversehe;
    char buf[PR_NETDB_BUF_SIZE];
    char reversebuf[PR_NETDB_BUF_SIZE];
    PRIntn idx;
    PRNetAddr addr;
    PLOptStatus os;
    PLOptState *opt = PL_CreateOptState(argc, argv, "h");

    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
        if (PL_OPT_BAD == os) continue;
        switch (opt->option) {
            case 0:  /* naked */
                hostName = opt->value;
                break;
            case 'h':  /* Help message */
            default:
                Help();
                return 2;
        }
    }
    PL_DestroyOptState(opt);

    PR_STDIO_INIT();
    outFile = PR_GetSpecialFD(PR_StandardError);

    if (PR_GetHostByName(hostName, buf, sizeof(buf), &he) == PR_FAILURE) {
        PR_fprintf(outFile, "PR_GetHostByName failed\n");
        exit(1);
    }
    PrintHostent(&he);
    idx = 0;

    while (1) {
        idx = PR_EnumerateHostEnt(idx, &he, 0, &addr);
        if (idx == -1) {
            PR_fprintf(outFile, "PR_EnumerateHostEnt failed\n");
            exit(1);
        }
        if (idx == 0) break;  /* normal loop termination */
        PR_fprintf(outFile, "reverse lookup\n");
        if (PR_GetHostByAddr(&addr, reversebuf, sizeof(reversebuf),
                &reversehe) == PR_FAILURE) {
            PR_fprintf(outFile, "PR_GetHostByAddr failed\n");
            exit(1);
        }
        PrintHostent(&reversehe);
    }

    PR_fprintf(outFile, "PR_GetIPNodeByName with PR_AF_INET\n");
    if (PR_GetIPNodeByName(hostName, PR_AF_INET, PR_AI_DEFAULT,
            buf, sizeof(buf), &he) == PR_FAILURE) {
        PR_fprintf(outFile, "PR_GetIPNodeByName failed\n");
        exit(1);
    }
    PrintHostent(&he);
    PR_fprintf(outFile, "PR_GetIPNodeByName with PR_AF_INET6\n");
    if (PR_GetIPNodeByName(hostName, PR_AF_INET6, PR_AI_DEFAULT,
            buf, sizeof(buf), &he) == PR_FAILURE) {
        PR_fprintf(outFile, "PR_GetIPNodeByName failed\n");
        exit(1);
    }
    PrintHostent(&he);
    idx = 0;
    PR_fprintf(outFile, "PR_GetHostByAddr with PR_AF_INET6\n");
    while (1) {
        idx = PR_EnumerateHostEnt(idx, &he, 0, &addr);
        if (idx == -1) {
            PR_fprintf(outFile, "PR_EnumerateHostEnt failed\n");
            exit(1);
        }
        if (idx == 0) break;  /* normal loop termination */
        PR_fprintf(outFile, "reverse lookup\n");
        if (PR_GetHostByAddr(&addr, reversebuf, sizeof(reversebuf),
                &reversehe) == PR_FAILURE) {
            PR_fprintf(outFile, "PR_GetHostByAddr failed\n");
            exit(1);
        }
        PrintHostent(&reversehe);
    }
    PR_fprintf(outFile, "PR_GetHostByAddr with PR_AF_INET6 done\n");
  
    PR_StringToNetAddr("::1", &addr);
    if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_TRUE) {
        PR_fprintf(outFile, "addr should not be ipv4 mapped address\n");
        exit(1);
    }
    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be loopback address\n");
        exit(1);
    }

    PR_StringToNetAddr("127.0.0.1", &addr);
    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be loopback address\n");
        exit(1);
    }
    PR_StringToNetAddr("::FFFF:127.0.0.1", &addr);
    if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be ipv4 mapped address\n");
        exit(1);
    }
    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be loopback address\n");
        exit(1);
    }

    if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) {
        PR_fprintf(outFile, "PR_InitializeNetAddr failed\n");
        exit(1);
    }
    if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be unspecified address\n");
        exit(1);
    }
    if (PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &addr) == PR_FAILURE) {
        PR_fprintf(outFile, "PR_InitializeNetAddr failed\n");
        exit(1);
    }
    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be loopback address\n");
        exit(1);
    }

    if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET, 0, &addr) == PR_FAILURE) {
        PR_fprintf(outFile, "PR_SetNetAddr failed\n");
        exit(1);
    }
    if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be unspecified address\n");
        exit(1);
    }
    if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET, 0, &addr) == PR_FAILURE) {
        PR_fprintf(outFile, "PR_SetNetAddr failed\n");
        exit(1);
    }
    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be loopback address\n");
        exit(1);
    }

    addr.inet.family = PR_AF_INET;
    addr.inet.port = 0;
    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
    if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be unspecified address\n");
        exit(1);
    }
	{
		char buf[256];
		PR_NetAddrToString(&addr, buf, 256);
		PR_fprintf(outFile, "IPv4 INADDRANY: %s\n", buf);
	}
    addr.inet.family = PR_AF_INET;
    addr.inet.port = 0;
    addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be loopback address\n");
        exit(1);
    }
	{
		char buf[256];
		PR_NetAddrToString(&addr, buf, 256);
		PR_fprintf(outFile, "IPv4 LOOPBACK: %s\n", buf);
	}

    if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
        PR_fprintf(outFile, "PR_SetNetAddr failed\n");
        exit(1);
    }
    if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be unspecified address\n");
        exit(1);
    }
	{
		char buf[256];
		PR_NetAddrToString(&addr, buf, 256);
		PR_fprintf(outFile, "IPv6 INADDRANY: %s\n", buf);
	}
    if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
        PR_fprintf(outFile, "PR_SetNetAddr failed\n");
        exit(1);
    }
    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
        PR_fprintf(outFile, "addr should be loopback address\n");
        exit(1);
    }
	{
		char buf[256];
		PR_NetAddrToString(&addr, buf, 256);
		PR_fprintf(outFile, "IPv6 LOOPBACK: %s\n", buf);
	}
	{
		PRIPv6Addr v6addr;
		char tmp_buf[256];

    	PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET, 0, &addr);

		PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &v6addr);
    	PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr);
		addr.ipv6.ip = v6addr;
		PR_NetAddrToString(&addr, tmp_buf, 256);
		PR_fprintf(outFile, "IPv4-mapped IPv6 LOOPBACK: %s\n", tmp_buf);
	}
    PR_fprintf(outFile, "PASS\n");
    return 0;
}