149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*56533Sbostic * @(#)esis.c 7.22 (Berkeley) 10/11/92 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 39*56533Sbostic #include <sys/param.h> 40*56533Sbostic #include <sys/systm.h> 41*56533Sbostic #include <sys/mbuf.h> 42*56533Sbostic #include <sys/domain.h> 43*56533Sbostic #include <sys/protosw.h> 44*56533Sbostic #include <sys/socket.h> 45*56533Sbostic #include <sys/socketvar.h> 46*56533Sbostic #include <sys/errno.h> 47*56533Sbostic #include <sys/kernel.h> 4836379Ssklower 49*56533Sbostic #include <net/if.h> 50*56533Sbostic #include <net/if_dl.h> 51*56533Sbostic #include <net/route.h> 52*56533Sbostic #include <net/raw_cb.h> 5336379Ssklower 54*56533Sbostic #include <netiso/iso.h> 55*56533Sbostic #include <netiso/iso_pcb.h> 56*56533Sbostic #include <netiso/iso_var.h> 57*56533Sbostic #include <netiso/iso_snpac.h> 58*56533Sbostic #include <netiso/clnl.h> 59*56533Sbostic #include <netiso/clnp.h> 60*56533Sbostic #include <netiso/clnp_stat.h> 61*56533Sbostic #include <netiso/esis.h> 62*56533Sbostic #include <netiso/argo_debug.h> 6336379Ssklower 6436379Ssklower /* 6536379Ssklower * Global variables to esis implementation 6636379Ssklower * 6736379Ssklower * esis_holding_time - the holding time (sec) parameter for outgoing pdus 6836379Ssklower * esis_config_time - the frequency (sec) that hellos are generated 6943421Ssklower * esis_esconfig_time - suggested es configuration time placed in the 7043421Ssklower * ish. 7136379Ssklower * 7236379Ssklower */ 7343421Ssklower struct rawcb esis_pcb; 7450234Ssklower int esis_config(), snpac_age(); 7536379Ssklower int esis_sendspace = 2048; 7636379Ssklower int esis_recvspace = 2048; 7736379Ssklower short esis_holding_time = ESIS_HT; 7836379Ssklower short esis_config_time = ESIS_CONFIG; 7943421Ssklower short esis_esconfig_time = ESIS_CONFIG; 8036379Ssklower extern int iso_systype; 8143421Ssklower struct sockaddr_dl esis_dl = { sizeof(esis_dl), AF_LINK }; 8243332Ssklower extern char all_es_snpa[], all_is_snpa[]; 8336379Ssklower 8437469Ssklower #define EXTEND_PACKET(m, mhdr, cp)\ 8536379Ssklower if (((m)->m_next = m_getclr(M_DONTWAIT, MT_HEADER)) == NULL) {\ 8636379Ssklower esis_stat.es_nomem++;\ 8736379Ssklower m_freem(mhdr);\ 8836379Ssklower return;\ 8936379Ssklower } else {\ 9036379Ssklower (m) = (m)->m_next;\ 9136379Ssklower (cp) = mtod((m), caddr_t);\ 9236379Ssklower } 9336379Ssklower /* 9436379Ssklower * FUNCTION: esis_init 9536379Ssklower * 9636379Ssklower * PURPOSE: Initialize the kernel portion of esis protocol 9736379Ssklower * 9836379Ssklower * RETURNS: nothing 9936379Ssklower * 10036379Ssklower * SIDE EFFECTS: 10136379Ssklower * 10236379Ssklower * NOTES: 10336379Ssklower */ 10436379Ssklower esis_init() 10536379Ssklower { 10636379Ssklower extern struct clnl_protosw clnl_protox[256]; 10743892Ssklower int esis_input(), isis_input(); 10836379Ssklower #ifdef ISO_X25ESIS 10943892Ssklower int x25esis_input(); 11036379Ssklower #endif ISO_X25ESIS 11136379Ssklower 11243421Ssklower esis_pcb.rcb_next = esis_pcb.rcb_prev = &esis_pcb; 11343421Ssklower llinfo_llc.lc_next = llinfo_llc.lc_prev = &llinfo_llc; 11436379Ssklower 11536379Ssklower timeout(snpac_age, (caddr_t)0, hz); 11636379Ssklower timeout(esis_config, (caddr_t)0, hz); 11736379Ssklower 11843892Ssklower clnl_protox[ISO9542_ESIS].clnl_input = esis_input; 11943892Ssklower clnl_protox[ISO10589_ISIS].clnl_input = isis_input; 12036379Ssklower #ifdef ISO_X25ESIS 12136379Ssklower clnl_protox[ISO9542X25_ESIS].clnl_input = x25esis_input; 12236379Ssklower #endif ISO_X25ESIS 12336379Ssklower } 12436379Ssklower 12536379Ssklower /* 12636379Ssklower * FUNCTION: esis_usrreq 12736379Ssklower * 12836379Ssklower * PURPOSE: Handle user level esis requests 12936379Ssklower * 13036379Ssklower * RETURNS: 0 or appropriate errno 13136379Ssklower * 13236379Ssklower * SIDE EFFECTS: 13336379Ssklower * 13436379Ssklower */ 13537469Ssklower /*ARGSUSED*/ 13640775Ssklower esis_usrreq(so, req, m, nam, control) 13736379Ssklower struct socket *so; /* socket: used only to get to this code */ 13836379Ssklower int req; /* request */ 13936379Ssklower struct mbuf *m; /* data for request */ 14036379Ssklower struct mbuf *nam; /* optional name */ 14140775Ssklower struct mbuf *control; /* optional control */ 14236379Ssklower { 14343421Ssklower struct rawcb *rp = sotorawcb(so); 14443421Ssklower int error = 0; 14543421Ssklower 14650234Ssklower if ((so->so_state & SS_PRIV) == 0) { 14743421Ssklower error = EACCES; 14843421Ssklower goto release; 14943421Ssklower } 15043421Ssklower if (rp == NULL && req != PRU_ATTACH) { 15143421Ssklower error = EINVAL; 15243421Ssklower goto release; 15343421Ssklower } 15443421Ssklower 15543421Ssklower switch (req) { 15643421Ssklower case PRU_ATTACH: 15743421Ssklower if (rp != NULL) { 15843421Ssklower error = EINVAL; 15943421Ssklower break; 16043421Ssklower } 16143421Ssklower MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); 16243421Ssklower if (so->so_pcb = (caddr_t)rp) { 16343421Ssklower bzero(so->so_pcb, sizeof(*rp)); 16443421Ssklower insque(rp, &esis_pcb); 16544946Ssklower rp->rcb_socket = so; 16643421Ssklower error = soreserve(so, esis_sendspace, esis_recvspace); 16743421Ssklower } else 16843421Ssklower error = ENOBUFS; 16943421Ssklower break; 17043421Ssklower 17143421Ssklower case PRU_SEND: 17243421Ssklower if (nam == NULL) { 17343421Ssklower error = EINVAL; 17443421Ssklower break; 17543421Ssklower } 17643421Ssklower /* error checking here */ 17743421Ssklower error = isis_output(mtod(nam,struct sockaddr_dl *), m); 17843421Ssklower m = NULL; 17943421Ssklower break; 18043421Ssklower 18143421Ssklower case PRU_DETACH: 18243421Ssklower raw_detach(rp); 18343421Ssklower break; 18443421Ssklower 18543421Ssklower case PRU_SHUTDOWN: 18643421Ssklower socantsendmore(so); 18743421Ssklower break; 18843421Ssklower 18943421Ssklower case PRU_ABORT: 19043421Ssklower soisdisconnected(so); 19143421Ssklower raw_detach(rp); 19243421Ssklower break; 19343421Ssklower 19443421Ssklower case PRU_SENSE: 19543421Ssklower return (0); 19643421Ssklower 19743421Ssklower default: 19843421Ssklower return (EOPNOTSUPP); 19943421Ssklower } 20043421Ssklower release: 20136379Ssklower if (m != NULL) 20236379Ssklower m_freem(m); 20336379Ssklower 20443421Ssklower return (error); 20536379Ssklower } 20636379Ssklower 20736379Ssklower /* 20836379Ssklower * FUNCTION: esis_input 20936379Ssklower * 21036379Ssklower * PURPOSE: Process an incoming esis packet 21136379Ssklower * 21236379Ssklower * RETURNS: nothing 21336379Ssklower * 21436379Ssklower * SIDE EFFECTS: 21536379Ssklower * 21636379Ssklower * NOTES: 21736379Ssklower */ 21836379Ssklower esis_input(m0, shp) 21936379Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 22036379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 22136379Ssklower { 22243421Ssklower register struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 22337469Ssklower register int type; 22436379Ssklower 22536379Ssklower /* 22636379Ssklower * check checksum if necessary 22736379Ssklower */ 22837469Ssklower if (ESIS_CKSUM_REQUIRED(pdu) && iso_check_csum(m0, (int)pdu->esis_hdr_len)) { 22936379Ssklower esis_stat.es_badcsum++; 23036379Ssklower goto bad; 23136379Ssklower } 23236379Ssklower 23336379Ssklower /* check version */ 23436379Ssklower if (pdu->esis_vers != ESIS_VERSION) { 23536379Ssklower esis_stat.es_badvers++; 23636379Ssklower goto bad; 23736379Ssklower } 23837469Ssklower type = pdu->esis_type & 0x1f; 23937469Ssklower switch (type) { 24036379Ssklower case ESIS_ESH: 24136379Ssklower esis_eshinput(m0, shp); 24243421Ssklower break; 24336379Ssklower 24436379Ssklower case ESIS_ISH: 24536379Ssklower esis_ishinput(m0, shp); 24643421Ssklower break; 24736379Ssklower 24836379Ssklower case ESIS_RD: 24936379Ssklower esis_rdinput(m0, shp); 25043421Ssklower break; 25136379Ssklower 25243421Ssklower default: 25336379Ssklower esis_stat.es_badtype++; 25436379Ssklower } 25536379Ssklower 25636379Ssklower bad: 25743421Ssklower if (esis_pcb.rcb_next != &esis_pcb) 25843421Ssklower isis_input(m0, shp); 25943421Ssklower else 26043421Ssklower m_freem(m0); 26136379Ssklower } 26236379Ssklower 26336379Ssklower /* 26436379Ssklower * FUNCTION: esis_rdoutput 26536379Ssklower * 26636379Ssklower * PURPOSE: Transmit a redirect pdu 26736379Ssklower * 26836379Ssklower * RETURNS: nothing 26936379Ssklower * 27036379Ssklower * SIDE EFFECTS: 27136379Ssklower * 27236379Ssklower * NOTES: Assumes there is enough space for fixed part of header, 27336379Ssklower * DA, BSNPA and NET in first mbuf. 27436379Ssklower */ 27543332Ssklower esis_rdoutput(inbound_shp, inbound_m, inbound_oidx, rd_dstnsap, rt) 27636379Ssklower struct snpa_hdr *inbound_shp; /* snpa hdr from incoming packet */ 27736379Ssklower struct mbuf *inbound_m; /* incoming pkt itself */ 27836379Ssklower struct clnp_optidx *inbound_oidx; /* clnp options assoc with incoming pkt */ 27936379Ssklower struct iso_addr *rd_dstnsap; /* ultimate destination of pkt */ 28043332Ssklower struct rtentry *rt; /* snpa cache info regarding next hop of 28136379Ssklower pkt */ 28236379Ssklower { 28336379Ssklower struct mbuf *m, *m0; 28436379Ssklower caddr_t cp; 28536379Ssklower struct esis_fixed *pdu; 28636379Ssklower int len, total_len = 0; 28736379Ssklower struct sockaddr_iso siso; 28836379Ssklower struct ifnet *ifp = inbound_shp->snh_ifp; 28943332Ssklower struct sockaddr_dl *sdl; 29043332Ssklower struct iso_addr *rd_gwnsap; 29136379Ssklower 29243332Ssklower if (rt->rt_flags & RTF_GATEWAY) { 29343332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt->rt_gateway)->siso_addr; 29443332Ssklower rt = rtalloc1(rt->rt_gateway, 0); 29543332Ssklower } else 29643332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt_key(rt))->siso_addr; 29743332Ssklower if (rt == 0 || (sdl = (struct sockaddr_dl *)rt->rt_gateway) == 0 || 29843332Ssklower sdl->sdl_family != AF_LINK) { 29943332Ssklower /* maybe we should have a function that you 30043332Ssklower could put in the iso_ifaddr structure 30143332Ssklower which could translate iso_addrs into snpa's 30243332Ssklower where there is a known mapping for that address type */ 30343332Ssklower esis_stat.es_badtype++; 30443332Ssklower return; 30543332Ssklower } 30636379Ssklower esis_stat.es_rdsent++; 30736379Ssklower IFDEBUG(D_ESISOUTPUT) 30836379Ssklower printf("esis_rdoutput: ifp x%x (%s%d), ht %d, m x%x, oidx x%x\n", 30936379Ssklower ifp, ifp->if_name, ifp->if_unit, esis_holding_time, inbound_m, 31036379Ssklower inbound_oidx); 31136379Ssklower printf("\tdestination: %s\n", clnp_iso_addrp(rd_dstnsap)); 31243332Ssklower printf("\tredirected toward:%s\n", clnp_iso_addrp(rd_gwnsap)); 31336379Ssklower ENDDEBUG 31436379Ssklower 31537469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 31636379Ssklower esis_stat.es_nomem++; 31736379Ssklower return; 31836379Ssklower } 31937469Ssklower bzero(mtod(m, caddr_t), MHLEN); 32036379Ssklower 32136379Ssklower pdu = mtod(m, struct esis_fixed *); 32237469Ssklower cp = (caddr_t)(pdu + 1); /*pointer arith.; 1st byte after header */ 32336379Ssklower len = sizeof(struct esis_fixed); 32436379Ssklower 32536379Ssklower /* 32636379Ssklower * Build fixed part of header 32736379Ssklower */ 32836379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 32936379Ssklower pdu->esis_vers = ESIS_VERSION; 33036379Ssklower pdu->esis_type = ESIS_RD; 33136379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, esis_holding_time); 33236379Ssklower 33336379Ssklower /* Insert destination address */ 33443072Ssklower (void) esis_insert_addr(&cp, &len, rd_dstnsap, m, 0); 33536379Ssklower 33636379Ssklower /* Insert the snpa of better next hop */ 33743332Ssklower *cp++ = sdl->sdl_alen; 33843332Ssklower bcopy(LLADDR(sdl), cp, sdl->sdl_alen); 33943332Ssklower cp += sdl->sdl_alen; 34043332Ssklower len += (sdl->sdl_alen + 1); 34136379Ssklower 34236379Ssklower /* 34336379Ssklower * If the next hop is not the destination, then it ought to be 34436379Ssklower * an IS and it should be inserted next. Else, set the 34536379Ssklower * NETL to 0 34636379Ssklower */ 34736379Ssklower /* PHASE2 use mask from ifp of outgoing interface */ 34843332Ssklower if (!iso_addrmatch1(rd_dstnsap, rd_gwnsap)) { 34943332Ssklower /* this should not happen: 35036379Ssklower if ((nhop_sc->sc_flags & SNPA_IS) == 0) { 35136379Ssklower printf("esis_rdoutput: next hop is not dst and not an IS\n"); 35236379Ssklower m_freem(m0); 35336379Ssklower return; 35443332Ssklower } */ 35543332Ssklower (void) esis_insert_addr(&cp, &len, rd_gwnsap, m, 0); 35636379Ssklower } else { 35736379Ssklower *cp++ = 0; /* NETL */ 35836379Ssklower len++; 35936379Ssklower } 36037469Ssklower m->m_len = len; 36136379Ssklower 36236379Ssklower /* 36336379Ssklower * PHASE2 36436379Ssklower * If redirect is to an IS, add an address mask. The mask to be 36536379Ssklower * used should be the mask present in the routing entry used to 36636379Ssklower * forward the original data packet. 36736379Ssklower */ 36836379Ssklower 36936379Ssklower /* 37036379Ssklower * Copy Qos, priority, or security options present in original npdu 37136379Ssklower */ 37236379Ssklower if (inbound_oidx) { 37343332Ssklower /* THIS CODE IS CURRENTLY (mostly) UNTESTED */ 37436379Ssklower int optlen = 0; 37536379Ssklower if (inbound_oidx->cni_qos_formatp) 37636379Ssklower optlen += (inbound_oidx->cni_qos_len + 2); 37736379Ssklower if (inbound_oidx->cni_priorp) /* priority option is 1 byte long */ 37836379Ssklower optlen += 3; 37936379Ssklower if (inbound_oidx->cni_securep) 38036379Ssklower optlen += (inbound_oidx->cni_secure_len + 2); 38137469Ssklower if (M_TRAILINGSPACE(m) < optlen) { 38237469Ssklower EXTEND_PACKET(m, m0, cp); 38337469Ssklower m->m_len = 0; 38436379Ssklower /* assumes MLEN > optlen */ 38536379Ssklower } 38636379Ssklower /* assume MLEN-len > optlen */ 38736379Ssklower /* 38836379Ssklower * When copying options, copy from ptr - 2 in order to grab 38936379Ssklower * the option code and length 39036379Ssklower */ 39136379Ssklower if (inbound_oidx->cni_qos_formatp) { 39243332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_qos_formatp - 2, 39343332Ssklower cp, (unsigned)(inbound_oidx->cni_qos_len + 2)); 39443332Ssklower cp += inbound_oidx->cni_qos_len + 2; 39536379Ssklower } 39636379Ssklower if (inbound_oidx->cni_priorp) { 39743332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_priorp - 2, 39843332Ssklower cp, 3); 39943332Ssklower cp += 3; 40036379Ssklower } 40136379Ssklower if (inbound_oidx->cni_securep) { 40243332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_securep - 2, cp, 40337469Ssklower (unsigned)(inbound_oidx->cni_secure_len + 2)); 40443332Ssklower cp += inbound_oidx->cni_secure_len + 2; 40536379Ssklower } 40637469Ssklower m->m_len += optlen; 40743332Ssklower len += optlen; 40836379Ssklower } 40936379Ssklower 41037469Ssklower pdu->esis_hdr_len = m0->m_pkthdr.len = len; 41136379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 41236379Ssklower 41337469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 41436379Ssklower siso.siso_family = AF_ISO; 41537469Ssklower siso.siso_data[0] = AFI_SNA; 41637469Ssklower siso.siso_nlen = 6 + 1; /* should be taken from snpa_hdr */ 41736379Ssklower /* +1 is for AFI */ 41837469Ssklower bcopy(inbound_shp->snh_shost, siso.siso_data + 1, 6); 41952625Ssklower (ifp->if_output)(ifp, m0, (struct sockaddr *)&siso, 0); 42036379Ssklower } 42136379Ssklower 42236379Ssklower /* 42336379Ssklower * FUNCTION: esis_insert_addr 42436379Ssklower * 42536379Ssklower * PURPOSE: Insert an iso_addr into a buffer 42636379Ssklower * 42736379Ssklower * RETURNS: true if buffer was big enough, else false 42836379Ssklower * 42936379Ssklower * SIDE EFFECTS: Increment buf & len according to size of iso_addr 43036379Ssklower * 43136379Ssklower * NOTES: Plus 1 here is for length byte 43236379Ssklower */ 43343072Ssklower esis_insert_addr(buf, len, isoa, m, nsellen) 43443332Ssklower register caddr_t *buf; /* ptr to buffer to put address into */ 43543332Ssklower int *len; /* ptr to length of buffer so far */ 43643332Ssklower register struct iso_addr *isoa; /* ptr to address */ 43743332Ssklower register struct mbuf *m; /* determine if there remains space */ 43843332Ssklower int nsellen; 43936379Ssklower { 44043332Ssklower register int newlen, result = 0; 44136379Ssklower 44243332Ssklower isoa->isoa_len -= nsellen; 44343332Ssklower newlen = isoa->isoa_len + 1; 44443332Ssklower if (newlen <= M_TRAILINGSPACE(m)) { 44543332Ssklower bcopy((caddr_t)isoa, *buf, newlen); 44643332Ssklower *len += newlen; 44743332Ssklower *buf += newlen; 44843332Ssklower m->m_len += newlen; 44943332Ssklower result = 1; 45043332Ssklower } 45143332Ssklower isoa->isoa_len += nsellen; 45243332Ssklower return (result); 45336379Ssklower } 45436379Ssklower 45539950Ssklower #define ESIS_EXTRACT_ADDR(d, b) { d = (struct iso_addr *)(b); b += (1 + *b); \ 45639950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45739950Ssklower #define ESIS_NEXT_OPTION(b) { b += (2 + b[1]); \ 45839950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45943430Ssklower int ESHonly = 0; 46036379Ssklower /* 46136379Ssklower 46236379Ssklower /* 46336379Ssklower * FUNCTION: esis_eshinput 46436379Ssklower * 46536379Ssklower * PURPOSE: Process an incoming ESH pdu 46636379Ssklower * 46736379Ssklower * RETURNS: nothing 46836379Ssklower * 46936379Ssklower * SIDE EFFECTS: 47036379Ssklower * 47136379Ssklower * NOTES: 47236379Ssklower */ 47336379Ssklower esis_eshinput(m, shp) 47436379Ssklower struct mbuf *m; /* esh pdu */ 47536379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 47636379Ssklower { 47743072Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 47836379Ssklower u_short ht; /* holding time */ 47943072Ssklower struct iso_addr *nsap; 48039950Ssklower int naddr; 48137469Ssklower u_char *buf = (u_char *)(pdu + 1); 48239950Ssklower u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 48343332Ssklower int new_entry = 0; 48436379Ssklower 48536379Ssklower esis_stat.es_eshrcvd++; 48636379Ssklower 48736379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 48836379Ssklower 48939950Ssklower naddr = *buf++; 49039950Ssklower if (buf >= buflim) 49136379Ssklower goto bad; 49243332Ssklower if (naddr == 1) { 49339950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 49443332Ssklower new_entry = snpac_add(shp->snh_ifp, 49543332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, 0); 49643332Ssklower } else { 49743332Ssklower int nsellength = 0, nlen = 0; 49843332Ssklower { 49943332Ssklower /* See if we want to compress out multiple nsaps differing 50043332Ssklower only by nsel */ 50143332Ssklower register struct ifaddr *ifa = shp->snh_ifp->if_addrlist; 50243332Ssklower for (; ifa; ifa = ifa->ifa_next) 50343332Ssklower if (ifa->ifa_addr->sa_family == AF_ISO) { 50443332Ssklower nsellength = ((struct iso_ifaddr *)ifa)->ia_addr.siso_tlen; 50543332Ssklower break; 50643332Ssklower } 50743332Ssklower } 50839950Ssklower IFDEBUG(D_ESISINPUT) 50943332Ssklower printf("esis_eshinput: esh: ht %d, naddr %d nsellength %d\n", 51043332Ssklower ht, naddr, nsellength); 51139950Ssklower ENDDEBUG 51243332Ssklower while (naddr-- > 0) { 51343332Ssklower struct iso_addr *nsap2; u_char *buf2; 51443332Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 51543332Ssklower /* see if there is at least one more nsap in ESH differing 51643332Ssklower only by nsel */ 51743332Ssklower if (nsellength != 0) for (buf2 = buf; buf2 < buflim;) { 51843332Ssklower ESIS_EXTRACT_ADDR(nsap2, buf2); 51943332Ssklower IFDEBUG(D_ESISINPUT) 52043332Ssklower printf("esis_eshinput: comparing %s ", 52143332Ssklower clnp_iso_addrp(nsap)); 52243332Ssklower printf("and %s\n", clnp_iso_addrp(nsap2)); 52343332Ssklower ENDDEBUG 52443332Ssklower if (Bcmp(nsap->isoa_genaddr, nsap2->isoa_genaddr, 52543332Ssklower nsap->isoa_len - nsellength) == 0) { 52643332Ssklower nlen = nsellength; 52743332Ssklower break; 52843332Ssklower } 52943332Ssklower } 53043332Ssklower new_entry |= snpac_add(shp->snh_ifp, 53143332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, nlen); 53243332Ssklower nlen = 0; 53343332Ssklower } 53439950Ssklower } 53543332Ssklower IFDEBUG(D_ESISINPUT) 53643332Ssklower printf("esis_eshinput: nsap %s is %s\n", 53743332Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 53843332Ssklower ENDDEBUG 53943332Ssklower if (new_entry && (iso_systype & SNPA_IS)) 54043332Ssklower esis_shoutput(shp->snh_ifp, ESIS_ISH, esis_holding_time, 54143332Ssklower shp->snh_shost, 6, (struct iso_addr *)0); 54237469Ssklower bad: 54339950Ssklower return; 54436379Ssklower } 54536379Ssklower 54636379Ssklower /* 54736379Ssklower * FUNCTION: esis_ishinput 54836379Ssklower * 54936379Ssklower * PURPOSE: process an incoming ISH pdu 55036379Ssklower * 55136379Ssklower * RETURNS: 55236379Ssklower * 55336379Ssklower * SIDE EFFECTS: 55436379Ssklower * 55536379Ssklower * NOTES: 55636379Ssklower */ 55736379Ssklower esis_ishinput(m, shp) 55836379Ssklower struct mbuf *m; /* esh pdu */ 55936379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 56036379Ssklower { 56136379Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 56243430Ssklower u_short ht, newct; /* holding time */ 56339950Ssklower struct iso_addr *nsap; /* Network Entity Title */ 56439950Ssklower register u_char *buf = (u_char *) (pdu + 1); 56539950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 56639950Ssklower int new_entry; 56736379Ssklower 56836379Ssklower esis_stat.es_ishrcvd++; 56936379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 57036379Ssklower 57136379Ssklower IFDEBUG(D_ESISINPUT) 57236379Ssklower printf("esis_ishinput: ish: ht %d\n", ht); 57336379Ssklower ENDDEBUG 57439950Ssklower if (ESHonly) 57537469Ssklower goto bad; 57636379Ssklower 57739950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 57839950Ssklower 57939950Ssklower while (buf < buflim) { 58039950Ssklower switch (*buf) { 58137469Ssklower case ESISOVAL_ESCT: 58244946Ssklower if (iso_systype & SNPA_IS) 58344946Ssklower break; 58439950Ssklower if (buf[1] != 2) 58537469Ssklower goto bad; 58643430Ssklower CTOH(buf[2], buf[3], newct); 58743430Ssklower if (esis_config_time != newct) { 58843430Ssklower untimeout(esis_config,0); 58943430Ssklower esis_config_time = newct; 59043430Ssklower esis_config(); 59143430Ssklower } 59239950Ssklower break; 59339950Ssklower 59439950Ssklower default: 59539950Ssklower printf("Unknown ISH option: %x\n", *buf); 59637469Ssklower } 59739950Ssklower ESIS_NEXT_OPTION(buf); 59837469Ssklower } 59943332Ssklower new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_IS, ht, 0); 60037469Ssklower IFDEBUG(D_ESISINPUT) 60137469Ssklower printf("esis_ishinput: nsap %s is %s\n", 60237469Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 60337469Ssklower ENDDEBUG 60437469Ssklower 60537469Ssklower if (new_entry) 60637469Ssklower esis_shoutput(shp->snh_ifp, 60737469Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 60843332Ssklower esis_holding_time, shp->snh_shost, 6, (struct iso_addr *)0); 60939950Ssklower bad: 61039950Ssklower return; 61136379Ssklower } 61236379Ssklower 61336379Ssklower /* 61436379Ssklower * FUNCTION: esis_rdinput 61536379Ssklower * 61636379Ssklower * PURPOSE: Process an incoming RD pdu 61736379Ssklower * 61836379Ssklower * RETURNS: 61936379Ssklower * 62036379Ssklower * SIDE EFFECTS: 62136379Ssklower * 62236379Ssklower * NOTES: 62336379Ssklower */ 62436379Ssklower esis_rdinput(m0, shp) 62536379Ssklower struct mbuf *m0; /* esh pdu */ 62636379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 62736379Ssklower { 62836379Ssklower struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 62936379Ssklower u_short ht; /* holding time */ 63039950Ssklower struct iso_addr *da, *net = 0, *netmask = 0, *snpamask = 0; 63139950Ssklower register struct iso_addr *bsnpa; 63239950Ssklower register u_char *buf = (u_char *)(pdu + 1); 63339950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 63436379Ssklower 63536379Ssklower esis_stat.es_rdrcvd++; 63636379Ssklower 63736379Ssklower /* intermediate systems ignore redirects */ 63836379Ssklower if (iso_systype & SNPA_IS) 63943421Ssklower return; 64039950Ssklower if (ESHonly) 64143421Ssklower return; 64236379Ssklower 64336379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 64439950Ssklower if (buf >= buflim) 64543421Ssklower return; 64636379Ssklower 64736379Ssklower /* Extract DA */ 64839950Ssklower ESIS_EXTRACT_ADDR(da, buf); 64937469Ssklower 65036379Ssklower /* Extract better snpa */ 65139950Ssklower ESIS_EXTRACT_ADDR(bsnpa, buf); 65239950Ssklower 65337469Ssklower /* Extract NET if present */ 65439950Ssklower if (buf < buflim) { 65543332Ssklower if (*buf == 0) 65643332Ssklower buf++; /* no NET present, skip NETL anyway */ 65743332Ssklower else 65843332Ssklower ESIS_EXTRACT_ADDR(net, buf); 65936379Ssklower } 66036379Ssklower 66137469Ssklower /* process options */ 66239950Ssklower while (buf < buflim) { 66339950Ssklower switch (*buf) { 66437469Ssklower case ESISOVAL_SNPAMASK: 66537469Ssklower if (snpamask) /* duplicate */ 66643421Ssklower return; 66739950Ssklower snpamask = (struct iso_addr *)(buf + 1); 66837469Ssklower break; 66937469Ssklower 67037469Ssklower case ESISOVAL_NETMASK: 67137469Ssklower if (netmask) /* duplicate */ 67243421Ssklower return; 67339950Ssklower netmask = (struct iso_addr *)(buf + 1); 67439950Ssklower break; 67539950Ssklower 67639950Ssklower default: 67739950Ssklower printf("Unknown option in ESIS RD (0x%x)\n", buf[-1]); 67837469Ssklower } 67939950Ssklower ESIS_NEXT_OPTION(buf); 68036379Ssklower } 68136379Ssklower 68236379Ssklower IFDEBUG(D_ESISINPUT) 68337469Ssklower printf("esis_rdinput: rd: ht %d, da %s\n", ht, clnp_iso_addrp(da)); 68437469Ssklower if (net) 68537469Ssklower printf("\t: net %s\n", clnp_iso_addrp(net)); 68636379Ssklower ENDDEBUG 68736379Ssklower /* 68836379Ssklower * If netl is zero, then redirect is to an ES. We need to add an entry 68936379Ssklower * to the snpa cache for (destination, better snpa). 69036379Ssklower * If netl is not zero, then the redirect is to an IS. In this 69136379Ssklower * case, add an snpa cache entry for (net, better snpa). 69236379Ssklower * 69336379Ssklower * If the redirect is to an IS, add a route entry towards that 69436379Ssklower * IS. 69536379Ssklower */ 69639950Ssklower if (net == 0 || net->isoa_len == 0 || snpamask) { 69736379Ssklower /* redirect to an ES */ 69839950Ssklower snpac_add(shp->snh_ifp, da, 69943332Ssklower bsnpa->isoa_genaddr, SNPA_ES, ht, 0); 70036379Ssklower } else { 70139950Ssklower snpac_add(shp->snh_ifp, net, 70243332Ssklower bsnpa->isoa_genaddr, SNPA_IS, ht, 0); 70339950Ssklower snpac_addrt(shp->snh_ifp, da, net, netmask); 70436379Ssklower } 70543421Ssklower bad: ; /* Needed by ESIS_NEXT_OPTION */ 70636379Ssklower } 70736379Ssklower 70836379Ssklower /* 70936379Ssklower * FUNCTION: esis_config 71036379Ssklower * 71136379Ssklower * PURPOSE: Report configuration 71236379Ssklower * 71336379Ssklower * RETURNS: 71436379Ssklower * 71536379Ssklower * SIDE EFFECTS: 71636379Ssklower * 71736379Ssklower * NOTES: Called every esis_config_time seconds 71836379Ssklower */ 71936379Ssklower esis_config() 72036379Ssklower { 72136379Ssklower register struct ifnet *ifp; 72236379Ssklower 72336379Ssklower timeout(esis_config, (caddr_t)0, hz * esis_config_time); 72436379Ssklower 72536379Ssklower /* 72636379Ssklower * Report configuration for each interface that 72736379Ssklower * - is UP 72848963Ssklower * - has BROADCAST capability 72936379Ssklower * - has an ISO address 73036379Ssklower */ 73148963Ssklower /* Todo: a better way would be to construct the esh or ish 73248963Ssklower * once and copy it out for all devices, possibly calling 73348963Ssklower * a method in the iso_ifaddr structure to encapsulate and 73448963Ssklower * transmit it. This could work to advantage for non-broadcast media 73548963Ssklower */ 73636379Ssklower 73736379Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 73836379Ssklower if ((ifp->if_flags & IFF_UP) && 73948963Ssklower (ifp->if_flags & IFF_BROADCAST)) { 74036379Ssklower /* search for an ISO address family */ 74136379Ssklower struct ifaddr *ia; 74236379Ssklower 74336379Ssklower for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { 74437469Ssklower if (ia->ifa_addr->sa_family == AF_ISO) { 74536379Ssklower esis_shoutput(ifp, 74636379Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 74736379Ssklower esis_holding_time, 74843332Ssklower (caddr_t)(iso_systype & SNPA_ES ? all_is_snpa : 74943332Ssklower all_es_snpa), 6, (struct iso_addr *)0); 75036379Ssklower break; 75136379Ssklower } 75236379Ssklower } 75336379Ssklower } 75436379Ssklower } 75536379Ssklower } 75636379Ssklower 75736379Ssklower /* 75836379Ssklower * FUNCTION: esis_shoutput 75936379Ssklower * 76036379Ssklower * PURPOSE: Transmit an esh or ish pdu 76136379Ssklower * 76236379Ssklower * RETURNS: nothing 76336379Ssklower * 76436379Ssklower * SIDE EFFECTS: 76536379Ssklower * 76636379Ssklower * NOTES: 76736379Ssklower */ 76843332Ssklower esis_shoutput(ifp, type, ht, sn_addr, sn_len, isoa) 76936379Ssklower struct ifnet *ifp; 77036379Ssklower int type; 77136379Ssklower short ht; 77236379Ssklower caddr_t sn_addr; 77336379Ssklower int sn_len; 77443332Ssklower struct iso_addr *isoa; 77536379Ssklower { 77636379Ssklower struct mbuf *m, *m0; 77736379Ssklower caddr_t cp, naddrp; 77836379Ssklower int naddr = 0; 77936379Ssklower struct esis_fixed *pdu; 78043332Ssklower struct iso_ifaddr *ia; 78137469Ssklower int len; 78236379Ssklower struct sockaddr_iso siso; 78336379Ssklower 78436379Ssklower if (type == ESIS_ESH) 78536379Ssklower esis_stat.es_eshsent++; 78636379Ssklower else if (type == ESIS_ISH) 78736379Ssklower esis_stat.es_ishsent++; 78836379Ssklower else { 78936379Ssklower printf("esis_shoutput: bad pdu type\n"); 79036379Ssklower return; 79136379Ssklower } 79236379Ssklower 79336379Ssklower IFDEBUG(D_ESISOUTPUT) 79436379Ssklower int i; 79536379Ssklower printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ", 79636379Ssklower ifp, ifp->if_name, ifp->if_unit, type == ESIS_ESH ? "esh" : "ish", 79736379Ssklower ht, sn_len); 79836379Ssklower for (i=0; i<sn_len; i++) 79936379Ssklower printf("%x%c", *(sn_addr+i), i < (sn_len-1) ? ':' : ' '); 80036379Ssklower printf("\n"); 80136379Ssklower ENDDEBUG 80236379Ssklower 80337469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 80436379Ssklower esis_stat.es_nomem++; 80536379Ssklower return; 80636379Ssklower } 80737469Ssklower bzero(mtod(m, caddr_t), MHLEN); 80836379Ssklower 80936379Ssklower pdu = mtod(m, struct esis_fixed *); 81037469Ssklower naddrp = cp = (caddr_t)(pdu + 1); 81136379Ssklower len = sizeof(struct esis_fixed); 81236379Ssklower 81336379Ssklower /* 81436379Ssklower * Build fixed part of header 81536379Ssklower */ 81636379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 81736379Ssklower pdu->esis_vers = ESIS_VERSION; 81836379Ssklower pdu->esis_type = type; 81936379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 82036379Ssklower 82136379Ssklower if (type == ESIS_ESH) { 82236379Ssklower cp++; 82336379Ssklower len++; 82436379Ssklower } 82536379Ssklower 82637469Ssklower m->m_len = len; 82743332Ssklower if (isoa) { 82843332Ssklower /* 82943332Ssklower * Here we are responding to a clnp packet sent to an NSAP 83043332Ssklower * that is ours which was sent to the MAC addr all_es's. 83143332Ssklower * It is possible that we did not specifically advertise this 83243332Ssklower * NSAP, even though it is ours, so we will respond 83343332Ssklower * directly to the sender that we are here. If we do have 83443332Ssklower * multiple NSEL's we'll tack them on so he can compress them out. 83543332Ssklower */ 83643332Ssklower (void) esis_insert_addr(&cp, &len, isoa, m, 0); 83743332Ssklower naddr = 1; 83843332Ssklower } 83943332Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 84043332Ssklower int nsellen = (type == ESIS_ISH ? ia->ia_addr.siso_tlen : 0); 84143332Ssklower int n = ia->ia_addr.siso_nlen; 84243332Ssklower register struct iso_ifaddr *ia2; 84343332Ssklower 84443332Ssklower if (type == ESIS_ISH && naddr > 0) 84543332Ssklower break; 84643332Ssklower for (ia2 = iso_ifaddr; ia2 != ia; ia2 = ia2->ia_next) 84743332Ssklower if (Bcmp(ia->ia_addr.siso_data, ia2->ia_addr.siso_data, n) == 0) 84843332Ssklower break; 84943332Ssklower if (ia2 != ia) 85043332Ssklower continue; /* Means we have previously copied this nsap */ 85143332Ssklower if (isoa && Bcmp(ia->ia_addr.siso_data, isoa->isoa_genaddr, n) == 0) { 85243332Ssklower isoa = 0; 85343332Ssklower continue; /* Ditto */ 85436379Ssklower } 85543332Ssklower IFDEBUG(D_ESISOUTPUT) 85643332Ssklower printf("esis_shoutput: adding NSAP %s\n", 85743332Ssklower clnp_iso_addrp(&ia->ia_addr.siso_addr)); 85843332Ssklower ENDDEBUG 85943332Ssklower if (!esis_insert_addr(&cp, &len, 86043332Ssklower &ia->ia_addr.siso_addr, m, nsellen)) { 86143332Ssklower EXTEND_PACKET(m, m0, cp); 86243332Ssklower (void) esis_insert_addr(&cp, &len, &ia->ia_addr.siso_addr, m, 86343332Ssklower nsellen); 86443332Ssklower } 86543332Ssklower naddr++; 86636379Ssklower } 86736379Ssklower 86836379Ssklower if (type == ESIS_ESH) 86936379Ssklower *naddrp = naddr; 87044254Ssklower else { 87144254Ssklower /* add suggested es config timer option to ISH */ 87244254Ssklower if (M_TRAILINGSPACE(m) < 4) { 87344254Ssklower printf("esis_shoutput: extending packet\n"); 87444254Ssklower EXTEND_PACKET(m, m0, cp); 87544254Ssklower } 87644254Ssklower *cp++ = ESISOVAL_ESCT; 87744254Ssklower *cp++ = 2; 87844254Ssklower HTOC(*cp, *(cp+1), esis_esconfig_time); 87944254Ssklower len += 4; 88044254Ssklower m->m_len += 4; 88144254Ssklower IFDEBUG(D_ESISOUTPUT) 88244254Ssklower printf("m0 0x%x, m 0x%x, data 0x%x, len %d, cp 0x%x\n", 88344254Ssklower m0, m, m->m_data, m->m_len, cp); 88444254Ssklower ENDDEBUG 88544254Ssklower } 88636379Ssklower 88737469Ssklower m0->m_pkthdr.len = len; 88837469Ssklower pdu->esis_hdr_len = len; 88936379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 89036379Ssklower 89137469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 89236379Ssklower siso.siso_family = AF_ISO; 89337469Ssklower siso.siso_data[0] = AFI_SNA; 89437469Ssklower siso.siso_nlen = sn_len + 1; 89537469Ssklower bcopy(sn_addr, siso.siso_data + 1, (unsigned)sn_len); 89652625Ssklower (ifp->if_output)(ifp, m0, (struct sockaddr *)&siso, 0); 89736379Ssklower } 89836379Ssklower 89936379Ssklower /* 90043421Ssklower * FUNCTION: isis_input 90143421Ssklower * 90243421Ssklower * PURPOSE: Process an incoming isis packet 90343421Ssklower * 90443421Ssklower * RETURNS: nothing 90543421Ssklower * 90643421Ssklower * SIDE EFFECTS: 90743421Ssklower * 90843421Ssklower * NOTES: 90943421Ssklower */ 91043421Ssklower isis_input(m0, shp) 91143421Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 91243421Ssklower struct snpa_hdr *shp; /* subnetwork header */ 91343421Ssklower { 91443421Ssklower register int type; 91543961Ssklower register struct rawcb *rp, *first_rp = 0; 91643421Ssklower struct ifnet *ifp = shp->snh_ifp; 91743421Ssklower char workbuf[16]; 91843421Ssklower struct mbuf *mm; 91943421Ssklower 92043421Ssklower IFDEBUG(D_ISISINPUT) 92143421Ssklower int i; 92243421Ssklower 92343421Ssklower printf("isis_input: pkt on ifp x%x (%s%d): from:", ifp, 92443421Ssklower ifp->if_name, ifp->if_unit); 92543421Ssklower for (i=0; i<6; i++) 92643421Ssklower printf("%x%c", shp->snh_shost[i]&0xff, (i<5) ? ':' : ' '); 92743421Ssklower printf(" to:"); 92843421Ssklower for (i=0; i<6; i++) 92943421Ssklower printf("%x%c", shp->snh_dhost[i]&0xff, (i<5) ? ':' : ' '); 93043421Ssklower printf("\n"); 93143421Ssklower ENDDEBUG 93243421Ssklower esis_dl.sdl_alen = ifp->if_addrlen; 93343421Ssklower esis_dl.sdl_index = ifp->if_index; 93443421Ssklower bcopy(shp->snh_shost, (caddr_t)esis_dl.sdl_data, esis_dl.sdl_alen); 93543421Ssklower for (rp = esis_pcb.rcb_next; rp != &esis_pcb; rp = rp->rcb_next) { 93643961Ssklower if (first_rp == 0) { 93743961Ssklower first_rp = rp; 93843421Ssklower continue; 93943421Ssklower } 94043421Ssklower if (mm = m_copy(m0, 0, M_COPYALL)) { /*can't block at interrupt level */ 94143421Ssklower if (sbappendaddr(&rp->rcb_socket->so_rcv, 94252114Ssklower &esis_dl, mm, (struct mbuf *)0) != 0) { 94343421Ssklower sorwakeup(rp->rcb_socket); 94452114Ssklower } else { 94543421Ssklower IFDEBUG(D_ISISINPUT) 94643421Ssklower printf("Error in sbappenaddr, mm = 0x%x\n", mm); 94743421Ssklower ENDDEBUG 94843421Ssklower m_freem(mm); 94943421Ssklower } 95043421Ssklower } 95143421Ssklower } 95243961Ssklower if (first_rp && sbappendaddr(&first_rp->rcb_socket->so_rcv, 95344946Ssklower &esis_dl, m0, (struct mbuf *)0) != 0) { 95443961Ssklower sorwakeup(first_rp->rcb_socket); 95543961Ssklower return; 95643421Ssklower } 95743961Ssklower m_freem(m0); 95843421Ssklower } 95943421Ssklower 96043421Ssklower isis_output(sdl, m) 96143421Ssklower register struct sockaddr_dl *sdl; 96243421Ssklower struct mbuf *m; 96343421Ssklower { 96443421Ssklower register struct ifnet *ifp; 96543421Ssklower struct ifaddr *ifa, *ifa_ifwithnet(); 96643421Ssklower struct sockaddr_iso siso; 96743421Ssklower int error = 0; 96843421Ssklower unsigned sn_len; 96943421Ssklower 97052625Ssklower ifa = ifa_ifwithnet((struct sockaddr *)sdl); /* get ifp from sdl */ 97143421Ssklower if (ifa == 0) { 97243421Ssklower IFDEBUG(D_ISISOUTPUT) 97343421Ssklower printf("isis_output: interface not found\n"); 97443421Ssklower ENDDEBUG 97543421Ssklower error = EINVAL; 97643421Ssklower goto release; 97743421Ssklower } 97843421Ssklower ifp = ifa->ifa_ifp; 97945896Ssklower sn_len = sdl->sdl_alen; 98043421Ssklower IFDEBUG(D_ISISOUTPUT) 98143421Ssklower u_char *cp = (u_char *)LLADDR(sdl), *cplim = cp + sn_len; 98243421Ssklower printf("isis_output: ifp 0x%x (%s%d), to: ", 98343421Ssklower ifp, ifp->if_name, ifp->if_unit); 98443421Ssklower while (cp < cplim) { 98543421Ssklower printf("%x", *cp++); 98643421Ssklower printf("%c", (cp < cplim) ? ':' : ' '); 98743421Ssklower } 98843421Ssklower printf("\n"); 98943421Ssklower ENDDEBUG 99043421Ssklower bzero((caddr_t)&siso, sizeof(siso)); 99143421Ssklower siso.siso_family = AF_ISO; /* This convention may be useful for X.25 */ 99243421Ssklower siso.siso_data[0] = AFI_SNA; 99343421Ssklower siso.siso_nlen = sn_len + 1; 99443421Ssklower bcopy(LLADDR(sdl), siso.siso_data + 1, sn_len); 99543421Ssklower error = (ifp->if_output)(ifp, m, (struct sockaddr *)&siso, 0); 99643421Ssklower if (error) { 99743421Ssklower IFDEBUG(D_ISISOUTPUT) 99843421Ssklower printf("isis_output: error from ether_output is %d\n", error); 99943421Ssklower ENDDEBUG 100043421Ssklower } 100143421Ssklower return (error); 100243421Ssklower 100343421Ssklower release: 100443421Ssklower if (m != NULL) 100543421Ssklower m_freem(m); 100643421Ssklower return(error); 100743421Ssklower } 100843421Ssklower 100943421Ssklower 101043421Ssklower /* 101136379Ssklower * FUNCTION: esis_ctlinput 101236379Ssklower * 101336379Ssklower * PURPOSE: Handle the PRC_IFDOWN transition 101436379Ssklower * 101536379Ssklower * RETURNS: nothing 101636379Ssklower * 101736379Ssklower * SIDE EFFECTS: 101836379Ssklower * 101936379Ssklower * NOTES: Calls snpac_flush for interface specified. 102036379Ssklower * The loop through iso_ifaddr is stupid because 102136379Ssklower * back in if_down, we knew the ifp... 102236379Ssklower */ 102336379Ssklower esis_ctlinput(req, siso) 102436379Ssklower int req; /* request: we handle only PRC_IFDOWN */ 102536379Ssklower struct sockaddr_iso *siso; /* address of ifp */ 102636379Ssklower { 102736379Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 102836379Ssklower 102937469Ssklower if (req == PRC_IFDOWN) 103037469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 103137469Ssklower if (iso_addrmatch(IA_SIS(ia), siso)) 103237469Ssklower snpac_flushifp(ia->ia_ifp); 103337469Ssklower } 103436379Ssklower } 103536379Ssklower 103636379Ssklower #endif ISO 1037