X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/98b6195e5225cea8b8f480fd1c44c9e8c4246753..cce93e4b226012d5eebcf7f7bd01cde8a8a07f51:/usr/src/sys/deprecated/netimp/if_imp.c diff --git a/usr/src/sys/deprecated/netimp/if_imp.c b/usr/src/sys/deprecated/netimp/if_imp.c index f7bd66fcbe..0767502bb5 100644 --- a/usr/src/sys/deprecated/netimp/if_imp.c +++ b/usr/src/sys/deprecated/netimp/if_imp.c @@ -1,15 +1,12 @@ -/* if_imp.c 4.23 82/04/10 */ +/* if_imp.c 4.45 82/12/14 */ #include "imp.h" #if NIMP > 0 /* - * ARPAnet IMP interface driver. + * ARPANET IMP interface driver. * * The IMP-host protocol is handled here, leaving * hardware specifics to the lower level interface driver. - * - * TODO: - * pass more error indications up to protocol modules */ #include "../h/param.h" #include "../h/systm.h" @@ -18,19 +15,24 @@ #include "../h/buf.h" #include "../h/protosw.h" #include "../h/socket.h" -#include "../h/ubareg.h" -#include "../h/ubavar.h" -#include "../h/cpu.h" -#include "../h/mtpr.h" #include "../h/vmmac.h" -#include "../net/in.h" -#include "../net/in_systm.h" + +#include "../vax/cpu.h" +#include "../vax/mtpr.h" +#include "../vaxuba/ubareg.h" +#include "../vaxuba/ubavar.h" + #include "../net/if.h" -#include "../net/if_imp.h" -#include "../net/if_imphost.h" -#include "../net/ip.h" -#include "../net/ip_var.h" #include "../net/route.h" +#include "../net/netisr.h" +#include "../netinet/in.h" +#include "../netinet/in_systm.h" +#include "../netinet/ip.h" +#include "../netinet/ip_var.h" +/* define IMPLEADERS here to get leader printing code */ +#include "../netimp/if_imp.h" +#include "../netimp/if_imphost.h" +#include /* * IMP software status per interface. @@ -74,19 +76,20 @@ int impdown(), impinit(), impoutput(); * structures. This is then used by the device's attach routine * set up its back pointers. */ -impattach(ui) +impattach(ui, reset) struct uba_device *ui; + int (*reset)(); { struct imp_softc *sc = &imp_softc[ui->ui_unit]; register struct ifnet *ifp = &sc->imp_if; struct sockaddr_in *sin; -COUNT(IMPATTACH); /* UNIT COULD BE AMBIGUOUS */ ifp->if_unit = ui->ui_unit; ifp->if_name = "imp"; ifp->if_mtu = IMPMTU - sizeof(struct imp_leader); ifp->if_net = ui->ui_flags; + ifp->if_reset = reset; /* the host and imp fields will be filled in by the imp */ sin = (struct sockaddr_in *)&ifp->if_addr; sin->sin_family = AF_INET; @@ -109,7 +112,6 @@ impinit(unit) int s = splimp(); register struct imp_softc *sc = &imp_softc[unit]; -COUNT(IMPINIT); if ((*sc->imp_cb.ic_init)(unit) == 0) { sc->imp_state = IMPS_DOWN; sc->imp_if.if_flags &= ~IFF_UP; @@ -118,13 +120,15 @@ COUNT(IMPINIT); } sc->imp_state = IMPS_INIT; impnoops(sc); - if_rtinit(&sc->imp_if, RTF_DIRECT|RTF_UP); splx(s); } struct sockproto impproto = { PF_IMPLINK }; struct sockaddr_in impdst = { AF_IMPLINK }; struct sockaddr_in impsrc = { AF_IMPLINK }; +#ifdef IMPLEADERS +int impprintfs = 0; +#endif /* * ARPAnet 1822 input routine. @@ -146,7 +150,6 @@ impinput(unit, m) struct mbuf *next; struct sockaddr_in *sin; -COUNT(IMPINPUT); /* verify leader length. */ if (m->m_len < sizeof(struct control_leader) && (m = m_pullup(m, sizeof(struct control_leader))) == 0) @@ -157,6 +160,10 @@ COUNT(IMPINPUT); (m = m_pullup(m, sizeof(struct imp_leader))) == 0) return; ip = mtod(m, struct imp_leader *); +#ifdef IMPLEADERS + if (impprintfs) + printleader("impinput", ip); +#endif /* check leader type */ if (ip->il_format != IMP_NFF) { @@ -164,28 +171,15 @@ COUNT(IMPINPUT); goto drop; } - /* - * Certain messages require a host structure. - * Do this in one shot here. - */ - switch (ip->il_mtype) { - - case IMPTYPE_RFNM: - case IMPTYPE_INCOMPLETE: - case IMPTYPE_HOSTDEAD: - case IMPTYPE_HOSTUNREACH: - case IMPTYPE_BADDATA: + if (ip->il_mtype != IMPTYPE_DATA) { #ifdef notdef addr.s_net = ip->il_network; #else - addr.s_net = 0; + addr.s_net = sc->imp_if.if_net; #endif addr.s_imp = ip->il_imp; addr.s_host = ip->il_host; - hp = hostlookup(addr); - break; } - switch (ip->il_mtype) { case IMPTYPE_DATA: @@ -203,10 +197,10 @@ COUNT(IMPINPUT); */ if (sc->imp_state != IMPS_INIT) { impmsg(sc, "leader error"); - hostreset(sc->imp_if.if_net); /* XXX */ + hostreset(sc->imp_if.if_net); impnoops(sc); } - goto rawlinkin; + goto drop; /* * IMP going down. Print message, and if not immediate, @@ -214,13 +208,15 @@ COUNT(IMPINPUT); * appropriate time. */ case IMPTYPE_DOWN: + if (sc->imp_state < IMPS_INIT) + goto drop; if ((ip->il_link & IMP_DMASK) == 0) { sc->imp_state = IMPS_GOINGDOWN; timeout(impdown, (caddr_t)sc, 30 * hz); } impmsg(sc, "going down %s", (u_int)impmessage[ip->il_link&IMP_DMASK]); - goto rawlinkin; + goto drop; /* * A NOP usually seen during the initialization sequence. @@ -245,51 +241,53 @@ COUNT(IMPINPUT); } sc->imp_state = IMPS_UP; sc->imp_if.if_flags |= IFF_UP; - /* restart output in case something was q'd */ - (*sc->imp_cb.ic_start)(sc->imp_if.if_unit); + if_rtinit(&sc->imp_if, RTF_UP); goto drop; /* - * RFNM or INCOMPLETE message, record in - * host table and prime output routine. - * - * SHOULD NOTIFY PROTOCOL ABOUT INCOMPLETES. + * RFNM or INCOMPLETE message, send next + * message on the q. We could pass incomplete's + * up to the next level, but this currently isn't + * needed. */ case IMPTYPE_RFNM: case IMPTYPE_INCOMPLETE: - if (hp && hp->h_rfnm) - if (next = hostdeque(hp)) + if (hp = hostlookup(addr)) { + if (hp->h_rfnm == 0) + hp->h_flags &= ~HF_INUSE; + else if (next = hostdeque(hp)) (void) impsnd(&sc->imp_if, next); + } goto drop; /* * Host or IMP can't be reached. Flush any packets * awaiting transmission and release the host structure. - * - * TODO: NOTIFY THE PROTOCOL */ case IMPTYPE_HOSTDEAD: - impmsg(sc, "host dead"); /* XXX */ - goto common; /* XXX */ - - /* SHOULD SIGNAL ROUTING DAEMON */ - case IMPTYPE_HOSTUNREACH: - impmsg(sc, "host unreachable"); /* XXX */ - common: - if (hp) - hostfree(hp); /* won't work right */ + case IMPTYPE_HOSTUNREACH: { + int s = splnet(); + impnotify((int)ip->il_mtype, (struct control_leader *)ip, + hostlookup(addr)); + splx(s); goto rawlinkin; + } /* * Error in data. Clear RFNM status for this host and send * noops to the IMP to clear the interface. */ - case IMPTYPE_BADDATA: + case IMPTYPE_BADDATA: { + int s; + impmsg(sc, "data error"); - if (hp) + s = splnet(); + if (hp = hostlookup(addr)) hp->h_rfnm = 0; + splx(s); impnoops(sc); - goto rawlinkin; + goto drop; + } /* * Interface reset. @@ -297,11 +295,11 @@ COUNT(IMPINPUT); case IMPTYPE_RESET: impmsg(sc, "interface reset"); impnoops(sc); - goto rawlinkin; + goto drop; default: sc->imp_if.if_collisions++; /* XXX */ - goto rawlinkin; + goto drop; } /* @@ -329,8 +327,8 @@ COUNT(IMPINPUT); 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, (struct sockaddr *)&impdst, - (struct sockaddr *)&impsrc); + raw_input(m, &impproto, (struct sockaddr *)&impsrc, + (struct sockaddr *)&impdst); return; } if (IF_QFULL(inq)) { @@ -352,9 +350,9 @@ impdown(sc) { sc->imp_state = IMPS_DOWN; - sc->imp_if.if_flags &= ~IFF_UP; impmsg(sc, "marked down"); - /* notify protocols with messages waiting? */ + hostreset(sc->imp_if.if_net); + if_down(&sc->imp_if); } /*VARARGS*/ @@ -369,6 +367,34 @@ impmsg(sc, fmt, a1, a2) printf("\n"); } +/* + * Process an IMP "error" message, passing this + * up to the higher level protocol. + */ +impnotify(what, cp, hp) + int what; + struct control_leader *cp; + struct host *hp; +{ + struct in_addr in; + +#ifdef notdef + in.s_net = cp->dl_network; +#else + in.s_net = 10; /* XXX */ +#endif + in.s_host = cp->dl_host; + in.s_imp = cp->dl_imp; + if (cp->dl_link != IMPLINK_IP) + raw_ctlinput(what, (caddr_t)&in); + else + ip_ctlinput(what, (caddr_t)&in); + if (hp) { + hp->h_flags |= (1 << what); + hostfree(hp); + } +} + /* * ARPAnet 1822 output routine. * Called from higher level protocol routines to set up messages for @@ -382,14 +408,16 @@ impoutput(ifp, m0, dst) { register struct imp_leader *imp; register struct mbuf *m = m0; - int x, dhost, dimp, dlink, len, dnet; + int dhost, dimp, dlink, len, dnet; + int error = 0; -COUNT(IMPOUTPUT); /* * Don't even try if the IMP is unavailable. */ - if (imp_softc[ifp->if_unit].imp_state != IMPS_UP) + if (imp_softc[ifp->if_unit].imp_state != IMPS_UP) { + error = ENETDOWN; goto drop; + } switch (dst->sa_family) { @@ -412,6 +440,7 @@ COUNT(IMPOUTPUT); default: printf("imp%d: can't handle af%d\n", ifp->if_unit, dst->sa_family); + error = EAFNOSUPPORT; goto drop; } @@ -422,11 +451,12 @@ COUNT(IMPOUTPUT); */ if (m->m_off > MMAXOFF || MMINOFF + sizeof(struct imp_leader) > m->m_off) { - m = m_get(M_DONTWAIT); - if (m == 0) + m = m_get(M_DONTWAIT, MT_HEADER); + if (m == 0) { + error = ENOBUFS; goto drop; + } m->m_next = m0; - m->m_off = MMINOFF; m->m_len = sizeof(struct imp_leader); } else { m->m_off -= sizeof(struct imp_leader); @@ -444,14 +474,10 @@ COUNT(IMPOUTPUT); imp->il_flags = imp->il_htype = imp->il_subtype = 0; leaderexists: - /* - * Hand message to impsnd to perform RFNM counting - * and eventual transmission. - */ return (impsnd(ifp, m)); drop: m_freem(m0); - return (0); + return (error); } /* @@ -466,28 +492,33 @@ impsnd(ifp, m) register struct imp_leader *ip; register struct host *hp; struct impcb *icp; - int x; + int s, error; -COUNT(IMPSND); ip = mtod(m, struct imp_leader *); /* * Do RFNM counting for data messages * (no more than 8 outstanding to any host) */ - x = splimp(); + s = splimp(); if (ip->il_mtype == IMPTYPE_DATA) { struct in_addr addr; #ifdef notdef addr.s_net = ip->il_network; #else - addr.s_net = 0; + addr.s_net = ifp->if_net; /* XXX */ #endif addr.s_host = ip->il_host; addr.s_imp = ip->il_imp; if ((hp = hostlookup(addr)) == 0) hp = hostenter(addr); + if (hp && (hp->h_flags & (HF_DEAD|HF_UNREACH))) { + error = hp->h_flags&HF_DEAD ? EHOSTDOWN : EHOSTUNREACH; + hp->h_timer = HOSTTIMER; + hp->h_flags &= ~HF_INUSE; + goto bad; + } /* * If IMP would block, queue until RFNM @@ -502,24 +533,25 @@ COUNT(IMPSND); goto start; } } - m_freem(m); - splx(x); - return (0); + error = ENOBUFS; + goto bad; } enque: if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); + error = ENOBUFS; +bad: m_freem(m); - splx(x); - return (0); + splx(s); + return (error); } IF_ENQUEUE(&ifp->if_snd, m); start: - splx(x); icp = &imp_softc[ifp->if_unit].imp_cb; if (icp->ic_oactive == 0) (*icp->ic_start)(ifp->if_unit); - return (1); + splx(s); + return (0); } /* @@ -527,6 +559,8 @@ start: * Part of host-IMP initialization procedure. * (Should return success/failure, but noone knows * what to do with this, so why bother?) + * This routine is always called at splimp, so we don't + * protect the call to IF_PREPEND. */ impnoops(sc) register struct imp_softc *sc; @@ -534,22 +568,17 @@ impnoops(sc) register i; register struct mbuf *m; register struct control_leader *cp; - int x; -COUNT(IMPNOOPS); sc->imp_dropcnt = IMP_DROPCNT; for (i = 0; i < IMP_DROPCNT + 1; i++ ) { - if ((m = m_getclr(M_DONTWAIT)) == 0) + if ((m = m_getclr(M_DONTWAIT, MT_HEADER)) == 0) return; - m->m_off = MMINOFF; m->m_len = sizeof(struct control_leader); cp = mtod(m, struct control_leader *); cp->dl_format = IMP_NFF; cp->dl_link = i; cp->dl_mtype = IMPTYPE_NOOP; - x = splimp(); IF_PREPEND(&sc->imp_if.if_snd, m); - splx(x); } if (sc->imp_cb.ic_oactive == 0) (*sc->imp_cb.ic_start)(sc->imp_if.if_unit);