1*49268Sbostic /*- 2*49268Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*49268Sbostic * All rights reserved. 4*49268Sbostic * 5*49268Sbostic * %sccs.include.redist.c% 6*49268Sbostic * 7*49268Sbostic * @(#)esis.c 7.18 (Berkeley) 05/06/91 8*49268Sbostic */ 9*49268Sbostic 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 "user.h" 4637469Ssklower #include "socket.h" 4737469Ssklower #include "socketvar.h" 4837469Ssklower #include "errno.h" 4937469Ssklower #include "kernel.h" 5036379Ssklower 5136379Ssklower #include "../net/if.h" 5243332Ssklower #include "../net/if_dl.h" 5336379Ssklower #include "../net/route.h" 5443421Ssklower #include "../net/raw_cb.h" 5536379Ssklower 5637469Ssklower #include "iso.h" 5737469Ssklower #include "iso_pcb.h" 5837469Ssklower #include "iso_var.h" 5937469Ssklower #include "iso_snpac.h" 6037469Ssklower #include "clnl.h" 6137469Ssklower #include "clnp.h" 6237469Ssklower #include "clnp_stat.h" 6338841Ssklower #include "esis.h" 6437469Ssklower #include "argo_debug.h" 6536379Ssklower 6636379Ssklower /* 6736379Ssklower * Global variables to esis implementation 6836379Ssklower * 6936379Ssklower * esis_holding_time - the holding time (sec) parameter for outgoing pdus 7036379Ssklower * esis_config_time - the frequency (sec) that hellos are generated 7143421Ssklower * esis_esconfig_time - suggested es configuration time placed in the 7243421Ssklower * ish. 7336379Ssklower * 7436379Ssklower */ 7543421Ssklower struct rawcb esis_pcb; 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(); 10943892Ssklower int esis_config(), snpac_age(); 11036379Ssklower #ifdef ISO_X25ESIS 11143892Ssklower int x25esis_input(); 11236379Ssklower #endif ISO_X25ESIS 11336379Ssklower 11443421Ssklower esis_pcb.rcb_next = esis_pcb.rcb_prev = &esis_pcb; 11543421Ssklower llinfo_llc.lc_next = llinfo_llc.lc_prev = &llinfo_llc; 11636379Ssklower 11736379Ssklower timeout(snpac_age, (caddr_t)0, hz); 11836379Ssklower timeout(esis_config, (caddr_t)0, hz); 11936379Ssklower 12043892Ssklower clnl_protox[ISO9542_ESIS].clnl_input = esis_input; 12143892Ssklower clnl_protox[ISO10589_ISIS].clnl_input = isis_input; 12236379Ssklower #ifdef ISO_X25ESIS 12336379Ssklower clnl_protox[ISO9542X25_ESIS].clnl_input = x25esis_input; 12436379Ssklower #endif ISO_X25ESIS 12536379Ssklower } 12636379Ssklower 12736379Ssklower /* 12836379Ssklower * FUNCTION: esis_usrreq 12936379Ssklower * 13036379Ssklower * PURPOSE: Handle user level esis requests 13136379Ssklower * 13236379Ssklower * RETURNS: 0 or appropriate errno 13336379Ssklower * 13436379Ssklower * SIDE EFFECTS: 13536379Ssklower * 13636379Ssklower */ 13737469Ssklower /*ARGSUSED*/ 13840775Ssklower esis_usrreq(so, req, m, nam, control) 13936379Ssklower struct socket *so; /* socket: used only to get to this code */ 14036379Ssklower int req; /* request */ 14136379Ssklower struct mbuf *m; /* data for request */ 14236379Ssklower struct mbuf *nam; /* optional name */ 14340775Ssklower struct mbuf *control; /* optional control */ 14436379Ssklower { 14543421Ssklower struct rawcb *rp = sotorawcb(so); 14643421Ssklower int error = 0; 14743421Ssklower 14843421Ssklower if (suser(u.u_cred, &u.u_acflag)) { 14943421Ssklower error = EACCES; 15043421Ssklower goto release; 15143421Ssklower } 15243421Ssklower if (rp == NULL && req != PRU_ATTACH) { 15343421Ssklower error = EINVAL; 15443421Ssklower goto release; 15543421Ssklower } 15643421Ssklower 15743421Ssklower switch (req) { 15843421Ssklower case PRU_ATTACH: 15943421Ssklower if (rp != NULL) { 16043421Ssklower error = EINVAL; 16143421Ssklower break; 16243421Ssklower } 16343421Ssklower MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); 16443421Ssklower if (so->so_pcb = (caddr_t)rp) { 16543421Ssklower bzero(so->so_pcb, sizeof(*rp)); 16643421Ssklower insque(rp, &esis_pcb); 16744946Ssklower rp->rcb_socket = so; 16843421Ssklower error = soreserve(so, esis_sendspace, esis_recvspace); 16943421Ssklower } else 17043421Ssklower error = ENOBUFS; 17143421Ssklower break; 17243421Ssklower 17343421Ssklower case PRU_SEND: 17443421Ssklower if (nam == NULL) { 17543421Ssklower error = EINVAL; 17643421Ssklower break; 17743421Ssklower } 17843421Ssklower /* error checking here */ 17943421Ssklower error = isis_output(mtod(nam,struct sockaddr_dl *), m); 18043421Ssklower m = NULL; 18143421Ssklower break; 18243421Ssklower 18343421Ssklower case PRU_DETACH: 18443421Ssklower raw_detach(rp); 18543421Ssklower break; 18643421Ssklower 18743421Ssklower case PRU_SHUTDOWN: 18843421Ssklower socantsendmore(so); 18943421Ssklower break; 19043421Ssklower 19143421Ssklower case PRU_ABORT: 19243421Ssklower soisdisconnected(so); 19343421Ssklower raw_detach(rp); 19443421Ssklower break; 19543421Ssklower 19643421Ssklower case PRU_SENSE: 19743421Ssklower return (0); 19843421Ssklower 19943421Ssklower default: 20043421Ssklower return (EOPNOTSUPP); 20143421Ssklower } 20243421Ssklower release: 20336379Ssklower if (m != NULL) 20436379Ssklower m_freem(m); 20536379Ssklower 20643421Ssklower return (error); 20736379Ssklower } 20836379Ssklower 20936379Ssklower /* 21036379Ssklower * FUNCTION: esis_input 21136379Ssklower * 21236379Ssklower * PURPOSE: Process an incoming esis packet 21336379Ssklower * 21436379Ssklower * RETURNS: nothing 21536379Ssklower * 21636379Ssklower * SIDE EFFECTS: 21736379Ssklower * 21836379Ssklower * NOTES: 21936379Ssklower */ 22036379Ssklower esis_input(m0, shp) 22136379Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 22236379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 22336379Ssklower { 22443421Ssklower register struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 22537469Ssklower register int type; 22636379Ssklower 22736379Ssklower /* 22836379Ssklower * check checksum if necessary 22936379Ssklower */ 23037469Ssklower if (ESIS_CKSUM_REQUIRED(pdu) && iso_check_csum(m0, (int)pdu->esis_hdr_len)) { 23136379Ssklower esis_stat.es_badcsum++; 23236379Ssklower goto bad; 23336379Ssklower } 23436379Ssklower 23536379Ssklower /* check version */ 23636379Ssklower if (pdu->esis_vers != ESIS_VERSION) { 23736379Ssklower esis_stat.es_badvers++; 23836379Ssklower goto bad; 23936379Ssklower } 24037469Ssklower type = pdu->esis_type & 0x1f; 24137469Ssklower switch (type) { 24236379Ssklower case ESIS_ESH: 24336379Ssklower esis_eshinput(m0, shp); 24443421Ssklower break; 24536379Ssklower 24636379Ssklower case ESIS_ISH: 24736379Ssklower esis_ishinput(m0, shp); 24843421Ssklower break; 24936379Ssklower 25036379Ssklower case ESIS_RD: 25136379Ssklower esis_rdinput(m0, shp); 25243421Ssklower break; 25336379Ssklower 25443421Ssklower default: 25536379Ssklower esis_stat.es_badtype++; 25636379Ssklower } 25736379Ssklower 25836379Ssklower bad: 25943421Ssklower if (esis_pcb.rcb_next != &esis_pcb) 26043421Ssklower isis_input(m0, shp); 26143421Ssklower else 26243421Ssklower m_freem(m0); 26336379Ssklower } 26436379Ssklower 26536379Ssklower /* 26636379Ssklower * FUNCTION: esis_rdoutput 26736379Ssklower * 26836379Ssklower * PURPOSE: Transmit a redirect pdu 26936379Ssklower * 27036379Ssklower * RETURNS: nothing 27136379Ssklower * 27236379Ssklower * SIDE EFFECTS: 27336379Ssklower * 27436379Ssklower * NOTES: Assumes there is enough space for fixed part of header, 27536379Ssklower * DA, BSNPA and NET in first mbuf. 27636379Ssklower */ 27743332Ssklower esis_rdoutput(inbound_shp, inbound_m, inbound_oidx, rd_dstnsap, rt) 27836379Ssklower struct snpa_hdr *inbound_shp; /* snpa hdr from incoming packet */ 27936379Ssklower struct mbuf *inbound_m; /* incoming pkt itself */ 28036379Ssklower struct clnp_optidx *inbound_oidx; /* clnp options assoc with incoming pkt */ 28136379Ssklower struct iso_addr *rd_dstnsap; /* ultimate destination of pkt */ 28243332Ssklower struct rtentry *rt; /* snpa cache info regarding next hop of 28336379Ssklower pkt */ 28436379Ssklower { 28536379Ssklower struct mbuf *m, *m0; 28636379Ssklower caddr_t cp; 28736379Ssklower struct esis_fixed *pdu; 28836379Ssklower int len, total_len = 0; 28936379Ssklower struct sockaddr_iso siso; 29036379Ssklower struct ifnet *ifp = inbound_shp->snh_ifp; 29143332Ssklower struct sockaddr_dl *sdl; 29243332Ssklower struct iso_addr *rd_gwnsap; 29336379Ssklower 29443332Ssklower if (rt->rt_flags & RTF_GATEWAY) { 29543332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt->rt_gateway)->siso_addr; 29643332Ssklower rt = rtalloc1(rt->rt_gateway, 0); 29743332Ssklower } else 29843332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt_key(rt))->siso_addr; 29943332Ssklower if (rt == 0 || (sdl = (struct sockaddr_dl *)rt->rt_gateway) == 0 || 30043332Ssklower sdl->sdl_family != AF_LINK) { 30143332Ssklower /* maybe we should have a function that you 30243332Ssklower could put in the iso_ifaddr structure 30343332Ssklower which could translate iso_addrs into snpa's 30443332Ssklower where there is a known mapping for that address type */ 30543332Ssklower esis_stat.es_badtype++; 30643332Ssklower return; 30743332Ssklower } 30836379Ssklower esis_stat.es_rdsent++; 30936379Ssklower IFDEBUG(D_ESISOUTPUT) 31036379Ssklower printf("esis_rdoutput: ifp x%x (%s%d), ht %d, m x%x, oidx x%x\n", 31136379Ssklower ifp, ifp->if_name, ifp->if_unit, esis_holding_time, inbound_m, 31236379Ssklower inbound_oidx); 31336379Ssklower printf("\tdestination: %s\n", clnp_iso_addrp(rd_dstnsap)); 31443332Ssklower printf("\tredirected toward:%s\n", clnp_iso_addrp(rd_gwnsap)); 31536379Ssklower ENDDEBUG 31636379Ssklower 31737469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 31836379Ssklower esis_stat.es_nomem++; 31936379Ssklower return; 32036379Ssklower } 32137469Ssklower bzero(mtod(m, caddr_t), MHLEN); 32236379Ssklower 32336379Ssklower pdu = mtod(m, struct esis_fixed *); 32437469Ssklower cp = (caddr_t)(pdu + 1); /*pointer arith.; 1st byte after header */ 32536379Ssklower len = sizeof(struct esis_fixed); 32636379Ssklower 32736379Ssklower /* 32836379Ssklower * Build fixed part of header 32936379Ssklower */ 33036379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 33136379Ssklower pdu->esis_vers = ESIS_VERSION; 33236379Ssklower pdu->esis_type = ESIS_RD; 33336379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, esis_holding_time); 33436379Ssklower 33536379Ssklower /* Insert destination address */ 33643072Ssklower (void) esis_insert_addr(&cp, &len, rd_dstnsap, m, 0); 33736379Ssklower 33836379Ssklower /* Insert the snpa of better next hop */ 33943332Ssklower *cp++ = sdl->sdl_alen; 34043332Ssklower bcopy(LLADDR(sdl), cp, sdl->sdl_alen); 34143332Ssklower cp += sdl->sdl_alen; 34243332Ssklower len += (sdl->sdl_alen + 1); 34336379Ssklower 34436379Ssklower /* 34536379Ssklower * If the next hop is not the destination, then it ought to be 34636379Ssklower * an IS and it should be inserted next. Else, set the 34736379Ssklower * NETL to 0 34836379Ssklower */ 34936379Ssklower /* PHASE2 use mask from ifp of outgoing interface */ 35043332Ssklower if (!iso_addrmatch1(rd_dstnsap, rd_gwnsap)) { 35143332Ssklower /* this should not happen: 35236379Ssklower if ((nhop_sc->sc_flags & SNPA_IS) == 0) { 35336379Ssklower printf("esis_rdoutput: next hop is not dst and not an IS\n"); 35436379Ssklower m_freem(m0); 35536379Ssklower return; 35643332Ssklower } */ 35743332Ssklower (void) esis_insert_addr(&cp, &len, rd_gwnsap, m, 0); 35836379Ssklower } else { 35936379Ssklower *cp++ = 0; /* NETL */ 36036379Ssklower len++; 36136379Ssklower } 36237469Ssklower m->m_len = len; 36336379Ssklower 36436379Ssklower /* 36536379Ssklower * PHASE2 36636379Ssklower * If redirect is to an IS, add an address mask. The mask to be 36736379Ssklower * used should be the mask present in the routing entry used to 36836379Ssklower * forward the original data packet. 36936379Ssklower */ 37036379Ssklower 37136379Ssklower /* 37236379Ssklower * Copy Qos, priority, or security options present in original npdu 37336379Ssklower */ 37436379Ssklower if (inbound_oidx) { 37543332Ssklower /* THIS CODE IS CURRENTLY (mostly) UNTESTED */ 37636379Ssklower int optlen = 0; 37736379Ssklower if (inbound_oidx->cni_qos_formatp) 37836379Ssklower optlen += (inbound_oidx->cni_qos_len + 2); 37936379Ssklower if (inbound_oidx->cni_priorp) /* priority option is 1 byte long */ 38036379Ssklower optlen += 3; 38136379Ssklower if (inbound_oidx->cni_securep) 38236379Ssklower optlen += (inbound_oidx->cni_secure_len + 2); 38337469Ssklower if (M_TRAILINGSPACE(m) < optlen) { 38437469Ssklower EXTEND_PACKET(m, m0, cp); 38537469Ssklower m->m_len = 0; 38636379Ssklower /* assumes MLEN > optlen */ 38736379Ssklower } 38836379Ssklower /* assume MLEN-len > optlen */ 38936379Ssklower /* 39036379Ssklower * When copying options, copy from ptr - 2 in order to grab 39136379Ssklower * the option code and length 39236379Ssklower */ 39336379Ssklower if (inbound_oidx->cni_qos_formatp) { 39443332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_qos_formatp - 2, 39543332Ssklower cp, (unsigned)(inbound_oidx->cni_qos_len + 2)); 39643332Ssklower cp += inbound_oidx->cni_qos_len + 2; 39736379Ssklower } 39836379Ssklower if (inbound_oidx->cni_priorp) { 39943332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_priorp - 2, 40043332Ssklower cp, 3); 40143332Ssklower cp += 3; 40236379Ssklower } 40336379Ssklower if (inbound_oidx->cni_securep) { 40443332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_securep - 2, cp, 40537469Ssklower (unsigned)(inbound_oidx->cni_secure_len + 2)); 40643332Ssklower cp += inbound_oidx->cni_secure_len + 2; 40736379Ssklower } 40837469Ssklower m->m_len += optlen; 40943332Ssklower len += optlen; 41036379Ssklower } 41136379Ssklower 41237469Ssklower pdu->esis_hdr_len = m0->m_pkthdr.len = len; 41336379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 41436379Ssklower 41537469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 41636379Ssklower siso.siso_family = AF_ISO; 41737469Ssklower siso.siso_data[0] = AFI_SNA; 41837469Ssklower siso.siso_nlen = 6 + 1; /* should be taken from snpa_hdr */ 41936379Ssklower /* +1 is for AFI */ 42037469Ssklower bcopy(inbound_shp->snh_shost, siso.siso_data + 1, 6); 42140775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 42236379Ssklower } 42336379Ssklower 42436379Ssklower /* 42536379Ssklower * FUNCTION: esis_insert_addr 42636379Ssklower * 42736379Ssklower * PURPOSE: Insert an iso_addr into a buffer 42836379Ssklower * 42936379Ssklower * RETURNS: true if buffer was big enough, else false 43036379Ssklower * 43136379Ssklower * SIDE EFFECTS: Increment buf & len according to size of iso_addr 43236379Ssklower * 43336379Ssklower * NOTES: Plus 1 here is for length byte 43436379Ssklower */ 43543072Ssklower esis_insert_addr(buf, len, isoa, m, nsellen) 43643332Ssklower register caddr_t *buf; /* ptr to buffer to put address into */ 43743332Ssklower int *len; /* ptr to length of buffer so far */ 43843332Ssklower register struct iso_addr *isoa; /* ptr to address */ 43943332Ssklower register struct mbuf *m; /* determine if there remains space */ 44043332Ssklower int nsellen; 44136379Ssklower { 44243332Ssklower register int newlen, result = 0; 44336379Ssklower 44443332Ssklower isoa->isoa_len -= nsellen; 44543332Ssklower newlen = isoa->isoa_len + 1; 44643332Ssklower if (newlen <= M_TRAILINGSPACE(m)) { 44743332Ssklower bcopy((caddr_t)isoa, *buf, newlen); 44843332Ssklower *len += newlen; 44943332Ssklower *buf += newlen; 45043332Ssklower m->m_len += newlen; 45143332Ssklower result = 1; 45243332Ssklower } 45343332Ssklower isoa->isoa_len += nsellen; 45443332Ssklower return (result); 45536379Ssklower } 45636379Ssklower 45739950Ssklower #define ESIS_EXTRACT_ADDR(d, b) { d = (struct iso_addr *)(b); b += (1 + *b); \ 45839950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45939950Ssklower #define ESIS_NEXT_OPTION(b) { b += (2 + b[1]); \ 46039950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 46143430Ssklower int ESHonly = 0; 46236379Ssklower /* 46336379Ssklower 46436379Ssklower /* 46536379Ssklower * FUNCTION: esis_eshinput 46636379Ssklower * 46736379Ssklower * PURPOSE: Process an incoming ESH pdu 46836379Ssklower * 46936379Ssklower * RETURNS: nothing 47036379Ssklower * 47136379Ssklower * SIDE EFFECTS: 47236379Ssklower * 47336379Ssklower * NOTES: 47436379Ssklower */ 47536379Ssklower esis_eshinput(m, shp) 47636379Ssklower struct mbuf *m; /* esh pdu */ 47736379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 47836379Ssklower { 47943072Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 48036379Ssklower u_short ht; /* holding time */ 48143072Ssklower struct iso_addr *nsap; 48239950Ssklower int naddr; 48337469Ssklower u_char *buf = (u_char *)(pdu + 1); 48439950Ssklower u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 48543332Ssklower int new_entry = 0; 48636379Ssklower 48736379Ssklower esis_stat.es_eshrcvd++; 48836379Ssklower 48936379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 49036379Ssklower 49139950Ssklower naddr = *buf++; 49239950Ssklower if (buf >= buflim) 49336379Ssklower goto bad; 49443332Ssklower if (naddr == 1) { 49539950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 49643332Ssklower new_entry = snpac_add(shp->snh_ifp, 49743332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, 0); 49843332Ssklower } else { 49943332Ssklower int nsellength = 0, nlen = 0; 50043332Ssklower { 50143332Ssklower /* See if we want to compress out multiple nsaps differing 50243332Ssklower only by nsel */ 50343332Ssklower register struct ifaddr *ifa = shp->snh_ifp->if_addrlist; 50443332Ssklower for (; ifa; ifa = ifa->ifa_next) 50543332Ssklower if (ifa->ifa_addr->sa_family == AF_ISO) { 50643332Ssklower nsellength = ((struct iso_ifaddr *)ifa)->ia_addr.siso_tlen; 50743332Ssklower break; 50843332Ssklower } 50943332Ssklower } 51039950Ssklower IFDEBUG(D_ESISINPUT) 51143332Ssklower printf("esis_eshinput: esh: ht %d, naddr %d nsellength %d\n", 51243332Ssklower ht, naddr, nsellength); 51339950Ssklower ENDDEBUG 51443332Ssklower while (naddr-- > 0) { 51543332Ssklower struct iso_addr *nsap2; u_char *buf2; 51643332Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 51743332Ssklower /* see if there is at least one more nsap in ESH differing 51843332Ssklower only by nsel */ 51943332Ssklower if (nsellength != 0) for (buf2 = buf; buf2 < buflim;) { 52043332Ssklower ESIS_EXTRACT_ADDR(nsap2, buf2); 52143332Ssklower IFDEBUG(D_ESISINPUT) 52243332Ssklower printf("esis_eshinput: comparing %s ", 52343332Ssklower clnp_iso_addrp(nsap)); 52443332Ssklower printf("and %s\n", clnp_iso_addrp(nsap2)); 52543332Ssklower ENDDEBUG 52643332Ssklower if (Bcmp(nsap->isoa_genaddr, nsap2->isoa_genaddr, 52743332Ssklower nsap->isoa_len - nsellength) == 0) { 52843332Ssklower nlen = nsellength; 52943332Ssklower break; 53043332Ssklower } 53143332Ssklower } 53243332Ssklower new_entry |= snpac_add(shp->snh_ifp, 53343332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, nlen); 53443332Ssklower nlen = 0; 53543332Ssklower } 53639950Ssklower } 53743332Ssklower IFDEBUG(D_ESISINPUT) 53843332Ssklower printf("esis_eshinput: nsap %s is %s\n", 53943332Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 54043332Ssklower ENDDEBUG 54143332Ssklower if (new_entry && (iso_systype & SNPA_IS)) 54243332Ssklower esis_shoutput(shp->snh_ifp, ESIS_ISH, esis_holding_time, 54343332Ssklower shp->snh_shost, 6, (struct iso_addr *)0); 54437469Ssklower bad: 54539950Ssklower return; 54636379Ssklower } 54736379Ssklower 54836379Ssklower /* 54936379Ssklower * FUNCTION: esis_ishinput 55036379Ssklower * 55136379Ssklower * PURPOSE: process an incoming ISH pdu 55236379Ssklower * 55336379Ssklower * RETURNS: 55436379Ssklower * 55536379Ssklower * SIDE EFFECTS: 55636379Ssklower * 55736379Ssklower * NOTES: 55836379Ssklower */ 55936379Ssklower esis_ishinput(m, shp) 56036379Ssklower struct mbuf *m; /* esh pdu */ 56136379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 56236379Ssklower { 56336379Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 56443430Ssklower u_short ht, newct; /* holding time */ 56539950Ssklower struct iso_addr *nsap; /* Network Entity Title */ 56639950Ssklower register u_char *buf = (u_char *) (pdu + 1); 56739950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 56839950Ssklower int new_entry; 56936379Ssklower 57036379Ssklower esis_stat.es_ishrcvd++; 57136379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 57236379Ssklower 57336379Ssklower IFDEBUG(D_ESISINPUT) 57436379Ssklower printf("esis_ishinput: ish: ht %d\n", ht); 57536379Ssklower ENDDEBUG 57639950Ssklower if (ESHonly) 57737469Ssklower goto bad; 57836379Ssklower 57939950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 58039950Ssklower 58139950Ssklower while (buf < buflim) { 58239950Ssklower switch (*buf) { 58337469Ssklower case ESISOVAL_ESCT: 58444946Ssklower if (iso_systype & SNPA_IS) 58544946Ssklower break; 58639950Ssklower if (buf[1] != 2) 58737469Ssklower goto bad; 58843430Ssklower CTOH(buf[2], buf[3], newct); 58943430Ssklower if (esis_config_time != newct) { 59043430Ssklower untimeout(esis_config,0); 59143430Ssklower esis_config_time = newct; 59243430Ssklower esis_config(); 59343430Ssklower } 59439950Ssklower break; 59539950Ssklower 59639950Ssklower default: 59739950Ssklower printf("Unknown ISH option: %x\n", *buf); 59837469Ssklower } 59939950Ssklower ESIS_NEXT_OPTION(buf); 60037469Ssklower } 60143332Ssklower new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_IS, ht, 0); 60237469Ssklower IFDEBUG(D_ESISINPUT) 60337469Ssklower printf("esis_ishinput: nsap %s is %s\n", 60437469Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 60537469Ssklower ENDDEBUG 60637469Ssklower 60737469Ssklower if (new_entry) 60837469Ssklower esis_shoutput(shp->snh_ifp, 60937469Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 61043332Ssklower esis_holding_time, shp->snh_shost, 6, (struct iso_addr *)0); 61139950Ssklower bad: 61239950Ssklower return; 61336379Ssklower } 61436379Ssklower 61536379Ssklower /* 61636379Ssklower * FUNCTION: esis_rdinput 61736379Ssklower * 61836379Ssklower * PURPOSE: Process an incoming RD pdu 61936379Ssklower * 62036379Ssklower * RETURNS: 62136379Ssklower * 62236379Ssklower * SIDE EFFECTS: 62336379Ssklower * 62436379Ssklower * NOTES: 62536379Ssklower */ 62636379Ssklower esis_rdinput(m0, shp) 62736379Ssklower struct mbuf *m0; /* esh pdu */ 62836379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 62936379Ssklower { 63036379Ssklower struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 63136379Ssklower u_short ht; /* holding time */ 63239950Ssklower struct iso_addr *da, *net = 0, *netmask = 0, *snpamask = 0; 63339950Ssklower register struct iso_addr *bsnpa; 63439950Ssklower register u_char *buf = (u_char *)(pdu + 1); 63539950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 63636379Ssklower 63736379Ssklower esis_stat.es_rdrcvd++; 63836379Ssklower 63936379Ssklower /* intermediate systems ignore redirects */ 64036379Ssklower if (iso_systype & SNPA_IS) 64143421Ssklower return; 64239950Ssklower if (ESHonly) 64343421Ssklower return; 64436379Ssklower 64536379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 64639950Ssklower if (buf >= buflim) 64743421Ssklower return; 64836379Ssklower 64936379Ssklower /* Extract DA */ 65039950Ssklower ESIS_EXTRACT_ADDR(da, buf); 65137469Ssklower 65236379Ssklower /* Extract better snpa */ 65339950Ssklower ESIS_EXTRACT_ADDR(bsnpa, buf); 65439950Ssklower 65537469Ssklower /* Extract NET if present */ 65639950Ssklower if (buf < buflim) { 65743332Ssklower if (*buf == 0) 65843332Ssklower buf++; /* no NET present, skip NETL anyway */ 65943332Ssklower else 66043332Ssklower ESIS_EXTRACT_ADDR(net, buf); 66136379Ssklower } 66236379Ssklower 66337469Ssklower /* process options */ 66439950Ssklower while (buf < buflim) { 66539950Ssklower switch (*buf) { 66637469Ssklower case ESISOVAL_SNPAMASK: 66737469Ssklower if (snpamask) /* duplicate */ 66843421Ssklower return; 66939950Ssklower snpamask = (struct iso_addr *)(buf + 1); 67037469Ssklower break; 67137469Ssklower 67237469Ssklower case ESISOVAL_NETMASK: 67337469Ssklower if (netmask) /* duplicate */ 67443421Ssklower return; 67539950Ssklower netmask = (struct iso_addr *)(buf + 1); 67639950Ssklower break; 67739950Ssklower 67839950Ssklower default: 67939950Ssklower printf("Unknown option in ESIS RD (0x%x)\n", buf[-1]); 68037469Ssklower } 68139950Ssklower ESIS_NEXT_OPTION(buf); 68236379Ssklower } 68336379Ssklower 68436379Ssklower IFDEBUG(D_ESISINPUT) 68537469Ssklower printf("esis_rdinput: rd: ht %d, da %s\n", ht, clnp_iso_addrp(da)); 68637469Ssklower if (net) 68737469Ssklower printf("\t: net %s\n", clnp_iso_addrp(net)); 68836379Ssklower ENDDEBUG 68936379Ssklower /* 69036379Ssklower * If netl is zero, then redirect is to an ES. We need to add an entry 69136379Ssklower * to the snpa cache for (destination, better snpa). 69236379Ssklower * If netl is not zero, then the redirect is to an IS. In this 69336379Ssklower * case, add an snpa cache entry for (net, better snpa). 69436379Ssklower * 69536379Ssklower * If the redirect is to an IS, add a route entry towards that 69636379Ssklower * IS. 69736379Ssklower */ 69839950Ssklower if (net == 0 || net->isoa_len == 0 || snpamask) { 69936379Ssklower /* redirect to an ES */ 70039950Ssklower snpac_add(shp->snh_ifp, da, 70143332Ssklower bsnpa->isoa_genaddr, SNPA_ES, ht, 0); 70236379Ssklower } else { 70339950Ssklower snpac_add(shp->snh_ifp, net, 70443332Ssklower bsnpa->isoa_genaddr, SNPA_IS, ht, 0); 70539950Ssklower snpac_addrt(shp->snh_ifp, da, net, netmask); 70636379Ssklower } 70743421Ssklower bad: ; /* Needed by ESIS_NEXT_OPTION */ 70836379Ssklower } 70936379Ssklower 71036379Ssklower /* 71136379Ssklower * FUNCTION: esis_config 71236379Ssklower * 71336379Ssklower * PURPOSE: Report configuration 71436379Ssklower * 71536379Ssklower * RETURNS: 71636379Ssklower * 71736379Ssklower * SIDE EFFECTS: 71836379Ssklower * 71936379Ssklower * NOTES: Called every esis_config_time seconds 72036379Ssklower */ 72136379Ssklower esis_config() 72236379Ssklower { 72336379Ssklower register struct ifnet *ifp; 72436379Ssklower 72536379Ssklower timeout(esis_config, (caddr_t)0, hz * esis_config_time); 72636379Ssklower 72736379Ssklower /* 72836379Ssklower * Report configuration for each interface that 72936379Ssklower * - is UP 73048963Ssklower * - has BROADCAST capability 73136379Ssklower * - has an ISO address 73236379Ssklower */ 73348963Ssklower /* Todo: a better way would be to construct the esh or ish 73448963Ssklower * once and copy it out for all devices, possibly calling 73548963Ssklower * a method in the iso_ifaddr structure to encapsulate and 73648963Ssklower * transmit it. This could work to advantage for non-broadcast media 73748963Ssklower */ 73836379Ssklower 73936379Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 74036379Ssklower if ((ifp->if_flags & IFF_UP) && 74148963Ssklower (ifp->if_flags & IFF_BROADCAST)) { 74236379Ssklower /* search for an ISO address family */ 74336379Ssklower struct ifaddr *ia; 74436379Ssklower 74536379Ssklower for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { 74637469Ssklower if (ia->ifa_addr->sa_family == AF_ISO) { 74736379Ssklower esis_shoutput(ifp, 74836379Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 74936379Ssklower esis_holding_time, 75043332Ssklower (caddr_t)(iso_systype & SNPA_ES ? all_is_snpa : 75143332Ssklower all_es_snpa), 6, (struct iso_addr *)0); 75236379Ssklower break; 75336379Ssklower } 75436379Ssklower } 75536379Ssklower } 75636379Ssklower } 75736379Ssklower } 75836379Ssklower 75936379Ssklower /* 76036379Ssklower * FUNCTION: esis_shoutput 76136379Ssklower * 76236379Ssklower * PURPOSE: Transmit an esh or ish pdu 76336379Ssklower * 76436379Ssklower * RETURNS: nothing 76536379Ssklower * 76636379Ssklower * SIDE EFFECTS: 76736379Ssklower * 76836379Ssklower * NOTES: 76936379Ssklower */ 77043332Ssklower esis_shoutput(ifp, type, ht, sn_addr, sn_len, isoa) 77136379Ssklower struct ifnet *ifp; 77236379Ssklower int type; 77336379Ssklower short ht; 77436379Ssklower caddr_t sn_addr; 77536379Ssklower int sn_len; 77643332Ssklower struct iso_addr *isoa; 77736379Ssklower { 77836379Ssklower struct mbuf *m, *m0; 77936379Ssklower caddr_t cp, naddrp; 78036379Ssklower int naddr = 0; 78136379Ssklower struct esis_fixed *pdu; 78243332Ssklower struct iso_ifaddr *ia; 78337469Ssklower int len; 78436379Ssklower struct sockaddr_iso siso; 78536379Ssklower 78636379Ssklower if (type == ESIS_ESH) 78736379Ssklower esis_stat.es_eshsent++; 78836379Ssklower else if (type == ESIS_ISH) 78936379Ssklower esis_stat.es_ishsent++; 79036379Ssklower else { 79136379Ssklower printf("esis_shoutput: bad pdu type\n"); 79236379Ssklower return; 79336379Ssklower } 79436379Ssklower 79536379Ssklower IFDEBUG(D_ESISOUTPUT) 79636379Ssklower int i; 79736379Ssklower printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ", 79836379Ssklower ifp, ifp->if_name, ifp->if_unit, type == ESIS_ESH ? "esh" : "ish", 79936379Ssklower ht, sn_len); 80036379Ssklower for (i=0; i<sn_len; i++) 80136379Ssklower printf("%x%c", *(sn_addr+i), i < (sn_len-1) ? ':' : ' '); 80236379Ssklower printf("\n"); 80336379Ssklower ENDDEBUG 80436379Ssklower 80537469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 80636379Ssklower esis_stat.es_nomem++; 80736379Ssklower return; 80836379Ssklower } 80937469Ssklower bzero(mtod(m, caddr_t), MHLEN); 81036379Ssklower 81136379Ssklower pdu = mtod(m, struct esis_fixed *); 81237469Ssklower naddrp = cp = (caddr_t)(pdu + 1); 81336379Ssklower len = sizeof(struct esis_fixed); 81436379Ssklower 81536379Ssklower /* 81636379Ssklower * Build fixed part of header 81736379Ssklower */ 81836379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 81936379Ssklower pdu->esis_vers = ESIS_VERSION; 82036379Ssklower pdu->esis_type = type; 82136379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 82236379Ssklower 82336379Ssklower if (type == ESIS_ESH) { 82436379Ssklower cp++; 82536379Ssklower len++; 82636379Ssklower } 82736379Ssklower 82837469Ssklower m->m_len = len; 82943332Ssklower if (isoa) { 83043332Ssklower /* 83143332Ssklower * Here we are responding to a clnp packet sent to an NSAP 83243332Ssklower * that is ours which was sent to the MAC addr all_es's. 83343332Ssklower * It is possible that we did not specifically advertise this 83443332Ssklower * NSAP, even though it is ours, so we will respond 83543332Ssklower * directly to the sender that we are here. If we do have 83643332Ssklower * multiple NSEL's we'll tack them on so he can compress them out. 83743332Ssklower */ 83843332Ssklower (void) esis_insert_addr(&cp, &len, isoa, m, 0); 83943332Ssklower naddr = 1; 84043332Ssklower } 84143332Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 84243332Ssklower int nsellen = (type == ESIS_ISH ? ia->ia_addr.siso_tlen : 0); 84343332Ssklower int n = ia->ia_addr.siso_nlen; 84443332Ssklower register struct iso_ifaddr *ia2; 84543332Ssklower 84643332Ssklower if (type == ESIS_ISH && naddr > 0) 84743332Ssklower break; 84843332Ssklower for (ia2 = iso_ifaddr; ia2 != ia; ia2 = ia2->ia_next) 84943332Ssklower if (Bcmp(ia->ia_addr.siso_data, ia2->ia_addr.siso_data, n) == 0) 85043332Ssklower break; 85143332Ssklower if (ia2 != ia) 85243332Ssklower continue; /* Means we have previously copied this nsap */ 85343332Ssklower if (isoa && Bcmp(ia->ia_addr.siso_data, isoa->isoa_genaddr, n) == 0) { 85443332Ssklower isoa = 0; 85543332Ssklower continue; /* Ditto */ 85636379Ssklower } 85743332Ssklower IFDEBUG(D_ESISOUTPUT) 85843332Ssklower printf("esis_shoutput: adding NSAP %s\n", 85943332Ssklower clnp_iso_addrp(&ia->ia_addr.siso_addr)); 86043332Ssklower ENDDEBUG 86143332Ssklower if (!esis_insert_addr(&cp, &len, 86243332Ssklower &ia->ia_addr.siso_addr, m, nsellen)) { 86343332Ssklower EXTEND_PACKET(m, m0, cp); 86443332Ssklower (void) esis_insert_addr(&cp, &len, &ia->ia_addr.siso_addr, m, 86543332Ssklower nsellen); 86643332Ssklower } 86743332Ssklower naddr++; 86836379Ssklower } 86936379Ssklower 87036379Ssklower if (type == ESIS_ESH) 87136379Ssklower *naddrp = naddr; 87244254Ssklower else { 87344254Ssklower /* add suggested es config timer option to ISH */ 87444254Ssklower if (M_TRAILINGSPACE(m) < 4) { 87544254Ssklower printf("esis_shoutput: extending packet\n"); 87644254Ssklower EXTEND_PACKET(m, m0, cp); 87744254Ssklower } 87844254Ssklower *cp++ = ESISOVAL_ESCT; 87944254Ssklower *cp++ = 2; 88044254Ssklower HTOC(*cp, *(cp+1), esis_esconfig_time); 88144254Ssklower len += 4; 88244254Ssklower m->m_len += 4; 88344254Ssklower IFDEBUG(D_ESISOUTPUT) 88444254Ssklower printf("m0 0x%x, m 0x%x, data 0x%x, len %d, cp 0x%x\n", 88544254Ssklower m0, m, m->m_data, m->m_len, cp); 88644254Ssklower ENDDEBUG 88744254Ssklower } 88836379Ssklower 88937469Ssklower m0->m_pkthdr.len = len; 89037469Ssklower pdu->esis_hdr_len = len; 89136379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 89236379Ssklower 89337469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 89436379Ssklower siso.siso_family = AF_ISO; 89537469Ssklower siso.siso_data[0] = AFI_SNA; 89637469Ssklower siso.siso_nlen = sn_len + 1; 89737469Ssklower bcopy(sn_addr, siso.siso_data + 1, (unsigned)sn_len); 89840775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 89936379Ssklower } 90036379Ssklower 90136379Ssklower /* 90243421Ssklower * FUNCTION: isis_input 90343421Ssklower * 90443421Ssklower * PURPOSE: Process an incoming isis packet 90543421Ssklower * 90643421Ssklower * RETURNS: nothing 90743421Ssklower * 90843421Ssklower * SIDE EFFECTS: 90943421Ssklower * 91043421Ssklower * NOTES: 91143421Ssklower */ 91243421Ssklower isis_input(m0, shp) 91343421Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 91443421Ssklower struct snpa_hdr *shp; /* subnetwork header */ 91543421Ssklower { 91643421Ssklower register int type; 91743961Ssklower register struct rawcb *rp, *first_rp = 0; 91843421Ssklower struct ifnet *ifp = shp->snh_ifp; 91943421Ssklower char workbuf[16]; 92043421Ssklower struct mbuf *mm; 92143421Ssklower 92243421Ssklower IFDEBUG(D_ISISINPUT) 92343421Ssklower int i; 92443421Ssklower 92543421Ssklower printf("isis_input: pkt on ifp x%x (%s%d): from:", ifp, 92643421Ssklower ifp->if_name, ifp->if_unit); 92743421Ssklower for (i=0; i<6; i++) 92843421Ssklower printf("%x%c", shp->snh_shost[i]&0xff, (i<5) ? ':' : ' '); 92943421Ssklower printf(" to:"); 93043421Ssklower for (i=0; i<6; i++) 93143421Ssklower printf("%x%c", shp->snh_dhost[i]&0xff, (i<5) ? ':' : ' '); 93243421Ssklower printf("\n"); 93343421Ssklower ENDDEBUG 93443421Ssklower esis_dl.sdl_alen = ifp->if_addrlen; 93543421Ssklower esis_dl.sdl_index = ifp->if_index; 93643421Ssklower bcopy(shp->snh_shost, (caddr_t)esis_dl.sdl_data, esis_dl.sdl_alen); 93743421Ssklower for (rp = esis_pcb.rcb_next; rp != &esis_pcb; rp = rp->rcb_next) { 93843961Ssklower if (first_rp == 0) { 93943961Ssklower first_rp = rp; 94043421Ssklower continue; 94143421Ssklower } 94243421Ssklower if (mm = m_copy(m0, 0, M_COPYALL)) { /*can't block at interrupt level */ 94343421Ssklower if (sbappendaddr(&rp->rcb_socket->so_rcv, 94443421Ssklower &esis_dl, mm, (struct mbuf *)0) != 0) 94543421Ssklower sorwakeup(rp->rcb_socket); 94643421Ssklower else { 94743421Ssklower IFDEBUG(D_ISISINPUT) 94843421Ssklower printf("Error in sbappenaddr, mm = 0x%x\n", mm); 94943421Ssklower ENDDEBUG 95043421Ssklower m_freem(mm); 95143421Ssklower } 95243421Ssklower } 95343421Ssklower } 95443961Ssklower if (first_rp && sbappendaddr(&first_rp->rcb_socket->so_rcv, 95544946Ssklower &esis_dl, m0, (struct mbuf *)0) != 0) { 95643961Ssklower sorwakeup(first_rp->rcb_socket); 95743961Ssklower return; 95843421Ssklower } 95943961Ssklower m_freem(m0); 96043421Ssklower } 96143421Ssklower 96243421Ssklower isis_output(sdl, m) 96343421Ssklower register struct sockaddr_dl *sdl; 96443421Ssklower struct mbuf *m; 96543421Ssklower { 96643421Ssklower register struct ifnet *ifp; 96743421Ssklower struct ifaddr *ifa, *ifa_ifwithnet(); 96843421Ssklower struct sockaddr_iso siso; 96943421Ssklower int error = 0; 97043421Ssklower unsigned sn_len; 97143421Ssklower 97243421Ssklower ifa = ifa_ifwithnet(sdl); /* extract ifp from sockaddr_dl */ 97343421Ssklower if (ifa == 0) { 97443421Ssklower IFDEBUG(D_ISISOUTPUT) 97543421Ssklower printf("isis_output: interface not found\n"); 97643421Ssklower ENDDEBUG 97743421Ssklower error = EINVAL; 97843421Ssklower goto release; 97943421Ssklower } 98043421Ssklower ifp = ifa->ifa_ifp; 98145896Ssklower sn_len = sdl->sdl_alen; 98243421Ssklower IFDEBUG(D_ISISOUTPUT) 98343421Ssklower u_char *cp = (u_char *)LLADDR(sdl), *cplim = cp + sn_len; 98443421Ssklower printf("isis_output: ifp 0x%x (%s%d), to: ", 98543421Ssklower ifp, ifp->if_name, ifp->if_unit); 98643421Ssklower while (cp < cplim) { 98743421Ssklower printf("%x", *cp++); 98843421Ssklower printf("%c", (cp < cplim) ? ':' : ' '); 98943421Ssklower } 99043421Ssklower printf("\n"); 99143421Ssklower ENDDEBUG 99243421Ssklower bzero((caddr_t)&siso, sizeof(siso)); 99343421Ssklower siso.siso_family = AF_ISO; /* This convention may be useful for X.25 */ 99443421Ssklower siso.siso_data[0] = AFI_SNA; 99543421Ssklower siso.siso_nlen = sn_len + 1; 99643421Ssklower bcopy(LLADDR(sdl), siso.siso_data + 1, sn_len); 99743421Ssklower error = (ifp->if_output)(ifp, m, (struct sockaddr *)&siso, 0); 99843421Ssklower if (error) { 99943421Ssklower IFDEBUG(D_ISISOUTPUT) 100043421Ssklower printf("isis_output: error from ether_output is %d\n", error); 100143421Ssklower ENDDEBUG 100243421Ssklower } 100343421Ssklower return (error); 100443421Ssklower 100543421Ssklower release: 100643421Ssklower if (m != NULL) 100743421Ssklower m_freem(m); 100843421Ssklower return(error); 100943421Ssklower } 101043421Ssklower 101143421Ssklower 101243421Ssklower /* 101336379Ssklower * FUNCTION: esis_ctlinput 101436379Ssklower * 101536379Ssklower * PURPOSE: Handle the PRC_IFDOWN transition 101636379Ssklower * 101736379Ssklower * RETURNS: nothing 101836379Ssklower * 101936379Ssklower * SIDE EFFECTS: 102036379Ssklower * 102136379Ssklower * NOTES: Calls snpac_flush for interface specified. 102236379Ssklower * The loop through iso_ifaddr is stupid because 102336379Ssklower * back in if_down, we knew the ifp... 102436379Ssklower */ 102536379Ssklower esis_ctlinput(req, siso) 102636379Ssklower int req; /* request: we handle only PRC_IFDOWN */ 102736379Ssklower struct sockaddr_iso *siso; /* address of ifp */ 102836379Ssklower { 102936379Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 103036379Ssklower 103137469Ssklower if (req == PRC_IFDOWN) 103237469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 103337469Ssklower if (iso_addrmatch(IA_SIS(ia), siso)) 103437469Ssklower snpac_flushifp(ia->ia_ifp); 103537469Ssklower } 103636379Ssklower } 103736379Ssklower 103836379Ssklower #endif ISO 1039