-/* if_imp.c 4.1 82/02/01 */
+/* if_imp.c 4.3 82/02/01 */
#include "imp.h"
#if NIMP > 0
}
struct sockproto impproto = { PF_IMPLINK };
-struct sockaddr_in impaddr = { AF_IMPLINK };
+struct sockaddr_in impdst = { AF_IMPLINK };
+struct sockaddr_in impsrc = { AF_IMPLINK };
/*
* ARPAnet 1822 input routine.
COUNT(IMP_INPUT);
m = m0;
+
+ /*
+ * We should generate a "bad leader" message
+ * to the IMP about messages too short.
+ */
if (m->m_len < sizeof(struct imp_leader) &&
m_pullup(m, sizeof(struct imp_leader)) == 0)
goto drop;
ip = mtod(m, struct imp_leader *);
- /* check leader type. */
+ /*
+ * Check leader type -- should notify IMP
+ * in case of failure...
+ */
if (ip->il_format != IMP_NFF)
goto drop;
case IMPTYPE_HOSTDEAD:
case IMPTYPE_HOSTUNREACH:
case IMPTYPE_BADDATA:
- addr.s_host = ntohs(ip->il_host);
+ addr.s_host = ntohs(ip->il_host); /* XXX */
hp = h_lookup(addr);
break;
}
* Data for a protocol. Dispatch to the appropriate
* protocol routine (running at software interrupt).
* If this isn't a raw interface, advance pointer
- * into mbuf past leader.
+ * into mbuf past leader (done below).
*/
case IMPTYPE_DATA:
ip->il_length = ntohs(ip->il_length) >> 3;
* IMP leader error. Reset the IMP and discard the packet.
*/
case IMPTYPE_BADLEADER:
- imperr(sc, "leader error");
- h_reset(sc->imp_if.if_net); /* XXX */
- impnoops(sc);
+ /*
+ * According to 1822 document, this message
+ * will be generated in response to the
+ * first noop sent to the IMP after
+ * the host resets the IMP interface.
+ */
+ if (sc->imp_state != IMPS_RESET) {
+ imperr(sc, "leader error");
+ h_reset(sc->imp_if.if_net); /* XXX */
+ impnoops(sc);
+ }
goto drop;
/*
case IMPTYPE_DOWN:
if ((ip->il_link & IMP_DMASK) == 0) {
sc->imp_state = IMPS_GOINGDOWN;
- sc->imp_timer = IMPTV_DOWN;
+ timeout(impdown, sc, 30 * 60 * HZ);
}
imperr(sc, "going down %s", impmsg[ip->il_link & IMP_DMASK]);
goto drop;
* Reset the local address notion if it doesn't match.
*/
case IMPTYPE_NOOP:
+ if (sc->imp_state == IMPS_DOWN) {
+ sc->imp_state = IMPS_INIT;
+ sc->imp_dropcnt = IMP_DROPCNT;
+ }
if (sc->imp_state == IMPS_INIT && --sc->imp_dropcnt == 0) {
sc->imp_state = IMPS_UP;
/* restart output in case something was q'd */
* RFNM or INCOMPLETE message, record in
* host table and prime output routine.
*
- * SHOULD RETRANSMIT ON INCOMPLETE.
+ * SHOULD NOTIFY PROTOCOL ABOUT INCOMPLETES.
*/
case IMPTYPE_RFNM:
case IMPTYPE_INCOMPLETE:
break;
/*
- * IMP reset complete.
+ * Interface reset.
*/
case IMPTYPE_RESET:
- if (sc->imp_state == IMPS_DOWN)
- sc->imp_state = IMPS_UP;
- else
- imperr(sc, "unexpected reset");
+ imperr(sc, "interface reset");
+ sc->imp_state = IMPS_RESET;
+ impnoops(sc);
goto drop;
default:
default:
impproto.sp_protocol = ip->il_link;
- impaddr.sin_addr.s_net = ip->il_network;
- impaddr.sin_addr.s_host = ip->il_host;
- impaddr.sin_addr.s_imp = ip->il_imp;
- raw_input(m, impproto, impaddr);
+ impdst.sin_addr = sc->imp_if.if_addr;
+ impsrc.sin_addr.s_net = ip->il_network;
+ impsrc.sin_addr.s_host = ip->il_host;
+ impsrc.sin_addr.s_imp = ip->il_imp;
+ raw_input(m, impproto, impdst, impsrc);
return;
}
IF_ENQUEUE(inq, m);
m_freem(m);
}
+/*
+ * Bring the IMP down after notification.
+ */
+impdown(sc)
+ struct imp_softc *sc;
+{
+ sc->imp_state = IMPS_DOWN;
+ /* notify protocols with messages waiting? */
+}
+
/*VARARGS*/
imperr(sc, fmt, a1, a2)
struct imp_softc *sc;
/*
* Don't even try if the IMP is unavailable.
*/
- if (imp_softc[ifp->if_unit].imp_state == IMPS_DOWN) {
- m_freem(m0);
- return (0);
- }
+ x = imp_softc[ifp->if_unit].imp_state;
+ if (x == IMPS_DOWN || x == IMPS_GOINGDOWN)
+ goto drop;
switch (pf) {
default:
printf("imp%d: can't encapsulate pf%d\n", ifp->if_unit, pf);
- m_freem(m0);
- return (0);
+ goto drop;
}
/*
if (m->m_off > MMAXOFF ||
MMINOFF + sizeof(struct imp_leader) > m->m_off) {
m = m_get(M_DONTWAIT);
- if (m == 0) {
- m_freem(m0);
- return (0);
- }
+ if (m == 0)
+ goto drop;
m->m_next = m0;
m->m_off = MMINOFF;
m->m_len = sizeof(struct imp_leader);
* and eventual transmission.
*/
return (impsnd(ifp, m));
+drop:
+ m_freem(m0);
+ return (0);
}
/*
hp = h_enter(addr);
/*
- * If IMP would block, queue until rfnm
+ * If IMP would block, queue until RFNM
*/
if (hp) {
register struct mbuf *n;
cnt++;
if (cnt >= 8)
goto drop;
+
+ /*
+ * Q is kept as circulare list with h_q
+ * (head) pointing to the last entry.
+ */
if ((n = hp->h_q) == 0)
hp->h_q = m->m_act = m;
else {