149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*50234Ssklower * @(#)esis.c 7.19 (Berkeley) 06/27/91 849268Sbostic */ 949268Sbostic 1036379Ssklower /*********************************************************** 1136379Ssklower Copyright IBM Corporation 1987 1236379Ssklower 1336379Ssklower All Rights Reserved 1436379Ssklower 1536379Ssklower Permission to use, copy, modify, and distribute this software and its 1636379Ssklower documentation for any purpose and without fee is hereby granted, 1736379Ssklower provided that the above copyright notice appear in all copies and that 1836379Ssklower both that copyright notice and this permission notice appear in 1936379Ssklower supporting documentation, and that the name of IBM not be 2036379Ssklower used in advertising or publicity pertaining to distribution of the 2136379Ssklower software without specific, written prior permission. 2236379Ssklower 2336379Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436379Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536379Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636379Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736379Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836379Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936379Ssklower SOFTWARE. 3036379Ssklower 3136379Ssklower ******************************************************************/ 3236379Ssklower 3336379Ssklower /* 3436379Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536379Ssklower */ 3636379Ssklower 3736379Ssklower #ifdef ISO 3836379Ssklower 3937469Ssklower #include "types.h" 4037469Ssklower #include "param.h" 4143451Smckusick #include "systm.h" 4237469Ssklower #include "mbuf.h" 4337469Ssklower #include "domain.h" 4437469Ssklower #include "protosw.h" 4537469Ssklower #include "socket.h" 4637469Ssklower #include "socketvar.h" 4737469Ssklower #include "errno.h" 4836379Ssklower 4936379Ssklower #include "../net/if.h" 5043332Ssklower #include "../net/if_dl.h" 5136379Ssklower #include "../net/route.h" 5243421Ssklower #include "../net/raw_cb.h" 5336379Ssklower 5437469Ssklower #include "iso.h" 5537469Ssklower #include "iso_pcb.h" 5637469Ssklower #include "iso_var.h" 5737469Ssklower #include "iso_snpac.h" 5837469Ssklower #include "clnl.h" 5937469Ssklower #include "clnp.h" 6037469Ssklower #include "clnp_stat.h" 6138841Ssklower #include "esis.h" 6237469Ssklower #include "argo_debug.h" 63*50234Ssklower #include "kernel.h" 6436379Ssklower 6536379Ssklower /* 6636379Ssklower * Global variables to esis implementation 6736379Ssklower * 6836379Ssklower * esis_holding_time - the holding time (sec) parameter for outgoing pdus 6936379Ssklower * esis_config_time - the frequency (sec) that hellos are generated 7043421Ssklower * esis_esconfig_time - suggested es configuration time placed in the 7143421Ssklower * ish. 7236379Ssklower * 7336379Ssklower */ 7443421Ssklower struct rawcb esis_pcb; 75*50234Ssklower int esis_config(), snpac_age(); 7636379Ssklower int esis_sendspace = 2048; 7736379Ssklower int esis_recvspace = 2048; 7836379Ssklower short esis_holding_time = ESIS_HT; 7936379Ssklower short esis_config_time = ESIS_CONFIG; 8043421Ssklower short esis_esconfig_time = ESIS_CONFIG; 8136379Ssklower extern int iso_systype; 8243421Ssklower struct sockaddr_dl esis_dl = { sizeof(esis_dl), AF_LINK }; 8343332Ssklower extern char all_es_snpa[], all_is_snpa[]; 8436379Ssklower 8537469Ssklower #define EXTEND_PACKET(m, mhdr, cp)\ 8636379Ssklower if (((m)->m_next = m_getclr(M_DONTWAIT, MT_HEADER)) == NULL) {\ 8736379Ssklower esis_stat.es_nomem++;\ 8836379Ssklower m_freem(mhdr);\ 8936379Ssklower return;\ 9036379Ssklower } else {\ 9136379Ssklower (m) = (m)->m_next;\ 9236379Ssklower (cp) = mtod((m), caddr_t);\ 9336379Ssklower } 9436379Ssklower /* 9536379Ssklower * FUNCTION: esis_init 9636379Ssklower * 9736379Ssklower * PURPOSE: Initialize the kernel portion of esis protocol 9836379Ssklower * 9936379Ssklower * RETURNS: nothing 10036379Ssklower * 10136379Ssklower * SIDE EFFECTS: 10236379Ssklower * 10336379Ssklower * NOTES: 10436379Ssklower */ 10536379Ssklower esis_init() 10636379Ssklower { 10736379Ssklower extern struct clnl_protosw clnl_protox[256]; 10843892Ssklower int esis_input(), isis_input(); 10936379Ssklower #ifdef ISO_X25ESIS 11043892Ssklower int x25esis_input(); 11136379Ssklower #endif ISO_X25ESIS 11236379Ssklower 11343421Ssklower esis_pcb.rcb_next = esis_pcb.rcb_prev = &esis_pcb; 11443421Ssklower llinfo_llc.lc_next = llinfo_llc.lc_prev = &llinfo_llc; 11536379Ssklower 11636379Ssklower timeout(snpac_age, (caddr_t)0, hz); 11736379Ssklower timeout(esis_config, (caddr_t)0, hz); 11836379Ssklower 11943892Ssklower clnl_protox[ISO9542_ESIS].clnl_input = esis_input; 12043892Ssklower clnl_protox[ISO10589_ISIS].clnl_input = isis_input; 12136379Ssklower #ifdef ISO_X25ESIS 12236379Ssklower clnl_protox[ISO9542X25_ESIS].clnl_input = x25esis_input; 12336379Ssklower #endif ISO_X25ESIS 12436379Ssklower } 12536379Ssklower 12636379Ssklower /* 12736379Ssklower * FUNCTION: esis_usrreq 12836379Ssklower * 12936379Ssklower * PURPOSE: Handle user level esis requests 13036379Ssklower * 13136379Ssklower * RETURNS: 0 or appropriate errno 13236379Ssklower * 13336379Ssklower * SIDE EFFECTS: 13436379Ssklower * 13536379Ssklower */ 13637469Ssklower /*ARGSUSED*/ 13740775Ssklower esis_usrreq(so, req, m, nam, control) 13836379Ssklower struct socket *so; /* socket: used only to get to this code */ 13936379Ssklower int req; /* request */ 14036379Ssklower struct mbuf *m; /* data for request */ 14136379Ssklower struct mbuf *nam; /* optional name */ 14240775Ssklower struct mbuf *control; /* optional control */ 14336379Ssklower { 14443421Ssklower struct rawcb *rp = sotorawcb(so); 14543421Ssklower int error = 0; 14643421Ssklower 147*50234Ssklower if ((so->so_state & SS_PRIV) == 0) { 14843421Ssklower error = EACCES; 14943421Ssklower goto release; 15043421Ssklower } 15143421Ssklower if (rp == NULL && req != PRU_ATTACH) { 15243421Ssklower error = EINVAL; 15343421Ssklower goto release; 15443421Ssklower } 15543421Ssklower 15643421Ssklower switch (req) { 15743421Ssklower case PRU_ATTACH: 15843421Ssklower if (rp != NULL) { 15943421Ssklower error = EINVAL; 16043421Ssklower break; 16143421Ssklower } 16243421Ssklower MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); 16343421Ssklower if (so->so_pcb = (caddr_t)rp) { 16443421Ssklower bzero(so->so_pcb, sizeof(*rp)); 16543421Ssklower insque(rp, &esis_pcb); 16644946Ssklower rp->rcb_socket = so; 16743421Ssklower error = soreserve(so, esis_sendspace, esis_recvspace); 16843421Ssklower } else 16943421Ssklower error = ENOBUFS; 17043421Ssklower break; 17143421Ssklower 17243421Ssklower case PRU_SEND: 17343421Ssklower if (nam == NULL) { 17443421Ssklower error = EINVAL; 17543421Ssklower break; 17643421Ssklower } 17743421Ssklower /* error checking here */ 17843421Ssklower error = isis_output(mtod(nam,struct sockaddr_dl *), m); 17943421Ssklower m = NULL; 18043421Ssklower break; 18143421Ssklower 18243421Ssklower case PRU_DETACH: 18343421Ssklower raw_detach(rp); 18443421Ssklower break; 18543421Ssklower 18643421Ssklower case PRU_SHUTDOWN: 18743421Ssklower socantsendmore(so); 18843421Ssklower break; 18943421Ssklower 19043421Ssklower case PRU_ABORT: 19143421Ssklower soisdisconnected(so); 19243421Ssklower raw_detach(rp); 19343421Ssklower break; 19443421Ssklower 19543421Ssklower case PRU_SENSE: 19643421Ssklower return (0); 19743421Ssklower 19843421Ssklower default: 19943421Ssklower return (EOPNOTSUPP); 20043421Ssklower } 20143421Ssklower release: 20236379Ssklower if (m != NULL) 20336379Ssklower m_freem(m); 20436379Ssklower 20543421Ssklower return (error); 20636379Ssklower } 20736379Ssklower 20836379Ssklower /* 20936379Ssklower * FUNCTION: esis_input 21036379Ssklower * 21136379Ssklower * PURPOSE: Process an incoming esis packet 21236379Ssklower * 21336379Ssklower * RETURNS: nothing 21436379Ssklower * 21536379Ssklower * SIDE EFFECTS: 21636379Ssklower * 21736379Ssklower * NOTES: 21836379Ssklower */ 21936379Ssklower esis_input(m0, shp) 22036379Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 22136379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 22236379Ssklower { 22343421Ssklower register struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 22437469Ssklower register int type; 22536379Ssklower 22636379Ssklower /* 22736379Ssklower * check checksum if necessary 22836379Ssklower */ 22937469Ssklower if (ESIS_CKSUM_REQUIRED(pdu) && iso_check_csum(m0, (int)pdu->esis_hdr_len)) { 23036379Ssklower esis_stat.es_badcsum++; 23136379Ssklower goto bad; 23236379Ssklower } 23336379Ssklower 23436379Ssklower /* check version */ 23536379Ssklower if (pdu->esis_vers != ESIS_VERSION) { 23636379Ssklower esis_stat.es_badvers++; 23736379Ssklower goto bad; 23836379Ssklower } 23937469Ssklower type = pdu->esis_type & 0x1f; 24037469Ssklower switch (type) { 24136379Ssklower case ESIS_ESH: 24236379Ssklower esis_eshinput(m0, shp); 24343421Ssklower break; 24436379Ssklower 24536379Ssklower case ESIS_ISH: 24636379Ssklower esis_ishinput(m0, shp); 24743421Ssklower break; 24836379Ssklower 24936379Ssklower case ESIS_RD: 25036379Ssklower esis_rdinput(m0, shp); 25143421Ssklower break; 25236379Ssklower 25343421Ssklower default: 25436379Ssklower esis_stat.es_badtype++; 25536379Ssklower } 25636379Ssklower 25736379Ssklower bad: 25843421Ssklower if (esis_pcb.rcb_next != &esis_pcb) 25943421Ssklower isis_input(m0, shp); 26043421Ssklower else 26143421Ssklower m_freem(m0); 26236379Ssklower } 26336379Ssklower 26436379Ssklower /* 26536379Ssklower * FUNCTION: esis_rdoutput 26636379Ssklower * 26736379Ssklower * PURPOSE: Transmit a redirect pdu 26836379Ssklower * 26936379Ssklower * RETURNS: nothing 27036379Ssklower * 27136379Ssklower * SIDE EFFECTS: 27236379Ssklower * 27336379Ssklower * NOTES: Assumes there is enough space for fixed part of header, 27436379Ssklower * DA, BSNPA and NET in first mbuf. 27536379Ssklower */ 27643332Ssklower esis_rdoutput(inbound_shp, inbound_m, inbound_oidx, rd_dstnsap, rt) 27736379Ssklower struct snpa_hdr *inbound_shp; /* snpa hdr from incoming packet */ 27836379Ssklower struct mbuf *inbound_m; /* incoming pkt itself */ 27936379Ssklower struct clnp_optidx *inbound_oidx; /* clnp options assoc with incoming pkt */ 28036379Ssklower struct iso_addr *rd_dstnsap; /* ultimate destination of pkt */ 28143332Ssklower struct rtentry *rt; /* snpa cache info regarding next hop of 28236379Ssklower pkt */ 28336379Ssklower { 28436379Ssklower struct mbuf *m, *m0; 28536379Ssklower caddr_t cp; 28636379Ssklower struct esis_fixed *pdu; 28736379Ssklower int len, total_len = 0; 28836379Ssklower struct sockaddr_iso siso; 28936379Ssklower struct ifnet *ifp = inbound_shp->snh_ifp; 29043332Ssklower struct sockaddr_dl *sdl; 29143332Ssklower struct iso_addr *rd_gwnsap; 29236379Ssklower 29343332Ssklower if (rt->rt_flags & RTF_GATEWAY) { 29443332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt->rt_gateway)->siso_addr; 29543332Ssklower rt = rtalloc1(rt->rt_gateway, 0); 29643332Ssklower } else 29743332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt_key(rt))->siso_addr; 29843332Ssklower if (rt == 0 || (sdl = (struct sockaddr_dl *)rt->rt_gateway) == 0 || 29943332Ssklower sdl->sdl_family != AF_LINK) { 30043332Ssklower /* maybe we should have a function that you 30143332Ssklower could put in the iso_ifaddr structure 30243332Ssklower which could translate iso_addrs into snpa's 30343332Ssklower where there is a known mapping for that address type */ 30443332Ssklower esis_stat.es_badtype++; 30543332Ssklower return; 30643332Ssklower } 30736379Ssklower esis_stat.es_rdsent++; 30836379Ssklower IFDEBUG(D_ESISOUTPUT) 30936379Ssklower printf("esis_rdoutput: ifp x%x (%s%d), ht %d, m x%x, oidx x%x\n", 31036379Ssklower ifp, ifp->if_name, ifp->if_unit, esis_holding_time, inbound_m, 31136379Ssklower inbound_oidx); 31236379Ssklower printf("\tdestination: %s\n", clnp_iso_addrp(rd_dstnsap)); 31343332Ssklower printf("\tredirected toward:%s\n", clnp_iso_addrp(rd_gwnsap)); 31436379Ssklower ENDDEBUG 31536379Ssklower 31637469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 31736379Ssklower esis_stat.es_nomem++; 31836379Ssklower return; 31936379Ssklower } 32037469Ssklower bzero(mtod(m, caddr_t), MHLEN); 32136379Ssklower 32236379Ssklower pdu = mtod(m, struct esis_fixed *); 32337469Ssklower cp = (caddr_t)(pdu + 1); /*pointer arith.; 1st byte after header */ 32436379Ssklower len = sizeof(struct esis_fixed); 32536379Ssklower 32636379Ssklower /* 32736379Ssklower * Build fixed part of header 32836379Ssklower */ 32936379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 33036379Ssklower pdu->esis_vers = ESIS_VERSION; 33136379Ssklower pdu->esis_type = ESIS_RD; 33236379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, esis_holding_time); 33336379Ssklower 33436379Ssklower /* Insert destination address */ 33543072Ssklower (void) esis_insert_addr(&cp, &len, rd_dstnsap, m, 0); 33636379Ssklower 33736379Ssklower /* Insert the snpa of better next hop */ 33843332Ssklower *cp++ = sdl->sdl_alen; 33943332Ssklower bcopy(LLADDR(sdl), cp, sdl->sdl_alen); 34043332Ssklower cp += sdl->sdl_alen; 34143332Ssklower len += (sdl->sdl_alen + 1); 34236379Ssklower 34336379Ssklower /* 34436379Ssklower * If the next hop is not the destination, then it ought to be 34536379Ssklower * an IS and it should be inserted next. Else, set the 34636379Ssklower * NETL to 0 34736379Ssklower */ 34836379Ssklower /* PHASE2 use mask from ifp of outgoing interface */ 34943332Ssklower if (!iso_addrmatch1(rd_dstnsap, rd_gwnsap)) { 35043332Ssklower /* this should not happen: 35136379Ssklower if ((nhop_sc->sc_flags & SNPA_IS) == 0) { 35236379Ssklower printf("esis_rdoutput: next hop is not dst and not an IS\n"); 35336379Ssklower m_freem(m0); 35436379Ssklower return; 35543332Ssklower } */ 35643332Ssklower (void) esis_insert_addr(&cp, &len, rd_gwnsap, m, 0); 35736379Ssklower } else { 35836379Ssklower *cp++ = 0; /* NETL */ 35936379Ssklower len++; 36036379Ssklower } 36137469Ssklower m->m_len = len; 36236379Ssklower 36336379Ssklower /* 36436379Ssklower * PHASE2 36536379Ssklower * If redirect is to an IS, add an address mask. The mask to be 36636379Ssklower * used should be the mask present in the routing entry used to 36736379Ssklower * forward the original data packet. 36836379Ssklower */ 36936379Ssklower 37036379Ssklower /* 37136379Ssklower * Copy Qos, priority, or security options present in original npdu 37236379Ssklower */ 37336379Ssklower if (inbound_oidx) { 37443332Ssklower /* THIS CODE IS CURRENTLY (mostly) UNTESTED */ 37536379Ssklower int optlen = 0; 37636379Ssklower if (inbound_oidx->cni_qos_formatp) 37736379Ssklower optlen += (inbound_oidx->cni_qos_len + 2); 37836379Ssklower if (inbound_oidx->cni_priorp) /* priority option is 1 byte long */ 37936379Ssklower optlen += 3; 38036379Ssklower if (inbound_oidx->cni_securep) 38136379Ssklower optlen += (inbound_oidx->cni_secure_len + 2); 38237469Ssklower if (M_TRAILINGSPACE(m) < optlen) { 38337469Ssklower EXTEND_PACKET(m, m0, cp); 38437469Ssklower m->m_len = 0; 38536379Ssklower /* assumes MLEN > optlen */ 38636379Ssklower } 38736379Ssklower /* assume MLEN-len > optlen */ 38836379Ssklower /* 38936379Ssklower * When copying options, copy from ptr - 2 in order to grab 39036379Ssklower * the option code and length 39136379Ssklower */ 39236379Ssklower if (inbound_oidx->cni_qos_formatp) { 39343332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_qos_formatp - 2, 39443332Ssklower cp, (unsigned)(inbound_oidx->cni_qos_len + 2)); 39543332Ssklower cp += inbound_oidx->cni_qos_len + 2; 39636379Ssklower } 39736379Ssklower if (inbound_oidx->cni_priorp) { 39843332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_priorp - 2, 39943332Ssklower cp, 3); 40043332Ssklower cp += 3; 40136379Ssklower } 40236379Ssklower if (inbound_oidx->cni_securep) { 40343332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_securep - 2, cp, 40437469Ssklower (unsigned)(inbound_oidx->cni_secure_len + 2)); 40543332Ssklower cp += inbound_oidx->cni_secure_len + 2; 40636379Ssklower } 40737469Ssklower m->m_len += optlen; 40843332Ssklower len += optlen; 40936379Ssklower } 41036379Ssklower 41137469Ssklower pdu->esis_hdr_len = m0->m_pkthdr.len = len; 41236379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 41336379Ssklower 41437469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 41536379Ssklower siso.siso_family = AF_ISO; 41637469Ssklower siso.siso_data[0] = AFI_SNA; 41737469Ssklower siso.siso_nlen = 6 + 1; /* should be taken from snpa_hdr */ 41836379Ssklower /* +1 is for AFI */ 41937469Ssklower bcopy(inbound_shp->snh_shost, siso.siso_data + 1, 6); 42040775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 42136379Ssklower } 42236379Ssklower 42336379Ssklower /* 42436379Ssklower * FUNCTION: esis_insert_addr 42536379Ssklower * 42636379Ssklower * PURPOSE: Insert an iso_addr into a buffer 42736379Ssklower * 42836379Ssklower * RETURNS: true if buffer was big enough, else false 42936379Ssklower * 43036379Ssklower * SIDE EFFECTS: Increment buf & len according to size of iso_addr 43136379Ssklower * 43236379Ssklower * NOTES: Plus 1 here is for length byte 43336379Ssklower */ 43443072Ssklower esis_insert_addr(buf, len, isoa, m, nsellen) 43543332Ssklower register caddr_t *buf; /* ptr to buffer to put address into */ 43643332Ssklower int *len; /* ptr to length of buffer so far */ 43743332Ssklower register struct iso_addr *isoa; /* ptr to address */ 43843332Ssklower register struct mbuf *m; /* determine if there remains space */ 43943332Ssklower int nsellen; 44036379Ssklower { 44143332Ssklower register int newlen, result = 0; 44236379Ssklower 44343332Ssklower isoa->isoa_len -= nsellen; 44443332Ssklower newlen = isoa->isoa_len + 1; 44543332Ssklower if (newlen <= M_TRAILINGSPACE(m)) { 44643332Ssklower bcopy((caddr_t)isoa, *buf, newlen); 44743332Ssklower *len += newlen; 44843332Ssklower *buf += newlen; 44943332Ssklower m->m_len += newlen; 45043332Ssklower result = 1; 45143332Ssklower } 45243332Ssklower isoa->isoa_len += nsellen; 45343332Ssklower return (result); 45436379Ssklower } 45536379Ssklower 45639950Ssklower #define ESIS_EXTRACT_ADDR(d, b) { d = (struct iso_addr *)(b); b += (1 + *b); \ 45739950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45839950Ssklower #define ESIS_NEXT_OPTION(b) { b += (2 + b[1]); \ 45939950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 46043430Ssklower int ESHonly = 0; 46136379Ssklower /* 46236379Ssklower 46336379Ssklower /* 46436379Ssklower * FUNCTION: esis_eshinput 46536379Ssklower * 46636379Ssklower * PURPOSE: Process an incoming ESH pdu 46736379Ssklower * 46836379Ssklower * RETURNS: nothing 46936379Ssklower * 47036379Ssklower * SIDE EFFECTS: 47136379Ssklower * 47236379Ssklower * NOTES: 47336379Ssklower */ 47436379Ssklower esis_eshinput(m, shp) 47536379Ssklower struct mbuf *m; /* esh pdu */ 47636379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 47736379Ssklower { 47843072Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 47936379Ssklower u_short ht; /* holding time */ 48043072Ssklower struct iso_addr *nsap; 48139950Ssklower int naddr; 48237469Ssklower u_char *buf = (u_char *)(pdu + 1); 48339950Ssklower u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 48443332Ssklower int new_entry = 0; 48536379Ssklower 48636379Ssklower esis_stat.es_eshrcvd++; 48736379Ssklower 48836379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 48936379Ssklower 49039950Ssklower naddr = *buf++; 49139950Ssklower if (buf >= buflim) 49236379Ssklower goto bad; 49343332Ssklower if (naddr == 1) { 49439950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 49543332Ssklower new_entry = snpac_add(shp->snh_ifp, 49643332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, 0); 49743332Ssklower } else { 49843332Ssklower int nsellength = 0, nlen = 0; 49943332Ssklower { 50043332Ssklower /* See if we want to compress out multiple nsaps differing 50143332Ssklower only by nsel */ 50243332Ssklower register struct ifaddr *ifa = shp->snh_ifp->if_addrlist; 50343332Ssklower for (; ifa; ifa = ifa->ifa_next) 50443332Ssklower if (ifa->ifa_addr->sa_family == AF_ISO) { 50543332Ssklower nsellength = ((struct iso_ifaddr *)ifa)->ia_addr.siso_tlen; 50643332Ssklower break; 50743332Ssklower } 50843332Ssklower } 50939950Ssklower IFDEBUG(D_ESISINPUT) 51043332Ssklower printf("esis_eshinput: esh: ht %d, naddr %d nsellength %d\n", 51143332Ssklower ht, naddr, nsellength); 51239950Ssklower ENDDEBUG 51343332Ssklower while (naddr-- > 0) { 51443332Ssklower struct iso_addr *nsap2; u_char *buf2; 51543332Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 51643332Ssklower /* see if there is at least one more nsap in ESH differing 51743332Ssklower only by nsel */ 51843332Ssklower if (nsellength != 0) for (buf2 = buf; buf2 < buflim;) { 51943332Ssklower ESIS_EXTRACT_ADDR(nsap2, buf2); 52043332Ssklower IFDEBUG(D_ESISINPUT) 52143332Ssklower printf("esis_eshinput: comparing %s ", 52243332Ssklower clnp_iso_addrp(nsap)); 52343332Ssklower printf("and %s\n", clnp_iso_addrp(nsap2)); 52443332Ssklower ENDDEBUG 52543332Ssklower if (Bcmp(nsap->isoa_genaddr, nsap2->isoa_genaddr, 52643332Ssklower nsap->isoa_len - nsellength) == 0) { 52743332Ssklower nlen = nsellength; 52843332Ssklower break; 52943332Ssklower } 53043332Ssklower } 53143332Ssklower new_entry |= snpac_add(shp->snh_ifp, 53243332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, nlen); 53343332Ssklower nlen = 0; 53443332Ssklower } 53539950Ssklower } 53643332Ssklower IFDEBUG(D_ESISINPUT) 53743332Ssklower printf("esis_eshinput: nsap %s is %s\n", 53843332Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 53943332Ssklower ENDDEBUG 54043332Ssklower if (new_entry && (iso_systype & SNPA_IS)) 54143332Ssklower esis_shoutput(shp->snh_ifp, ESIS_ISH, esis_holding_time, 54243332Ssklower shp->snh_shost, 6, (struct iso_addr *)0); 54337469Ssklower bad: 54439950Ssklower return; 54536379Ssklower } 54636379Ssklower 54736379Ssklower /* 54836379Ssklower * FUNCTION: esis_ishinput 54936379Ssklower * 55036379Ssklower * PURPOSE: process an incoming ISH pdu 55136379Ssklower * 55236379Ssklower * RETURNS: 55336379Ssklower * 55436379Ssklower * SIDE EFFECTS: 55536379Ssklower * 55636379Ssklower * NOTES: 55736379Ssklower */ 55836379Ssklower esis_ishinput(m, shp) 55936379Ssklower struct mbuf *m; /* esh pdu */ 56036379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 56136379Ssklower { 56236379Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 56343430Ssklower u_short ht, newct; /* holding time */ 56439950Ssklower struct iso_addr *nsap; /* Network Entity Title */ 56539950Ssklower register u_char *buf = (u_char *) (pdu + 1); 56639950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 56739950Ssklower int new_entry; 56836379Ssklower 56936379Ssklower esis_stat.es_ishrcvd++; 57036379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 57136379Ssklower 57236379Ssklower IFDEBUG(D_ESISINPUT) 57336379Ssklower printf("esis_ishinput: ish: ht %d\n", ht); 57436379Ssklower ENDDEBUG 57539950Ssklower if (ESHonly) 57637469Ssklower goto bad; 57736379Ssklower 57839950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 57939950Ssklower 58039950Ssklower while (buf < buflim) { 58139950Ssklower switch (*buf) { 58237469Ssklower case ESISOVAL_ESCT: 58344946Ssklower if (iso_systype & SNPA_IS) 58444946Ssklower break; 58539950Ssklower if (buf[1] != 2) 58637469Ssklower goto bad; 58743430Ssklower CTOH(buf[2], buf[3], newct); 58843430Ssklower if (esis_config_time != newct) { 58943430Ssklower untimeout(esis_config,0); 59043430Ssklower esis_config_time = newct; 59143430Ssklower esis_config(); 59243430Ssklower } 59339950Ssklower break; 59439950Ssklower 59539950Ssklower default: 59639950Ssklower printf("Unknown ISH option: %x\n", *buf); 59737469Ssklower } 59839950Ssklower ESIS_NEXT_OPTION(buf); 59937469Ssklower } 60043332Ssklower new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_IS, ht, 0); 60137469Ssklower IFDEBUG(D_ESISINPUT) 60237469Ssklower printf("esis_ishinput: nsap %s is %s\n", 60337469Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 60437469Ssklower ENDDEBUG 60537469Ssklower 60637469Ssklower if (new_entry) 60737469Ssklower esis_shoutput(shp->snh_ifp, 60837469Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 60943332Ssklower esis_holding_time, shp->snh_shost, 6, (struct iso_addr *)0); 61039950Ssklower bad: 61139950Ssklower return; 61236379Ssklower } 61336379Ssklower 61436379Ssklower /* 61536379Ssklower * FUNCTION: esis_rdinput 61636379Ssklower * 61736379Ssklower * PURPOSE: Process an incoming RD pdu 61836379Ssklower * 61936379Ssklower * RETURNS: 62036379Ssklower * 62136379Ssklower * SIDE EFFECTS: 62236379Ssklower * 62336379Ssklower * NOTES: 62436379Ssklower */ 62536379Ssklower esis_rdinput(m0, shp) 62636379Ssklower struct mbuf *m0; /* esh pdu */ 62736379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 62836379Ssklower { 62936379Ssklower struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 63036379Ssklower u_short ht; /* holding time */ 63139950Ssklower struct iso_addr *da, *net = 0, *netmask = 0, *snpamask = 0; 63239950Ssklower register struct iso_addr *bsnpa; 63339950Ssklower register u_char *buf = (u_char *)(pdu + 1); 63439950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 63536379Ssklower 63636379Ssklower esis_stat.es_rdrcvd++; 63736379Ssklower 63836379Ssklower /* intermediate systems ignore redirects */ 63936379Ssklower if (iso_systype & SNPA_IS) 64043421Ssklower return; 64139950Ssklower if (ESHonly) 64243421Ssklower return; 64336379Ssklower 64436379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 64539950Ssklower if (buf >= buflim) 64643421Ssklower return; 64736379Ssklower 64836379Ssklower /* Extract DA */ 64939950Ssklower ESIS_EXTRACT_ADDR(da, buf); 65037469Ssklower 65136379Ssklower /* Extract better snpa */ 65239950Ssklower ESIS_EXTRACT_ADDR(bsnpa, buf); 65339950Ssklower 65437469Ssklower /* Extract NET if present */ 65539950Ssklower if (buf < buflim) { 65643332Ssklower if (*buf == 0) 65743332Ssklower buf++; /* no NET present, skip NETL anyway */ 65843332Ssklower else 65943332Ssklower ESIS_EXTRACT_ADDR(net, buf); 66036379Ssklower } 66136379Ssklower 66237469Ssklower /* process options */ 66339950Ssklower while (buf < buflim) { 66439950Ssklower switch (*buf) { 66537469Ssklower case ESISOVAL_SNPAMASK: 66637469Ssklower if (snpamask) /* duplicate */ 66743421Ssklower return; 66839950Ssklower snpamask = (struct iso_addr *)(buf + 1); 66937469Ssklower break; 67037469Ssklower 67137469Ssklower case ESISOVAL_NETMASK: 67237469Ssklower if (netmask) /* duplicate */ 67343421Ssklower return; 67439950Ssklower netmask = (struct iso_addr *)(buf + 1); 67539950Ssklower break; 67639950Ssklower 67739950Ssklower default: 67839950Ssklower printf("Unknown option in ESIS RD (0x%x)\n", buf[-1]); 67937469Ssklower } 68039950Ssklower ESIS_NEXT_OPTION(buf); 68136379Ssklower } 68236379Ssklower 68336379Ssklower IFDEBUG(D_ESISINPUT) 68437469Ssklower printf("esis_rdinput: rd: ht %d, da %s\n", ht, clnp_iso_addrp(da)); 68537469Ssklower if (net) 68637469Ssklower printf("\t: net %s\n", clnp_iso_addrp(net)); 68736379Ssklower ENDDEBUG 68836379Ssklower /* 68936379Ssklower * If netl is zero, then redirect is to an ES. We need to add an entry 69036379Ssklower * to the snpa cache for (destination, better snpa). 69136379Ssklower * If netl is not zero, then the redirect is to an IS. In this 69236379Ssklower * case, add an snpa cache entry for (net, better snpa). 69336379Ssklower * 69436379Ssklower * If the redirect is to an IS, add a route entry towards that 69536379Ssklower * IS. 69636379Ssklower */ 69739950Ssklower if (net == 0 || net->isoa_len == 0 || snpamask) { 69836379Ssklower /* redirect to an ES */ 69939950Ssklower snpac_add(shp->snh_ifp, da, 70043332Ssklower bsnpa->isoa_genaddr, SNPA_ES, ht, 0); 70136379Ssklower } else { 70239950Ssklower snpac_add(shp->snh_ifp, net, 70343332Ssklower bsnpa->isoa_genaddr, SNPA_IS, ht, 0); 70439950Ssklower snpac_addrt(shp->snh_ifp, da, net, netmask); 70536379Ssklower } 70643421Ssklower bad: ; /* Needed by ESIS_NEXT_OPTION */ 70736379Ssklower } 70836379Ssklower 70936379Ssklower /* 71036379Ssklower * FUNCTION: esis_config 71136379Ssklower * 71236379Ssklower * PURPOSE: Report configuration 71336379Ssklower * 71436379Ssklower * RETURNS: 71536379Ssklower * 71636379Ssklower * SIDE EFFECTS: 71736379Ssklower * 71836379Ssklower * NOTES: Called every esis_config_time seconds 71936379Ssklower */ 72036379Ssklower esis_config() 72136379Ssklower { 72236379Ssklower register struct ifnet *ifp; 72336379Ssklower 72436379Ssklower timeout(esis_config, (caddr_t)0, hz * esis_config_time); 72536379Ssklower 72636379Ssklower /* 72736379Ssklower * Report configuration for each interface that 72836379Ssklower * - is UP 72948963Ssklower * - has BROADCAST capability 73036379Ssklower * - has an ISO address 73136379Ssklower */ 73248963Ssklower /* Todo: a better way would be to construct the esh or ish 73348963Ssklower * once and copy it out for all devices, possibly calling 73448963Ssklower * a method in the iso_ifaddr structure to encapsulate and 73548963Ssklower * transmit it. This could work to advantage for non-broadcast media 73648963Ssklower */ 73736379Ssklower 73836379Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 73936379Ssklower if ((ifp->if_flags & IFF_UP) && 74048963Ssklower (ifp->if_flags & IFF_BROADCAST)) { 74136379Ssklower /* search for an ISO address family */ 74236379Ssklower struct ifaddr *ia; 74336379Ssklower 74436379Ssklower for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { 74537469Ssklower if (ia->ifa_addr->sa_family == AF_ISO) { 74636379Ssklower esis_shoutput(ifp, 74736379Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 74836379Ssklower esis_holding_time, 74943332Ssklower (caddr_t)(iso_systype & SNPA_ES ? all_is_snpa : 75043332Ssklower all_es_snpa), 6, (struct iso_addr *)0); 75136379Ssklower break; 75236379Ssklower } 75336379Ssklower } 75436379Ssklower } 75536379Ssklower } 75636379Ssklower } 75736379Ssklower 75836379Ssklower /* 75936379Ssklower * FUNCTION: esis_shoutput 76036379Ssklower * 76136379Ssklower * PURPOSE: Transmit an esh or ish pdu 76236379Ssklower * 76336379Ssklower * RETURNS: nothing 76436379Ssklower * 76536379Ssklower * SIDE EFFECTS: 76636379Ssklower * 76736379Ssklower * NOTES: 76836379Ssklower */ 76943332Ssklower esis_shoutput(ifp, type, ht, sn_addr, sn_len, isoa) 77036379Ssklower struct ifnet *ifp; 77136379Ssklower int type; 77236379Ssklower short ht; 77336379Ssklower caddr_t sn_addr; 77436379Ssklower int sn_len; 77543332Ssklower struct iso_addr *isoa; 77636379Ssklower { 77736379Ssklower struct mbuf *m, *m0; 77836379Ssklower caddr_t cp, naddrp; 77936379Ssklower int naddr = 0; 78036379Ssklower struct esis_fixed *pdu; 78143332Ssklower struct iso_ifaddr *ia; 78237469Ssklower int len; 78336379Ssklower struct sockaddr_iso siso; 78436379Ssklower 78536379Ssklower if (type == ESIS_ESH) 78636379Ssklower esis_stat.es_eshsent++; 78736379Ssklower else if (type == ESIS_ISH) 78836379Ssklower esis_stat.es_ishsent++; 78936379Ssklower else { 79036379Ssklower printf("esis_shoutput: bad pdu type\n"); 79136379Ssklower return; 79236379Ssklower } 79336379Ssklower 79436379Ssklower IFDEBUG(D_ESISOUTPUT) 79536379Ssklower int i; 79636379Ssklower printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ", 79736379Ssklower ifp, ifp->if_name, ifp->if_unit, type == ESIS_ESH ? "esh" : "ish", 79836379Ssklower ht, sn_len); 79936379Ssklower for (i=0; i<sn_len; i++) 80036379Ssklower printf("%x%c", *(sn_addr+i), i < (sn_len-1) ? ':' : ' '); 80136379Ssklower printf("\n"); 80236379Ssklower ENDDEBUG 80336379Ssklower 80437469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 80536379Ssklower esis_stat.es_nomem++; 80636379Ssklower return; 80736379Ssklower } 80837469Ssklower bzero(mtod(m, caddr_t), MHLEN); 80936379Ssklower 81036379Ssklower pdu = mtod(m, struct esis_fixed *); 81137469Ssklower naddrp = cp = (caddr_t)(pdu + 1); 81236379Ssklower len = sizeof(struct esis_fixed); 81336379Ssklower 81436379Ssklower /* 81536379Ssklower * Build fixed part of header 81636379Ssklower */ 81736379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 81836379Ssklower pdu->esis_vers = ESIS_VERSION; 81936379Ssklower pdu->esis_type = type; 82036379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 82136379Ssklower 82236379Ssklower if (type == ESIS_ESH) { 82336379Ssklower cp++; 82436379Ssklower len++; 82536379Ssklower } 82636379Ssklower 82737469Ssklower m->m_len = len; 82843332Ssklower if (isoa) { 82943332Ssklower /* 83043332Ssklower * Here we are responding to a clnp packet sent to an NSAP 83143332Ssklower * that is ours which was sent to the MAC addr all_es's. 83243332Ssklower * It is possible that we did not specifically advertise this 83343332Ssklower * NSAP, even though it is ours, so we will respond 83443332Ssklower * directly to the sender that we are here. If we do have 83543332Ssklower * multiple NSEL's we'll tack them on so he can compress them out. 83643332Ssklower */ 83743332Ssklower (void) esis_insert_addr(&cp, &len, isoa, m, 0); 83843332Ssklower naddr = 1; 83943332Ssklower } 84043332Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 84143332Ssklower int nsellen = (type == ESIS_ISH ? ia->ia_addr.siso_tlen : 0); 84243332Ssklower int n = ia->ia_addr.siso_nlen; 84343332Ssklower register struct iso_ifaddr *ia2; 84443332Ssklower 84543332Ssklower if (type == ESIS_ISH && naddr > 0) 84643332Ssklower break; 84743332Ssklower for (ia2 = iso_ifaddr; ia2 != ia; ia2 = ia2->ia_next) 84843332Ssklower if (Bcmp(ia->ia_addr.siso_data, ia2->ia_addr.siso_data, n) == 0) 84943332Ssklower break; 85043332Ssklower if (ia2 != ia) 85143332Ssklower continue; /* Means we have previously copied this nsap */ 85243332Ssklower if (isoa && Bcmp(ia->ia_addr.siso_data, isoa->isoa_genaddr, n) == 0) { 85343332Ssklower isoa = 0; 85443332Ssklower continue; /* Ditto */ 85536379Ssklower } 85643332Ssklower IFDEBUG(D_ESISOUTPUT) 85743332Ssklower printf("esis_shoutput: adding NSAP %s\n", 85843332Ssklower clnp_iso_addrp(&ia->ia_addr.siso_addr)); 85943332Ssklower ENDDEBUG 86043332Ssklower if (!esis_insert_addr(&cp, &len, 86143332Ssklower &ia->ia_addr.siso_addr, m, nsellen)) { 86243332Ssklower EXTEND_PACKET(m, m0, cp); 86343332Ssklower (void) esis_insert_addr(&cp, &len, &ia->ia_addr.siso_addr, m, 86443332Ssklower nsellen); 86543332Ssklower } 86643332Ssklower naddr++; 86736379Ssklower } 86836379Ssklower 86936379Ssklower if (type == ESIS_ESH) 87036379Ssklower *naddrp = naddr; 87144254Ssklower else { 87244254Ssklower /* add suggested es config timer option to ISH */ 87344254Ssklower if (M_TRAILINGSPACE(m) < 4) { 87444254Ssklower printf("esis_shoutput: extending packet\n"); 87544254Ssklower EXTEND_PACKET(m, m0, cp); 87644254Ssklower } 87744254Ssklower *cp++ = ESISOVAL_ESCT; 87844254Ssklower *cp++ = 2; 87944254Ssklower HTOC(*cp, *(cp+1), esis_esconfig_time); 88044254Ssklower len += 4; 88144254Ssklower m->m_len += 4; 88244254Ssklower IFDEBUG(D_ESISOUTPUT) 88344254Ssklower printf("m0 0x%x, m 0x%x, data 0x%x, len %d, cp 0x%x\n", 88444254Ssklower m0, m, m->m_data, m->m_len, cp); 88544254Ssklower ENDDEBUG 88644254Ssklower } 88736379Ssklower 88837469Ssklower m0->m_pkthdr.len = len; 88937469Ssklower pdu->esis_hdr_len = len; 89036379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 89136379Ssklower 89237469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 89336379Ssklower siso.siso_family = AF_ISO; 89437469Ssklower siso.siso_data[0] = AFI_SNA; 89537469Ssklower siso.siso_nlen = sn_len + 1; 89637469Ssklower bcopy(sn_addr, siso.siso_data + 1, (unsigned)sn_len); 89740775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 89836379Ssklower } 89936379Ssklower 90036379Ssklower /* 90143421Ssklower * FUNCTION: isis_input 90243421Ssklower * 90343421Ssklower * PURPOSE: Process an incoming isis packet 90443421Ssklower * 90543421Ssklower * RETURNS: nothing 90643421Ssklower * 90743421Ssklower * SIDE EFFECTS: 90843421Ssklower * 90943421Ssklower * NOTES: 91043421Ssklower */ 91143421Ssklower isis_input(m0, shp) 91243421Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 91343421Ssklower struct snpa_hdr *shp; /* subnetwork header */ 91443421Ssklower { 91543421Ssklower register int type; 91643961Ssklower register struct rawcb *rp, *first_rp = 0; 91743421Ssklower struct ifnet *ifp = shp->snh_ifp; 91843421Ssklower char workbuf[16]; 91943421Ssklower struct mbuf *mm; 92043421Ssklower 92143421Ssklower IFDEBUG(D_ISISINPUT) 92243421Ssklower int i; 92343421Ssklower 92443421Ssklower printf("isis_input: pkt on ifp x%x (%s%d): from:", ifp, 92543421Ssklower ifp->if_name, ifp->if_unit); 92643421Ssklower for (i=0; i<6; i++) 92743421Ssklower printf("%x%c", shp->snh_shost[i]&0xff, (i<5) ? ':' : ' '); 92843421Ssklower printf(" to:"); 92943421Ssklower for (i=0; i<6; i++) 93043421Ssklower printf("%x%c", shp->snh_dhost[i]&0xff, (i<5) ? ':' : ' '); 93143421Ssklower printf("\n"); 93243421Ssklower ENDDEBUG 93343421Ssklower esis_dl.sdl_alen = ifp->if_addrlen; 93443421Ssklower esis_dl.sdl_index = ifp->if_index; 93543421Ssklower bcopy(shp->snh_shost, (caddr_t)esis_dl.sdl_data, esis_dl.sdl_alen); 93643421Ssklower for (rp = esis_pcb.rcb_next; rp != &esis_pcb; rp = rp->rcb_next) { 93743961Ssklower if (first_rp == 0) { 93843961Ssklower first_rp = rp; 93943421Ssklower continue; 94043421Ssklower } 94143421Ssklower if (mm = m_copy(m0, 0, M_COPYALL)) { /*can't block at interrupt level */ 94243421Ssklower if (sbappendaddr(&rp->rcb_socket->so_rcv, 94343421Ssklower &esis_dl, mm, (struct mbuf *)0) != 0) 94443421Ssklower sorwakeup(rp->rcb_socket); 94543421Ssklower else { 94643421Ssklower IFDEBUG(D_ISISINPUT) 94743421Ssklower printf("Error in sbappenaddr, mm = 0x%x\n", mm); 94843421Ssklower ENDDEBUG 94943421Ssklower m_freem(mm); 95043421Ssklower } 95143421Ssklower } 95243421Ssklower } 95343961Ssklower if (first_rp && sbappendaddr(&first_rp->rcb_socket->so_rcv, 95444946Ssklower &esis_dl, m0, (struct mbuf *)0) != 0) { 95543961Ssklower sorwakeup(first_rp->rcb_socket); 95643961Ssklower return; 95743421Ssklower } 95843961Ssklower m_freem(m0); 95943421Ssklower } 96043421Ssklower 96143421Ssklower isis_output(sdl, m) 96243421Ssklower register struct sockaddr_dl *sdl; 96343421Ssklower struct mbuf *m; 96443421Ssklower { 96543421Ssklower register struct ifnet *ifp; 96643421Ssklower struct ifaddr *ifa, *ifa_ifwithnet(); 96743421Ssklower struct sockaddr_iso siso; 96843421Ssklower int error = 0; 96943421Ssklower unsigned sn_len; 97043421Ssklower 97143421Ssklower ifa = ifa_ifwithnet(sdl); /* extract ifp from sockaddr_dl */ 97243421Ssklower if (ifa == 0) { 97343421Ssklower IFDEBUG(D_ISISOUTPUT) 97443421Ssklower printf("isis_output: interface not found\n"); 97543421Ssklower ENDDEBUG 97643421Ssklower error = EINVAL; 97743421Ssklower goto release; 97843421Ssklower } 97943421Ssklower ifp = ifa->ifa_ifp; 98045896Ssklower sn_len = sdl->sdl_alen; 98143421Ssklower IFDEBUG(D_ISISOUTPUT) 98243421Ssklower u_char *cp = (u_char *)LLADDR(sdl), *cplim = cp + sn_len; 98343421Ssklower printf("isis_output: ifp 0x%x (%s%d), to: ", 98443421Ssklower ifp, ifp->if_name, ifp->if_unit); 98543421Ssklower while (cp < cplim) { 98643421Ssklower printf("%x", *cp++); 98743421Ssklower printf("%c", (cp < cplim) ? ':' : ' '); 98843421Ssklower } 98943421Ssklower printf("\n"); 99043421Ssklower ENDDEBUG 99143421Ssklower bzero((caddr_t)&siso, sizeof(siso)); 99243421Ssklower siso.siso_family = AF_ISO; /* This convention may be useful for X.25 */ 99343421Ssklower siso.siso_data[0] = AFI_SNA; 99443421Ssklower siso.siso_nlen = sn_len + 1; 99543421Ssklower bcopy(LLADDR(sdl), siso.siso_data + 1, sn_len); 99643421Ssklower error = (ifp->if_output)(ifp, m, (struct sockaddr *)&siso, 0); 99743421Ssklower if (error) { 99843421Ssklower IFDEBUG(D_ISISOUTPUT) 99943421Ssklower printf("isis_output: error from ether_output is %d\n", error); 100043421Ssklower ENDDEBUG 100143421Ssklower } 100243421Ssklower return (error); 100343421Ssklower 100443421Ssklower release: 100543421Ssklower if (m != NULL) 100643421Ssklower m_freem(m); 100743421Ssklower return(error); 100843421Ssklower } 100943421Ssklower 101043421Ssklower 101143421Ssklower /* 101236379Ssklower * FUNCTION: esis_ctlinput 101336379Ssklower * 101436379Ssklower * PURPOSE: Handle the PRC_IFDOWN transition 101536379Ssklower * 101636379Ssklower * RETURNS: nothing 101736379Ssklower * 101836379Ssklower * SIDE EFFECTS: 101936379Ssklower * 102036379Ssklower * NOTES: Calls snpac_flush for interface specified. 102136379Ssklower * The loop through iso_ifaddr is stupid because 102236379Ssklower * back in if_down, we knew the ifp... 102336379Ssklower */ 102436379Ssklower esis_ctlinput(req, siso) 102536379Ssklower int req; /* request: we handle only PRC_IFDOWN */ 102636379Ssklower struct sockaddr_iso *siso; /* address of ifp */ 102736379Ssklower { 102836379Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 102936379Ssklower 103037469Ssklower if (req == PRC_IFDOWN) 103137469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 103237469Ssklower if (iso_addrmatch(IA_SIS(ia), siso)) 103337469Ssklower snpac_flushifp(ia->ia_ifp); 103437469Ssklower } 103536379Ssklower } 103636379Ssklower 103736379Ssklower #endif ISO 1038