1*5771Swnj /* if_imphost.c 4.2 82/02/12 */ 25712Ssam 35712Ssam #include "imp.h" 45712Ssam #if NIMP > 0 55712Ssam /* 65712Ssam * Host table manipulation routines. 75712Ssam * Only needed when shipping stuff through an IMP. 85712Ssam */ 95712Ssam 105712Ssam #include "../h/param.h" 115712Ssam #include "../h/mbuf.h" 125712Ssam #include "../net/in.h" 135712Ssam #include "../net/in_systm.h" 145712Ssam #include "../net/host.h" 155712Ssam #include "../net/if_imp.h" 165712Ssam 175712Ssam /* 185712Ssam * Head of host table hash chains. 195712Ssam */ 205712Ssam struct mbuf hosttable = { 0, MMINOFF }; 215712Ssam 225712Ssam /* 235712Ssam * Given an internet address 245712Ssam * return a host structure (if it exists). 255712Ssam */ 265712Ssam struct host * 27*5771Swnj hostlookup(addr) 285712Ssam struct in_addr addr; 295712Ssam { 305712Ssam register struct host *hp; 315712Ssam register struct mbuf *m; 325712Ssam register int hash = HOSTHASH(addr); 335712Ssam 34*5771Swnj COUNT(HOSTLOOKUP); 35*5771Swnj printf("hostlookup(%x)\n", addr); 365712Ssam for (m = &hosttable; m; m = m->m_next) { 375712Ssam hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 385712Ssam if (hp->h_refcnt == 0) 395712Ssam break; 40*5771Swnj printf("hostlookup: addr=%x\n", hp->h_addr.s_addr); 415712Ssam if (hp->h_addr.s_addr == addr.s_addr) 425712Ssam return (hp); 435712Ssam } 445712Ssam return (0); 455712Ssam } 465712Ssam 475712Ssam /* 485712Ssam * Enter a reference to this host's internet 495712Ssam * address. If no host structure exists, create 505712Ssam * one and hook it into the host database. 515712Ssam */ 525712Ssam struct host * 53*5771Swnj hostenter(addr) 545712Ssam struct in_addr addr; 555712Ssam { 565712Ssam register struct mbuf *m, *mprev; 575712Ssam register struct host *hp; 585712Ssam register int hash = HOSTHASH(addr); 595712Ssam 60*5771Swnj COUNT(HOSTENTER); 61*5771Swnj printf("hostenter(%x)\n", addr); 625712Ssam for (m = &hosttable; m; mprev = m, m = m->m_next) { 635712Ssam hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 645712Ssam if (hp->h_refcnt == 0) 655712Ssam break; 66*5771Swnj printf("hostenter: addr=%x\n", addr); 675712Ssam if (hp->h_addr.s_addr == addr.s_addr) 685712Ssam goto foundhost; 695712Ssam } 705712Ssam 715712Ssam /* 725712Ssam * No current host structure, make one. 735712Ssam * If our search ran off the end of the 745712Ssam * chain of mbuf's, allocate another. 755712Ssam */ 76*5771Swnj printf("hostenter: new host\n"); 775712Ssam if (m == 0) { 785712Ssam m = m_getclr(M_DONTWAIT); 795712Ssam if (m == 0) 805712Ssam return (0); 815712Ssam mprev->m_next = m; 825712Ssam m->m_act = mprev; 835712Ssam hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 845712Ssam } 855712Ssam mtod(m, struct hmbuf *)->hm_count++; 865712Ssam hp->h_addr = addr; 875712Ssam hp->h_status = HOSTS_UP; 885712Ssam 895712Ssam foundhost: 905712Ssam hp->h_refcnt++; /* know new structures have 0 val */ 915712Ssam return (hp); 925712Ssam } 935712Ssam 945712Ssam /* 955712Ssam * Free a reference to a host. If this causes the 965712Ssam * host structure to be released do so. 975712Ssam */ 98*5771Swnj hostfree(addr) 995712Ssam struct in_addr addr; 1005712Ssam { 1015712Ssam register struct mbuf *m; 1025712Ssam register struct host *hp; 1035712Ssam register int hash = HOSTHASH(addr); 1045712Ssam 105*5771Swnj COUNT(HOSTFREE); 106*5771Swnj printf("hostfree(%x)\n", addr); 1075712Ssam for (m = &hosttable; m; m = m->m_next) { 1085712Ssam hp = &mtod(m, struct hmbuf *)->hm_hosts[hash]; 1095712Ssam if (hp->h_refcnt == 0) 1105712Ssam return; 1115712Ssam if (hp->h_addr.s_addr == addr.s_addr) { 1125712Ssam if (--hp->h_refcnt == 0) 113*5771Swnj hostrelease(mtod(m, struct hmbuf *), hp); 1145712Ssam return; 1155712Ssam } 1165712Ssam } 117*5771Swnj panic("hostfree"); 1185712Ssam } 1195712Ssam 1205712Ssam /* 1215712Ssam * Reset a given network's host entries. 1225712Ssam * This involves clearing all packet queue's 1235712Ssam * and releasing host structures. 1245712Ssam */ 125*5771Swnj hostreset(net) 1265712Ssam int net; 1275712Ssam { 1285712Ssam register struct mbuf *m; 1295712Ssam register struct host *hp, *lp; 1305712Ssam 131*5771Swnj COUNT(HOSTRESET); 132*5771Swnj printf("hostreset(%x)\n", net); 1335712Ssam for (m = &hosttable; m; m = m->m_next) { 1345712Ssam hp = mtod(m, struct hmbuf *)->hm_hosts; 1355712Ssam lp = hp + HPMBUF; 1365712Ssam while (hp < lp) { 1375712Ssam if (hp->h_addr.s_net == net) 138*5771Swnj hostrelease(mtod(m, struct hmbuf *), hp); 1395712Ssam hp++; 1405712Ssam } 1415712Ssam } 1425712Ssam } 1435712Ssam 1445712Ssam /* 1455712Ssam * Remove a host structure and release 1465712Ssam * any resources it's accumulated. 1475712Ssam */ 148*5771Swnj hostrelease(hm, hp) 1495712Ssam struct hmbuf *hm; 1505712Ssam register struct host *hp; 1515712Ssam { 1525712Ssam register struct mbuf *m; 1535712Ssam 154*5771Swnj COUNT(HOSTRELEASE); 155*5771Swnj printf("hostrelease(%x,%x)\n", hm, hp); 1565712Ssam /* 1575712Ssam * Discard any packets left on the waiting q 1585712Ssam */ 159*5771Swnj if (m = hp->h_q) { 160*5771Swnj m = m->m_next; 161*5771Swnj hp->h_q->m_next = 0; 162*5771Swnj hp->h_q = 0; 1635712Ssam m_freem(m); 1645712Ssam } 1655712Ssam /* 1665712Ssam * We could compact the database here, but is 1675712Ssam * it worth it? For now we assume not and just 1685712Ssam * handle the simple case. 1695712Ssam */ 170*5771Swnj printf("hostrelease: count=%d\n", hm->hm_count); 1715712Ssam if (--hm->hm_count || (m = dtom(hm)) == &hosttable) 1725712Ssam return; 1735712Ssam m->m_act->m_next = m->m_next; 1745712Ssam m->m_next->m_act = m->m_act; 175*5771Swnj (void) m_free(m); 1765712Ssam } 177