123168Smckusick /* 233453Skarels * Copyright (c) 1982,1986,1988 Regents of the University of California. 333453Skarels * All rights reserved. 423168Smckusick * 533453Skarels * Redistribution and use in source and binary forms are permitted 633453Skarels * provided that this notice is preserved and that due credit is given 733453Skarels * to the University of California at Berkeley. The name of the University 833453Skarels * may not be used to endorse or promote products derived from this 933453Skarels * software without specific prior written permission. This software 1033453Skarels * is provided ``as is'' without express or implied warranty. 1133453Skarels * 12*34459Skarels * @(#)if_imphost.c 7.7 (Berkeley) 05/24/88 1323168Smckusick */ 145712Ssam 155712Ssam #include "imp.h" 165712Ssam #if NIMP > 0 175712Ssam /* 185712Ssam * Host table manipulation routines. 195712Ssam * Only needed when shipping stuff through an IMP. 2011231Ssam * 2111231Ssam * Everything in here is called at splimp from 2211231Ssam * from the IMP protocol code (if_imp.c), or 2311231Ssam * interlocks with the code at splimp. 245712Ssam */ 2517069Sbloom #include "param.h" 2617069Sbloom #include "mbuf.h" 2733427Skarels #include "socket.h" 2824778Skarels #include "syslog.h" 2911231Ssam 3033427Skarels #include "../net/if.h" 3133427Skarels 328412Swnj #include "../netinet/in.h" 338412Swnj #include "../netinet/in_systm.h" 3411231Ssam 3517069Sbloom #include "if_imp.h" 3617069Sbloom #include "if_imphost.h" 375712Ssam 3833427Skarels extern struct imp_softc imp_softc[]; 395712Ssam 405712Ssam /* 415712Ssam * Given an internet address 425712Ssam * return a host structure (if it exists). 435712Ssam */ 445712Ssam struct host * 4533427Skarels hostlookup(imp, host, unit) 4633427Skarels int imp, host, unit; 475712Ssam { 485712Ssam register struct host *hp; 495712Ssam register struct mbuf *m; 5033427Skarels register int hash = HOSTHASH(imp, host); 515712Ssam 5233453Skarels for (m = imp_softc[unit].imp_hosts; m; m = m->m_next) { 535712Ssam hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 5433453Skarels if (hp->h_imp == imp && hp->h_host == host) { 5534209Skarels if ((hp->h_flags & HF_INUSE) == 0) 5633453Skarels mtod(dtom(hp), struct hmbuf *)->hm_count++; 576589Ssam hp->h_flags |= HF_INUSE; 5811231Ssam return (hp); 596589Ssam } 605712Ssam } 6111231Ssam return ((struct host *)0); 625712Ssam } 635712Ssam 645712Ssam /* 655712Ssam * Enter a reference to this host's internet 665712Ssam * address. If no host structure exists, create 675712Ssam * one and hook it into the host database. 685712Ssam */ 695712Ssam struct host * 7033427Skarels hostenter(imp, host, unit) 7133427Skarels int imp, host, unit; 725712Ssam { 735860Sroot register struct mbuf *m, **mprev; 745860Sroot register struct host *hp, *hp0 = 0; 7533427Skarels register int hash = HOSTHASH(imp, host); 765712Ssam 7733453Skarels mprev = &imp_softc[unit].imp_hosts; 785860Sroot while (m = *mprev) { 796209Swnj mprev = &m->m_next; 805712Ssam hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 8133453Skarels if (hp->h_imp == imp && hp->h_host == host) { 8234209Skarels if ((hp->h_flags & HF_INUSE) == 0) 8333453Skarels mtod(dtom(hp), struct hmbuf *)->hm_count++; 8433427Skarels goto foundhost; 8533453Skarels } 866589Ssam if ((hp->h_flags & HF_INUSE) == 0) { 875860Sroot if (hp0 == 0) 885860Sroot hp0 = hp; 895860Sroot continue; 905860Sroot } 915712Ssam } 925712Ssam 935712Ssam /* 945712Ssam * No current host structure, make one. 955712Ssam * If our search ran off the end of the 965712Ssam * chain of mbuf's, allocate another. 975712Ssam */ 985860Sroot if (hp0 == 0) { 999646Ssam m = m_getclr(M_DONTWAIT, MT_HTABLE); 10011231Ssam if (m == NULL) 10111231Ssam return ((struct host *)0); 1025860Sroot *mprev = m; 1035860Sroot hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 1045712Ssam } 1055860Sroot hp = hp0; 10634209Skarels mtod(dtom(hp), struct hmbuf *)->hm_count++; 10733427Skarels hp->h_imp = imp; 10833427Skarels hp->h_host = host; 1096589Ssam hp->h_timer = 0; 1106725Ssam hp->h_flags = 0; 1115712Ssam 1125712Ssam foundhost: 1136589Ssam hp->h_flags |= HF_INUSE; 1145712Ssam return (hp); 1155712Ssam } 1165712Ssam 1175712Ssam /* 11833427Skarels * Reset a given imp unit's host entries. 1195712Ssam */ 12033427Skarels hostreset(unit) 12133427Skarels int unit; 1225712Ssam { 1235712Ssam register struct mbuf *m; 1245712Ssam register struct host *hp, *lp; 1255860Sroot struct hmbuf *hm; 1265712Ssam 12733453Skarels for (m = imp_softc[unit].imp_hosts; m; m = m->m_next) { 1285860Sroot hm = mtod(m, struct hmbuf *); 1295860Sroot hp = hm->hm_hosts; 1305712Ssam lp = hp + HPMBUF; 1316589Ssam while (hm->hm_count > 0 && hp < lp) { 13233453Skarels hostrelease(hp); 1335712Ssam hp++; 1345712Ssam } 1355712Ssam } 13633453Skarels hostcompress(unit); 1375712Ssam } 1385712Ssam 1395712Ssam /* 1405712Ssam * Remove a host structure and release 1415712Ssam * any resources it's accumulated. 1425712Ssam */ 1435860Sroot hostrelease(hp) 1445712Ssam register struct host *hp; 1455712Ssam { 1465712Ssam 14734209Skarels if (hp->h_q) 14834209Skarels hostflush(hp); 14934209Skarels hp->h_rfnm = 0; 15034209Skarels if (hp->h_flags & HF_INUSE) 15134209Skarels --mtod(dtom(hp), struct hmbuf *)->hm_count; 15233453Skarels hp->h_flags = 0; 15333453Skarels } 15433453Skarels 15533453Skarels /* 15633453Skarels * Flush the message queue for a host. 15733453Skarels */ 15833453Skarels hostflush(hp) 15933453Skarels register struct host *hp; 16033453Skarels { 161*34459Skarels register struct mbuf *m; 16233453Skarels 1635712Ssam /* 1645712Ssam * Discard any packets left on the waiting q 1655712Ssam */ 1665771Swnj if (m = hp->h_q) { 1675868Sroot register struct mbuf *n; 1685868Sroot 1695868Sroot do { 1705868Sroot n = m->m_act; 1715868Sroot m_freem(m); 1725868Sroot m = n; 1735868Sroot } while (m != hp->h_q); 1745771Swnj hp->h_q = 0; 17533453Skarels hp->h_qcnt = 0; 1765712Ssam } 1775712Ssam } 1785924Sroot 17933453Skarels hostcompress(unit) 18033453Skarels int unit; 1815924Sroot { 18233427Skarels register struct mbuf *m, **mprev; 1835924Sroot 18433453Skarels mprev = &imp_softc[unit].imp_hosts; 18533427Skarels while (m = *mprev) { 18633427Skarels if (mtod(m, struct hmbuf *)->hm_count == 0) 18733427Skarels *mprev = m_free(m); 18833427Skarels else 18933427Skarels mprev = &m->m_next; 19033427Skarels } 1915924Sroot } 1926589Ssam 1936589Ssam /* 1946589Ssam * Host data base timer routine. 1956589Ssam * Decrement timers on structures which are 1966589Ssam * waiting to be deallocated. On expiration 1976589Ssam * release resources, possibly deallocating 1986589Ssam * mbuf associated with structure. 1996589Ssam */ 2006589Ssam hostslowtimo() 2016589Ssam { 2026589Ssam register struct mbuf *m; 2036589Ssam register struct host *hp, *lp; 20433454Skarels struct imp_softc *sc; 2056589Ssam struct hmbuf *hm; 20633453Skarels int s = splimp(), unit, any; 2076589Ssam 20833453Skarels for (unit = 0; unit < NIMP; unit++) { 20933453Skarels any = 0; 21033454Skarels sc = &imp_softc[unit]; 21133454Skarels for (m = sc->imp_hosts; m; m = m->m_next) { 2126589Ssam hm = mtod(m, struct hmbuf *); 2136589Ssam hp = hm->hm_hosts; 2146589Ssam lp = hp + HPMBUF; 2156779Ssam for (; hm->hm_count > 0 && hp < lp; hp++) { 21633427Skarels if (hp->h_timer && --hp->h_timer == 0) { 21733427Skarels if (hp->h_rfnm) { 21834260Skarels log(LOG_INFO, /* XXX */ 21933453Skarels "imp%d: host %d/imp %d, lost rfnm\n", 22033453Skarels unit, hp->h_host, ntohs(hp->h_imp)); 22134209Skarels sc->imp_lostrfnm++; 22234209Skarels imprestarthost(sc, hp); 22334209Skarels } else { 22433453Skarels any = 1; 22533453Skarels hostrelease(hp); 22633454Skarels if (sc->imp_hostq == m) 22733454Skarels sc->imp_hostq = 0; 22833453Skarels } 22933427Skarels } 2306589Ssam } 23133453Skarels } 23234209Skarels if (any) 23333453Skarels hostcompress(unit); 2346589Ssam } 23511241Ssam splx(s); 2366589Ssam } 23713081Ssam #endif 238