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; }
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; }
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; }