-}
-
-/*
- * Ethernet output routine.
- * Encapsulate a packet of type family for the local net.
- * Use trailer local net encapsulation if enough data in first
- * packet leaves a multiple of 512 bytes of data in remainder.
- */
-iloutput(ifp, m0, dst)
- struct ifnet *ifp;
- struct mbuf *m0;
- struct sockaddr *dst;
-{
- int type, s, error;
- u_char edst[6];
- struct in_addr idst;
- register struct il_softc *is = &il_softc[ifp->if_unit];
- register struct mbuf *m = m0;
- register struct ether_header *il;
- register int off;
-
- switch (dst->sa_family) {
-
-#ifdef INET
- case AF_INET:
- idst = ((struct sockaddr_in *)dst)->sin_addr;
- if (!arpresolve(&is->is_ac, m, &idst, edst))
- return (0); /* if not yet resolved */
- off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
- if (off > 0 && (off & 0x1ff) == 0 &&
- m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
- type = ETHERPUP_TRAIL + (off>>9);
- m->m_off -= 2 * sizeof (u_short);
- m->m_len += 2 * sizeof (u_short);
- *mtod(m, u_short *) = htons((u_short)ETHERPUP_IPTYPE);
- *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
- goto gottrailertype;
- }
- type = ETHERPUP_IPTYPE;
- off = 0;
- goto gottype;
-#endif
-
- case AF_UNSPEC:
- il = (struct ether_header *)dst->sa_data;
- bcopy((caddr_t)il->ether_dhost, (caddr_t)edst, sizeof (edst));
- type = il->ether_type;
- goto gottype;
-
- default:
- printf("il%d: can't handle af%d\n", ifp->if_unit,
- dst->sa_family);
- error = EAFNOSUPPORT;
- goto bad;
- }
-
-gottrailertype:
- /*
- * Packet to be sent as trailer: move first packet
- * (control information) to end of chain.
- */
- while (m->m_next)
- m = m->m_next;
- m->m_next = m0;
- m = m0->m_next;
- m0->m_next = 0;
- m0 = m;
-
-gottype:
- /*
- * Add local net header. If no space in first mbuf,
- * allocate another.
- */
- if (m->m_off > MMAXOFF ||
- MMINOFF + sizeof (struct ether_header) > m->m_off) {
- m = m_get(M_DONTWAIT, MT_HEADER);
- if (m == 0) {
- error = ENOBUFS;
- goto bad;
- }
- m->m_next = m0;
- m->m_off = MMINOFF;
- m->m_len = sizeof (struct ether_header);
- } else {
- m->m_off -= sizeof (struct ether_header);
- m->m_len += sizeof (struct ether_header);
- }
- il = mtod(m, struct ether_header *);
- il->ether_type = htons((u_short)type);
- bcopy((caddr_t)edst, (caddr_t)il->ether_dhost, sizeof (edst));
- bcopy((caddr_t)is->is_addr, (caddr_t)il->ether_shost, 6);
-
- /*
- * Queue message on interface, and start output if interface
- * not yet active.
- */
- s = splimp();
- if (IF_QFULL(&ifp->if_snd)) {
- IF_DROP(&ifp->if_snd);
- splx(s);
- m_freem(m);
- return (ENOBUFS);
- }
- IF_ENQUEUE(&ifp->if_snd, m);
- if ((is->is_flags & ILF_OACTIVE) == 0)
- ilstart(ifp->if_unit);