136379Ssklower /*********************************************************** 236379Ssklower Copyright IBM Corporation 1987 336379Ssklower 436379Ssklower All Rights Reserved 536379Ssklower 636379Ssklower Permission to use, copy, modify, and distribute this software and its 736379Ssklower documentation for any purpose and without fee is hereby granted, 836379Ssklower provided that the above copyright notice appear in all copies and that 936379Ssklower both that copyright notice and this permission notice appear in 1036379Ssklower supporting documentation, and that the name of IBM not be 1136379Ssklower used in advertising or publicity pertaining to distribution of the 1236379Ssklower software without specific, written prior permission. 1336379Ssklower 1436379Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536379Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636379Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736379Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836379Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936379Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036379Ssklower SOFTWARE. 2136379Ssklower 2236379Ssklower ******************************************************************/ 2336379Ssklower 2436379Ssklower /* 2536379Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636379Ssklower */ 27*43421Ssklower /* @(#)esis.c 7.9 (Berkeley) 06/22/90 */ 2836379Ssklower #ifndef lint 2936379Ssklower static char *rcsid = "$Header: esis.c,v 4.10 88/09/15 18:57:03 hagens Exp $"; 3036379Ssklower #endif 3136379Ssklower 3236379Ssklower #ifdef ISO 3336379Ssklower 3437469Ssklower #include "types.h" 3537469Ssklower #include "param.h" 3637469Ssklower #include "mbuf.h" 3737469Ssklower #include "domain.h" 3837469Ssklower #include "protosw.h" 3937469Ssklower #include "user.h" 4037469Ssklower #include "socket.h" 4137469Ssklower #include "socketvar.h" 4237469Ssklower #include "errno.h" 4337469Ssklower #include "kernel.h" 4436379Ssklower 4536379Ssklower #include "../net/if.h" 4643332Ssklower #include "../net/if_dl.h" 4736379Ssklower #include "../net/route.h" 48*43421Ssklower #include "../net/raw_cb.h" 4936379Ssklower 5037469Ssklower #include "iso.h" 5137469Ssklower #include "iso_pcb.h" 5237469Ssklower #include "iso_var.h" 5337469Ssklower #include "iso_snpac.h" 5437469Ssklower #include "clnl.h" 5537469Ssklower #include "clnp.h" 5637469Ssklower #include "clnp_stat.h" 5738841Ssklower #include "esis.h" 5837469Ssklower #include "argo_debug.h" 5936379Ssklower 6036379Ssklower /* 6136379Ssklower * Global variables to esis implementation 6236379Ssklower * 6336379Ssklower * esis_holding_time - the holding time (sec) parameter for outgoing pdus 6436379Ssklower * esis_config_time - the frequency (sec) that hellos are generated 65*43421Ssklower * esis_esconfig_time - suggested es configuration time placed in the 66*43421Ssklower * ish. 6736379Ssklower * 6836379Ssklower */ 69*43421Ssklower struct rawcb esis_pcb; 7036379Ssklower int esis_sendspace = 2048; 7136379Ssklower int esis_recvspace = 2048; 7236379Ssklower short esis_holding_time = ESIS_HT; 7336379Ssklower short esis_config_time = ESIS_CONFIG; 74*43421Ssklower short esis_esconfig_time = ESIS_CONFIG; 7536379Ssklower extern int iso_systype; 76*43421Ssklower struct sockaddr_dl esis_dl = { sizeof(esis_dl), AF_LINK }; 7743332Ssklower extern char all_es_snpa[], all_is_snpa[]; 7836379Ssklower 7937469Ssklower #define EXTEND_PACKET(m, mhdr, cp)\ 8036379Ssklower if (((m)->m_next = m_getclr(M_DONTWAIT, MT_HEADER)) == NULL) {\ 8136379Ssklower esis_stat.es_nomem++;\ 8236379Ssklower m_freem(mhdr);\ 8336379Ssklower return;\ 8436379Ssklower } else {\ 8536379Ssklower (m) = (m)->m_next;\ 8636379Ssklower (cp) = mtod((m), caddr_t);\ 8736379Ssklower } 8836379Ssklower /* 8936379Ssklower * FUNCTION: esis_init 9036379Ssklower * 9136379Ssklower * PURPOSE: Initialize the kernel portion of esis protocol 9236379Ssklower * 9336379Ssklower * RETURNS: nothing 9436379Ssklower * 9536379Ssklower * SIDE EFFECTS: 9636379Ssklower * 9736379Ssklower * NOTES: 9836379Ssklower */ 9936379Ssklower esis_init() 10036379Ssklower { 10136379Ssklower extern struct clnl_protosw clnl_protox[256]; 10236379Ssklower int esis_input(); 103*43421Ssklower int esis_config(); 10436379Ssklower int snpac_age(); 10536379Ssklower #ifdef ISO_X25ESIS 10636379Ssklower x25esis_input(); 10736379Ssklower #endif ISO_X25ESIS 10836379Ssklower 109*43421Ssklower esis_pcb.rcb_next = esis_pcb.rcb_prev = &esis_pcb; 110*43421Ssklower llinfo_llc.lc_next = llinfo_llc.lc_prev = &llinfo_llc; 11136379Ssklower 11236379Ssklower clnl_protox[ISO9542_ESIS].clnl_input = esis_input; 11336379Ssklower timeout(snpac_age, (caddr_t)0, hz); 11436379Ssklower timeout(esis_config, (caddr_t)0, hz); 11536379Ssklower 11636379Ssklower #ifdef ISO_X25ESIS 11736379Ssklower clnl_protox[ISO9542X25_ESIS].clnl_input = x25esis_input; 11836379Ssklower #endif ISO_X25ESIS 11936379Ssklower } 12036379Ssklower 12136379Ssklower /* 12236379Ssklower * FUNCTION: esis_usrreq 12336379Ssklower * 12436379Ssklower * PURPOSE: Handle user level esis requests 12536379Ssklower * 12636379Ssklower * RETURNS: 0 or appropriate errno 12736379Ssklower * 12836379Ssklower * SIDE EFFECTS: 12936379Ssklower * 13036379Ssklower */ 13137469Ssklower /*ARGSUSED*/ 13240775Ssklower esis_usrreq(so, req, m, nam, control) 13336379Ssklower struct socket *so; /* socket: used only to get to this code */ 13436379Ssklower int req; /* request */ 13536379Ssklower struct mbuf *m; /* data for request */ 13636379Ssklower struct mbuf *nam; /* optional name */ 13740775Ssklower struct mbuf *control; /* optional control */ 13836379Ssklower { 139*43421Ssklower struct rawcb *rp = sotorawcb(so); 140*43421Ssklower int error = 0; 141*43421Ssklower 142*43421Ssklower if (suser(u.u_cred, &u.u_acflag)) { 143*43421Ssklower error = EACCES; 144*43421Ssklower goto release; 145*43421Ssklower } 146*43421Ssklower if (rp == NULL && req != PRU_ATTACH) { 147*43421Ssklower error = EINVAL; 148*43421Ssklower goto release; 149*43421Ssklower } 150*43421Ssklower 151*43421Ssklower switch (req) { 152*43421Ssklower case PRU_ATTACH: 153*43421Ssklower if (rp != NULL) { 154*43421Ssklower error = EINVAL; 155*43421Ssklower break; 156*43421Ssklower } 157*43421Ssklower MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); 158*43421Ssklower if (so->so_pcb = (caddr_t)rp) { 159*43421Ssklower bzero(so->so_pcb, sizeof(*rp)); 160*43421Ssklower insque(rp, &esis_pcb); 161*43421Ssklower error = soreserve(so, esis_sendspace, esis_recvspace); 162*43421Ssklower } else 163*43421Ssklower error = ENOBUFS; 164*43421Ssklower break; 165*43421Ssklower 166*43421Ssklower case PRU_SEND: 167*43421Ssklower if (nam == NULL) { 168*43421Ssklower error = EINVAL; 169*43421Ssklower break; 170*43421Ssklower } 171*43421Ssklower /* error checking here */ 172*43421Ssklower error = isis_output(mtod(nam,struct sockaddr_dl *), m); 173*43421Ssklower m = NULL; 174*43421Ssklower break; 175*43421Ssklower 176*43421Ssklower case PRU_DETACH: 177*43421Ssklower raw_detach(rp); 178*43421Ssklower break; 179*43421Ssklower 180*43421Ssklower case PRU_SHUTDOWN: 181*43421Ssklower socantsendmore(so); 182*43421Ssklower break; 183*43421Ssklower 184*43421Ssklower case PRU_ABORT: 185*43421Ssklower soisdisconnected(so); 186*43421Ssklower raw_detach(rp); 187*43421Ssklower break; 188*43421Ssklower 189*43421Ssklower case PRU_SENSE: 190*43421Ssklower return (0); 191*43421Ssklower 192*43421Ssklower default: 193*43421Ssklower return (EOPNOTSUPP); 194*43421Ssklower } 195*43421Ssklower release: 19636379Ssklower if (m != NULL) 19736379Ssklower m_freem(m); 19836379Ssklower 199*43421Ssklower return (error); 20036379Ssklower } 20136379Ssklower 20236379Ssklower /* 20336379Ssklower * FUNCTION: esis_input 20436379Ssklower * 20536379Ssklower * PURPOSE: Process an incoming esis packet 20636379Ssklower * 20736379Ssklower * RETURNS: nothing 20836379Ssklower * 20936379Ssklower * SIDE EFFECTS: 21036379Ssklower * 21136379Ssklower * NOTES: 21236379Ssklower */ 21336379Ssklower esis_input(m0, shp) 21436379Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 21536379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 21636379Ssklower { 217*43421Ssklower register struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 21837469Ssklower register int type; 21936379Ssklower 22036379Ssklower /* 22136379Ssklower * check checksum if necessary 22236379Ssklower */ 22337469Ssklower if (ESIS_CKSUM_REQUIRED(pdu) && iso_check_csum(m0, (int)pdu->esis_hdr_len)) { 22436379Ssklower esis_stat.es_badcsum++; 22536379Ssklower goto bad; 22636379Ssklower } 22736379Ssklower 22836379Ssklower /* check version */ 22936379Ssklower if (pdu->esis_vers != ESIS_VERSION) { 23036379Ssklower esis_stat.es_badvers++; 23136379Ssklower goto bad; 23236379Ssklower } 23337469Ssklower type = pdu->esis_type & 0x1f; 23437469Ssklower switch (type) { 23536379Ssklower case ESIS_ESH: 23636379Ssklower esis_eshinput(m0, shp); 237*43421Ssklower break; 23836379Ssklower 23936379Ssklower case ESIS_ISH: 24036379Ssklower esis_ishinput(m0, shp); 241*43421Ssklower break; 24236379Ssklower 24336379Ssklower case ESIS_RD: 24436379Ssklower esis_rdinput(m0, shp); 245*43421Ssklower break; 24636379Ssklower 247*43421Ssklower default: 24836379Ssklower esis_stat.es_badtype++; 24936379Ssklower } 25036379Ssklower 25136379Ssklower bad: 252*43421Ssklower if (esis_pcb.rcb_next != &esis_pcb) 253*43421Ssklower isis_input(m0, shp); 254*43421Ssklower else 255*43421Ssklower m_freem(m0); 25636379Ssklower } 25736379Ssklower 25836379Ssklower /* 25936379Ssklower * FUNCTION: esis_rdoutput 26036379Ssklower * 26136379Ssklower * PURPOSE: Transmit a redirect pdu 26236379Ssklower * 26336379Ssklower * RETURNS: nothing 26436379Ssklower * 26536379Ssklower * SIDE EFFECTS: 26636379Ssklower * 26736379Ssklower * NOTES: Assumes there is enough space for fixed part of header, 26836379Ssklower * DA, BSNPA and NET in first mbuf. 26936379Ssklower */ 27043332Ssklower esis_rdoutput(inbound_shp, inbound_m, inbound_oidx, rd_dstnsap, rt) 27136379Ssklower struct snpa_hdr *inbound_shp; /* snpa hdr from incoming packet */ 27236379Ssklower struct mbuf *inbound_m; /* incoming pkt itself */ 27336379Ssklower struct clnp_optidx *inbound_oidx; /* clnp options assoc with incoming pkt */ 27436379Ssklower struct iso_addr *rd_dstnsap; /* ultimate destination of pkt */ 27543332Ssklower struct rtentry *rt; /* snpa cache info regarding next hop of 27636379Ssklower pkt */ 27736379Ssklower { 27836379Ssklower struct mbuf *m, *m0; 27936379Ssklower caddr_t cp; 28036379Ssklower struct esis_fixed *pdu; 28136379Ssklower int len, total_len = 0; 28236379Ssklower struct sockaddr_iso siso; 28336379Ssklower struct ifnet *ifp = inbound_shp->snh_ifp; 28443332Ssklower struct sockaddr_dl *sdl; 28543332Ssklower struct iso_addr *rd_gwnsap; 28636379Ssklower 28743332Ssklower if (rt->rt_flags & RTF_GATEWAY) { 28843332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt->rt_gateway)->siso_addr; 28943332Ssklower rt = rtalloc1(rt->rt_gateway, 0); 29043332Ssklower } else 29143332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt_key(rt))->siso_addr; 29243332Ssklower if (rt == 0 || (sdl = (struct sockaddr_dl *)rt->rt_gateway) == 0 || 29343332Ssklower sdl->sdl_family != AF_LINK) { 29443332Ssklower /* maybe we should have a function that you 29543332Ssklower could put in the iso_ifaddr structure 29643332Ssklower which could translate iso_addrs into snpa's 29743332Ssklower where there is a known mapping for that address type */ 29843332Ssklower esis_stat.es_badtype++; 29943332Ssklower return; 30043332Ssklower } 30136379Ssklower esis_stat.es_rdsent++; 30236379Ssklower IFDEBUG(D_ESISOUTPUT) 30336379Ssklower printf("esis_rdoutput: ifp x%x (%s%d), ht %d, m x%x, oidx x%x\n", 30436379Ssklower ifp, ifp->if_name, ifp->if_unit, esis_holding_time, inbound_m, 30536379Ssklower inbound_oidx); 30636379Ssklower printf("\tdestination: %s\n", clnp_iso_addrp(rd_dstnsap)); 30743332Ssklower printf("\tredirected toward:%s\n", clnp_iso_addrp(rd_gwnsap)); 30836379Ssklower ENDDEBUG 30936379Ssklower 31037469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 31136379Ssklower esis_stat.es_nomem++; 31236379Ssklower return; 31336379Ssklower } 31437469Ssklower bzero(mtod(m, caddr_t), MHLEN); 31536379Ssklower 31636379Ssklower pdu = mtod(m, struct esis_fixed *); 31737469Ssklower cp = (caddr_t)(pdu + 1); /*pointer arith.; 1st byte after header */ 31836379Ssklower len = sizeof(struct esis_fixed); 31936379Ssklower 32036379Ssklower /* 32136379Ssklower * Build fixed part of header 32236379Ssklower */ 32336379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 32436379Ssklower pdu->esis_vers = ESIS_VERSION; 32536379Ssklower pdu->esis_type = ESIS_RD; 32636379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, esis_holding_time); 32736379Ssklower 32836379Ssklower /* Insert destination address */ 32943072Ssklower (void) esis_insert_addr(&cp, &len, rd_dstnsap, m, 0); 33036379Ssklower 33136379Ssklower /* Insert the snpa of better next hop */ 33243332Ssklower *cp++ = sdl->sdl_alen; 33343332Ssklower bcopy(LLADDR(sdl), cp, sdl->sdl_alen); 33443332Ssklower cp += sdl->sdl_alen; 33543332Ssklower len += (sdl->sdl_alen + 1); 33636379Ssklower 33736379Ssklower /* 33836379Ssklower * If the next hop is not the destination, then it ought to be 33936379Ssklower * an IS and it should be inserted next. Else, set the 34036379Ssklower * NETL to 0 34136379Ssklower */ 34236379Ssklower /* PHASE2 use mask from ifp of outgoing interface */ 34343332Ssklower if (!iso_addrmatch1(rd_dstnsap, rd_gwnsap)) { 34443332Ssklower /* this should not happen: 34536379Ssklower if ((nhop_sc->sc_flags & SNPA_IS) == 0) { 34636379Ssklower printf("esis_rdoutput: next hop is not dst and not an IS\n"); 34736379Ssklower m_freem(m0); 34836379Ssklower return; 34943332Ssklower } */ 35043332Ssklower (void) esis_insert_addr(&cp, &len, rd_gwnsap, m, 0); 35136379Ssklower } else { 35236379Ssklower *cp++ = 0; /* NETL */ 35336379Ssklower len++; 35436379Ssklower } 35537469Ssklower m->m_len = len; 35636379Ssklower 35736379Ssklower /* 35836379Ssklower * PHASE2 35936379Ssklower * If redirect is to an IS, add an address mask. The mask to be 36036379Ssklower * used should be the mask present in the routing entry used to 36136379Ssklower * forward the original data packet. 36236379Ssklower */ 36336379Ssklower 36436379Ssklower /* 36536379Ssklower * Copy Qos, priority, or security options present in original npdu 36636379Ssklower */ 36736379Ssklower if (inbound_oidx) { 36843332Ssklower /* THIS CODE IS CURRENTLY (mostly) UNTESTED */ 36936379Ssklower int optlen = 0; 37036379Ssklower if (inbound_oidx->cni_qos_formatp) 37136379Ssklower optlen += (inbound_oidx->cni_qos_len + 2); 37236379Ssklower if (inbound_oidx->cni_priorp) /* priority option is 1 byte long */ 37336379Ssklower optlen += 3; 37436379Ssklower if (inbound_oidx->cni_securep) 37536379Ssklower optlen += (inbound_oidx->cni_secure_len + 2); 37637469Ssklower if (M_TRAILINGSPACE(m) < optlen) { 37737469Ssklower EXTEND_PACKET(m, m0, cp); 37837469Ssklower m->m_len = 0; 37936379Ssklower /* assumes MLEN > optlen */ 38036379Ssklower } 38136379Ssklower /* assume MLEN-len > optlen */ 38236379Ssklower /* 38336379Ssklower * When copying options, copy from ptr - 2 in order to grab 38436379Ssklower * the option code and length 38536379Ssklower */ 38636379Ssklower if (inbound_oidx->cni_qos_formatp) { 38743332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_qos_formatp - 2, 38843332Ssklower cp, (unsigned)(inbound_oidx->cni_qos_len + 2)); 38943332Ssklower cp += inbound_oidx->cni_qos_len + 2; 39036379Ssklower } 39136379Ssklower if (inbound_oidx->cni_priorp) { 39243332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_priorp - 2, 39343332Ssklower cp, 3); 39443332Ssklower cp += 3; 39536379Ssklower } 39636379Ssklower if (inbound_oidx->cni_securep) { 39743332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_securep - 2, cp, 39837469Ssklower (unsigned)(inbound_oidx->cni_secure_len + 2)); 39943332Ssklower cp += inbound_oidx->cni_secure_len + 2; 40036379Ssklower } 40137469Ssklower m->m_len += optlen; 40243332Ssklower len += optlen; 40336379Ssklower } 40436379Ssklower 40537469Ssklower pdu->esis_hdr_len = m0->m_pkthdr.len = len; 40636379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 40736379Ssklower 40837469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 40936379Ssklower siso.siso_family = AF_ISO; 41037469Ssklower siso.siso_data[0] = AFI_SNA; 41137469Ssklower siso.siso_nlen = 6 + 1; /* should be taken from snpa_hdr */ 41236379Ssklower /* +1 is for AFI */ 41337469Ssklower bcopy(inbound_shp->snh_shost, siso.siso_data + 1, 6); 41440775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 41536379Ssklower } 41636379Ssklower 41736379Ssklower /* 41836379Ssklower * FUNCTION: esis_insert_addr 41936379Ssklower * 42036379Ssklower * PURPOSE: Insert an iso_addr into a buffer 42136379Ssklower * 42236379Ssklower * RETURNS: true if buffer was big enough, else false 42336379Ssklower * 42436379Ssklower * SIDE EFFECTS: Increment buf & len according to size of iso_addr 42536379Ssklower * 42636379Ssklower * NOTES: Plus 1 here is for length byte 42736379Ssklower */ 42843072Ssklower esis_insert_addr(buf, len, isoa, m, nsellen) 42943332Ssklower register caddr_t *buf; /* ptr to buffer to put address into */ 43043332Ssklower int *len; /* ptr to length of buffer so far */ 43143332Ssklower register struct iso_addr *isoa; /* ptr to address */ 43243332Ssklower register struct mbuf *m; /* determine if there remains space */ 43343332Ssklower int nsellen; 43436379Ssklower { 43543332Ssklower register int newlen, result = 0; 43636379Ssklower 43743332Ssklower isoa->isoa_len -= nsellen; 43843332Ssklower newlen = isoa->isoa_len + 1; 43943332Ssklower if (newlen <= M_TRAILINGSPACE(m)) { 44043332Ssklower bcopy((caddr_t)isoa, *buf, newlen); 44143332Ssklower *len += newlen; 44243332Ssklower *buf += newlen; 44343332Ssklower m->m_len += newlen; 44443332Ssklower result = 1; 44543332Ssklower } 44643332Ssklower isoa->isoa_len += nsellen; 44743332Ssklower return (result); 44836379Ssklower } 44936379Ssklower 45039950Ssklower #define ESIS_EXTRACT_ADDR(d, b) { d = (struct iso_addr *)(b); b += (1 + *b); \ 45139950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45239950Ssklower #define ESIS_NEXT_OPTION(b) { b += (2 + b[1]); \ 45339950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45440775Ssklower int ESHonly = 1; 45536379Ssklower /* 45636379Ssklower 45736379Ssklower /* 45836379Ssklower * FUNCTION: esis_eshinput 45936379Ssklower * 46036379Ssklower * PURPOSE: Process an incoming ESH pdu 46136379Ssklower * 46236379Ssklower * RETURNS: nothing 46336379Ssklower * 46436379Ssklower * SIDE EFFECTS: 46536379Ssklower * 46636379Ssklower * NOTES: 46736379Ssklower */ 46836379Ssklower esis_eshinput(m, shp) 46936379Ssklower struct mbuf *m; /* esh pdu */ 47036379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 47136379Ssklower { 47243072Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 47336379Ssklower u_short ht; /* holding time */ 47443072Ssklower struct iso_addr *nsap; 47539950Ssklower int naddr; 47637469Ssklower u_char *buf = (u_char *)(pdu + 1); 47739950Ssklower u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 47843332Ssklower int new_entry = 0; 47936379Ssklower 48036379Ssklower esis_stat.es_eshrcvd++; 48136379Ssklower 48236379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 48336379Ssklower 48439950Ssklower naddr = *buf++; 48539950Ssklower if (buf >= buflim) 48636379Ssklower goto bad; 48743332Ssklower if (naddr == 1) { 48839950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 48943332Ssklower new_entry = snpac_add(shp->snh_ifp, 49043332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, 0); 49143332Ssklower } else { 49243332Ssklower int nsellength = 0, nlen = 0; 49343332Ssklower { 49443332Ssklower /* See if we want to compress out multiple nsaps differing 49543332Ssklower only by nsel */ 49643332Ssklower register struct ifaddr *ifa = shp->snh_ifp->if_addrlist; 49743332Ssklower for (; ifa; ifa = ifa->ifa_next) 49843332Ssklower if (ifa->ifa_addr->sa_family == AF_ISO) { 49943332Ssklower nsellength = ((struct iso_ifaddr *)ifa)->ia_addr.siso_tlen; 50043332Ssklower break; 50143332Ssklower } 50243332Ssklower } 50339950Ssklower IFDEBUG(D_ESISINPUT) 50443332Ssklower printf("esis_eshinput: esh: ht %d, naddr %d nsellength %d\n", 50543332Ssklower ht, naddr, nsellength); 50639950Ssklower ENDDEBUG 50743332Ssklower while (naddr-- > 0) { 50843332Ssklower struct iso_addr *nsap2; u_char *buf2; 50943332Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 51043332Ssklower /* see if there is at least one more nsap in ESH differing 51143332Ssklower only by nsel */ 51243332Ssklower if (nsellength != 0) for (buf2 = buf; buf2 < buflim;) { 51343332Ssklower ESIS_EXTRACT_ADDR(nsap2, buf2); 51443332Ssklower IFDEBUG(D_ESISINPUT) 51543332Ssklower printf("esis_eshinput: comparing %s ", 51643332Ssklower clnp_iso_addrp(nsap)); 51743332Ssklower printf("and %s\n", clnp_iso_addrp(nsap2)); 51843332Ssklower ENDDEBUG 51943332Ssklower if (Bcmp(nsap->isoa_genaddr, nsap2->isoa_genaddr, 52043332Ssklower nsap->isoa_len - nsellength) == 0) { 52143332Ssklower nlen = nsellength; 52243332Ssklower break; 52343332Ssklower } 52443332Ssklower } 52543332Ssklower new_entry |= snpac_add(shp->snh_ifp, 52643332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, nlen); 52743332Ssklower nlen = 0; 52843332Ssklower } 52939950Ssklower } 53043332Ssklower IFDEBUG(D_ESISINPUT) 53143332Ssklower printf("esis_eshinput: nsap %s is %s\n", 53243332Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 53343332Ssklower ENDDEBUG 53443332Ssklower if (new_entry && (iso_systype & SNPA_IS)) 53543332Ssklower esis_shoutput(shp->snh_ifp, ESIS_ISH, esis_holding_time, 53643332Ssklower shp->snh_shost, 6, (struct iso_addr *)0); 53737469Ssklower bad: 53839950Ssklower return; 53936379Ssklower } 54036379Ssklower 54136379Ssklower /* 54236379Ssklower * FUNCTION: esis_ishinput 54336379Ssklower * 54436379Ssklower * PURPOSE: process an incoming ISH pdu 54536379Ssklower * 54636379Ssklower * RETURNS: 54736379Ssklower * 54836379Ssklower * SIDE EFFECTS: 54936379Ssklower * 55036379Ssklower * NOTES: 55136379Ssklower */ 55236379Ssklower esis_ishinput(m, shp) 55336379Ssklower struct mbuf *m; /* esh pdu */ 55436379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 55536379Ssklower { 55636379Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 55739950Ssklower u_short ht; /* holding time */ 55839950Ssklower struct iso_addr *nsap; /* Network Entity Title */ 55939950Ssklower register u_char *buf = (u_char *) (pdu + 1); 56039950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 56139950Ssklower int new_entry; 56236379Ssklower 56336379Ssklower esis_stat.es_ishrcvd++; 56436379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 56536379Ssklower 56636379Ssklower IFDEBUG(D_ESISINPUT) 56736379Ssklower printf("esis_ishinput: ish: ht %d\n", ht); 56836379Ssklower ENDDEBUG 56939950Ssklower if (ESHonly) 57037469Ssklower goto bad; 57136379Ssklower 57239950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 57339950Ssklower 57439950Ssklower while (buf < buflim) { 57539950Ssklower switch (*buf) { 57637469Ssklower case ESISOVAL_ESCT: 57739950Ssklower if (buf[1] != 2) 57837469Ssklower goto bad; 57939950Ssklower CTOH(buf[2], buf[3], esis_config_time); 58039950Ssklower break; 58139950Ssklower 58239950Ssklower default: 58339950Ssklower printf("Unknown ISH option: %x\n", *buf); 58437469Ssklower } 58539950Ssklower ESIS_NEXT_OPTION(buf); 58637469Ssklower } 58743332Ssklower new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_IS, ht, 0); 58837469Ssklower IFDEBUG(D_ESISINPUT) 58937469Ssklower printf("esis_ishinput: nsap %s is %s\n", 59037469Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 59137469Ssklower ENDDEBUG 59237469Ssklower 59337469Ssklower if (new_entry) 59437469Ssklower esis_shoutput(shp->snh_ifp, 59537469Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 59643332Ssklower esis_holding_time, shp->snh_shost, 6, (struct iso_addr *)0); 59739950Ssklower bad: 59839950Ssklower return; 59936379Ssklower } 60036379Ssklower 60136379Ssklower /* 60236379Ssklower * FUNCTION: esis_rdinput 60336379Ssklower * 60436379Ssklower * PURPOSE: Process an incoming RD pdu 60536379Ssklower * 60636379Ssklower * RETURNS: 60736379Ssklower * 60836379Ssklower * SIDE EFFECTS: 60936379Ssklower * 61036379Ssklower * NOTES: 61136379Ssklower */ 61236379Ssklower esis_rdinput(m0, shp) 61336379Ssklower struct mbuf *m0; /* esh pdu */ 61436379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 61536379Ssklower { 61636379Ssklower struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 61736379Ssklower u_short ht; /* holding time */ 61839950Ssklower struct iso_addr *da, *net = 0, *netmask = 0, *snpamask = 0; 61939950Ssklower register struct iso_addr *bsnpa; 62039950Ssklower register u_char *buf = (u_char *)(pdu + 1); 62139950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 62236379Ssklower 62336379Ssklower esis_stat.es_rdrcvd++; 62436379Ssklower 62536379Ssklower /* intermediate systems ignore redirects */ 62636379Ssklower if (iso_systype & SNPA_IS) 627*43421Ssklower return; 62839950Ssklower if (ESHonly) 629*43421Ssklower return; 63036379Ssklower 63136379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 63239950Ssklower if (buf >= buflim) 633*43421Ssklower return; 63436379Ssklower 63536379Ssklower /* Extract DA */ 63639950Ssklower ESIS_EXTRACT_ADDR(da, buf); 63737469Ssklower 63836379Ssklower /* Extract better snpa */ 63939950Ssklower ESIS_EXTRACT_ADDR(bsnpa, buf); 64039950Ssklower 64137469Ssklower /* Extract NET if present */ 64239950Ssklower if (buf < buflim) { 64343332Ssklower if (*buf == 0) 64443332Ssklower buf++; /* no NET present, skip NETL anyway */ 64543332Ssklower else 64643332Ssklower ESIS_EXTRACT_ADDR(net, buf); 64736379Ssklower } 64836379Ssklower 64937469Ssklower /* process options */ 65039950Ssklower while (buf < buflim) { 65139950Ssklower switch (*buf) { 65237469Ssklower case ESISOVAL_SNPAMASK: 65337469Ssklower if (snpamask) /* duplicate */ 654*43421Ssklower return; 65539950Ssklower snpamask = (struct iso_addr *)(buf + 1); 65637469Ssklower break; 65737469Ssklower 65837469Ssklower case ESISOVAL_NETMASK: 65937469Ssklower if (netmask) /* duplicate */ 660*43421Ssklower return; 66139950Ssklower netmask = (struct iso_addr *)(buf + 1); 66239950Ssklower break; 66339950Ssklower 66439950Ssklower default: 66539950Ssklower printf("Unknown option in ESIS RD (0x%x)\n", buf[-1]); 66637469Ssklower } 66739950Ssklower ESIS_NEXT_OPTION(buf); 66836379Ssklower } 66936379Ssklower 67036379Ssklower IFDEBUG(D_ESISINPUT) 67137469Ssklower printf("esis_rdinput: rd: ht %d, da %s\n", ht, clnp_iso_addrp(da)); 67237469Ssklower if (net) 67337469Ssklower printf("\t: net %s\n", clnp_iso_addrp(net)); 67436379Ssklower ENDDEBUG 67536379Ssklower /* 67636379Ssklower * If netl is zero, then redirect is to an ES. We need to add an entry 67736379Ssklower * to the snpa cache for (destination, better snpa). 67836379Ssklower * If netl is not zero, then the redirect is to an IS. In this 67936379Ssklower * case, add an snpa cache entry for (net, better snpa). 68036379Ssklower * 68136379Ssklower * If the redirect is to an IS, add a route entry towards that 68236379Ssklower * IS. 68336379Ssklower */ 68439950Ssklower if (net == 0 || net->isoa_len == 0 || snpamask) { 68536379Ssklower /* redirect to an ES */ 68639950Ssklower snpac_add(shp->snh_ifp, da, 68743332Ssklower bsnpa->isoa_genaddr, SNPA_ES, ht, 0); 68836379Ssklower } else { 68939950Ssklower snpac_add(shp->snh_ifp, net, 69043332Ssklower bsnpa->isoa_genaddr, SNPA_IS, ht, 0); 69139950Ssklower snpac_addrt(shp->snh_ifp, da, net, netmask); 69236379Ssklower } 693*43421Ssklower bad: ; /* Needed by ESIS_NEXT_OPTION */ 69436379Ssklower } 69536379Ssklower 69636379Ssklower /* 69736379Ssklower * FUNCTION: esis_config 69836379Ssklower * 69936379Ssklower * PURPOSE: Report configuration 70036379Ssklower * 70136379Ssklower * RETURNS: 70236379Ssklower * 70336379Ssklower * SIDE EFFECTS: 70436379Ssklower * 70536379Ssklower * NOTES: Called every esis_config_time seconds 70636379Ssklower */ 70736379Ssklower esis_config() 70836379Ssklower { 70936379Ssklower register struct ifnet *ifp; 71036379Ssklower 71136379Ssklower timeout(esis_config, (caddr_t)0, hz * esis_config_time); 71236379Ssklower 71336379Ssklower /* 71436379Ssklower * Report configuration for each interface that 71536379Ssklower * - is UP 71636379Ssklower * - is not loopback 71736379Ssklower * - has an ISO address 71836379Ssklower */ 71936379Ssklower 72036379Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 72136379Ssklower if ((ifp->if_flags & IFF_UP) && 72236379Ssklower ((ifp->if_flags & IFF_LOOPBACK) == 0)) { 72336379Ssklower /* search for an ISO address family */ 72436379Ssklower struct ifaddr *ia; 72536379Ssklower 72636379Ssklower for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { 72737469Ssklower if (ia->ifa_addr->sa_family == AF_ISO) { 72836379Ssklower esis_shoutput(ifp, 72936379Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 73036379Ssklower esis_holding_time, 73143332Ssklower (caddr_t)(iso_systype & SNPA_ES ? all_is_snpa : 73243332Ssklower all_es_snpa), 6, (struct iso_addr *)0); 73336379Ssklower break; 73436379Ssklower } 73536379Ssklower } 73636379Ssklower } 73736379Ssklower } 73836379Ssklower } 73936379Ssklower 74036379Ssklower /* 74136379Ssklower * FUNCTION: esis_shoutput 74236379Ssklower * 74336379Ssklower * PURPOSE: Transmit an esh or ish pdu 74436379Ssklower * 74536379Ssklower * RETURNS: nothing 74636379Ssklower * 74736379Ssklower * SIDE EFFECTS: 74836379Ssklower * 74936379Ssklower * NOTES: 75036379Ssklower */ 75143332Ssklower esis_shoutput(ifp, type, ht, sn_addr, sn_len, isoa) 75236379Ssklower struct ifnet *ifp; 75336379Ssklower int type; 75436379Ssklower short ht; 75536379Ssklower caddr_t sn_addr; 75636379Ssklower int sn_len; 75743332Ssklower struct iso_addr *isoa; 75836379Ssklower { 75936379Ssklower struct mbuf *m, *m0; 76036379Ssklower caddr_t cp, naddrp; 76136379Ssklower int naddr = 0; 76236379Ssklower struct esis_fixed *pdu; 76343332Ssklower struct iso_ifaddr *ia; 76437469Ssklower int len; 76536379Ssklower struct sockaddr_iso siso; 76636379Ssklower 76736379Ssklower if (type == ESIS_ESH) 76836379Ssklower esis_stat.es_eshsent++; 76936379Ssklower else if (type == ESIS_ISH) 77036379Ssklower esis_stat.es_ishsent++; 77136379Ssklower else { 77236379Ssklower printf("esis_shoutput: bad pdu type\n"); 77336379Ssklower return; 77436379Ssklower } 77536379Ssklower 77636379Ssklower IFDEBUG(D_ESISOUTPUT) 77736379Ssklower int i; 77836379Ssklower printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ", 77936379Ssklower ifp, ifp->if_name, ifp->if_unit, type == ESIS_ESH ? "esh" : "ish", 78036379Ssklower ht, sn_len); 78136379Ssklower for (i=0; i<sn_len; i++) 78236379Ssklower printf("%x%c", *(sn_addr+i), i < (sn_len-1) ? ':' : ' '); 78336379Ssklower printf("\n"); 78436379Ssklower ENDDEBUG 78536379Ssklower 78637469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 78736379Ssklower esis_stat.es_nomem++; 78836379Ssklower return; 78936379Ssklower } 79037469Ssklower bzero(mtod(m, caddr_t), MHLEN); 79136379Ssklower 79236379Ssklower pdu = mtod(m, struct esis_fixed *); 79337469Ssklower naddrp = cp = (caddr_t)(pdu + 1); 79436379Ssklower len = sizeof(struct esis_fixed); 79536379Ssklower 79636379Ssklower /* 79736379Ssklower * Build fixed part of header 79836379Ssklower */ 79936379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 80036379Ssklower pdu->esis_vers = ESIS_VERSION; 80136379Ssklower pdu->esis_type = type; 80236379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 80336379Ssklower 80436379Ssklower if (type == ESIS_ESH) { 80536379Ssklower cp++; 80636379Ssklower len++; 80736379Ssklower } 80836379Ssklower 80937469Ssklower m->m_len = len; 81043332Ssklower if (isoa) { 81143332Ssklower /* 81243332Ssklower * Here we are responding to a clnp packet sent to an NSAP 81343332Ssklower * that is ours which was sent to the MAC addr all_es's. 81443332Ssklower * It is possible that we did not specifically advertise this 81543332Ssklower * NSAP, even though it is ours, so we will respond 81643332Ssklower * directly to the sender that we are here. If we do have 81743332Ssklower * multiple NSEL's we'll tack them on so he can compress them out. 81843332Ssklower */ 81943332Ssklower (void) esis_insert_addr(&cp, &len, isoa, m, 0); 82043332Ssklower naddr = 1; 82143332Ssklower } 82243332Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 82343332Ssklower int nsellen = (type == ESIS_ISH ? ia->ia_addr.siso_tlen : 0); 82443332Ssklower int n = ia->ia_addr.siso_nlen; 82543332Ssklower register struct iso_ifaddr *ia2; 82643332Ssklower 82743332Ssklower if (type == ESIS_ISH && naddr > 0) 82843332Ssklower break; 82943332Ssklower for (ia2 = iso_ifaddr; ia2 != ia; ia2 = ia2->ia_next) 83043332Ssklower if (Bcmp(ia->ia_addr.siso_data, ia2->ia_addr.siso_data, n) == 0) 83143332Ssklower break; 83243332Ssklower if (ia2 != ia) 83343332Ssklower continue; /* Means we have previously copied this nsap */ 83443332Ssklower if (isoa && Bcmp(ia->ia_addr.siso_data, isoa->isoa_genaddr, n) == 0) { 83543332Ssklower isoa = 0; 83643332Ssklower continue; /* Ditto */ 83736379Ssklower } 83843332Ssklower IFDEBUG(D_ESISOUTPUT) 83943332Ssklower printf("esis_shoutput: adding NSAP %s\n", 84043332Ssklower clnp_iso_addrp(&ia->ia_addr.siso_addr)); 84143332Ssklower ENDDEBUG 84243332Ssklower if (!esis_insert_addr(&cp, &len, 84343332Ssklower &ia->ia_addr.siso_addr, m, nsellen)) { 84443332Ssklower EXTEND_PACKET(m, m0, cp); 84543332Ssklower (void) esis_insert_addr(&cp, &len, &ia->ia_addr.siso_addr, m, 84643332Ssklower nsellen); 84743332Ssklower } 84843332Ssklower naddr++; 84936379Ssklower } 85036379Ssklower 85136379Ssklower if (type == ESIS_ESH) 85236379Ssklower *naddrp = naddr; 85336379Ssklower 85437469Ssklower m0->m_pkthdr.len = len; 85537469Ssklower pdu->esis_hdr_len = len; 85636379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 85736379Ssklower 85837469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 85936379Ssklower siso.siso_family = AF_ISO; 86037469Ssklower siso.siso_data[0] = AFI_SNA; 86137469Ssklower siso.siso_nlen = sn_len + 1; 86237469Ssklower bcopy(sn_addr, siso.siso_data + 1, (unsigned)sn_len); 86340775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 86436379Ssklower } 86536379Ssklower 86636379Ssklower /* 867*43421Ssklower * FUNCTION: isis_input 868*43421Ssklower * 869*43421Ssklower * PURPOSE: Process an incoming isis packet 870*43421Ssklower * 871*43421Ssklower * RETURNS: nothing 872*43421Ssklower * 873*43421Ssklower * SIDE EFFECTS: 874*43421Ssklower * 875*43421Ssklower * NOTES: 876*43421Ssklower */ 877*43421Ssklower isis_input(m0, shp) 878*43421Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 879*43421Ssklower struct snpa_hdr *shp; /* subnetwork header */ 880*43421Ssklower { 881*43421Ssklower register int type; 882*43421Ssklower struct rawcb *rp; 883*43421Ssklower struct ifnet *ifp = shp->snh_ifp; 884*43421Ssklower struct sockbuf *sb = 0; 885*43421Ssklower char workbuf[16]; 886*43421Ssklower struct mbuf *mm; 887*43421Ssklower 888*43421Ssklower IFDEBUG(D_ISISINPUT) 889*43421Ssklower int i; 890*43421Ssklower 891*43421Ssklower printf("isis_input: pkt on ifp x%x (%s%d): from:", ifp, 892*43421Ssklower ifp->if_name, ifp->if_unit); 893*43421Ssklower for (i=0; i<6; i++) 894*43421Ssklower printf("%x%c", shp->snh_shost[i]&0xff, (i<5) ? ':' : ' '); 895*43421Ssklower printf(" to:"); 896*43421Ssklower for (i=0; i<6; i++) 897*43421Ssklower printf("%x%c", shp->snh_dhost[i]&0xff, (i<5) ? ':' : ' '); 898*43421Ssklower printf("\n"); 899*43421Ssklower ENDDEBUG 900*43421Ssklower esis_dl.sdl_alen = ifp->if_addrlen; 901*43421Ssklower esis_dl.sdl_index = ifp->if_index; 902*43421Ssklower bcopy(shp->snh_shost, (caddr_t)esis_dl.sdl_data, esis_dl.sdl_alen); 903*43421Ssklower for (rp = esis_pcb.rcb_next; rp != &esis_pcb; rp = rp->rcb_next) { 904*43421Ssklower if (sb == 0) { 905*43421Ssklower sb = &rp->rcb_socket->so_rcv; 906*43421Ssklower continue; 907*43421Ssklower } 908*43421Ssklower if (mm = m_copy(m0, 0, M_COPYALL)) { /*can't block at interrupt level */ 909*43421Ssklower if (sbappendaddr(&rp->rcb_socket->so_rcv, 910*43421Ssklower &esis_dl, mm, (struct mbuf *)0) != 0) 911*43421Ssklower sorwakeup(rp->rcb_socket); 912*43421Ssklower else { 913*43421Ssklower IFDEBUG(D_ISISINPUT) 914*43421Ssklower printf("Error in sbappenaddr, mm = 0x%x\n", mm); 915*43421Ssklower ENDDEBUG 916*43421Ssklower m_freem(mm); 917*43421Ssklower } 918*43421Ssklower } 919*43421Ssklower } 920*43421Ssklower if (sb) { 921*43421Ssklower if (sbappendaddr(&rp->rcb_socket->so_rcv, 922*43421Ssklower &esis_dl, mm, (struct mbuf *)0) != 0) 923*43421Ssklower sorwakeup(rp->rcb_socket); 924*43421Ssklower else 925*43421Ssklower m_freem(m0); 926*43421Ssklower } 927*43421Ssklower } 928*43421Ssklower 929*43421Ssklower isis_output(sdl, m) 930*43421Ssklower register struct sockaddr_dl *sdl; 931*43421Ssklower struct mbuf *m; 932*43421Ssklower { 933*43421Ssklower register struct ifnet *ifp; 934*43421Ssklower struct ifaddr *ifa, *ifa_ifwithnet(); 935*43421Ssklower struct sockaddr_iso siso; 936*43421Ssklower int error = 0; 937*43421Ssklower unsigned sn_len; 938*43421Ssklower 939*43421Ssklower ifa = ifa_ifwithnet(sdl); /* extract ifp from sockaddr_dl */ 940*43421Ssklower if (ifa == 0) { 941*43421Ssklower IFDEBUG(D_ISISOUTPUT) 942*43421Ssklower printf("isis_output: interface not found\n"); 943*43421Ssklower ENDDEBUG 944*43421Ssklower error = EINVAL; 945*43421Ssklower goto release; 946*43421Ssklower } 947*43421Ssklower ifp = ifa->ifa_ifp; 948*43421Ssklower sn_len = ifp->if_addrlen; 949*43421Ssklower IFDEBUG(D_ISISOUTPUT) 950*43421Ssklower u_char *cp = (u_char *)LLADDR(sdl), *cplim = cp + sn_len; 951*43421Ssklower printf("isis_output: ifp 0x%x (%s%d), to: ", 952*43421Ssklower ifp, ifp->if_name, ifp->if_unit); 953*43421Ssklower while (cp < cplim) { 954*43421Ssklower printf("%x", *cp++); 955*43421Ssklower printf("%c", (cp < cplim) ? ':' : ' '); 956*43421Ssklower } 957*43421Ssklower printf("\n"); 958*43421Ssklower ENDDEBUG 959*43421Ssklower bzero((caddr_t)&siso, sizeof(siso)); 960*43421Ssklower siso.siso_family = AF_ISO; /* This convention may be useful for X.25 */ 961*43421Ssklower siso.siso_data[0] = AFI_SNA; 962*43421Ssklower siso.siso_nlen = sn_len + 1; 963*43421Ssklower bcopy(LLADDR(sdl), siso.siso_data + 1, sn_len); 964*43421Ssklower error = (ifp->if_output)(ifp, m, (struct sockaddr *)&siso, 0); 965*43421Ssklower if (error) { 966*43421Ssklower IFDEBUG(D_ISISOUTPUT) 967*43421Ssklower printf("isis_output: error from ether_output is %d\n", error); 968*43421Ssklower ENDDEBUG 969*43421Ssklower } 970*43421Ssklower return (error); 971*43421Ssklower 972*43421Ssklower release: 973*43421Ssklower if (m != NULL) 974*43421Ssklower m_freem(m); 975*43421Ssklower return(error); 976*43421Ssklower } 977*43421Ssklower 978*43421Ssklower 979*43421Ssklower /* 98036379Ssklower * FUNCTION: esis_ctlinput 98136379Ssklower * 98236379Ssklower * PURPOSE: Handle the PRC_IFDOWN transition 98336379Ssklower * 98436379Ssklower * RETURNS: nothing 98536379Ssklower * 98636379Ssklower * SIDE EFFECTS: 98736379Ssklower * 98836379Ssklower * NOTES: Calls snpac_flush for interface specified. 98936379Ssklower * The loop through iso_ifaddr is stupid because 99036379Ssklower * back in if_down, we knew the ifp... 99136379Ssklower */ 99236379Ssklower esis_ctlinput(req, siso) 99336379Ssklower int req; /* request: we handle only PRC_IFDOWN */ 99436379Ssklower struct sockaddr_iso *siso; /* address of ifp */ 99536379Ssklower { 99636379Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 99736379Ssklower 99837469Ssklower if (req == PRC_IFDOWN) 99937469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 100037469Ssklower if (iso_addrmatch(IA_SIS(ia), siso)) 100137469Ssklower snpac_flushifp(ia->ia_ifp); 100237469Ssklower } 100336379Ssklower } 100436379Ssklower 100536379Ssklower #endif ISO 1006