Beispiel #1
0
OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean enableReuseIPMode)

{
    UInt8    buf[kOTFourByteOptionSize]; // define buffer for fourByte Option size
    TOption* opt;                        // option ptr to make items easier to access
    TOptMgmt req;
    TOptMgmt ret;
    OSStatus err;

    if (!OTIsSynchronous(ep))
    {
        return (-1);
    }
	opt = (TOption*)buf;					// set option ptr to buffer
	req.opt.buf	= buf;
	req.opt.len	= sizeof(buf);
	req.flags	= T_NEGOTIATE;				// negotiate for option

	ret.opt.buf = buf;
	ret.opt.maxlen = kOTFourByteOptionSize;

	opt->level	= INET_IP;					// dealing with an IP Level function
#ifdef __DARWIN__
	opt->name	= kIP_REUSEADDR;
#else
	opt->name	= IP_REUSEADDR;
#endif
	opt->len	= kOTFourByteOptionSize;
	opt->status = 0;
	*(UInt32*)opt->value = enableReuseIPMode;		// set the desired option level, true or false

	err = OTOptionManagement(ep, &req, &ret);
	
		// if no error then return the option status value
	if (err == kOTNoError)
	{
		if (opt->status != T_SUCCESS)
			err = opt->status;
		else
			err = kOTNoError;
	}
				
	return err;
}
Beispiel #2
0
PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
{
	OSStatus err;
	PRInt32 osfd = fd->secret->md.osfd;
	EndpointRef endpoint = (EndpointRef) osfd;
	TOptMgmt cmd;
	TOption *opt;
	PRThread *me = _PR_MD_CURRENT_THREAD();
	unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData) + 1];
	
	if (endpoint == NULL) {
		err = kEBADFErr;
		goto ErrorExit;
	}
	
	/* 
	OT wants IPPROTO_IP for level and not XTI_GENERIC.  SO_REUSEADDR and SO_KEEPALIVE 
	are equated to IP level and TCP level options respectively and hence we need to set 
	the level correctly.
	*/
	if (level == SOL_SOCKET) {
		if (optname == SO_REUSEADDR)
			level = IPPROTO_IP;
		else if (optname == SO_KEEPALIVE)
			level = INET_TCP;
	}

	opt = (TOption *)&optionBuffer[0];
	opt->len = kOTOptionHeaderSize + optlen;

	/* special case adjustments for length follow */
	if (optname == SO_KEEPALIVE) /* we need to pass the timeout value for OT */
		opt->len = kOTOptionHeaderSize + sizeof(t_kpalive);
	if (optname == IP_MULTICAST_TTL || optname == IP_TTL) /* it is an unsigned char value */
		opt->len = kOTOneByteOptionSize;
	if (optname == IP_TOS && level == IPPROTO_IP)
		opt->len = kOTOneByteOptionSize;

	opt->level = level;
	opt->name = optname;
	opt->status = 0;
	
	cmd.opt.len = opt->len;
	cmd.opt.maxlen = sizeof(optionBuffer);
	cmd.opt.buf = (UInt8*)optionBuffer;
	
	optionBuffer[opt->len] = 0;
	
	cmd.flags = T_NEGOTIATE;

	switch (optname) {
		case SO_LINGER:
			*((t_linger*)&opt->value) = *((t_linger*)optval);
			break;
		case SO_REUSEADDR:
		case TCP_NODELAY:
		case SO_RCVBUF:
		case SO_SNDBUF:
			*((PRIntn*)&opt->value) = *((PRIntn*)optval);
			break;
		case IP_MULTICAST_LOOP:
			if (*optval != 0)
				opt->value[0] = T_YES;
			else
				opt->value[0] = T_NO;
			break;
		case SO_KEEPALIVE:
			{
			t_kpalive *kpalive = (t_kpalive *)&opt->value;
			
			kpalive->kp_onoff = *((long*)optval);
			kpalive->kp_timeout = 10; /* timeout in minutes */
			break;
			}
		case IP_TTL:
			*((unsigned char*)&opt->value) = *((PRUintn*)optval);
			break;
		case IP_MULTICAST_TTL:
			*((unsigned char*)&opt->value) = *optval;
			break;
		case IP_ADD_MEMBERSHIP:
		case IP_DROP_MEMBERSHIP:
			{
			/* struct ip_mreq and TIPAddMulticast are the same size and optval 
			   is pointing to struct ip_mreq */
			*((TIPAddMulticast *)&opt->value) = *((TIPAddMulticast *)optval);
			break;
			}
		case IP_MULTICAST_IF:
			{
			*((PRUint32*)&opt->value) = *((PRUint32*)optval);
			break;
			}
		/*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
		case TCP_MAXSEG:
			if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
				*((PRIntn*)&opt->value) = *((PRIntn*)optval);
			} else { /* it is IP_TOS */
				*((unsigned char*)&opt->value) = *((PRUintn*)optval);
			}
			break;
		default:
			PR_ASSERT(0);
			break;	
	}
	
	PrepareThreadForAsyncIO(me, endpoint, osfd);    

	err = OTOptionManagement(endpoint, &cmd, &cmd);
	if (err != kOTNoError)
		goto ErrorExit;

	WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

	err = me->md.osErrCode;
	if (err != kOTNoError)
		goto ErrorExit;

	if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
		err = kEOPNOTSUPPErr;
		goto ErrorExit;
	}
	
	if (level == IPPROTO_TCP && optname == TCP_MAXSEG && opt->status == T_READONLY) {
		err = kEOPNOTSUPPErr;
		goto ErrorExit;
	}

	PR_ASSERT(opt->status == T_SUCCESS);

	return PR_SUCCESS;

ErrorExit:
	macsock_map_error(err);
    return PR_FAILURE;
}
Beispiel #3
0
PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
{
	OSStatus err;
	PRInt32 osfd = fd->secret->md.osfd;
	EndpointRef endpoint = (EndpointRef) osfd;
	TOptMgmt cmd;
	TOption *opt;
	PRThread *me = _PR_MD_CURRENT_THREAD();
	unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData)];
	
	if (endpoint == NULL) {
		err = kEBADFErr;
		goto ErrorExit;
	}
	
	/* 
	OT wants IPPROTO_IP for level and not XTI_GENERIC.  SO_REUSEADDR and SO_KEEPALIVE 
	are equated to IP level and TCP level options respectively and hence we need to set 
	the level correctly.
	*/
	if (level == SOL_SOCKET) {
		if (optname == SO_REUSEADDR)
			level = IPPROTO_IP;
		else if (optname == SO_KEEPALIVE)
			level = INET_TCP;
	}

	opt = (TOption *)&optionBuffer[0];
	opt->len = sizeof(TOption);
	opt->level = level;
	opt->name = optname;
	opt->status = 0;
	
	cmd.opt.len = sizeof(TOption);
	cmd.opt.maxlen = sizeof(optionBuffer);
	cmd.opt.buf = (UInt8*)optionBuffer;
	cmd.flags = T_CURRENT;

	PrepareThreadForAsyncIO(me, endpoint, osfd);    

	err = OTOptionManagement(endpoint, &cmd, &cmd);
	if (err != kOTNoError)
		goto ErrorExit;

	WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

	err = me->md.osErrCode;
	if (err != kOTNoError)
		goto ErrorExit;

	if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
		err = kEOPNOTSUPPErr;
		goto ErrorExit;
	}

	PR_ASSERT(opt->status == T_SUCCESS);

	switch (optname) {
		case SO_LINGER:
			*((t_linger*)optval) = *((t_linger*)&opt->value);
			*optlen = sizeof(t_linger);
			break;
		case SO_REUSEADDR:
		case TCP_NODELAY:
		case SO_KEEPALIVE:
		case SO_RCVBUF:
		case SO_SNDBUF:
			*((PRIntn*)optval) = *((PRIntn*)&opt->value);
			*optlen = sizeof(PRIntn);
			break;
		case IP_MULTICAST_LOOP:
			*((PRUint8*)optval) = *((PRIntn*)&opt->value);
			*optlen = sizeof(PRUint8);
			break;
		case IP_TTL:
			*((PRUintn*)optval) = *((PRUint8*)&opt->value);
			*optlen = sizeof(PRUintn);
			break;
		case IP_MULTICAST_TTL:
			*((PRUint8*)optval) = *((PRUint8*)&opt->value);
			*optlen = sizeof(PRUint8);
			break;
		case IP_ADD_MEMBERSHIP:
		case IP_DROP_MEMBERSHIP:
			{
			/* struct ip_mreq and TIPAddMulticast are the same size and optval 
			   is pointing to struct ip_mreq */
			*((struct ip_mreq *)optval) = *((struct ip_mreq *)&opt->value);
			*optlen = sizeof(struct ip_mreq);
			break;
			}
		case IP_MULTICAST_IF:
			{
			*((PRUint32*)optval) = *((PRUint32*)&opt->value);
			*optlen = sizeof(PRUint32);
			break;
			}
		/*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
		case TCP_MAXSEG:
			if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
				*((PRIntn*)optval) = *((PRIntn*)&opt->value);
				*optlen = sizeof(PRIntn);
			} else { /* it is IP_TOS */
				*((PRUintn*)optval) = *((PRUint8*)&opt->value);
				*optlen = sizeof(PRUintn);
			}
			break;
		default:
			PR_ASSERT(0);
			break;	
	}
	
	return PR_SUCCESS;

ErrorExit:
	macsock_map_error(err);
    return PR_FAILURE;
}
NMErr
OTIPEnumerator::StartEnumeration(void)
{
	TEndpointInfo	info;
	NMErr			status = kNMNoError;
	TBind			request;
	TOption			optBuf;
	//NMUInt8			optBuf[64];
	//NMUInt8			fooBuf[32];
	TOptMgmt		cmd;
	//NMUInt8 			*foo = fooBuf;

	
	//	If they don't want us to actively get the enumeration, there is nothing to do
	if (! bActive)
		return kNMNoError;
	
	//	first clear out any current items
	(mCallback)(mContext, kNMEnumClear, NULL);	// [Edmark/PBE] 11/16/99 added

	bFirstIdle = true;
	
	//	Create an OT endpoint
	mEP = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, &info, &status);
	if (status)
		goto error;

	// fill in the option request
	cmd.flags = T_NEGOTIATE;
	cmd.opt.len = kOTFourByteOptionSize;
	cmd.opt.maxlen = kOTFourByteOptionSize;
	cmd.opt.buf = (NMUInt8*)&optBuf;

	// fill in the toption struct
	optBuf.len = sizeof(TOption);
	optBuf.level = INET_IP;
	optBuf.name = kIP_BROADCAST;
	optBuf.status = 0;
	optBuf.value[0] = 1;

/*
	cmd.opt.len = 0;
	cmd.opt.maxlen = 64;
	cmd.opt.buf = (NMUInt8*)optBuf;
	cmd.flags = T_NEGOTIATE;

	//	Option management kinda sucks
	strcpy((char *) fooBuf, "Broadcast = 1");
	status = OTCreateOptions(kRawIPName, (char **)&foo, &cmd.opt);
*/

	status = OTOptionManagement(mEP, &cmd, &cmd);
	if (status)
		goto error;
	
	//	Allocate the buffer for receiving the endpoint
	mIncomingData.udata.buf = (NMUInt8 *) InterruptSafe_alloc(info.tsdu);
	if (mIncomingData.udata.buf == NULL){
		status = kNSpMemAllocationErr;
		goto error;
	}
	
	mIncomingData.udata.maxlen = info.tsdu;
	
	//	Bind it
	request.addr.buf = NULL;
	request.addr.len = 0;
	request.addr.maxlen = 0;
	request.qlen = 0;
	
	status = OTBind(mEP, &request, NULL);
	if (status)
		goto error;

	OTSetNonBlocking(mEP);
	
	//	Get our interface info (for the broadcast address)
	//	Do this after we bind so that we know the interface is live
	if (! bGotInterfaceInfo)
	{
		status = OTInetGetInterfaceInfo(&mInterfaceInfo, kDefaultInetInterface);
		if (status)
			goto error;
		
		bGotInterfaceInfo = true;
	}
	
	//	Install notifier
	status = OTInstallNotifier(mEP, mNotifier.fUPP, this);
	if (status)
		goto error;
	
	//	Make is asynchronous
	status = OTSetAsynchronous(mEP);
	if (status)
		goto error;
	
	//	Send out the query
	mEnumPeriod = 250;
	status = SendQuery();

error:
	if (status)
	{
		if (mEP)
		{
			OTCloseProvider(mEP);			// ignore errors
			mEP = kOTInvalidEndpointRef;
		}
	}
	return status;
}