errno_t
ether_check_multi(
	__unused ifnet_t		ifp,
	const struct sockaddr	*proto_addr)
{
	errno_t	result = EAFNOSUPPORT;
	const u_char *e_addr;
	
	/*
	 * AF_SPEC and AF_LINK don't require translation. We do
	 * want to verify that they specify a valid multicast.
	 */
	switch(proto_addr->sa_family) {
		case AF_UNSPEC:
			e_addr = (const u_char*)&proto_addr->sa_data[0];
			if ((e_addr[0] & 0x01) != 0x01)
				result = EADDRNOTAVAIL;
			else
				result = 0;
			break;
		
		case AF_LINK:
			e_addr = CONST_LLADDR((const struct sockaddr_dl*)proto_addr); 
			if ((e_addr[0] & 0x01) != 0x01)
				result = EADDRNOTAVAIL;
			else
				result = 0;
			break;
	}
	
	return result;
}
Exemple #2
0
errno_t
firewire_inet_arp(
    ifnet_t								ifp,
    u_short								arpop,
    const struct sockaddr_dl*			sender_hw,
    const struct sockaddr*				sender_proto,
    const struct sockaddr_dl*			target_hw,
    const struct sockaddr*				target_proto)
{
    mbuf_t	m;
    errno_t	result;
    register struct firewire_header *fwh;
    register IP1394_ARP *fwa;
    const struct sockaddr_in* sender_ip = (const struct sockaddr_in*)sender_proto;
    const struct sockaddr_in* target_ip = (const struct sockaddr_in*)target_proto;
    char *datap;

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

    if(fwIf == NULL)
        return EINVAL;

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

    if(fwIpObj == NULL)
        return EINVAL;

    LCB	*lcb = fwIpObj->getLcb();

    if (target_ip == NULL)
        return EINVAL;

    if ((sender_ip && sender_ip->sin_family != AF_INET) ||
            (target_ip && target_ip->sin_family != AF_INET))
        return EAFNOSUPPORT;

    result = mbuf_gethdr(MBUF_DONTWAIT, MBUF_TYPE_DATA, &m);
    if (result != 0)
        return result;

    mbuf_setlen(m, sizeof(*fwa));
    mbuf_pkthdr_setlen(m, sizeof(*fwa));

    /* Move the data pointer in the mbuf to the end, aligned to 4 bytes */
    datap = (char*)mbuf_datastart(m);
    datap += mbuf_trailingspace(m);
    datap -= (((u_long)datap) & 0x3);
    mbuf_setdata(m, datap, sizeof(*fwa));
    fwa = (IP1394_ARP*)mbuf_data(m);
    bzero((caddr_t)fwa, sizeof(*fwa));

    /* Prepend the ethernet header, we will send the raw frame */
    result = mbuf_prepend(&m, sizeof(*fwh), MBUF_DONTWAIT);
    if(result != 0)
        return result;

    fwh = (struct firewire_header*)mbuf_data(m);
    fwh->fw_type = htons(FWTYPE_ARP);

    /* Fill out the arp packet */
    fwa->hardwareType = htons(ARP_HDW_TYPE);
    fwa->protocolType = htons(FWTYPE_IP);
    fwa->hwAddrLen = sizeof(IP1394_HDW_ADDR);
    fwa->ipAddrLen = IPV4_ADDR_SIZE;
    fwa->opcode = htons(arpop);
    fwa->senderMaxRec = lcb->ownHardwareAddress.maxRec;
    fwa->sspd = lcb->ownHardwareAddress.spd;
    fwa->senderUnicastFifoHi = htons(lcb->ownHardwareAddress.unicastFifoHi);
    fwa->senderUnicastFifoLo = htonl(lcb->ownHardwareAddress.unicastFifoLo);

    /* Sender Hardware */
    if (sender_hw != NULL)
        bcopy(CONST_LLADDR(sender_hw), &fwa->senderUniqueID, sizeof(fwa->senderUniqueID));
    else
        ifnet_lladdr_copy_bytes(ifp, &fwa->senderUniqueID, FIREWIRE_ADDR_LEN);

    ifnet_lladdr_copy_bytes(ifp, fwh->fw_shost, sizeof(fwh->fw_shost));

    /* Sender IP */
    if (sender_ip != NULL)
        fwa->senderIpAddress = sender_ip->sin_addr.s_addr;
    else
    {
        ifaddr_t	*addresses;
        struct sockaddr sa;

        if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0)
        {
            ifaddr_address( addresses[0], &sa, 16 );
            fwa->senderIpAddress  = ((UInt32)(sa.sa_data[5] & 0xFF)) << 24;
            fwa->senderIpAddress |= ((UInt32)(sa.sa_data[4] & 0xFF)) << 16;
            fwa->senderIpAddress |= ((UInt32)(sa.sa_data[3] & 0xFF)) << 8;
            fwa->senderIpAddress |= ((UInt32)(sa.sa_data[2] & 0xFF));

            ifnet_free_address_list(addresses);
        }
        else
        {
            mbuf_free(m);
            return ENXIO;
        }
    }

    /* Target Hardware */
    if (target_hw == 0)
        bcopy(fwbroadcastaddr, fwh->fw_dhost, sizeof(fwh->fw_dhost));
    else
        bcopy(CONST_LLADDR(target_hw), fwh->fw_dhost, sizeof(fwh->fw_dhost));

    /* Target IP */
    fwa->targetIpAddress = target_ip->sin_addr.s_addr;

    ifnet_output_raw(ifp, PF_INET, m);

    return 0;
}