Exemplo n.º 1
0
Arquivo: krpc_subr.c Projeto: argp/xnu
/*
 * Call portmap to lookup a port number for a particular rpc program
 * Returns non-zero error on failure.
 */
int
krpc_portmap(
	struct sockaddr_in *sin,	/* server address */
	u_int prog, u_int vers, u_int proto,	/* host order */
	u_int16_t *portp)		/* network order */
{
	struct sdata {
		u_int32_t prog;		/* call program */
		u_int32_t vers;		/* call version */
		u_int32_t proto;	/* call protocol */
		u_int32_t port;		/* call port (unused) */
	} *sdata;
	struct rdata {
		u_int16_t pad;
		u_int16_t port;
	} *rdata;
	mbuf_t m;
	int error;

	/* The portmapper port is fixed. */
	if (prog == PMAPPROG) {
		*portp = htons(PMAPPORT);
		return 0;
	}

	error = mbuf_gethdr(MBUF_WAITOK, MBUF_TYPE_DATA, &m);
	if (error)
		return error;
	mbuf_setlen(m, sizeof(*sdata));
	mbuf_pkthdr_setlen(m, sizeof(*sdata));
	sdata = mbuf_data(m);

	/* Do the RPC to get it. */
	sdata->prog = htonl(prog);
	sdata->vers = htonl(vers);
	sdata->proto = htonl(proto);
	sdata->port = 0;

	sin->sin_port = htons(PMAPPORT);
	error = krpc_call(sin, SOCK_DGRAM, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, &m, NULL);
	if (error) 
		return error;

	rdata = mbuf_data(m);

	if (mbuf_len(m) >= sizeof(*rdata)) {
		*portp = rdata->port;
	}

	if (mbuf_len(m) < sizeof(*rdata) || !rdata->port)
		error = EPROGUNAVAIL;

	mbuf_freem(m);
	return (error);
}
Exemplo n.º 2
0
/*
 * Copy a string into mbuf(s).
 * Return the number of bytes output, including XDR overheads.
 */
APPLESTATIC int
nfsm_strtom(struct nfsrv_descript *nd, const char *cp, int siz)
{
	mbuf_t m2;
	int xfer, left;
	mbuf_t m1;
	int rem, bytesize;
	u_int32_t *tl;
	char *cp2;

	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
	*tl = txdr_unsigned(siz);
	rem = NFSM_RNDUP(siz) - siz;
	bytesize = NFSX_UNSIGNED + siz + rem;
	m2 = nd->nd_mb;
	cp2 = nd->nd_bpos;
	left = M_TRAILINGSPACE(m2);

	/*
	 * Loop around copying the string to mbuf(s).
	 */
	while (siz > 0) {
		if (left == 0) {
			if (siz > ncl_mbuf_mlen)
				NFSMCLGET(m1, M_WAITOK);
			else
				NFSMGET(m1);
			mbuf_setlen(m1, 0);
			mbuf_setnext(m2, m1);
			m2 = m1;
			cp2 = NFSMTOD(m2, caddr_t);
			left = M_TRAILINGSPACE(m2);
		}
		if (left >= siz)
			xfer = siz;
		else
			xfer = left;
		NFSBCOPY(cp, cp2, xfer);
		cp += xfer;
		mbuf_setlen(m2, mbuf_len(m2) + xfer);
		siz -= xfer;
		left -= xfer;
		if (siz == 0 && rem) {
			if (left < rem)
				panic("nfsm_strtom");
			NFSBZERO(cp2 + xfer, rem);
			mbuf_setlen(m2, mbuf_len(m2) + rem);
		}
	}
	nd->nd_mb = m2;
	nd->nd_bpos = NFSMTOD(m2, caddr_t) + mbuf_len(m2);
	return (bytesize);
}
Exemplo n.º 3
0
IOReturn MbufUtils::copyFromBufferToMbuf(mbuf_t mbuf, UInt32 from, UInt32 bufferSize, void *data) {
    if (bufferSize > (UInt32) MbufUtils::mbufTotalLength(mbuf)-from) {
        IOLog("MbufUtils::copyFromBufferToMbuf(): Got insufficiently large buffer (mbuf too small).\n");
        return kIOReturnNoMemory;
    }
    
    UInt8 *inBuffer = (UInt8 *)data;
    UInt8 *mbufBuffer = (UInt8 *)mbuf_data(mbuf);
    size_t mbufLength = mbuf_len(mbuf);
    UInt32 bytesLeft = bufferSize;
    
    skip_mbuf_macro();
    
    while (bytesLeft) {
        ensure_mbuf_macro();
        
        *mbufBuffer = *inBuffer;
        
        ++mbufBuffer;
        ++inBuffer;
        --mbufLength;
        --bytesLeft;
    }
    
    return kIOReturnSuccess;
}
Exemplo n.º 4
0
/* Network Interface functions */
static errno_t
ipsec_demux(__unused ifnet_t	interface,
			mbuf_t				data,
			__unused char		*frame_header,
			protocol_family_t	*protocol)
{
    struct ip *ip;
    u_int ip_version;
    
	while (data != NULL && mbuf_len(data) < 1) {
		data = mbuf_next(data);
	}
	
	if (data == NULL)
		return ENOENT;
    
    ip = mtod(data, struct ip *);
    ip_version = ip->ip_v;
    
    switch(ip_version) {
		case 4:
            *protocol = PF_INET;
			return 0;
		case 6:
            *protocol = PF_INET6;
			return 0;
		default:
			break;
	}
	
	return 0;
}
Exemplo n.º 5
0
size_t MbufUtils::mbufTotalLength(mbuf_t mbuf) {
    size_t len = 0;
    do {
        len += mbuf_len(mbuf);
    } while ((mbuf = mbuf_next(mbuf)));
    return len;
}
Exemplo n.º 6
0
/**
 * Calculates the number of segments required to represent the mbuf.
 *
 * @returns Number of segments.
 * @param   pThis               The instance.
 * @param   pMBuf               The mbuf.
 * @param   pvFrame             The frame pointer, optional.
 */
DECLINLINE(unsigned) vboxNetFltDarwinMBufCalcSGSegs(PVBOXNETFLTINS pThis, mbuf_t pMBuf, void *pvFrame)
{
    NOREF(pThis);

    /*
     * Count the buffers in the chain.
     */
    unsigned cSegs = 0;
    for (mbuf_t pCur = pMBuf; pCur; pCur = mbuf_next(pCur))
        if (mbuf_len(pCur))
            cSegs++;
        else if (   !cSegs
                 && pvFrame
                 && (uintptr_t)pvFrame - (uintptr_t)mbuf_datastart(pMBuf) < mbuf_maxlen(pMBuf))
            cSegs++;

#ifdef PADD_RUNT_FRAMES_FROM_HOST
    /*
     * Add one buffer if the total is less than the ethernet minimum 60 bytes.
     * This may allocate a segment too much if the ethernet header is separated,
     * but that shouldn't harm us much.
     */
    if (mbuf_pkthdr_len(pMBuf) < 60)
        cSegs++;
#endif

#ifdef VBOXNETFLT_DARWIN_TEST_SEG_SIZE
    /* maximize the number of segments. */
    cSegs = RT_MAX(VBOXNETFLT_DARWIN_MAX_SEGS - 1, cSegs);
#endif

    return cSegs ? cSegs : 1;
}
Exemplo n.º 7
0
errno_t	IOWebFilterClass::tl_data_in_func(void *cookie, socket_t so,
                                          const struct sockaddr *from, mbuf_t *data, mbuf_t *control,
                                          sflt_data_flag_t flags)
{
    SocketTracker *tracker = (SocketTracker*)cookie;

//    __asm__("int3");

    LOG(LOG_DEBUG, "I am in, %s, magic=%ld", tracker->proc_name, tracker->magic);

    if(tracker==NULL || data==NULL || (tracker->magic&(kSocketTrackerInvalid|kSocketTrackerDetach))!=0)
    {
        LOG(LOG_DEBUG, "in return process");
        return 0;
    }
    if(tracker->lock==NULL)
    {
        tracker->magic=kSocketTrackerInvalid;
        return 0;
    }

    IOLockLock(tracker->lock);
    mbuf_t head = *data;
    uint64_t len=0;

    if(head==NULL)
    {
        tracker->magic=kSocketTrackerInvalid;
        IOLockUnlock(tracker->lock);
        return 0;
    }

    while(head)
    {
        len += mbuf_len(head);
        head = mbuf_next(head);
    }

    if(len>sizeof(tracker->request_meg)-1)
    {
        tracker->magic=kSocketTrackerInvalid;
        IOLockUnlock(tracker->lock);
        return 0;
    }
    bzero(tracker->request_meg, sizeof(tracker->request_meg));
    mbuf_copydata(*data, 0, len, tracker->request_meg);

    //todo: sync to shared memory, record a new request
    if(_queue)
    {
        LOG(LOG_DEBUG, "enter queue");
        _queue->EnqueueTracker((DataArgs*)tracker);
    }

    IOLockUnlock(tracker->lock);
    return 0;
}
Exemplo n.º 8
0
int  vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
{
    NOREF(pvIfData);

    int rc = VINF_SUCCESS;
    ifnet_t pIfNet = vboxNetFltDarwinRetainIfNet(pThis);
    if (pIfNet)
    {
        /*
         * Create a mbuf for the gather list and push it onto the wire.
         *
         * Note! If the interface is in the promiscuous mode we need to send the
         *       packet down the stack so it reaches the driver and Berkeley
         *       Packet Filter (see @bugref{5817}).
         */
        if ((fDst & INTNETTRUNKDIR_WIRE) || vboxNetFltDarwinIsPromiscuous(pThis))
        {
            mbuf_t pMBuf = vboxNetFltDarwinMBufFromSG(pThis, pSG);
            if (pMBuf)
            {
                errno_t err = ifnet_output_raw(pIfNet, PF_LINK, pMBuf);
                if (err)
                    rc = RTErrConvertFromErrno(err);
            }
            else
                rc = VERR_NO_MEMORY;
        }

        /*
         * Create a mbuf for the gather list and push it onto the host stack.
         */
        if (fDst & INTNETTRUNKDIR_HOST)
        {
            mbuf_t pMBuf = vboxNetFltDarwinMBufFromSG(pThis, pSG);
            if (pMBuf)
            {
                /* This is what IONetworkInterface::inputPacket does. */
                unsigned const cbEthHdr = 14;
                mbuf_pkthdr_setheader(pMBuf, mbuf_data(pMBuf));
                mbuf_pkthdr_setlen(pMBuf, mbuf_pkthdr_len(pMBuf) - cbEthHdr);
                mbuf_setdata(pMBuf, (uint8_t *)mbuf_data(pMBuf) + cbEthHdr, mbuf_len(pMBuf) - cbEthHdr);
                mbuf_pkthdr_setrcvif(pMBuf, pIfNet); /* will crash without this. */

                errno_t err = ifnet_input(pIfNet, pMBuf, NULL);
                if (err)
                    rc = RTErrConvertFromErrno(err);
            }
            else
                rc = VERR_NO_MEMORY;
        }

        vboxNetFltDarwinReleaseIfNet(pThis, pIfNet);
    }

    return rc;
}
Exemplo n.º 9
0
size_t MbufUtils::attemptToSetLength(mbuf_t mbuf, size_t targetLength) {
    size_t mbufLength = mbuf_len(mbuf);
    size_t mbufMaxLength = mbuf_maxlen(mbuf);
    if (targetLength > mbufLength && mbufMaxLength != mbufLength) {
        size_t newBufLen = min_macro(targetLength, mbufMaxLength);
        mbuf_setlen(mbuf, newBufLen);
        mbufLength = newBufLen;
    }
    return mbufLength;
}
Exemplo n.º 10
0
Arquivo: raw.c Projeto: B1NG0/cifs
static int
smb_ioc_request(
        void *				hContext,
        struct smb_header *	header,
        const mbuf_t		words,
        const mbuf_t		bytes,
        mbuf_t				response)
{
    struct smbioc_rq krq;

	bzero(&krq, sizeof(krq));
    krq.ioc_version = SMB_IOC_STRUCT_VERSION;
    krq.ioc_cmd = header->command;

    /* XXX For large I/O requests where the uint16_t byte count
     * (ioc_tbc) wraps to 0, this interface will get horribly
     * confused. I don't think we can fix this without revving the
     * ioctl version -- jpeach
     */

    /* Set transmit words buffer ... */
    krq.ioc_twc = mbuf_len(words) / sizeof(uint16_t);
    krq.ioc_twords = mbuf_data(words);
    /* Set transmit bytes buffer ... */
    krq.ioc_tbc = mbuf_len(bytes);
    krq.ioc_tbytes = mbuf_data(bytes);
    /* Set receive buffer, reserving space for the word count and byte count ... */
    krq.ioc_rpbufsz = (int32_t)mbuf_maxlen(response);
    krq.ioc_rpbuf = mbuf_data(response);

    if (smb_ioctl_call(((struct smb_ctx *)hContext)->ct_fd,
                SMBIOC_REQUEST, &krq) == -1) {
        return errno;
    }
	
	header->flags = krq.ioc_flags;
	header->flags2 = krq.ioc_flags2;
	header->status = krq.ioc_ntstatus;
	mbuf_setlen(response, krq.ioc_rpbufsz);

    return 0;
}
Exemplo n.º 11
0
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
void ppp_comp_logmbuf(char *msg, mbuf_t m) 
{
    int 	i, lcount, copycount, count;
    char 	lbuf[16], *data;

    if (m == NULL)
        return;

    IOLog("%s: \n", msg);

    for (count = mbuf_len(m), data = mbuf_data(m); m != NULL; ) {
        /* build a line of output */
        for(lcount = 0; lcount < sizeof(lbuf); lcount += copycount) {
            if (!count) {
                m = mbuf_next(m);
                if (m == NULL)
                    break;
                count = mbuf_len(m);
                data  = mbuf_data(m);
            }
            copycount = (count > sizeof(lbuf) - lcount) ? sizeof(lbuf) - lcount : count;
            bcopy(data, &lbuf[lcount], copycount);
            data  += copycount;
            count -= copycount;
        }

        /* output line (hex 1st, then ascii) */
        IOLog("%s:  0x  ", msg);
        for(i = 0; i < lcount; i++) {
            if (i == 8) IOLog("  ");
            IOLog("%02x ", (u_char)lbuf[i]);
        }
        for( ; i < sizeof(lbuf); i++) {
            if (i == 8) IOLog("  ");
            IOLog("   ");
        }
        IOLog("  '");
        for(i = 0; i < lcount; i++)
            IOLog("%c",(lbuf[i]>=040 && lbuf[i]<=0176)?lbuf[i]:'.');
        IOLog("'\n");
    }
}
Exemplo n.º 12
0
////////////////////////////////////////////////////////////////////////////////
//
// in_firewire_arp_input
//
// IN: register struct mbuf *m
//
// Invoked by :
// firewire_arpintr calls it from the context of dlil_input_thread queue
//
// ARP for Internet protocols on 10 Mb/s Ethernet.
// Algorithm is that given in RFC 826.
// In addition, a sanity check is performed on the sender
// protocol address, to catch impersonators.
// We no longer handle negotiations for use of trailer protocol:
// Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
// along with IP replies if we wanted trailers sent to us,
// and also sent them in response to IP replies.
// This allowed either end to announce the desire to receive trailer packets.
// We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
// but formerly didn't normally send requests.
//
////////////////////////////////////////////////////////////////////////////////
static void
inet_firewire_arp_input(
    mbuf_t m)
{
    IP1394_ARP *fwa;
    struct sockaddr_dl	sender_hw;
    struct sockaddr_in	sender_ip;
    struct sockaddr_in	target_ip;

    ifnet_t		  ifp		= mbuf_pkthdr_rcvif((mbuf_t)m);

    IOFWInterface *fwIf		= (IOFWInterface*)ifnet_softc(ifp);

    if(fwIf == NULL)
        return;

    IOFireWireIP  *fwIpObj	= (IOFireWireIP*)fwIf->getController();

    if(fwIpObj == NULL)
        return;

    if (mbuf_len(m) < (int)sizeof(IP1394_ARP) &&
            mbuf_pullup(&m, sizeof(IP1394_ARP)) != 0)
        return;

    fwa = (IP1394_ARP*)mbuf_data(m);

    // Verify this is an firewire/ip arp and address lengths are correct
    if (fwa->hardwareType != htons(ARP_HDW_TYPE) || fwa->protocolType != htons(FWTYPE_IP)
            || fwa->hwAddrLen != sizeof(IP1394_HDW_ADDR) || fwa->ipAddrLen != IPV4_ADDR_SIZE)
    {
        mbuf_free(m);
        return;
    }

    bzero(&sender_ip, sizeof(sender_ip));
    sender_ip.sin_len = sizeof(sender_ip);
    sender_ip.sin_family = AF_INET;
    sender_ip.sin_addr.s_addr = fwa->senderIpAddress;
    target_ip = sender_ip;
    target_ip.sin_addr.s_addr = fwa->targetIpAddress;

    bzero(&sender_hw, sizeof(sender_hw));
    sender_hw.sdl_len = sizeof(sender_hw);
    sender_hw.sdl_family = AF_LINK;
    sender_hw.sdl_type = IFT_IEEE1394;
    sender_hw.sdl_alen = FIREWIRE_ADDR_LEN;
    bcopy(&fwa->senderUniqueID, LLADDR(&sender_hw), FIREWIRE_ADDR_LEN);

    if(fwIpObj->arpCacheHandler(fwa))
        inet_arp_handle_input(ifp, ntohs(fwa->opcode), &sender_hw, &sender_ip, &target_ip);

    mbuf_free((mbuf_t)m);
}
Exemplo n.º 13
0
static errno_t vboxNetAdpDarwinOutput(ifnet_t pIface, mbuf_t pMBuf)
{
    PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
    Assert(pThis);
    if (pThis->u.s.nTapMode & BPF_MODE_OUTPUT)
    {
        Log2(("vboxnetadp: out len=%d\n%.*Rhxd\n", mbuf_len(pMBuf), 14, mbuf_data(pMBuf)));
        bpf_tap_out(pIface, DLT_EN10MB, pMBuf, NULL, 0);
    }
    mbuf_freem_list(pMBuf);
    return 0;
}
Exemplo n.º 14
0
/* -----------------------------------------------------------------------------
Called by socket layer to send a packet
----------------------------------------------------------------------------- */
int l2tp_send(struct socket *so, int flags, mbuf_t m, struct sockaddr *to,
	    mbuf_t control, struct proc *p)
{

    if (control)
        mbuf_freem(control);
    if (mbuf_len(m) == 0) {
        mbuf_freem(m);
        return 0;
    }

    return l2tp_rfc_output(so->so_pcb, m, to);
}
Exemplo n.º 15
0
/*
 * Advance the position in the mbuf chain.
 * If offs == 0, this is a no-op, but it is simpler to just return from
 * here than check for offs > 0 for all calls to nfsm_advance.
 * If left == -1, it should be calculated here.
 */
APPLESTATIC int
nfsm_advance(struct nfsrv_descript *nd, int offs, int left)
{
	int error = 0;

	if (offs == 0)
		goto out;
	/*
	 * A negative offs should be considered a serious problem.
	 */
	if (offs < 0)
		panic("nfsrv_advance");

	/*
	 * If left == -1, calculate it here.
	 */
	if (left == -1)
		left = NFSMTOD(nd->nd_md, caddr_t) + mbuf_len(nd->nd_md) -
		    nd->nd_dpos;

	/*
	 * Loop around, advancing over the mbuf data.
	 */
	while (offs > left) {
		offs -= left;
		nd->nd_md = mbuf_next(nd->nd_md);
		if (nd->nd_md == NULL) {
			error = EBADRPC;
			goto out;
		}
		left = mbuf_len(nd->nd_md);
		nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t);
	}
	nd->nd_dpos += offs;

out:
	NFSEXITCODE(error);
	return (error);
}
Exemplo n.º 16
0
/*
 * Help break down an mbuf chain by setting the first siz bytes contiguous
 * pointed to by returned val.
 * This is used by the macro NFSM_DISSECT for tough
 * cases.
 */
APPLESTATIC void *
nfsm_dissct(struct nfsrv_descript *nd, int siz, int how)
{
	mbuf_t mp2;
	int siz2, xfer;
	caddr_t p;
	int left;
	caddr_t retp;

	retp = NULL;
	left = NFSMTOD(nd->nd_md, caddr_t) + mbuf_len(nd->nd_md) - nd->nd_dpos;
	while (left == 0) {
		nd->nd_md = mbuf_next(nd->nd_md);
		if (nd->nd_md == NULL)
			return (retp);
		left = mbuf_len(nd->nd_md);
		nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t);
	}
	if (left >= siz) {
		retp = nd->nd_dpos;
		nd->nd_dpos += siz;
	} else if (mbuf_next(nd->nd_md) == NULL) {
		return (retp);
	} else if (siz > ncl_mbuf_mhlen) {
		panic("nfs S too big");
	} else {
		MGET(mp2, MT_DATA, how);
		if (mp2 == NULL)
			return (NULL);
		mbuf_setnext(mp2, mbuf_next(nd->nd_md));
		mbuf_setnext(nd->nd_md, mp2);
		mbuf_setlen(nd->nd_md, mbuf_len(nd->nd_md) - left);
		nd->nd_md = mp2;
		retp = p = NFSMTOD(mp2, caddr_t);
		NFSBCOPY(nd->nd_dpos, p, left);	/* Copy what was left */
		siz2 = siz - left;
		p += left;
		mp2 = mbuf_next(mp2);
		/* Loop around copying up the siz2 bytes */
		while (siz2 > 0) {
			if (mp2 == NULL)
				return (NULL);
			xfer = (siz2 > mbuf_len(mp2)) ? mbuf_len(mp2) : siz2;
			if (xfer > 0) {
				NFSBCOPY(NFSMTOD(mp2, caddr_t), p, xfer);
				NFSM_DATAP(mp2, xfer);
				mbuf_setlen(mp2, mbuf_len(mp2) - xfer);
				p += xfer;
				siz2 -= xfer;
			}
			if (siz2 > 0)
				mp2 = mbuf_next(mp2);
		}
		mbuf_setlen(nd->nd_md, siz);
		nd->nd_md = mp2;
		nd->nd_dpos = NFSMTOD(mp2, caddr_t);
	}
	return (retp);
}
Exemplo n.º 17
0
static errno_t vboxNetAdpDarwinDemux(ifnet_t pIface, mbuf_t pMBuf,
                                     char *pFrameHeader,
                                     protocol_family_t *pProtocolFamily)
{
    PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
    Assert(pThis);
    Log2(("vboxNetAdpDarwinDemux: mode=%d\n", pThis->u.s.nTapMode));
    if (pThis->u.s.nTapMode & BPF_MODE_INPUT)
    {
        Log2(("vboxnetadp: in len=%d\n%.*Rhxd\n", mbuf_len(pMBuf), 14, pFrameHeader));
        bpf_tap_in(pIface, DLT_EN10MB, pMBuf, pFrameHeader, ETHER_HDR_LEN);
    }
    return ether_demux(pIface, pMBuf, pFrameHeader, pProtocolFamily);
}
Exemplo n.º 18
0
/* Network Interface functions */
static errno_t
utun_demux(
	__unused ifnet_t	interface,
	mbuf_t				data,
	__unused char		*frame_header,
	protocol_family_t	*protocol)
{
	
	while (data != NULL && mbuf_len(data) < 1) {
		data = mbuf_next(data);
	}
	
	if (data == NULL)
		return ENOENT;
	
	*protocol = *(u_int32_t *)mbuf_data(data);
	return 0;
}
Exemplo n.º 19
0
void net_habitue_device_SC101::handleResolvePacket(sockaddr_in *addr, mbuf_t m, size_t len, outstanding *out, void *ctx)
{
  clock_get_uptime(&_lastReply);
  
  if (mbuf_len(m) < out->len &&
      mbuf_pullup(&m, out->len) != 0)
  {
    KINFO("pullup failed");
    return;
  }
  
  KDEBUG("resolve succeeded!");
  
  psan_resolve_response_t *res = (psan_resolve_response_t *)mbuf_data(m);
  
  sockaddr_in part;
  bzero(&part, sizeof(part));
  part.sin_len = sizeof(part);
  part.sin_family = AF_INET;
  part.sin_port = htons(PSAN_PORT);
  part.sin_addr = res->ip4;
  
  OSData *partData = OSData::withBytes(&part, sizeof(part));
  if (partData)
  {
    setProperty(gSC101DevicePartitionAddressKey, partData);
    partData->release();
  }
  
  OSData *rootData = OSData::withBytes(addr, sizeof(*addr));
  if (rootData)
  {
    setProperty(gSC101DeviceRootAddressKey, rootData);
    rootData->release();
  }
  
  IODelete(out, outstanding, 1);
  
  mbuf_freem(m);

  if (!getProperty(gSC101DeviceSizeKey))
    disk();
}
Exemplo n.º 20
0
__private_extern__ errno_t ANControlListEntryAppend(OSMallocTag tag, ANControlListEntry * entry, mbuf_t packet) {
    uint32_t packSize = (uint32_t)mbuf_len(packet);
    if (packSize == 0) return 0;
    
    uint32_t newSize = packSize + entry->bufferLength;
            
    char * buffer = (char *)OSMalloc(newSize, tag);
    if (!buffer) return ENOMEM;
    
    if (entry->packetBuffer) {
        // copy old data to the buffer
        memcpy(buffer, entry->packetBuffer, entry->bufferLength);
        OSFree(entry->packetBuffer, entry->bufferLength, tag);
    }
    
    mbuf_copydata(packet, 0, packSize, &buffer[entry->bufferLength]);
    entry->packetBuffer = buffer;
    entry->bufferLength = newSize;
    return 0;
}
Exemplo n.º 21
0
IOReturn MbufUtils::copyAudioFromMbufToBuffer(mbuf_t mbuf, UInt32 from, UInt32 bufferSize, UInt8 *inBuffer) {
    if (bufferSize > (UInt32) MbufUtils::mbufTotalLength(mbuf)-from) {
        IOLog("MbufUtils::copyAudioFromMbufToBuffer(): Got insufficiently large buffer (mbuf too small).\n");
        return kIOReturnNoMemory;
    }
    
    if (0 != bufferSize % (REAC_RESOLUTION*2)) {
        IOLog("MbufUtils::copyAudioFromMbufToBuffer(): Buffer size must be a multiple of %d.\n", REAC_RESOLUTION*2);
        return kIOReturnBadArgument;
    }
    
    UInt8 *inBufferEnd = inBuffer + bufferSize;
    UInt8 intermediaryBuffer[6];
    UInt8 *mbufBuffer = (UInt8 *)mbuf_data(mbuf);
    size_t mbufLength = mbuf_len(mbuf);
    
    skip_mbuf_macro();
    
    while (inBuffer < inBufferEnd) {
        for (UInt32 i=0; i<sizeof(intermediaryBuffer); i++) {
            ensure_mbuf_macro();
            
            intermediaryBuffer[i] = *mbufBuffer;
            ++mbufBuffer;
            --mbufLength;
        }
        
        inBuffer[0] = intermediaryBuffer[1];
        inBuffer[1] = intermediaryBuffer[0];
        inBuffer[2] = intermediaryBuffer[3];
        
        inBuffer[3] = intermediaryBuffer[2];
        inBuffer[4] = intermediaryBuffer[5];
        inBuffer[5] = intermediaryBuffer[4];
        
        inBuffer += REAC_RESOLUTION*2;
    }
    
    return kIOReturnSuccess;
}
Exemplo n.º 22
0
UInt32 VoodooIntel3945::outputPacket( mbuf_t m, void* param ) {
	struct wpi_softc* sc = &fSelfData;
	struct ieee80211com* ic = &sc->sc_ic;
	struct ieee80211_node *ni;
	
	DPRINTF(("TX: mbuf len=%u\n", mbuf_len(m)));
	
	if (m == 0)
		return kIOReturnOutputDropped; // ???
	
	ExtraMbufParams* p = (ExtraMbufParams*)param;
	if (p->is80211ManagementFrame) {
		ni = (struct ieee80211_node *)mbuf_pkthdr_rcvif(m);
	} else {
		if (sc->qfullmsk != 0) {
			freePacket(m);
			return kIOReturnOutputDropped;
		}
		
		if (ic->ic_state != IEEE80211_S_RUN) {
			freePacket(m);
			return kIOReturnOutputDropped;
		}
		
		/* Encapsulate and send data frames. */
		if ((m = ieee80211_encap(ic, m, &ni)) == NULL)
			return kIOReturnOutputDropped;
	}
				
	if (wpi_tx(sc, m, ni) != 0) {
		ieee80211_release_node(ic, ni);
		if (m) freePacket(m);
		return kIOReturnOutputDropped;
	} else {
		DPRINTF(("(prev tx success)\n"));
		sc->sc_tx_timer = 5;
		return kIOReturnOutputSuccess;
	}
}
Exemplo n.º 23
0
IOReturn MbufUtils::zeroMbuf(mbuf_t mbuf, UInt32 from, UInt32 len) {
    if (from+len > (UInt32) MbufUtils::mbufTotalLength(mbuf)) {
        IOLog("MbufUtils::zeroMbuf(): Got insufficiently large buffer.\n");
        return kIOReturnNoMemory;
    }
    
    UInt8 *mbufBuffer = (UInt8 *)mbuf_data(mbuf);
    size_t mbufLength = mbuf_len(mbuf);
    UInt32 bytesLeft = len;
    
    skip_mbuf_macro();
    
    while (bytesLeft) {
        ensure_mbuf_macro();
        *mbufBuffer = 0;
        
        ++mbufBuffer;
        --mbufLength;
        --bytesLeft;
    }
    
    return kIOReturnSuccess;
}
Exemplo n.º 24
0
IOReturn MbufUtils::copyAudioFromBufferToMbuf(mbuf_t mbuf, UInt32 from, UInt32 bufferSize, UInt8 *inBuffer) {
    if (bufferSize > (UInt32) MbufUtils::mbufTotalLength(mbuf)-from) {
        IOLog("MbufUtils::copyAudioFromBufferToMbuf(): Got insufficiently large buffer (mbuf too small).\n");
        return kIOReturnNoMemory;
    }
    
    if (0 != bufferSize % (REAC_RESOLUTION*2)) {
        IOLog("MbufUtils::copyAudioFromBufferToMbuf(): Buffer size must be a multiple of %d.\n", REAC_RESOLUTION*2);
        return kIOReturnBadArgument;
    }
    
    UInt8 *mbufBuffer = (UInt8 *)mbuf_data(mbuf);
    size_t mbufLength = mbuf_len(mbuf);
    UInt32 bytesLeft = bufferSize;
    
    skip_mbuf_macro();

#   define mbuf_move_buffer_forward_macro() \
        ++mbufBuffer; \
        --mbufLength;
    
    while (bytesLeft) {
        ensure_mbuf_macro(); *mbufBuffer = inBuffer[1]; mbuf_move_buffer_forward_macro();
        ensure_mbuf_macro(); *mbufBuffer = inBuffer[0]; mbuf_move_buffer_forward_macro();
        ensure_mbuf_macro(); *mbufBuffer = inBuffer[3]; mbuf_move_buffer_forward_macro();
        
        ensure_mbuf_macro(); *mbufBuffer = inBuffer[2]; mbuf_move_buffer_forward_macro();
        ensure_mbuf_macro(); *mbufBuffer = inBuffer[5]; mbuf_move_buffer_forward_macro();
        ensure_mbuf_macro(); *mbufBuffer = inBuffer[4]; mbuf_move_buffer_forward_macro();
        
        inBuffer += REAC_RESOLUTION*2;
        bytesLeft -= REAC_RESOLUTION*2;
    }
    
    return kIOReturnSuccess;
}
Exemplo n.º 25
0
UInt32 HoRNDIS::outputPacket(mbuf_t packet, void *param) {
	mbuf_t m;
	size_t pktlen = 0;
	IOReturn ior = kIOReturnSuccess;
	UInt32 poolIndx;
	int i;

	LOG(V_DEBUG, "");
	
	/* Count the total size of this packet */
	m = packet;
	while (m) {
		pktlen += mbuf_len(m);
		m = mbuf_next(m);
	}
	
	LOG(V_DEBUG, "%ld bytes", pktlen);
	
	if (pktlen > (mtu + 14)) {
		LOG(V_ERROR, "packet too large (%ld bytes, but I told you you could have %d!)", pktlen, mtu);
		fpNetStats->outputErrors++;
		return false;
	}
	
	/* Find an output buffer in the pool */
	IOLockLock(outbuf_lock);
	for (i = 0; i < OUT_BUF_MAX_TRIES; i++) {
		AbsoluteTime ivl, deadl;
		
		for (poolIndx = 0; poolIndx < N_OUT_BUFS; poolIndx++)
			if (!outbufs[poolIndx].inuse) {
				outbufs[poolIndx].inuse = true;
				break;
			}
		if (poolIndx != N_OUT_BUFS)
			break;
		
		/* "while", not "if".  See Symphony X's seminal work on this topic, /Paradise Lost/ (2007). */
		nanoseconds_to_absolutetime(OUT_BUF_WAIT_TIME, &ivl);
		clock_absolutetime_interval_to_deadline(ivl, &deadl);
		LOG(V_NOTE, "waiting for buffer...");
		IOLockSleepDeadline(outbuf_lock, outbufs, deadl, THREAD_INTERRUPTIBLE);
	}
	IOLockUnlock(outbuf_lock);
	
	if (poolIndx == N_OUT_BUFS) {
		LOG(V_ERROR, "timed out waiting for buffer");
		return kIOReturnTimeout;
	}
	
	/* Start filling in the send buffer */
	struct rndis_data_hdr *hdr;
	hdr = (struct rndis_data_hdr *)outbufs[poolIndx].buf;
	
	outbufs[poolIndx].inuse = true;
	
	outbufs[poolIndx].mdp->setLength(pktlen + sizeof *hdr);
	
	memset(hdr, 0, sizeof *hdr);
	hdr->msg_type = RNDIS_MSG_PACKET;
	hdr->msg_len = cpu_to_le32(pktlen + sizeof *hdr);
	hdr->data_offset = cpu_to_le32(sizeof(*hdr) - 8);
	hdr->data_len = cpu_to_le32(pktlen);
	mbuf_copydata(packet, 0, pktlen, hdr + 1);
	
	freePacket(packet);
	
	/* Now, fire it off! */
	outbufs[poolIndx].comp.target    = this;
	outbufs[poolIndx].comp.parameter = (void *)poolIndx;
	outbufs[poolIndx].comp.action    = dataWriteComplete;
	
	ior = fOutPipe->Write(outbufs[poolIndx].mdp, &outbufs[poolIndx].comp);
	if (ior != kIOReturnSuccess) {
		LOG(V_ERROR, "write failed");
		if (ior == kIOUSBPipeStalled) {
			fOutPipe->Reset();
			ior = fOutPipe->Write(outbufs[poolIndx].mdp, &outbufs[poolIndx].comp);
			if (ior != kIOReturnSuccess) {
				LOG(V_ERROR, "write really failed");
				fpNetStats->outputErrors++;
				return ior;
			}
		}
	}
	fpNetStats->outputPackets++;
	
	return kIOReturnOutputSuccess;
}
Exemplo n.º 26
0
UInt32 darwin_iwi3945::outputPacket(mbuf_t m, void * param)
{
	//IOLog("outputPacket\n");
	if((fNetif->getFlags() & IFF_RUNNING)!=0 || m==NULL)
	{
		if (m)
		if (!(mbuf_type(m) == MBUF_TYPE_FREE) ) freePacket(m);
		m=NULL;
		netStats->outputErrors++;
		return kIOReturnOutputDropped;
	}
	
	
	mbuf_t nm;
	int ret = kIOReturnOutputDropped;

	//checking supported packet
	
	IWI_DEBUG("outputPacket t: %d f:%04x\n",mbuf_type(m),mbuf_flags(m));
	
	//drop mbuf is not PKTHDR
	if (!(mbuf_flags(m) & MBUF_PKTHDR) ){
		IWI_ERR("BUG: dont support mbuf without pkthdr and dropped \n");
		netStats->outputErrors++;
		goto finish;
	}
	
	if(mbuf_type(m) == MBUF_TYPE_FREE){
		IWI_ERR("BUG: this is freed packet and dropped \n");
		netStats->outputErrors++;
		goto finish;
	}
	
	nm = mergePacket(m);
	
	if (nm==NULL) 
	{
		netStats->outputErrors++;
		goto finish;
	}
	
	if(mbuf_next(nm)){
		IWI_ERR("BUG: dont support chains mbuf\n");
		IWI_ERR("BUG: tx packet is not single mbuf mbuf_len(%d) mbuf_pkthdr_len(%d)\n",mbuf_len(nm) , mbuf_pkthdr_len(nm) );
		IWI_ERR("BUG: next mbuf size %d\n",mbuf_len(mbuf_next(nm)));
	}
	
	IWI_DEBUG_FULL("call ieee80211_xmit - not done yet\n");
	//ret  = ieee80211_xmit(nm,priv->net_dev);
	//struct ieee80211_tx_control ctrl;
	//ret=ipw_tx_skb(priv, nm, &ctrl);

finish:	
	
	/* free finished packet */
	//freePacket(m);
	//m=NULL;
	if (ret ==  kIOReturnOutputDropped) { 
		//if (nm)
		//if (!(mbuf_type(nm) == MBUF_TYPE_FREE) ) freePacket(nm);
		//nm=NULL;
	}
	return ret;	
}
Exemplo n.º 27
0
mbuf_t darwin_iwi3945::mergePacket(mbuf_t m)
{
	mbuf_t nm,nm2;
	int offset;
	if(!mbuf_next(m))
	{
		offset = (4 - ((int)(mbuf_data(m)) & 3)) % 4;    //packet needs to be 4 byte aligned
		if (offset==0) return m;
		IWI_DEBUG_FULL("this packet dont have mbuf_next, merge  is not required\n");
		goto copy_packet;
	}

	/* allocate and Initialize New mbuf */
	nm = allocatePacket(mbuf_pkthdr_len(m));
	if (nm==0) return NULL;
	//if (mbuf_getpacket(MBUF_WAITOK, &nm)!=0) return NULL;
	mbuf_setlen(nm,0);
	mbuf_pkthdr_setlen(nm,0);
	if( mbuf_next(nm)) IWI_ERR("merged mbuf_next\n");
	
	/* merging chains to single mbuf */
	for (nm2 = m; nm2;  nm2 = mbuf_next(nm2)) {
		memcpy (skb_put (nm, mbuf_len(nm2)), (UInt8*)mbuf_data(nm2), mbuf_len(nm2));
	}

	/* checking if merged or not. */
	if( mbuf_len(nm) == mbuf_pkthdr_len(m) ) 
	{
		if (m!=NULL)
		if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m);
		m=NULL;
		return nm;
	}
	/* merging is not completed. */
	IWI_LOG("mergePacket is failed: data copy dont work collectly\n");
	//IWI_LOG("orig_len %d orig_pktlen %d new_len  %d new_pktlen  %d\n",
	//				mbuf_len(m),mbuf_pkthdr_len(m),
	//				mbuf_len(nm),mbuf_pkthdr_len(nm) );
	if (m!=NULL)
	if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m);
	m=NULL;
	if (nm!=NULL)
	if (!(mbuf_type(nm) == MBUF_TYPE_FREE) ) freePacket(nm);
	nm=NULL;
	return NULL;

copy_packet: 
		if (mbuf_dup(m, MBUF_WAITOK , &nm)!=0)
		{
			if (m!=NULL)
			if (!(mbuf_type(m) == MBUF_TYPE_FREE)) freePacket(m);
			m=NULL;
			return NULL;
		}
		if (m!=NULL)
		if (!(mbuf_type(m) == MBUF_TYPE_FREE) ) freePacket(m);
		m=NULL;
		return nm;
		//return copyPacket(m, 0); 

}
Exemplo n.º 28
0
//callback for incoming data
// only interested in DNS responses for IP:URL mappings
// code inspired by: https://github.com/williamluke/peerguardian-linux/blob/master/pgosx/kern/ppfilter.c
static errno_t data_in(void *cookie, socket_t so, const struct sockaddr *from, mbuf_t *data, mbuf_t *control, sflt_data_flag_t flags)
{
    //dbg msg
    IOLog("LULU: in %s\n", __FUNCTION__);
    
    //port
    in_port_t port = 0;
    
    //peer name
    struct sockaddr_in6 peerName = {0};
    
    //mem buffer
    mbuf_t memBuffer = NULL;
    
    //response size
    size_t responseSize = 0;
    
    //dns header
    dnsHeader* dnsHeader = NULL;
    
    //firewall event
    firewallEvent event = {0};
    
    //destination socket ('from') might be null?
    // if so, grab it via 'getpeername' from the socket
    if(NULL == from)
    {
        //lookup remote socket info
        if(0 != sock_getpeername(so, (struct sockaddr*)&peerName, sizeof(peerName)))
        {
            //err msg
            IOLog("LULU ERROR: sock_getpeername() failed\n");
            
            //bail
            goto bail;
        }
        
        //now, assign
        from = (const struct sockaddr*)&peerName;
    }

    //get port
    switch(from->sa_family)
    {
        //IPv4
        case AF_INET:
            port = ntohs(((const struct sockaddr_in*)from)->sin_port);
            break;
            
        //IPv6
        case AF_INET6:
            port = ntohs(((const struct sockaddr_in6*)from)->sin6_port);
            break;
            
        default:
            break;
    }
    
    //ignore non-DNS
    if(53 != port)
    {
        //bail
        goto bail;
    }
    
    //init memory buffer
    memBuffer = *data;
    if(NULL == memBuffer)
    {
        //bail
        goto bail;
    }
    
    //get memory buffer
    while(MBUF_TYPE_DATA != mbuf_type(memBuffer))
    {
        //get next
        memBuffer = mbuf_next(memBuffer);
        if(NULL == memBuffer)
        {
            //bail
            goto bail;
        }
    }
    
    //sanity check length
    if(mbuf_len(memBuffer) <= sizeof(struct dnsHeader))
    {
        //bail
        goto bail;
    }
    
    //get data
    // should be a DNS header
    dnsHeader = (struct dnsHeader*)mbuf_data(memBuffer);
    
    //ignore everything that isn't a DNS response
    // top bit flag will be 0x1, for "a name service response"
    if(0 == ((ntohs(dnsHeader->flags)) & (1<<(15))))
    {
        //bail
        goto bail;
    }
    
    //ignore any errors
    // bottom (4) bits will be 0x0 for "successful response"
    if(0 != ((ntohs(dnsHeader->flags)) & (1<<(0))))
    {
        //bail
        goto bail;
    }
    
    //ignore any packets that don't have answers
    if(0 == ntohs(dnsHeader->ancount))
    {
        //bail
        goto bail;
    }
    
    //zero out event struct
    bzero(&event, sizeof(firewallEvent));
    
    //set type
    event.dnsResponseEvent.type = EVENT_DNS_RESPONSE;
    
    //set size
    // max, 512
    responseSize = MIN(sizeof(event.dnsResponseEvent.response), mbuf_len(memBuffer));
    
    //copy response
    memcpy(event.dnsResponseEvent.response, mbuf_data(memBuffer), responseSize);
    
    //queue it up
    sharedDataQueue->enqueue_tail(&event, sizeof(firewallEvent));
    
bail:
    
    return kIOReturnSuccess;
}
Exemplo n.º 29
0
Arquivo: krpc_subr.c Projeto: argp/xnu
/*
 * Do a remote procedure call (RPC) and wait for its reply.
 * If from_p is non-null, then we are doing broadcast, and
 * the address from whence the response came is saved there.
 */
int
krpc_call(
	struct sockaddr_in *sa,
	u_int sotype, u_int prog, u_int vers, u_int func,
	mbuf_t *data,			/* input/output */
	struct sockaddr_in *from_p)	/* output */
{
	socket_t so;
	struct sockaddr_in *sin;
	mbuf_t m, nam, mhead;
	struct rpc_call *call;
	struct rpc_reply *reply;
	int error, timo, secs;
	size_t len;
	static u_int32_t xid = ~0xFF;
	u_int16_t tport;
	size_t maxpacket = 1<<16;

	/*
	 * Validate address family.
	 * Sorry, this is INET specific...
	 */
	if (sa->sin_family != AF_INET)
		return (EAFNOSUPPORT);

	/* Free at end if not null. */
	nam = mhead = NULL;

	/*
	 * Create socket and set its recieve timeout.
	 */
	if ((error = sock_socket(AF_INET, sotype, 0, 0, 0, &so)))
		goto out1;

	{
		struct timeval tv;

		tv.tv_sec = 1;
		tv.tv_usec = 0;

		if ((error = sock_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))))
		    goto out;

	}

	/*
	 * Enable broadcast if necessary.
	 */

	if (from_p && (sotype == SOCK_DGRAM)) {
		int on = 1;
		if ((error = sock_setsockopt(so, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))))
			goto out;
	}

	/*
	 * Bind the local endpoint to a reserved port,
	 * because some NFS servers refuse requests from
	 * non-reserved (non-privileged) ports.
	 */
	if ((error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &m)))
		goto out;
	sin = mbuf_data(m);
	bzero(sin, sizeof(*sin));
	mbuf_setlen(m, sizeof(*sin));
	sin->sin_len = sizeof(*sin);
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = INADDR_ANY;
	tport = IPPORT_RESERVED;
	do {
		tport--;
		sin->sin_port = htons(tport);
		error = sock_bind(so, (struct sockaddr*)sin);
	} while (error == EADDRINUSE &&
			 tport > IPPORT_RESERVED / 2);
	mbuf_freem(m);
	m = NULL;
	if (error) {
		printf("bind failed\n");
		goto out;
	}

	/*
	 * Setup socket address for the server.
	 */
	if ((error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &nam)))
		goto out;
	sin = mbuf_data(nam);
	mbuf_setlen(nam, sa->sin_len);
	bcopy((caddr_t)sa, (caddr_t)sin, sa->sin_len);

	if (sotype == SOCK_STREAM) {
		struct timeval tv;
		tv.tv_sec = 60;
		tv.tv_usec = 0;
		error = sock_connect(so, mbuf_data(nam), MSG_DONTWAIT);
		if (error && (error != EINPROGRESS))
			goto out;
		error = sock_connectwait(so, &tv);
		if (error) {
			if (error == EINPROGRESS)
				error = ETIMEDOUT;
			printf("krpc_call: error waiting for TCP socket connect: %d\n", error);
			goto out;
		}
	}

	/*
	 * Prepend RPC message header.
	 */
	m = *data;
	*data = NULL;
#if	DIAGNOSTIC
	if ((mbuf_flags(m) & MBUF_PKTHDR) == 0)
		panic("krpc_call: send data w/o pkthdr");
	if (mbuf_pkthdr_len(m) < mbuf_len(m))
		panic("krpc_call: pkthdr.len not set");
#endif
	len = sizeof(*call);
	if (sotype == SOCK_STREAM)
		len += 4;  /* account for RPC record marker */
	mhead = m;
	if ((error = mbuf_prepend(&mhead, len, MBUF_WAITOK)))
		goto out;
	if ((error = mbuf_pkthdr_setrcvif(mhead, NULL)))
		goto out;

	/*
	 * Fill in the RPC header
	 */
	if (sotype == SOCK_STREAM) {
		/* first, fill in RPC record marker */
		u_int32_t *recmark = mbuf_data(mhead);
		*recmark = htonl(0x80000000 | (mbuf_pkthdr_len(mhead) - 4));
		call = (struct rpc_call *)(recmark + 1);
	} else {
		call = mbuf_data(mhead);
	}
	bzero((caddr_t)call, sizeof(*call));
	xid++;
	call->rp_xid = htonl(xid);
	/* call->rp_direction = 0; */
	call->rp_rpcvers = htonl(2);
	call->rp_prog = htonl(prog);
	call->rp_vers = htonl(vers);
	call->rp_proc = htonl(func);
	/* call->rp_auth = 0; */
	/* call->rp_verf = 0; */

	/*
	 * Send it, repeatedly, until a reply is received,
	 * but delay each re-send by an increasing amount.
	 * If the delay hits the maximum, start complaining.
	 */
	timo = 0;
	for (;;) {
		struct msghdr msg;
		
		/* Send RPC request (or re-send). */
		if ((error = mbuf_copym(mhead, 0, MBUF_COPYALL, MBUF_WAITOK, &m)))
			goto out;
		bzero(&msg, sizeof(msg));
		if (sotype == SOCK_STREAM) {
			msg.msg_name = NULL;
			msg.msg_namelen = 0;
		} else {
			msg.msg_name = mbuf_data(nam);
			msg.msg_namelen = mbuf_len(nam);
		}
		error = sock_sendmbuf(so, &msg, m, 0, 0);
		if (error) {
			printf("krpc_call: sosend: %d\n", error);
			goto out;
		}
		m = NULL;

		/* Determine new timeout. */
		if (timo < MAX_RESEND_DELAY)
			timo++;
            	else
           		printf("RPC timeout for server " IP_FORMAT "\n",
				IP_LIST(&(sin->sin_addr.s_addr)));

		/*
		 * Wait for up to timo seconds for a reply.
		 * The socket receive timeout was set to 1 second.
		 */
		secs = timo;
		while (secs > 0) {
			size_t readlen;
			
			if (m) {
				mbuf_freem(m);
				m = NULL;
			}
			if (sotype == SOCK_STREAM) {
				int maxretries = 60;
				struct iovec aio;
				aio.iov_base = &len;
				aio.iov_len = sizeof(u_int32_t);
				bzero(&msg, sizeof(msg));
				msg.msg_iov = &aio;
				msg.msg_iovlen = 1;
				do {
				   error = sock_receive(so, &msg, MSG_WAITALL, &readlen);
				   if ((error == EWOULDBLOCK) && (--maxretries <= 0))
					error = ETIMEDOUT;
				} while (error == EWOULDBLOCK);
				if (!error && readlen < aio.iov_len) {
				    /* only log a message if we got a partial word */
				    if (readlen != 0)
					    printf("short receive (%ld/%ld) from server " IP_FORMAT "\n",
						 readlen, sizeof(u_int32_t), IP_LIST(&(sin->sin_addr.s_addr)));
				    error = EPIPE;
				}
				if (error)
					goto out;
				len = ntohl(len) & ~0x80000000;
				/*
				 * This is SERIOUS! We are out of sync with the sender
				 * and forcing a disconnect/reconnect is all I can do.
				 */
				if (len > maxpacket) {
				    printf("impossible packet length (%ld) from server " IP_FORMAT "\n",
					len, IP_LIST(&(sin->sin_addr.s_addr)));
				    error = EFBIG;
				    goto out;
				}
				
				do {
				    readlen = len;
				    error = sock_receivembuf(so, NULL, &m, MSG_WAITALL, &readlen);
				} while (error == EWOULDBLOCK);

				if (!error && (len > readlen)) {
				    printf("short receive (%ld/%ld) from server " IP_FORMAT "\n",
					readlen, len, IP_LIST(&(sin->sin_addr.s_addr)));
				    error = EPIPE;
				}
			} else {
				len = maxpacket;
				readlen = len;
				bzero(&msg, sizeof(msg));
				msg.msg_name = from_p;
				msg.msg_namelen = (from_p == NULL) ? 0 : sizeof(*from_p);
				error = sock_receivembuf(so, &msg, &m, 0, &readlen);
			}

			if (error == EWOULDBLOCK) {
				secs--;
				continue;
			}
			if (error)
				goto out;
			len = readlen;

			/* Does the reply contain at least a header? */
			if (len < MIN_REPLY_HDR)
				continue;
			if (mbuf_len(m) < MIN_REPLY_HDR)
				continue;
			reply = mbuf_data(m);

			/* Is it the right reply? */
			if (reply->rp_direction != htonl(RPC_REPLY))
				continue;

			if (reply->rp_xid != htonl(xid))
				continue;
			
			/* Was RPC accepted? (authorization OK) */
			if (reply->rp_astatus != 0) {
				error = ntohl(reply->rp_u.rpu_errno);
				printf("rpc denied, error=%d\n", error);
				/* convert rpc error to errno */
				switch (error) {
				case RPC_MISMATCH:
					error = ERPCMISMATCH;
					break;
				case RPC_AUTHERR:
					error = EAUTH;
					break;
				}
				goto out;
			}


			if (mbuf_len(m) < REPLY_SIZE) {
				error = RPC_SYSTEM_ERR;
			}
			else {
				error = ntohl(reply->rp_u.rpu_ok.rp_rstatus);
			}

			/* Did the call succeed? */
			if (error != 0) {
				printf("rpc status=%d\n", error);
				/* convert rpc error to errno */
				switch (error) {
				case RPC_PROGUNAVAIL:
					error = EPROGUNAVAIL;
					break;
				case RPC_PROGMISMATCH:
					error = EPROGMISMATCH;
					break;
				case RPC_PROCUNAVAIL:
					error = EPROCUNAVAIL;
					break;
				case RPC_GARBAGE:
					error = EINVAL;
					break;
				case RPC_SYSTEM_ERR:
					error = EIO;
					break;
				}
				goto out;
			}

			goto gotreply;	/* break two levels */

		} /* while secs */
	} /* forever send/receive */

	error = ETIMEDOUT;
	goto out;

 gotreply:

	/*
	 * Pull as much as we can into first mbuf, to make
	 * result buffer contiguous.  Note that if the entire
	 * result won't fit into one mbuf, you're out of luck.
	 * XXX - Should not rely on making the entire reply
	 * contiguous (fix callers instead). -gwr
	 */
#if	DIAGNOSTIC
	if ((mbuf_flags(m) & MBUF_PKTHDR) == 0)
		panic("krpc_call: received pkt w/o header?");
#endif
	len = mbuf_pkthdr_len(m);
	if (sotype == SOCK_STREAM)
		len -= 4;  /* the RPC record marker was read separately */
	if (mbuf_len(m) < len) {
		if ((error = mbuf_pullup(&m, len)))
			goto out;
		reply = mbuf_data(m);
	}

	/*
	 * Strip RPC header
	 */
	len = sizeof(*reply);
	if (reply->rp_u.rpu_ok.rp_auth.rp_atype != 0) {
		len += ntohl(reply->rp_u.rpu_ok.rp_auth.rp_alen);
		len = (len + 3) & ~3; /* XXX? */
	}
	mbuf_adj(m, len);

	/* result */
	*data = m;
 out:
	sock_close(so);
out1:
	if (nam) mbuf_freem(nam);
	if (mhead) mbuf_freem(mhead);
	return error;
}
Exemplo n.º 30
0
// data in is currently used for PASV FTP support
static
errno_t	ppfilter_data_in (__unused void *cookie, socket_t so, const struct sockaddr *from,
                          mbuf_t *data, __unused mbuf_t *control, __unused sflt_data_flag_t flags)
{
    in_addr_t ip4;
    in_port_t port;

    if (!from) {
        struct sockaddr_in6 local;
        if (0 != sock_getpeername(so, (struct sockaddr*)&local, sizeof(local)))
            bzero(&local, sizeof(local));
        from = (const struct sockaddr*)&local;
    }

    if (AF_INET == from->sa_family) {
        port = ntohs(((const struct sockaddr_in*)from)->sin_port);
    } else if (AF_INET6 == from->sa_family) {
        const struct sockaddr_in6* addr6 = (const struct sockaddr_in6*)from;
        if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) || !IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr))
            return (0); // tables do not contain native ip6 addreses
        port = ntohs(addr6->sin6_port);
    } else
        return (0);

    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // Short-circuit optimization for ftp filter -- if any other filters are ever added,
    // this will have to be removed.
    if (21 != port)
        return (0);
    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    mbuf_t mdata = *data;
    while (mdata && MBUF_TYPE_DATA != mbuf_type(mdata)) {
        mdata = mbuf_next(mdata);
    }
    if (!mdata)
        return (0);

    char *pkt = mbuf_data(mdata);
    if (!pkt)
        return (0);
    size_t len = mbuf_len(mdata);

    ip4 = INADDR_NONE;
    int block, i;
    pp_data_filter_t filt = pp_data_filters[0];
    for (i = 1; filt; ++i) {
        block = filt(pkt, len, &ip4, &port);
        if (INADDR_NONE != ip4) {
            // add to dynamic list
            pp_dynentries_lock();
            pp_dyn_entry_t e = pp_dyn_entry_get();
            if (e) {
                e->addr = ip4;
                e->port = port;
                e->block = block;
            }
            pp_dynentries_unlock();
            break;
        }
        filt = pp_data_filters[i];
    }

    return (0);
}