123168Smckusick /* 234853Sbostic * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 333453Skarels * All rights reserved. 423168Smckusick * 5*44468Sbostic * %sccs.include.redist.c% 633453Skarels * 7*44468Sbostic * @(#)if_imphost.c 7.10 (Berkeley) 06/28/90 823168Smckusick */ 95712Ssam 105712Ssam #include "imp.h" 115712Ssam #if NIMP > 0 125712Ssam /* 135712Ssam * Host table manipulation routines. 145712Ssam * Only needed when shipping stuff through an IMP. 1511231Ssam * 1611231Ssam * Everything in here is called at splimp from 1711231Ssam * from the IMP protocol code (if_imp.c), or 1811231Ssam * interlocks with the code at splimp. 195712Ssam */ 2017069Sbloom #include "param.h" 2117069Sbloom #include "mbuf.h" 2233427Skarels #include "socket.h" 2324778Skarels #include "syslog.h" 2411231Ssam 2533427Skarels #include "../net/if.h" 2633427Skarels 278412Swnj #include "../netinet/in.h" 288412Swnj #include "../netinet/in_systm.h" 2911231Ssam 3017069Sbloom #include "if_imp.h" 3117069Sbloom #include "if_imphost.h" 325712Ssam 3333427Skarels extern struct imp_softc imp_softc[]; 345712Ssam 355712Ssam /* 365712Ssam * Given an internet address 375712Ssam * return a host structure (if it exists). 385712Ssam */ 395712Ssam struct host * 4033427Skarels hostlookup(imp, host, unit) 4133427Skarels int imp, host, unit; 425712Ssam { 435712Ssam register struct host *hp; 445712Ssam register struct mbuf *m; 4533427Skarels register int hash = HOSTHASH(imp, host); 465712Ssam 4733453Skarels for (m = imp_softc[unit].imp_hosts; m; m = m->m_next) { 485712Ssam hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 4933453Skarels if (hp->h_imp == imp && hp->h_host == host) { 5034209Skarels if ((hp->h_flags & HF_INUSE) == 0) 5133453Skarels mtod(dtom(hp), struct hmbuf *)->hm_count++; 526589Ssam hp->h_flags |= HF_INUSE; 5311231Ssam return (hp); 546589Ssam } 555712Ssam } 5611231Ssam return ((struct host *)0); 575712Ssam } 585712Ssam 595712Ssam /* 605712Ssam * Enter a reference to this host's internet 615712Ssam * address. If no host structure exists, create 625712Ssam * one and hook it into the host database. 635712Ssam */ 645712Ssam struct host * 6533427Skarels hostenter(imp, host, unit) 6633427Skarels int imp, host, unit; 675712Ssam { 685860Sroot register struct mbuf *m, **mprev; 695860Sroot register struct host *hp, *hp0 = 0; 7033427Skarels register int hash = HOSTHASH(imp, host); 715712Ssam 7233453Skarels mprev = &imp_softc[unit].imp_hosts; 735860Sroot while (m = *mprev) { 746209Swnj mprev = &m->m_next; 755712Ssam hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 7633453Skarels if (hp->h_imp == imp && hp->h_host == host) { 7734209Skarels if ((hp->h_flags & HF_INUSE) == 0) 7833453Skarels mtod(dtom(hp), struct hmbuf *)->hm_count++; 7933427Skarels goto foundhost; 8033453Skarels } 816589Ssam if ((hp->h_flags & HF_INUSE) == 0) { 825860Sroot if (hp0 == 0) 835860Sroot hp0 = hp; 845860Sroot continue; 855860Sroot } 865712Ssam } 875712Ssam 885712Ssam /* 895712Ssam * No current host structure, make one. 905712Ssam * If our search ran off the end of the 915712Ssam * chain of mbuf's, allocate another. 925712Ssam */ 935860Sroot if (hp0 == 0) { 949646Ssam m = m_getclr(M_DONTWAIT, MT_HTABLE); 9511231Ssam if (m == NULL) 9611231Ssam return ((struct host *)0); 975860Sroot *mprev = m; 985860Sroot hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 995712Ssam } 1005860Sroot hp = hp0; 10134209Skarels mtod(dtom(hp), struct hmbuf *)->hm_count++; 10233427Skarels hp->h_imp = imp; 10333427Skarels hp->h_host = host; 1046589Ssam hp->h_timer = 0; 1056725Ssam hp->h_flags = 0; 1065712Ssam 1075712Ssam foundhost: 1086589Ssam hp->h_flags |= HF_INUSE; 1095712Ssam return (hp); 1105712Ssam } 1115712Ssam 1125712Ssam /* 11333427Skarels * Reset a given imp unit's host entries. 11434693Skarels * Must be called at splimp. 1155712Ssam */ 11633427Skarels hostreset(unit) 11733427Skarels int unit; 1185712Ssam { 1195712Ssam register struct mbuf *m; 1205712Ssam register struct host *hp, *lp; 1215860Sroot struct hmbuf *hm; 1225712Ssam 12333453Skarels for (m = imp_softc[unit].imp_hosts; m; m = m->m_next) { 1245860Sroot hm = mtod(m, struct hmbuf *); 1255860Sroot hp = hm->hm_hosts; 1265712Ssam lp = hp + HPMBUF; 1276589Ssam while (hm->hm_count > 0 && hp < lp) { 12833453Skarels hostrelease(hp); 1295712Ssam hp++; 1305712Ssam } 1315712Ssam } 13233453Skarels hostcompress(unit); 1335712Ssam } 1345712Ssam 1355712Ssam /* 1365712Ssam * Remove a host structure and release 1375712Ssam * any resources it's accumulated. 1385712Ssam */ 1395860Sroot hostrelease(hp) 1405712Ssam register struct host *hp; 1415712Ssam { 1425712Ssam 14334209Skarels if (hp->h_q) 14434209Skarels hostflush(hp); 14534209Skarels hp->h_rfnm = 0; 14634209Skarels if (hp->h_flags & HF_INUSE) 14734209Skarels --mtod(dtom(hp), struct hmbuf *)->hm_count; 14833453Skarels hp->h_flags = 0; 14933453Skarels } 15033453Skarels 15133453Skarels /* 15233453Skarels * Flush the message queue for a host. 15333453Skarels */ 15433453Skarels hostflush(hp) 15533453Skarels register struct host *hp; 15633453Skarels { 15734459Skarels register struct mbuf *m; 15833453Skarels 1595712Ssam /* 1605712Ssam * Discard any packets left on the waiting q 1615712Ssam */ 1625771Swnj if (m = hp->h_q) { 1635868Sroot register struct mbuf *n; 1645868Sroot 1655868Sroot do { 1665868Sroot n = m->m_act; 1675868Sroot m_freem(m); 1685868Sroot m = n; 1695868Sroot } while (m != hp->h_q); 1705771Swnj hp->h_q = 0; 17133453Skarels hp->h_qcnt = 0; 1725712Ssam } 1735712Ssam } 1745924Sroot 17534693Skarels /* 17634693Skarels * Release mbufs in host table that contain no entries 17734693Skarels * currently in use. Must be called at splimp. 17834693Skarels */ 17933453Skarels hostcompress(unit) 18033453Skarels int unit; 1815924Sroot { 18233427Skarels register struct mbuf *m, **mprev; 18334693Skarels struct imp_softc *sc = &imp_softc[unit]; 1845924Sroot 18534693Skarels mprev = &sc->imp_hosts; 18634693Skarels sc->imp_hostq = 0; 18733427Skarels while (m = *mprev) { 18833427Skarels if (mtod(m, struct hmbuf *)->hm_count == 0) 18933427Skarels *mprev = m_free(m); 19033427Skarels else 19133427Skarels mprev = &m->m_next; 19233427Skarels } 1935924Sroot } 1946589Ssam 1956589Ssam /* 1966589Ssam * Host data base timer routine. 1976589Ssam * Decrement timers on structures which are 1986589Ssam * waiting to be deallocated. On expiration 1996589Ssam * release resources, possibly deallocating 2006589Ssam * mbuf associated with structure. 2016589Ssam */ 2026589Ssam hostslowtimo() 2036589Ssam { 2046589Ssam register struct mbuf *m; 2056589Ssam register struct host *hp, *lp; 20633454Skarels struct imp_softc *sc; 2076589Ssam struct hmbuf *hm; 20833453Skarels int s = splimp(), unit, any; 2096589Ssam 21033453Skarels for (unit = 0; unit < NIMP; unit++) { 21133453Skarels any = 0; 21233454Skarels sc = &imp_softc[unit]; 21333454Skarels for (m = sc->imp_hosts; m; m = m->m_next) { 2146589Ssam hm = mtod(m, struct hmbuf *); 2156589Ssam hp = hm->hm_hosts; 2166589Ssam lp = hp + HPMBUF; 2176779Ssam for (; hm->hm_count > 0 && hp < lp; hp++) { 21833427Skarels if (hp->h_timer && --hp->h_timer == 0) { 21933427Skarels if (hp->h_rfnm) { 22034260Skarels log(LOG_INFO, /* XXX */ 22133453Skarels "imp%d: host %d/imp %d, lost rfnm\n", 22233453Skarels unit, hp->h_host, ntohs(hp->h_imp)); 22334209Skarels sc->imp_lostrfnm++; 22434209Skarels imprestarthost(sc, hp); 22534209Skarels } else { 22633453Skarels any = 1; 22733453Skarels hostrelease(hp); 22833454Skarels if (sc->imp_hostq == m) 22933454Skarels sc->imp_hostq = 0; 23033453Skarels } 23133427Skarels } 2326589Ssam } 23333453Skarels } 23434209Skarels if (any) 23533453Skarels hostcompress(unit); 2366589Ssam } 23711241Ssam splx(s); 2386589Ssam } 23913081Ssam #endif 240