123168Smckusick /*
223168Smckusick  * Copyright (c) 1982 Regents of the University of California.
323168Smckusick  * All rights reserved.  The Berkeley software License Agreement
423168Smckusick  * specifies the terms and conditions for redistribution.
523168Smckusick  *
6*24778Skarels  *	@(#)if_imphost.c	6.5 (Berkeley) 09/16/85
723168Smckusick  */
85712Ssam 
95712Ssam #include "imp.h"
105712Ssam #if NIMP > 0
115712Ssam /*
125712Ssam  * Host table manipulation routines.
135712Ssam  * Only needed when shipping stuff through an IMP.
1411231Ssam  *
1511231Ssam  * Everything in here is called at splimp from
1611231Ssam  * from the IMP protocol code (if_imp.c), or
1711231Ssam  * interlocks with the code at splimp.
185712Ssam  */
1917069Sbloom #include "param.h"
2017069Sbloom #include "mbuf.h"
21*24778Skarels #include "syslog.h"
2211231Ssam 
238412Swnj #include "../netinet/in.h"
248412Swnj #include "../netinet/in_systm.h"
2511231Ssam 
2617069Sbloom #include "if_imp.h"
2717069Sbloom #include "if_imphost.h"
285712Ssam 
295712Ssam /*
305712Ssam  * Head of host table hash chains.
315712Ssam  */
325860Sroot struct mbuf *hosts;
335712Ssam 
345712Ssam /*
355712Ssam  * Given an internet address
365712Ssam  * return a host structure (if it exists).
375712Ssam  */
385712Ssam struct host *
395771Swnj hostlookup(addr)
405712Ssam 	struct in_addr addr;
415712Ssam {
425712Ssam 	register struct host *hp;
435712Ssam 	register struct mbuf *m;
445712Ssam 	register int hash = HOSTHASH(addr);
455712Ssam 
465860Sroot 	for (m = hosts; m; m = m->m_next) {
475712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
486589Ssam 	        if (hp->h_addr.s_addr == addr.s_addr) {
496589Ssam 			hp->h_flags |= HF_INUSE;
5011231Ssam 			return (hp);
516589Ssam 		}
525712Ssam 	}
5311231Ssam 	return ((struct host *)0);
545712Ssam }
555712Ssam 
565712Ssam /*
575712Ssam  * Enter a reference to this host's internet
585712Ssam  * address.  If no host structure exists, create
595712Ssam  * one and hook it into the host database.
605712Ssam  */
615712Ssam struct host *
625771Swnj hostenter(addr)
635712Ssam 	struct in_addr addr;
645712Ssam {
655860Sroot 	register struct mbuf *m, **mprev;
665860Sroot 	register struct host *hp, *hp0 = 0;
675712Ssam 	register int hash = HOSTHASH(addr);
685712Ssam 
695860Sroot 	mprev = &hosts;
705860Sroot 	while (m = *mprev) {
716209Swnj 		mprev = &m->m_next;
725712Ssam 		hp = &mtod(m, struct hmbuf *)->hm_hosts[hash];
736589Ssam 		if ((hp->h_flags & HF_INUSE) == 0) {
746589Ssam 			if (hp->h_addr.s_addr == addr.s_addr)
756589Ssam 				goto foundhost;
765860Sroot 			if (hp0 == 0)
775860Sroot 				hp0 = hp;
785860Sroot 			continue;
795860Sroot 		}
805712Ssam 	        if (hp->h_addr.s_addr == addr.s_addr)
815712Ssam 			goto foundhost;
825712Ssam 	}
835712Ssam 
845712Ssam 	/*
855712Ssam 	 * No current host structure, make one.
865712Ssam 	 * If our search ran off the end of the
875712Ssam 	 * chain of mbuf's, allocate another.
885712Ssam 	 */
895860Sroot 	if (hp0 == 0) {
909646Ssam 		m = m_getclr(M_DONTWAIT, MT_HTABLE);
9111231Ssam 		if (m == NULL)
9211231Ssam 			return ((struct host *)0);
935860Sroot 		*mprev = m;
945860Sroot 		hp0 = &mtod(m, struct hmbuf *)->hm_hosts[hash];
955712Ssam 	}
965860Sroot 	mtod(dtom(hp0), struct hmbuf *)->hm_count++;
975860Sroot 	hp = hp0;
985712Ssam 	hp->h_addr = addr;
996589Ssam 	hp->h_timer = 0;
1006725Ssam 	hp->h_flags = 0;
1015712Ssam 
1025712Ssam foundhost:
1036589Ssam 	hp->h_flags |= HF_INUSE;
1045712Ssam 	return (hp);
1055712Ssam }
1065712Ssam 
1075712Ssam /*
1086589Ssam  * Mark a host structure free and set it's
1096589Ssam  * timer going.
1105712Ssam  */
1115860Sroot hostfree(hp)
1125860Sroot 	register struct host *hp;
1135712Ssam {
1146589Ssam 
1156589Ssam 	hp->h_flags &= ~HF_INUSE;
1166589Ssam 	hp->h_timer = HOSTTIMER;
1176589Ssam 	hp->h_rfnm = 0;
1185712Ssam }
1195712Ssam 
1205712Ssam /*
1215712Ssam  * Reset a given network's host entries.
1225712Ssam  */
1235771Swnj hostreset(net)
124*24778Skarels 	u_long net;
1255712Ssam {
1265712Ssam 	register struct mbuf *m;
1275712Ssam 	register struct host *hp, *lp;
1285860Sroot 	struct hmbuf *hm;
129*24778Skarels 	struct mbuf *mnext;
1305712Ssam 
131*24778Skarels 	for (m = hosts; m; m = mnext) {
132*24778Skarels 		mnext = m->m_next;
1335860Sroot 		hm = mtod(m, struct hmbuf *);
1345860Sroot 		hp = hm->hm_hosts;
1355712Ssam 		lp = hp + HPMBUF;
1366589Ssam 		while (hm->hm_count > 0 && hp < lp) {
13718133Skarels 			if (in_netof(hp->h_addr) == net) {
1386589Ssam 				hp->h_flags &= ~HF_INUSE;
1396145Ssam 				hostrelease(hp);
1406089Sroot 			}
1415712Ssam 			hp++;
1425712Ssam 		}
1435712Ssam 	}
1445712Ssam }
1455712Ssam 
1465712Ssam /*
1475712Ssam  * Remove a host structure and release
1485712Ssam  * any resources it's accumulated.
1495712Ssam  */
1505860Sroot hostrelease(hp)
1515712Ssam 	register struct host *hp;
1525712Ssam {
1535860Sroot 	register struct mbuf *m, **mprev, *mh = dtom(hp);
1545712Ssam 
1555712Ssam 	/*
1565712Ssam 	 * Discard any packets left on the waiting q
1575712Ssam 	 */
1585771Swnj 	if (m = hp->h_q) {
1595868Sroot 		register struct mbuf *n;
1605868Sroot 
1615868Sroot 		do {
1625868Sroot 			n = m->m_act;
1635868Sroot 			m_freem(m);
1645868Sroot 			m = n;
1655868Sroot 		} while (m != hp->h_q);
1665771Swnj 		hp->h_q = 0;
1675712Ssam 	}
1686725Ssam 	hp->h_flags = 0;
16918133Skarels 	hp->h_rfnm = 0;
1705860Sroot 	if (--mtod(mh, struct hmbuf *)->hm_count)
1715712Ssam 		return;
1725860Sroot 	mprev = &hosts;
1735860Sroot 	while ((m = *mprev) != mh)
1745860Sroot 		mprev = &m->m_next;
1756589Ssam 	*mprev = m_free(mh);
1765712Ssam }
1775924Sroot 
1785924Sroot /*
1795924Sroot  * Remove a packet from the holding q.
1805924Sroot  * The RFNM counter is also bumped.
1815924Sroot  */
1825924Sroot struct mbuf *
1835924Sroot hostdeque(hp)
1845924Sroot 	register struct host *hp;
1855924Sroot {
1865924Sroot 	register struct mbuf *m;
1875924Sroot 
1885924Sroot 	hp->h_rfnm--;
1895924Sroot 	HOST_DEQUE(hp, m);
1905924Sroot 	if (m)
1915924Sroot 		return (m);
1925924Sroot 	if (hp->h_rfnm == 0)
1935924Sroot 		hostfree(hp);
1945924Sroot 	return (0);
1955924Sroot }
1966589Ssam 
1976589Ssam /*
1986589Ssam  * Host data base timer routine.
1996589Ssam  * Decrement timers on structures which are
2006589Ssam  * waiting to be deallocated.  On expiration
2016589Ssam  * release resources, possibly deallocating
2026589Ssam  * mbuf associated with structure.
2036589Ssam  */
2046589Ssam hostslowtimo()
2056589Ssam {
2066589Ssam 	register struct mbuf *m;
2076589Ssam 	register struct host *hp, *lp;
2086589Ssam 	struct hmbuf *hm;
209*24778Skarels 	struct mbuf *mnext;
21011231Ssam 	int s = splimp();
2116589Ssam 
212*24778Skarels 	for (m = hosts; m; m = mnext) {
213*24778Skarels 		mnext = 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++) {
218*24778Skarels 			if (hp->h_timer && --hp->h_timer == 0) {
219*24778Skarels 				if (hp->h_rfnm)
220*24778Skarels 				    log(KERN_RECOV,
221*24778Skarels 					"imp?: host %x, lost %d rfnms\n",
222*24778Skarels 					ntohs(hp->h_addr.s_addr), hp->h_rfnm);
2236589Ssam 				hostrelease(hp);
224*24778Skarels 			}
2256589Ssam 		}
2266589Ssam 	}
22711241Ssam 	splx(s);
2286589Ssam }
22913081Ssam #endif
230