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*43961Ssklower /* @(#)esis.c 7.13 (Berkeley) 06/25/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" 3643451Smckusick #include "systm.h" 3737469Ssklower #include "mbuf.h" 3837469Ssklower #include "domain.h" 3937469Ssklower #include "protosw.h" 4037469Ssklower #include "user.h" 4137469Ssklower #include "socket.h" 4237469Ssklower #include "socketvar.h" 4337469Ssklower #include "errno.h" 4437469Ssklower #include "kernel.h" 4536379Ssklower 4636379Ssklower #include "../net/if.h" 4743332Ssklower #include "../net/if_dl.h" 4836379Ssklower #include "../net/route.h" 4943421Ssklower #include "../net/raw_cb.h" 5036379Ssklower 5137469Ssklower #include "iso.h" 5237469Ssklower #include "iso_pcb.h" 5337469Ssklower #include "iso_var.h" 5437469Ssklower #include "iso_snpac.h" 5537469Ssklower #include "clnl.h" 5637469Ssklower #include "clnp.h" 5737469Ssklower #include "clnp_stat.h" 5838841Ssklower #include "esis.h" 5937469Ssklower #include "argo_debug.h" 6036379Ssklower 6136379Ssklower /* 6236379Ssklower * Global variables to esis implementation 6336379Ssklower * 6436379Ssklower * esis_holding_time - the holding time (sec) parameter for outgoing pdus 6536379Ssklower * esis_config_time - the frequency (sec) that hellos are generated 6643421Ssklower * esis_esconfig_time - suggested es configuration time placed in the 6743421Ssklower * ish. 6836379Ssklower * 6936379Ssklower */ 7043421Ssklower struct rawcb esis_pcb; 7136379Ssklower int esis_sendspace = 2048; 7236379Ssklower int esis_recvspace = 2048; 7336379Ssklower short esis_holding_time = ESIS_HT; 7436379Ssklower short esis_config_time = ESIS_CONFIG; 7543421Ssklower short esis_esconfig_time = ESIS_CONFIG; 7636379Ssklower extern int iso_systype; 7743421Ssklower struct sockaddr_dl esis_dl = { sizeof(esis_dl), AF_LINK }; 7843332Ssklower extern char all_es_snpa[], all_is_snpa[]; 7936379Ssklower 8037469Ssklower #define EXTEND_PACKET(m, mhdr, cp)\ 8136379Ssklower if (((m)->m_next = m_getclr(M_DONTWAIT, MT_HEADER)) == NULL) {\ 8236379Ssklower esis_stat.es_nomem++;\ 8336379Ssklower m_freem(mhdr);\ 8436379Ssklower return;\ 8536379Ssklower } else {\ 8636379Ssklower (m) = (m)->m_next;\ 8736379Ssklower (cp) = mtod((m), caddr_t);\ 8836379Ssklower } 8936379Ssklower /* 9036379Ssklower * FUNCTION: esis_init 9136379Ssklower * 9236379Ssklower * PURPOSE: Initialize the kernel portion of esis protocol 9336379Ssklower * 9436379Ssklower * RETURNS: nothing 9536379Ssklower * 9636379Ssklower * SIDE EFFECTS: 9736379Ssklower * 9836379Ssklower * NOTES: 9936379Ssklower */ 10036379Ssklower esis_init() 10136379Ssklower { 10236379Ssklower extern struct clnl_protosw clnl_protox[256]; 10343892Ssklower int esis_input(), isis_input(); 10443892Ssklower int esis_config(), snpac_age(); 10536379Ssklower #ifdef ISO_X25ESIS 10643892Ssklower int x25esis_input(); 10736379Ssklower #endif ISO_X25ESIS 10836379Ssklower 10943421Ssklower esis_pcb.rcb_next = esis_pcb.rcb_prev = &esis_pcb; 11043421Ssklower llinfo_llc.lc_next = llinfo_llc.lc_prev = &llinfo_llc; 11136379Ssklower 11236379Ssklower timeout(snpac_age, (caddr_t)0, hz); 11336379Ssklower timeout(esis_config, (caddr_t)0, hz); 11436379Ssklower 11543892Ssklower clnl_protox[ISO9542_ESIS].clnl_input = esis_input; 11643892Ssklower clnl_protox[ISO10589_ISIS].clnl_input = isis_input; 11736379Ssklower #ifdef ISO_X25ESIS 11836379Ssklower clnl_protox[ISO9542X25_ESIS].clnl_input = x25esis_input; 11936379Ssklower #endif ISO_X25ESIS 12036379Ssklower } 12136379Ssklower 12236379Ssklower /* 12336379Ssklower * FUNCTION: esis_usrreq 12436379Ssklower * 12536379Ssklower * PURPOSE: Handle user level esis requests 12636379Ssklower * 12736379Ssklower * RETURNS: 0 or appropriate errno 12836379Ssklower * 12936379Ssklower * SIDE EFFECTS: 13036379Ssklower * 13136379Ssklower */ 13237469Ssklower /*ARGSUSED*/ 13340775Ssklower esis_usrreq(so, req, m, nam, control) 13436379Ssklower struct socket *so; /* socket: used only to get to this code */ 13536379Ssklower int req; /* request */ 13636379Ssklower struct mbuf *m; /* data for request */ 13736379Ssklower struct mbuf *nam; /* optional name */ 13840775Ssklower struct mbuf *control; /* optional control */ 13936379Ssklower { 14043421Ssklower struct rawcb *rp = sotorawcb(so); 14143421Ssklower int error = 0; 14243421Ssklower 14343421Ssklower if (suser(u.u_cred, &u.u_acflag)) { 14443421Ssklower error = EACCES; 14543421Ssklower goto release; 14643421Ssklower } 14743421Ssklower if (rp == NULL && req != PRU_ATTACH) { 14843421Ssklower error = EINVAL; 14943421Ssklower goto release; 15043421Ssklower } 15143421Ssklower 15243421Ssklower switch (req) { 15343421Ssklower case PRU_ATTACH: 15443421Ssklower if (rp != NULL) { 15543421Ssklower error = EINVAL; 15643421Ssklower break; 15743421Ssklower } 15843421Ssklower MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); 15943421Ssklower if (so->so_pcb = (caddr_t)rp) { 16043421Ssklower bzero(so->so_pcb, sizeof(*rp)); 16143421Ssklower insque(rp, &esis_pcb); 16243421Ssklower error = soreserve(so, esis_sendspace, esis_recvspace); 16343421Ssklower } else 16443421Ssklower error = ENOBUFS; 16543421Ssklower break; 16643421Ssklower 16743421Ssklower case PRU_SEND: 16843421Ssklower if (nam == NULL) { 16943421Ssklower error = EINVAL; 17043421Ssklower break; 17143421Ssklower } 17243421Ssklower /* error checking here */ 17343421Ssklower error = isis_output(mtod(nam,struct sockaddr_dl *), m); 17443421Ssklower m = NULL; 17543421Ssklower break; 17643421Ssklower 17743421Ssklower case PRU_DETACH: 17843421Ssklower raw_detach(rp); 17943421Ssklower break; 18043421Ssklower 18143421Ssklower case PRU_SHUTDOWN: 18243421Ssklower socantsendmore(so); 18343421Ssklower break; 18443421Ssklower 18543421Ssklower case PRU_ABORT: 18643421Ssklower soisdisconnected(so); 18743421Ssklower raw_detach(rp); 18843421Ssklower break; 18943421Ssklower 19043421Ssklower case PRU_SENSE: 19143421Ssklower return (0); 19243421Ssklower 19343421Ssklower default: 19443421Ssklower return (EOPNOTSUPP); 19543421Ssklower } 19643421Ssklower release: 19736379Ssklower if (m != NULL) 19836379Ssklower m_freem(m); 19936379Ssklower 20043421Ssklower return (error); 20136379Ssklower } 20236379Ssklower 20336379Ssklower /* 20436379Ssklower * FUNCTION: esis_input 20536379Ssklower * 20636379Ssklower * PURPOSE: Process an incoming esis packet 20736379Ssklower * 20836379Ssklower * RETURNS: nothing 20936379Ssklower * 21036379Ssklower * SIDE EFFECTS: 21136379Ssklower * 21236379Ssklower * NOTES: 21336379Ssklower */ 21436379Ssklower esis_input(m0, shp) 21536379Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 21636379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 21736379Ssklower { 21843421Ssklower register struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 21937469Ssklower register int type; 22036379Ssklower 22136379Ssklower /* 22236379Ssklower * check checksum if necessary 22336379Ssklower */ 22437469Ssklower if (ESIS_CKSUM_REQUIRED(pdu) && iso_check_csum(m0, (int)pdu->esis_hdr_len)) { 22536379Ssklower esis_stat.es_badcsum++; 22636379Ssklower goto bad; 22736379Ssklower } 22836379Ssklower 22936379Ssklower /* check version */ 23036379Ssklower if (pdu->esis_vers != ESIS_VERSION) { 23136379Ssklower esis_stat.es_badvers++; 23236379Ssklower goto bad; 23336379Ssklower } 23437469Ssklower type = pdu->esis_type & 0x1f; 23537469Ssklower switch (type) { 23636379Ssklower case ESIS_ESH: 23736379Ssklower esis_eshinput(m0, shp); 23843421Ssklower break; 23936379Ssklower 24036379Ssklower case ESIS_ISH: 24136379Ssklower esis_ishinput(m0, shp); 24243421Ssklower break; 24336379Ssklower 24436379Ssklower case ESIS_RD: 24536379Ssklower esis_rdinput(m0, shp); 24643421Ssklower break; 24736379Ssklower 24843421Ssklower default: 24936379Ssklower esis_stat.es_badtype++; 25036379Ssklower } 25136379Ssklower 25236379Ssklower bad: 25343421Ssklower if (esis_pcb.rcb_next != &esis_pcb) 25443421Ssklower isis_input(m0, shp); 25543421Ssklower else 25643421Ssklower m_freem(m0); 25736379Ssklower } 25836379Ssklower 25936379Ssklower /* 26036379Ssklower * FUNCTION: esis_rdoutput 26136379Ssklower * 26236379Ssklower * PURPOSE: Transmit a redirect pdu 26336379Ssklower * 26436379Ssklower * RETURNS: nothing 26536379Ssklower * 26636379Ssklower * SIDE EFFECTS: 26736379Ssklower * 26836379Ssklower * NOTES: Assumes there is enough space for fixed part of header, 26936379Ssklower * DA, BSNPA and NET in first mbuf. 27036379Ssklower */ 27143332Ssklower esis_rdoutput(inbound_shp, inbound_m, inbound_oidx, rd_dstnsap, rt) 27236379Ssklower struct snpa_hdr *inbound_shp; /* snpa hdr from incoming packet */ 27336379Ssklower struct mbuf *inbound_m; /* incoming pkt itself */ 27436379Ssklower struct clnp_optidx *inbound_oidx; /* clnp options assoc with incoming pkt */ 27536379Ssklower struct iso_addr *rd_dstnsap; /* ultimate destination of pkt */ 27643332Ssklower struct rtentry *rt; /* snpa cache info regarding next hop of 27736379Ssklower pkt */ 27836379Ssklower { 27936379Ssklower struct mbuf *m, *m0; 28036379Ssklower caddr_t cp; 28136379Ssklower struct esis_fixed *pdu; 28236379Ssklower int len, total_len = 0; 28336379Ssklower struct sockaddr_iso siso; 28436379Ssklower struct ifnet *ifp = inbound_shp->snh_ifp; 28543332Ssklower struct sockaddr_dl *sdl; 28643332Ssklower struct iso_addr *rd_gwnsap; 28736379Ssklower 28843332Ssklower if (rt->rt_flags & RTF_GATEWAY) { 28943332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt->rt_gateway)->siso_addr; 29043332Ssklower rt = rtalloc1(rt->rt_gateway, 0); 29143332Ssklower } else 29243332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt_key(rt))->siso_addr; 29343332Ssklower if (rt == 0 || (sdl = (struct sockaddr_dl *)rt->rt_gateway) == 0 || 29443332Ssklower sdl->sdl_family != AF_LINK) { 29543332Ssklower /* maybe we should have a function that you 29643332Ssklower could put in the iso_ifaddr structure 29743332Ssklower which could translate iso_addrs into snpa's 29843332Ssklower where there is a known mapping for that address type */ 29943332Ssklower esis_stat.es_badtype++; 30043332Ssklower return; 30143332Ssklower } 30236379Ssklower esis_stat.es_rdsent++; 30336379Ssklower IFDEBUG(D_ESISOUTPUT) 30436379Ssklower printf("esis_rdoutput: ifp x%x (%s%d), ht %d, m x%x, oidx x%x\n", 30536379Ssklower ifp, ifp->if_name, ifp->if_unit, esis_holding_time, inbound_m, 30636379Ssklower inbound_oidx); 30736379Ssklower printf("\tdestination: %s\n", clnp_iso_addrp(rd_dstnsap)); 30843332Ssklower printf("\tredirected toward:%s\n", clnp_iso_addrp(rd_gwnsap)); 30936379Ssklower ENDDEBUG 31036379Ssklower 31137469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 31236379Ssklower esis_stat.es_nomem++; 31336379Ssklower return; 31436379Ssklower } 31537469Ssklower bzero(mtod(m, caddr_t), MHLEN); 31636379Ssklower 31736379Ssklower pdu = mtod(m, struct esis_fixed *); 31837469Ssklower cp = (caddr_t)(pdu + 1); /*pointer arith.; 1st byte after header */ 31936379Ssklower len = sizeof(struct esis_fixed); 32036379Ssklower 32136379Ssklower /* 32236379Ssklower * Build fixed part of header 32336379Ssklower */ 32436379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 32536379Ssklower pdu->esis_vers = ESIS_VERSION; 32636379Ssklower pdu->esis_type = ESIS_RD; 32736379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, esis_holding_time); 32836379Ssklower 32936379Ssklower /* Insert destination address */ 33043072Ssklower (void) esis_insert_addr(&cp, &len, rd_dstnsap, m, 0); 33136379Ssklower 33236379Ssklower /* Insert the snpa of better next hop */ 33343332Ssklower *cp++ = sdl->sdl_alen; 33443332Ssklower bcopy(LLADDR(sdl), cp, sdl->sdl_alen); 33543332Ssklower cp += sdl->sdl_alen; 33643332Ssklower len += (sdl->sdl_alen + 1); 33736379Ssklower 33836379Ssklower /* 33936379Ssklower * If the next hop is not the destination, then it ought to be 34036379Ssklower * an IS and it should be inserted next. Else, set the 34136379Ssklower * NETL to 0 34236379Ssklower */ 34336379Ssklower /* PHASE2 use mask from ifp of outgoing interface */ 34443332Ssklower if (!iso_addrmatch1(rd_dstnsap, rd_gwnsap)) { 34543332Ssklower /* this should not happen: 34636379Ssklower if ((nhop_sc->sc_flags & SNPA_IS) == 0) { 34736379Ssklower printf("esis_rdoutput: next hop is not dst and not an IS\n"); 34836379Ssklower m_freem(m0); 34936379Ssklower return; 35043332Ssklower } */ 35143332Ssklower (void) esis_insert_addr(&cp, &len, rd_gwnsap, m, 0); 35236379Ssklower } else { 35336379Ssklower *cp++ = 0; /* NETL */ 35436379Ssklower len++; 35536379Ssklower } 35637469Ssklower m->m_len = len; 35736379Ssklower 35836379Ssklower /* 35936379Ssklower * PHASE2 36036379Ssklower * If redirect is to an IS, add an address mask. The mask to be 36136379Ssklower * used should be the mask present in the routing entry used to 36236379Ssklower * forward the original data packet. 36336379Ssklower */ 36436379Ssklower 36536379Ssklower /* 36636379Ssklower * Copy Qos, priority, or security options present in original npdu 36736379Ssklower */ 36836379Ssklower if (inbound_oidx) { 36943332Ssklower /* THIS CODE IS CURRENTLY (mostly) UNTESTED */ 37036379Ssklower int optlen = 0; 37136379Ssklower if (inbound_oidx->cni_qos_formatp) 37236379Ssklower optlen += (inbound_oidx->cni_qos_len + 2); 37336379Ssklower if (inbound_oidx->cni_priorp) /* priority option is 1 byte long */ 37436379Ssklower optlen += 3; 37536379Ssklower if (inbound_oidx->cni_securep) 37636379Ssklower optlen += (inbound_oidx->cni_secure_len + 2); 37737469Ssklower if (M_TRAILINGSPACE(m) < optlen) { 37837469Ssklower EXTEND_PACKET(m, m0, cp); 37937469Ssklower m->m_len = 0; 38036379Ssklower /* assumes MLEN > optlen */ 38136379Ssklower } 38236379Ssklower /* assume MLEN-len > optlen */ 38336379Ssklower /* 38436379Ssklower * When copying options, copy from ptr - 2 in order to grab 38536379Ssklower * the option code and length 38636379Ssklower */ 38736379Ssklower if (inbound_oidx->cni_qos_formatp) { 38843332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_qos_formatp - 2, 38943332Ssklower cp, (unsigned)(inbound_oidx->cni_qos_len + 2)); 39043332Ssklower cp += inbound_oidx->cni_qos_len + 2; 39136379Ssklower } 39236379Ssklower if (inbound_oidx->cni_priorp) { 39343332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_priorp - 2, 39443332Ssklower cp, 3); 39543332Ssklower cp += 3; 39636379Ssklower } 39736379Ssklower if (inbound_oidx->cni_securep) { 39843332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_securep - 2, cp, 39937469Ssklower (unsigned)(inbound_oidx->cni_secure_len + 2)); 40043332Ssklower cp += inbound_oidx->cni_secure_len + 2; 40136379Ssklower } 40237469Ssklower m->m_len += optlen; 40343332Ssklower len += optlen; 40436379Ssklower } 40536379Ssklower 40637469Ssklower pdu->esis_hdr_len = m0->m_pkthdr.len = len; 40736379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 40836379Ssklower 40937469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 41036379Ssklower siso.siso_family = AF_ISO; 41137469Ssklower siso.siso_data[0] = AFI_SNA; 41237469Ssklower siso.siso_nlen = 6 + 1; /* should be taken from snpa_hdr */ 41336379Ssklower /* +1 is for AFI */ 41437469Ssklower bcopy(inbound_shp->snh_shost, siso.siso_data + 1, 6); 41540775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 41636379Ssklower } 41736379Ssklower 41836379Ssklower /* 41936379Ssklower * FUNCTION: esis_insert_addr 42036379Ssklower * 42136379Ssklower * PURPOSE: Insert an iso_addr into a buffer 42236379Ssklower * 42336379Ssklower * RETURNS: true if buffer was big enough, else false 42436379Ssklower * 42536379Ssklower * SIDE EFFECTS: Increment buf & len according to size of iso_addr 42636379Ssklower * 42736379Ssklower * NOTES: Plus 1 here is for length byte 42836379Ssklower */ 42943072Ssklower esis_insert_addr(buf, len, isoa, m, nsellen) 43043332Ssklower register caddr_t *buf; /* ptr to buffer to put address into */ 43143332Ssklower int *len; /* ptr to length of buffer so far */ 43243332Ssklower register struct iso_addr *isoa; /* ptr to address */ 43343332Ssklower register struct mbuf *m; /* determine if there remains space */ 43443332Ssklower int nsellen; 43536379Ssklower { 43643332Ssklower register int newlen, result = 0; 43736379Ssklower 43843332Ssklower isoa->isoa_len -= nsellen; 43943332Ssklower newlen = isoa->isoa_len + 1; 44043332Ssklower if (newlen <= M_TRAILINGSPACE(m)) { 44143332Ssklower bcopy((caddr_t)isoa, *buf, newlen); 44243332Ssklower *len += newlen; 44343332Ssklower *buf += newlen; 44443332Ssklower m->m_len += newlen; 44543332Ssklower result = 1; 44643332Ssklower } 44743332Ssklower isoa->isoa_len += nsellen; 44843332Ssklower return (result); 44936379Ssklower } 45036379Ssklower 45139950Ssklower #define ESIS_EXTRACT_ADDR(d, b) { d = (struct iso_addr *)(b); b += (1 + *b); \ 45239950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45339950Ssklower #define ESIS_NEXT_OPTION(b) { b += (2 + b[1]); \ 45439950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45543430Ssklower int ESHonly = 0; 45636379Ssklower /* 45736379Ssklower 45836379Ssklower /* 45936379Ssklower * FUNCTION: esis_eshinput 46036379Ssklower * 46136379Ssklower * PURPOSE: Process an incoming ESH pdu 46236379Ssklower * 46336379Ssklower * RETURNS: nothing 46436379Ssklower * 46536379Ssklower * SIDE EFFECTS: 46636379Ssklower * 46736379Ssklower * NOTES: 46836379Ssklower */ 46936379Ssklower esis_eshinput(m, shp) 47036379Ssklower struct mbuf *m; /* esh pdu */ 47136379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 47236379Ssklower { 47343072Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 47436379Ssklower u_short ht; /* holding time */ 47543072Ssklower struct iso_addr *nsap; 47639950Ssklower int naddr; 47737469Ssklower u_char *buf = (u_char *)(pdu + 1); 47839950Ssklower u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 47943332Ssklower int new_entry = 0; 48036379Ssklower 48136379Ssklower esis_stat.es_eshrcvd++; 48236379Ssklower 48336379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 48436379Ssklower 48539950Ssklower naddr = *buf++; 48639950Ssklower if (buf >= buflim) 48736379Ssklower goto bad; 48843332Ssklower if (naddr == 1) { 48939950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 49043332Ssklower new_entry = snpac_add(shp->snh_ifp, 49143332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, 0); 49243332Ssklower } else { 49343332Ssklower int nsellength = 0, nlen = 0; 49443332Ssklower { 49543332Ssklower /* See if we want to compress out multiple nsaps differing 49643332Ssklower only by nsel */ 49743332Ssklower register struct ifaddr *ifa = shp->snh_ifp->if_addrlist; 49843332Ssklower for (; ifa; ifa = ifa->ifa_next) 49943332Ssklower if (ifa->ifa_addr->sa_family == AF_ISO) { 50043332Ssklower nsellength = ((struct iso_ifaddr *)ifa)->ia_addr.siso_tlen; 50143332Ssklower break; 50243332Ssklower } 50343332Ssklower } 50439950Ssklower IFDEBUG(D_ESISINPUT) 50543332Ssklower printf("esis_eshinput: esh: ht %d, naddr %d nsellength %d\n", 50643332Ssklower ht, naddr, nsellength); 50739950Ssklower ENDDEBUG 50843332Ssklower while (naddr-- > 0) { 50943332Ssklower struct iso_addr *nsap2; u_char *buf2; 51043332Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 51143332Ssklower /* see if there is at least one more nsap in ESH differing 51243332Ssklower only by nsel */ 51343332Ssklower if (nsellength != 0) for (buf2 = buf; buf2 < buflim;) { 51443332Ssklower ESIS_EXTRACT_ADDR(nsap2, buf2); 51543332Ssklower IFDEBUG(D_ESISINPUT) 51643332Ssklower printf("esis_eshinput: comparing %s ", 51743332Ssklower clnp_iso_addrp(nsap)); 51843332Ssklower printf("and %s\n", clnp_iso_addrp(nsap2)); 51943332Ssklower ENDDEBUG 52043332Ssklower if (Bcmp(nsap->isoa_genaddr, nsap2->isoa_genaddr, 52143332Ssklower nsap->isoa_len - nsellength) == 0) { 52243332Ssklower nlen = nsellength; 52343332Ssklower break; 52443332Ssklower } 52543332Ssklower } 52643332Ssklower new_entry |= snpac_add(shp->snh_ifp, 52743332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, nlen); 52843332Ssklower nlen = 0; 52943332Ssklower } 53039950Ssklower } 53143332Ssklower IFDEBUG(D_ESISINPUT) 53243332Ssklower printf("esis_eshinput: nsap %s is %s\n", 53343332Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 53443332Ssklower ENDDEBUG 53543332Ssklower if (new_entry && (iso_systype & SNPA_IS)) 53643332Ssklower esis_shoutput(shp->snh_ifp, ESIS_ISH, esis_holding_time, 53743332Ssklower shp->snh_shost, 6, (struct iso_addr *)0); 53837469Ssklower bad: 53939950Ssklower return; 54036379Ssklower } 54136379Ssklower 54236379Ssklower /* 54336379Ssklower * FUNCTION: esis_ishinput 54436379Ssklower * 54536379Ssklower * PURPOSE: process an incoming ISH pdu 54636379Ssklower * 54736379Ssklower * RETURNS: 54836379Ssklower * 54936379Ssklower * SIDE EFFECTS: 55036379Ssklower * 55136379Ssklower * NOTES: 55236379Ssklower */ 55336379Ssklower esis_ishinput(m, shp) 55436379Ssklower struct mbuf *m; /* esh pdu */ 55536379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 55636379Ssklower { 55736379Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 55843430Ssklower u_short ht, newct; /* holding time */ 55939950Ssklower struct iso_addr *nsap; /* Network Entity Title */ 56039950Ssklower register u_char *buf = (u_char *) (pdu + 1); 56139950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 56239950Ssklower int new_entry; 56336379Ssklower 56436379Ssklower esis_stat.es_ishrcvd++; 56536379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 56636379Ssklower 56736379Ssklower IFDEBUG(D_ESISINPUT) 56836379Ssklower printf("esis_ishinput: ish: ht %d\n", ht); 56936379Ssklower ENDDEBUG 57039950Ssklower if (ESHonly) 57137469Ssklower goto bad; 57236379Ssklower 57339950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 57439950Ssklower 57539950Ssklower while (buf < buflim) { 57639950Ssklower switch (*buf) { 57737469Ssklower case ESISOVAL_ESCT: 57839950Ssklower if (buf[1] != 2) 57937469Ssklower goto bad; 58043430Ssklower CTOH(buf[2], buf[3], newct); 58143430Ssklower if (esis_config_time != newct) { 58243430Ssklower untimeout(esis_config,0); 58343430Ssklower esis_config_time = newct; 58443430Ssklower esis_config(); 58543430Ssklower } 58639950Ssklower break; 58739950Ssklower 58839950Ssklower default: 58939950Ssklower printf("Unknown ISH option: %x\n", *buf); 59037469Ssklower } 59139950Ssklower ESIS_NEXT_OPTION(buf); 59237469Ssklower } 59343332Ssklower new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_IS, ht, 0); 59437469Ssklower IFDEBUG(D_ESISINPUT) 59537469Ssklower printf("esis_ishinput: nsap %s is %s\n", 59637469Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 59737469Ssklower ENDDEBUG 59837469Ssklower 59937469Ssklower if (new_entry) 60037469Ssklower esis_shoutput(shp->snh_ifp, 60137469Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 60243332Ssklower esis_holding_time, shp->snh_shost, 6, (struct iso_addr *)0); 60339950Ssklower bad: 60439950Ssklower return; 60536379Ssklower } 60636379Ssklower 60736379Ssklower /* 60836379Ssklower * FUNCTION: esis_rdinput 60936379Ssklower * 61036379Ssklower * PURPOSE: Process an incoming RD pdu 61136379Ssklower * 61236379Ssklower * RETURNS: 61336379Ssklower * 61436379Ssklower * SIDE EFFECTS: 61536379Ssklower * 61636379Ssklower * NOTES: 61736379Ssklower */ 61836379Ssklower esis_rdinput(m0, shp) 61936379Ssklower struct mbuf *m0; /* esh pdu */ 62036379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 62136379Ssklower { 62236379Ssklower struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 62336379Ssklower u_short ht; /* holding time */ 62439950Ssklower struct iso_addr *da, *net = 0, *netmask = 0, *snpamask = 0; 62539950Ssklower register struct iso_addr *bsnpa; 62639950Ssklower register u_char *buf = (u_char *)(pdu + 1); 62739950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 62836379Ssklower 62936379Ssklower esis_stat.es_rdrcvd++; 63036379Ssklower 63136379Ssklower /* intermediate systems ignore redirects */ 63236379Ssklower if (iso_systype & SNPA_IS) 63343421Ssklower return; 63439950Ssklower if (ESHonly) 63543421Ssklower return; 63636379Ssklower 63736379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 63839950Ssklower if (buf >= buflim) 63943421Ssklower return; 64036379Ssklower 64136379Ssklower /* Extract DA */ 64239950Ssklower ESIS_EXTRACT_ADDR(da, buf); 64337469Ssklower 64436379Ssklower /* Extract better snpa */ 64539950Ssklower ESIS_EXTRACT_ADDR(bsnpa, buf); 64639950Ssklower 64737469Ssklower /* Extract NET if present */ 64839950Ssklower if (buf < buflim) { 64943332Ssklower if (*buf == 0) 65043332Ssklower buf++; /* no NET present, skip NETL anyway */ 65143332Ssklower else 65243332Ssklower ESIS_EXTRACT_ADDR(net, buf); 65336379Ssklower } 65436379Ssklower 65537469Ssklower /* process options */ 65639950Ssklower while (buf < buflim) { 65739950Ssklower switch (*buf) { 65837469Ssklower case ESISOVAL_SNPAMASK: 65937469Ssklower if (snpamask) /* duplicate */ 66043421Ssklower return; 66139950Ssklower snpamask = (struct iso_addr *)(buf + 1); 66237469Ssklower break; 66337469Ssklower 66437469Ssklower case ESISOVAL_NETMASK: 66537469Ssklower if (netmask) /* duplicate */ 66643421Ssklower return; 66739950Ssklower netmask = (struct iso_addr *)(buf + 1); 66839950Ssklower break; 66939950Ssklower 67039950Ssklower default: 67139950Ssklower printf("Unknown option in ESIS RD (0x%x)\n", buf[-1]); 67237469Ssklower } 67339950Ssklower ESIS_NEXT_OPTION(buf); 67436379Ssklower } 67536379Ssklower 67636379Ssklower IFDEBUG(D_ESISINPUT) 67737469Ssklower printf("esis_rdinput: rd: ht %d, da %s\n", ht, clnp_iso_addrp(da)); 67837469Ssklower if (net) 67937469Ssklower printf("\t: net %s\n", clnp_iso_addrp(net)); 68036379Ssklower ENDDEBUG 68136379Ssklower /* 68236379Ssklower * If netl is zero, then redirect is to an ES. We need to add an entry 68336379Ssklower * to the snpa cache for (destination, better snpa). 68436379Ssklower * If netl is not zero, then the redirect is to an IS. In this 68536379Ssklower * case, add an snpa cache entry for (net, better snpa). 68636379Ssklower * 68736379Ssklower * If the redirect is to an IS, add a route entry towards that 68836379Ssklower * IS. 68936379Ssklower */ 69039950Ssklower if (net == 0 || net->isoa_len == 0 || snpamask) { 69136379Ssklower /* redirect to an ES */ 69239950Ssklower snpac_add(shp->snh_ifp, da, 69343332Ssklower bsnpa->isoa_genaddr, SNPA_ES, ht, 0); 69436379Ssklower } else { 69539950Ssklower snpac_add(shp->snh_ifp, net, 69643332Ssklower bsnpa->isoa_genaddr, SNPA_IS, ht, 0); 69739950Ssklower snpac_addrt(shp->snh_ifp, da, net, netmask); 69836379Ssklower } 69943421Ssklower bad: ; /* Needed by ESIS_NEXT_OPTION */ 70036379Ssklower } 70136379Ssklower 70236379Ssklower /* 70336379Ssklower * FUNCTION: esis_config 70436379Ssklower * 70536379Ssklower * PURPOSE: Report configuration 70636379Ssklower * 70736379Ssklower * RETURNS: 70836379Ssklower * 70936379Ssklower * SIDE EFFECTS: 71036379Ssklower * 71136379Ssklower * NOTES: Called every esis_config_time seconds 71236379Ssklower */ 71336379Ssklower esis_config() 71436379Ssklower { 71536379Ssklower register struct ifnet *ifp; 71636379Ssklower 71736379Ssklower timeout(esis_config, (caddr_t)0, hz * esis_config_time); 71836379Ssklower 71936379Ssklower /* 72036379Ssklower * Report configuration for each interface that 72136379Ssklower * - is UP 72236379Ssklower * - is not loopback 72336379Ssklower * - has an ISO address 72436379Ssklower */ 72536379Ssklower 72636379Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 72736379Ssklower if ((ifp->if_flags & IFF_UP) && 72836379Ssklower ((ifp->if_flags & IFF_LOOPBACK) == 0)) { 72936379Ssklower /* search for an ISO address family */ 73036379Ssklower struct ifaddr *ia; 73136379Ssklower 73236379Ssklower for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { 73337469Ssklower if (ia->ifa_addr->sa_family == AF_ISO) { 73436379Ssklower esis_shoutput(ifp, 73536379Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 73636379Ssklower esis_holding_time, 73743332Ssklower (caddr_t)(iso_systype & SNPA_ES ? all_is_snpa : 73843332Ssklower all_es_snpa), 6, (struct iso_addr *)0); 73936379Ssklower break; 74036379Ssklower } 74136379Ssklower } 74236379Ssklower } 74336379Ssklower } 74436379Ssklower } 74536379Ssklower 74636379Ssklower /* 74736379Ssklower * FUNCTION: esis_shoutput 74836379Ssklower * 74936379Ssklower * PURPOSE: Transmit an esh or ish pdu 75036379Ssklower * 75136379Ssklower * RETURNS: nothing 75236379Ssklower * 75336379Ssklower * SIDE EFFECTS: 75436379Ssklower * 75536379Ssklower * NOTES: 75636379Ssklower */ 75743332Ssklower esis_shoutput(ifp, type, ht, sn_addr, sn_len, isoa) 75836379Ssklower struct ifnet *ifp; 75936379Ssklower int type; 76036379Ssklower short ht; 76136379Ssklower caddr_t sn_addr; 76236379Ssklower int sn_len; 76343332Ssklower struct iso_addr *isoa; 76436379Ssklower { 76536379Ssklower struct mbuf *m, *m0; 76636379Ssklower caddr_t cp, naddrp; 76736379Ssklower int naddr = 0; 76836379Ssklower struct esis_fixed *pdu; 76943332Ssklower struct iso_ifaddr *ia; 77037469Ssklower int len; 77136379Ssklower struct sockaddr_iso siso; 77236379Ssklower 77336379Ssklower if (type == ESIS_ESH) 77436379Ssklower esis_stat.es_eshsent++; 77536379Ssklower else if (type == ESIS_ISH) 77636379Ssklower esis_stat.es_ishsent++; 77736379Ssklower else { 77836379Ssklower printf("esis_shoutput: bad pdu type\n"); 77936379Ssklower return; 78036379Ssklower } 78136379Ssklower 78236379Ssklower IFDEBUG(D_ESISOUTPUT) 78336379Ssklower int i; 78436379Ssklower printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ", 78536379Ssklower ifp, ifp->if_name, ifp->if_unit, type == ESIS_ESH ? "esh" : "ish", 78636379Ssklower ht, sn_len); 78736379Ssklower for (i=0; i<sn_len; i++) 78836379Ssklower printf("%x%c", *(sn_addr+i), i < (sn_len-1) ? ':' : ' '); 78936379Ssklower printf("\n"); 79036379Ssklower ENDDEBUG 79136379Ssklower 79237469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 79336379Ssklower esis_stat.es_nomem++; 79436379Ssklower return; 79536379Ssklower } 79637469Ssklower bzero(mtod(m, caddr_t), MHLEN); 79736379Ssklower 79836379Ssklower pdu = mtod(m, struct esis_fixed *); 79937469Ssklower naddrp = cp = (caddr_t)(pdu + 1); 80036379Ssklower len = sizeof(struct esis_fixed); 80136379Ssklower 80236379Ssklower /* 80336379Ssklower * Build fixed part of header 80436379Ssklower */ 80536379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 80636379Ssklower pdu->esis_vers = ESIS_VERSION; 80736379Ssklower pdu->esis_type = type; 80836379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 80936379Ssklower 81036379Ssklower if (type == ESIS_ESH) { 81136379Ssklower cp++; 81236379Ssklower len++; 81336379Ssklower } 81436379Ssklower 81537469Ssklower m->m_len = len; 81643332Ssklower if (isoa) { 81743332Ssklower /* 81843332Ssklower * Here we are responding to a clnp packet sent to an NSAP 81943332Ssklower * that is ours which was sent to the MAC addr all_es's. 82043332Ssklower * It is possible that we did not specifically advertise this 82143332Ssklower * NSAP, even though it is ours, so we will respond 82243332Ssklower * directly to the sender that we are here. If we do have 82343332Ssklower * multiple NSEL's we'll tack them on so he can compress them out. 82443332Ssklower */ 82543332Ssklower (void) esis_insert_addr(&cp, &len, isoa, m, 0); 82643332Ssklower naddr = 1; 82743332Ssklower } 82843332Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 82943332Ssklower int nsellen = (type == ESIS_ISH ? ia->ia_addr.siso_tlen : 0); 83043332Ssklower int n = ia->ia_addr.siso_nlen; 83143332Ssklower register struct iso_ifaddr *ia2; 83243332Ssklower 83343332Ssklower if (type == ESIS_ISH && naddr > 0) 83443332Ssklower break; 83543332Ssklower for (ia2 = iso_ifaddr; ia2 != ia; ia2 = ia2->ia_next) 83643332Ssklower if (Bcmp(ia->ia_addr.siso_data, ia2->ia_addr.siso_data, n) == 0) 83743332Ssklower break; 83843332Ssklower if (ia2 != ia) 83943332Ssklower continue; /* Means we have previously copied this nsap */ 84043332Ssklower if (isoa && Bcmp(ia->ia_addr.siso_data, isoa->isoa_genaddr, n) == 0) { 84143332Ssklower isoa = 0; 84243332Ssklower continue; /* Ditto */ 84336379Ssklower } 84443332Ssklower IFDEBUG(D_ESISOUTPUT) 84543332Ssklower printf("esis_shoutput: adding NSAP %s\n", 84643332Ssklower clnp_iso_addrp(&ia->ia_addr.siso_addr)); 84743332Ssklower ENDDEBUG 84843332Ssklower if (!esis_insert_addr(&cp, &len, 84943332Ssklower &ia->ia_addr.siso_addr, m, nsellen)) { 85043332Ssklower EXTEND_PACKET(m, m0, cp); 85143332Ssklower (void) esis_insert_addr(&cp, &len, &ia->ia_addr.siso_addr, m, 85243332Ssklower nsellen); 85343332Ssklower } 85443332Ssklower naddr++; 85536379Ssklower } 85636379Ssklower 85736379Ssklower if (type == ESIS_ESH) 85836379Ssklower *naddrp = naddr; 85936379Ssklower 86037469Ssklower m0->m_pkthdr.len = len; 86137469Ssklower pdu->esis_hdr_len = len; 86236379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 86336379Ssklower 86437469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 86536379Ssklower siso.siso_family = AF_ISO; 86637469Ssklower siso.siso_data[0] = AFI_SNA; 86737469Ssklower siso.siso_nlen = sn_len + 1; 86837469Ssklower bcopy(sn_addr, siso.siso_data + 1, (unsigned)sn_len); 86940775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 87036379Ssklower } 87136379Ssklower 87236379Ssklower /* 87343421Ssklower * FUNCTION: isis_input 87443421Ssklower * 87543421Ssklower * PURPOSE: Process an incoming isis packet 87643421Ssklower * 87743421Ssklower * RETURNS: nothing 87843421Ssklower * 87943421Ssklower * SIDE EFFECTS: 88043421Ssklower * 88143421Ssklower * NOTES: 88243421Ssklower */ 88343421Ssklower isis_input(m0, shp) 88443421Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 88543421Ssklower struct snpa_hdr *shp; /* subnetwork header */ 88643421Ssklower { 88743421Ssklower register int type; 888*43961Ssklower register struct rawcb *rp, *first_rp = 0; 88943421Ssklower struct ifnet *ifp = shp->snh_ifp; 89043421Ssklower char workbuf[16]; 89143421Ssklower struct mbuf *mm; 89243421Ssklower 89343421Ssklower IFDEBUG(D_ISISINPUT) 89443421Ssklower int i; 89543421Ssklower 89643421Ssklower printf("isis_input: pkt on ifp x%x (%s%d): from:", ifp, 89743421Ssklower ifp->if_name, ifp->if_unit); 89843421Ssklower for (i=0; i<6; i++) 89943421Ssklower printf("%x%c", shp->snh_shost[i]&0xff, (i<5) ? ':' : ' '); 90043421Ssklower printf(" to:"); 90143421Ssklower for (i=0; i<6; i++) 90243421Ssklower printf("%x%c", shp->snh_dhost[i]&0xff, (i<5) ? ':' : ' '); 90343421Ssklower printf("\n"); 90443421Ssklower ENDDEBUG 90543421Ssklower esis_dl.sdl_alen = ifp->if_addrlen; 90643421Ssklower esis_dl.sdl_index = ifp->if_index; 90743421Ssklower bcopy(shp->snh_shost, (caddr_t)esis_dl.sdl_data, esis_dl.sdl_alen); 90843421Ssklower for (rp = esis_pcb.rcb_next; rp != &esis_pcb; rp = rp->rcb_next) { 909*43961Ssklower if (first_rp == 0) { 910*43961Ssklower first_rp = rp; 91143421Ssklower continue; 91243421Ssklower } 91343421Ssklower if (mm = m_copy(m0, 0, M_COPYALL)) { /*can't block at interrupt level */ 91443421Ssklower if (sbappendaddr(&rp->rcb_socket->so_rcv, 91543421Ssklower &esis_dl, mm, (struct mbuf *)0) != 0) 91643421Ssklower sorwakeup(rp->rcb_socket); 91743421Ssklower else { 91843421Ssklower IFDEBUG(D_ISISINPUT) 91943421Ssklower printf("Error in sbappenaddr, mm = 0x%x\n", mm); 92043421Ssklower ENDDEBUG 92143421Ssklower m_freem(mm); 92243421Ssklower } 92343421Ssklower } 92443421Ssklower } 925*43961Ssklower if (first_rp && sbappendaddr(&first_rp->rcb_socket->so_rcv, 926*43961Ssklower &esis_dl, mm, (struct mbuf *)0) != 0) { 927*43961Ssklower sorwakeup(first_rp->rcb_socket); 928*43961Ssklower return; 92943421Ssklower } 930*43961Ssklower m_freem(m0); 93143421Ssklower } 93243421Ssklower 93343421Ssklower isis_output(sdl, m) 93443421Ssklower register struct sockaddr_dl *sdl; 93543421Ssklower struct mbuf *m; 93643421Ssklower { 93743421Ssklower register struct ifnet *ifp; 93843421Ssklower struct ifaddr *ifa, *ifa_ifwithnet(); 93943421Ssklower struct sockaddr_iso siso; 94043421Ssklower int error = 0; 94143421Ssklower unsigned sn_len; 94243421Ssklower 94343421Ssklower ifa = ifa_ifwithnet(sdl); /* extract ifp from sockaddr_dl */ 94443421Ssklower if (ifa == 0) { 94543421Ssklower IFDEBUG(D_ISISOUTPUT) 94643421Ssklower printf("isis_output: interface not found\n"); 94743421Ssklower ENDDEBUG 94843421Ssklower error = EINVAL; 94943421Ssklower goto release; 95043421Ssklower } 95143421Ssklower ifp = ifa->ifa_ifp; 95243421Ssklower sn_len = ifp->if_addrlen; 95343421Ssklower IFDEBUG(D_ISISOUTPUT) 95443421Ssklower u_char *cp = (u_char *)LLADDR(sdl), *cplim = cp + sn_len; 95543421Ssklower printf("isis_output: ifp 0x%x (%s%d), to: ", 95643421Ssklower ifp, ifp->if_name, ifp->if_unit); 95743421Ssklower while (cp < cplim) { 95843421Ssklower printf("%x", *cp++); 95943421Ssklower printf("%c", (cp < cplim) ? ':' : ' '); 96043421Ssklower } 96143421Ssklower printf("\n"); 96243421Ssklower ENDDEBUG 96343421Ssklower bzero((caddr_t)&siso, sizeof(siso)); 96443421Ssklower siso.siso_family = AF_ISO; /* This convention may be useful for X.25 */ 96543421Ssklower siso.siso_data[0] = AFI_SNA; 96643421Ssklower siso.siso_nlen = sn_len + 1; 96743421Ssklower bcopy(LLADDR(sdl), siso.siso_data + 1, sn_len); 96843421Ssklower error = (ifp->if_output)(ifp, m, (struct sockaddr *)&siso, 0); 96943421Ssklower if (error) { 97043421Ssklower IFDEBUG(D_ISISOUTPUT) 97143421Ssklower printf("isis_output: error from ether_output is %d\n", error); 97243421Ssklower ENDDEBUG 97343421Ssklower } 97443421Ssklower return (error); 97543421Ssklower 97643421Ssklower release: 97743421Ssklower if (m != NULL) 97843421Ssklower m_freem(m); 97943421Ssklower return(error); 98043421Ssklower } 98143421Ssklower 98243421Ssklower 98343421Ssklower /* 98436379Ssklower * FUNCTION: esis_ctlinput 98536379Ssklower * 98636379Ssklower * PURPOSE: Handle the PRC_IFDOWN transition 98736379Ssklower * 98836379Ssklower * RETURNS: nothing 98936379Ssklower * 99036379Ssklower * SIDE EFFECTS: 99136379Ssklower * 99236379Ssklower * NOTES: Calls snpac_flush for interface specified. 99336379Ssklower * The loop through iso_ifaddr is stupid because 99436379Ssklower * back in if_down, we knew the ifp... 99536379Ssklower */ 99636379Ssklower esis_ctlinput(req, siso) 99736379Ssklower int req; /* request: we handle only PRC_IFDOWN */ 99836379Ssklower struct sockaddr_iso *siso; /* address of ifp */ 99936379Ssklower { 100036379Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 100136379Ssklower 100237469Ssklower if (req == PRC_IFDOWN) 100337469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 100437469Ssklower if (iso_addrmatch(IA_SIS(ia), siso)) 100537469Ssklower snpac_flushifp(ia->ia_ifp); 100637469Ssklower } 100736379Ssklower } 100836379Ssklower 100936379Ssklower #endif ISO 1010