Exemplo n.º 1
0
/*
 * ARCnet output routine.
 * Encapsulate a packet of type family for the local net.
 * Assumes that ifp is actually pointer to arccom structure.
 */
int
arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
    struct route *ro)
{
	struct arc_header	*ah;
	int			error;
	u_int8_t		atype, adst;
	int			loop_copy = 0;
	int			isphds;
#if defined(INET) || defined(INET6)
	struct llentry		*lle;
#endif

	if (!((ifp->if_flags & IFF_UP) &&
	    (ifp->if_drv_flags & IFF_DRV_RUNNING)))
		return(ENETDOWN); /* m, m1 aren't initialized yet */

	error = 0;

	switch (dst->sa_family) {
#ifdef INET
	case AF_INET:

		/*
		 * For now, use the simple IP addr -> ARCnet addr mapping
		 */
		if (m->m_flags & (M_BCAST|M_MCAST))
			adst = arcbroadcastaddr; /* ARCnet broadcast address */
		else if (ifp->if_flags & IFF_NOARP)
			adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
		else {
			error = arpresolve(ifp, ro ? ro->ro_rt : NULL,
			                   m, dst, &adst, &lle);
			if (error)
				return (error == EWOULDBLOCK ? 0 : error);
		}

		atype = (ifp->if_flags & IFF_LINK0) ?
			ARCTYPE_IP_OLD : ARCTYPE_IP;
		break;
	case AF_ARP:
	{
		struct arphdr *ah;
		ah = mtod(m, struct arphdr *);
		ah->ar_hrd = htons(ARPHRD_ARCNET);

		loop_copy = -1; /* if this is for us, don't do it */

		switch(ntohs(ah->ar_op)) {
		case ARPOP_REVREQUEST:
		case ARPOP_REVREPLY:
			atype = ARCTYPE_REVARP;
			break;
		case ARPOP_REQUEST:
		case ARPOP_REPLY:
		default:
			atype = ARCTYPE_ARP;
			break;
		}

		if (m->m_flags & M_BCAST)
			bcopy(ifp->if_broadcastaddr, &adst, ARC_ADDR_LEN);
		else
			bcopy(ar_tha(ah), &adst, ARC_ADDR_LEN);
        
	}
	break;
#endif
#ifdef INET6
	case AF_INET6:
		error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, &lle);
		if (error)
			return (error);
		atype = ARCTYPE_INET6;
		break;
#endif
#ifdef IPX
	case AF_IPX:
		adst = SIPX(dst)->sipx_addr.x_host.c_host[5];
		atype = ARCTYPE_IPX;
		if (adst == 0xff)
			adst = arcbroadcastaddr;
		break;
#endif

	case AF_UNSPEC:
		loop_copy = -1;
		ah = (struct arc_header *)dst->sa_data;
		adst = ah->arc_dhost;
		atype = ah->arc_type;

		if (atype == ARCTYPE_ARP) {
			atype = (ifp->if_flags & IFF_LINK0) ?
			    ARCTYPE_ARP_OLD: ARCTYPE_ARP;

#ifdef ARCNET_ALLOW_BROKEN_ARP
			/*
			 * XXX It's not clear per RFC826 if this is needed, but
			 * "assigned numbers" say this is wrong.
			 * However, e.g., AmiTCP 3.0Beta used it... we make this
			 * switchable for emergency cases. Not perfect, but...
			 */
			if (ifp->if_flags & IFF_LINK2)
				mtod(m, struct arphdr *)->ar_pro = atype - 1;
#endif
		}
		break;

	default:
		if_printf(ifp, "can't handle af%d\n", dst->sa_family);
		senderr(EAFNOSUPPORT);
	}

	isphds = arc_isphds(atype);
	M_PREPEND(m, isphds ? ARC_HDRNEWLEN : ARC_HDRLEN, M_DONTWAIT);
	if (m == 0)
		senderr(ENOBUFS);
	ah = mtod(m, struct arc_header *);
	ah->arc_type = atype;
	ah->arc_dhost = adst;
	ah->arc_shost = ARC_LLADDR(ifp);
	if (isphds) {
		ah->arc_flag = 0;
		ah->arc_seqid = 0;
	}

	if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) {
		if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
			struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);

			(void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN);
		} else if (ah->arc_dhost == ah->arc_shost) {
			(void) if_simloop(ifp, m, dst->sa_family, ARC_HDRLEN);
			return (0);     /* XXX */
		}
	}

	BPF_MTAP(ifp, m);

	error = ifp->if_transmit(ifp, m);

	return (error);

bad:
	if (m)
		m_freem(m);
	return (error);
}
Exemplo n.º 2
0
    printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr));

    if (ifa->ifa_flags & IFF_POINTOPOINT) {
        sipx = (struct sockaddr_ipx *)ifa->ifa_dstaddr;
        if (sipx == NULL) {
            memset(&null_sipx, 0, sizeof(null_sipx));
            sipx = &null_sipx;
        }
        printf("--> %s ", ipx_ntoa(sipx->sipx_addr));
    }
    putchar('\n');
}

#define SIPX(x) ((struct sockaddr_ipx *) &(x))
struct sockaddr_ipx *sipxtab[] = {
    SIPX(ipx_ridreq.ifr_addr), SIPX(ipx_addreq.ifra_addr),
    SIPX(ipx_addreq.ifra_mask), SIPX(ipx_addreq.ifra_broadaddr)
};

static void
ipx_getaddr(const char *addr, int which)
{
    struct sockaddr_ipx *sipx = sipxtab[which];

    sipx->sipx_family = AF_IPX;
    sipx->sipx_len = sizeof(*sipx);
    sipx->sipx_addr = ipx_addr(addr);
    if (which == MASK)
        printf("Attempt to set IPX netmask will be ineffectual\n");
}