136379Ssklower /*********************************************************** 236379Ssklower Copyright IBM Corporation 1987 336379Ssklower 436379Ssklower All Rights Reserved 536379Ssklower 636379Ssklower Permission to use, copy, modify, and distribute this software and its 736379Ssklower documentation for any purpose and without fee is hereby granted, 836379Ssklower provided that the above copyright notice appear in all copies and that 936379Ssklower both that copyright notice and this permission notice appear in 1036379Ssklower supporting documentation, and that the name of IBM not be 1136379Ssklower used in advertising or publicity pertaining to distribution of the 1236379Ssklower software without specific, written prior permission. 1336379Ssklower 1436379Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536379Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636379Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736379Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836379Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936379Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036379Ssklower SOFTWARE. 2136379Ssklower 2236379Ssklower ******************************************************************/ 2336379Ssklower 2436379Ssklower /* 2536379Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636379Ssklower */ 27*48963Ssklower /* @(#)esis.c 7.17 (Berkeley) 05/02/91 */ 2836379Ssklower #ifndef lint 2936379Ssklower static char *rcsid = "$Header: esis.c,v 4.10 88/09/15 18:57:03 hagens Exp $"; 3036379Ssklower #endif 3136379Ssklower 3236379Ssklower #ifdef ISO 3336379Ssklower 3437469Ssklower #include "types.h" 3537469Ssklower #include "param.h" 3643451Smckusick #include "systm.h" 3737469Ssklower #include "mbuf.h" 3837469Ssklower #include "domain.h" 3937469Ssklower #include "protosw.h" 4037469Ssklower #include "user.h" 4137469Ssklower #include "socket.h" 4237469Ssklower #include "socketvar.h" 4337469Ssklower #include "errno.h" 4437469Ssklower #include "kernel.h" 4536379Ssklower 4636379Ssklower #include "../net/if.h" 4743332Ssklower #include "../net/if_dl.h" 4836379Ssklower #include "../net/route.h" 4943421Ssklower #include "../net/raw_cb.h" 5036379Ssklower 5137469Ssklower #include "iso.h" 5237469Ssklower #include "iso_pcb.h" 5337469Ssklower #include "iso_var.h" 5437469Ssklower #include "iso_snpac.h" 5537469Ssklower #include "clnl.h" 5637469Ssklower #include "clnp.h" 5737469Ssklower #include "clnp_stat.h" 5838841Ssklower #include "esis.h" 5937469Ssklower #include "argo_debug.h" 6036379Ssklower 6136379Ssklower /* 6236379Ssklower * Global variables to esis implementation 6336379Ssklower * 6436379Ssklower * esis_holding_time - the holding time (sec) parameter for outgoing pdus 6536379Ssklower * esis_config_time - the frequency (sec) that hellos are generated 6643421Ssklower * esis_esconfig_time - suggested es configuration time placed in the 6743421Ssklower * ish. 6836379Ssklower * 6936379Ssklower */ 7043421Ssklower struct rawcb esis_pcb; 7136379Ssklower int esis_sendspace = 2048; 7236379Ssklower int esis_recvspace = 2048; 7336379Ssklower short esis_holding_time = ESIS_HT; 7436379Ssklower short esis_config_time = ESIS_CONFIG; 7543421Ssklower short esis_esconfig_time = ESIS_CONFIG; 7636379Ssklower extern int iso_systype; 7743421Ssklower struct sockaddr_dl esis_dl = { sizeof(esis_dl), AF_LINK }; 7843332Ssklower extern char all_es_snpa[], all_is_snpa[]; 7936379Ssklower 8037469Ssklower #define EXTEND_PACKET(m, mhdr, cp)\ 8136379Ssklower if (((m)->m_next = m_getclr(M_DONTWAIT, MT_HEADER)) == NULL) {\ 8236379Ssklower esis_stat.es_nomem++;\ 8336379Ssklower m_freem(mhdr);\ 8436379Ssklower return;\ 8536379Ssklower } else {\ 8636379Ssklower (m) = (m)->m_next;\ 8736379Ssklower (cp) = mtod((m), caddr_t);\ 8836379Ssklower } 8936379Ssklower /* 9036379Ssklower * FUNCTION: esis_init 9136379Ssklower * 9236379Ssklower * PURPOSE: Initialize the kernel portion of esis protocol 9336379Ssklower * 9436379Ssklower * RETURNS: nothing 9536379Ssklower * 9636379Ssklower * SIDE EFFECTS: 9736379Ssklower * 9836379Ssklower * NOTES: 9936379Ssklower */ 10036379Ssklower esis_init() 10136379Ssklower { 10236379Ssklower extern struct clnl_protosw clnl_protox[256]; 10343892Ssklower int esis_input(), isis_input(); 10443892Ssklower int esis_config(), snpac_age(); 10536379Ssklower #ifdef ISO_X25ESIS 10643892Ssklower int x25esis_input(); 10736379Ssklower #endif ISO_X25ESIS 10836379Ssklower 10943421Ssklower esis_pcb.rcb_next = esis_pcb.rcb_prev = &esis_pcb; 11043421Ssklower llinfo_llc.lc_next = llinfo_llc.lc_prev = &llinfo_llc; 11136379Ssklower 11236379Ssklower timeout(snpac_age, (caddr_t)0, hz); 11336379Ssklower timeout(esis_config, (caddr_t)0, hz); 11436379Ssklower 11543892Ssklower clnl_protox[ISO9542_ESIS].clnl_input = esis_input; 11643892Ssklower clnl_protox[ISO10589_ISIS].clnl_input = isis_input; 11736379Ssklower #ifdef ISO_X25ESIS 11836379Ssklower clnl_protox[ISO9542X25_ESIS].clnl_input = x25esis_input; 11936379Ssklower #endif ISO_X25ESIS 12036379Ssklower } 12136379Ssklower 12236379Ssklower /* 12336379Ssklower * FUNCTION: esis_usrreq 12436379Ssklower * 12536379Ssklower * PURPOSE: Handle user level esis requests 12636379Ssklower * 12736379Ssklower * RETURNS: 0 or appropriate errno 12836379Ssklower * 12936379Ssklower * SIDE EFFECTS: 13036379Ssklower * 13136379Ssklower */ 13237469Ssklower /*ARGSUSED*/ 13340775Ssklower esis_usrreq(so, req, m, nam, control) 13436379Ssklower struct socket *so; /* socket: used only to get to this code */ 13536379Ssklower int req; /* request */ 13636379Ssklower struct mbuf *m; /* data for request */ 13736379Ssklower struct mbuf *nam; /* optional name */ 13840775Ssklower struct mbuf *control; /* optional control */ 13936379Ssklower { 14043421Ssklower struct rawcb *rp = sotorawcb(so); 14143421Ssklower int error = 0; 14243421Ssklower 14343421Ssklower if (suser(u.u_cred, &u.u_acflag)) { 14443421Ssklower error = EACCES; 14543421Ssklower goto release; 14643421Ssklower } 14743421Ssklower if (rp == NULL && req != PRU_ATTACH) { 14843421Ssklower error = EINVAL; 14943421Ssklower goto release; 15043421Ssklower } 15143421Ssklower 15243421Ssklower switch (req) { 15343421Ssklower case PRU_ATTACH: 15443421Ssklower if (rp != NULL) { 15543421Ssklower error = EINVAL; 15643421Ssklower break; 15743421Ssklower } 15843421Ssklower MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); 15943421Ssklower if (so->so_pcb = (caddr_t)rp) { 16043421Ssklower bzero(so->so_pcb, sizeof(*rp)); 16143421Ssklower insque(rp, &esis_pcb); 16244946Ssklower rp->rcb_socket = so; 16343421Ssklower error = soreserve(so, esis_sendspace, esis_recvspace); 16443421Ssklower } else 16543421Ssklower error = ENOBUFS; 16643421Ssklower break; 16743421Ssklower 16843421Ssklower case PRU_SEND: 16943421Ssklower if (nam == NULL) { 17043421Ssklower error = EINVAL; 17143421Ssklower break; 17243421Ssklower } 17343421Ssklower /* error checking here */ 17443421Ssklower error = isis_output(mtod(nam,struct sockaddr_dl *), m); 17543421Ssklower m = NULL; 17643421Ssklower break; 17743421Ssklower 17843421Ssklower case PRU_DETACH: 17943421Ssklower raw_detach(rp); 18043421Ssklower break; 18143421Ssklower 18243421Ssklower case PRU_SHUTDOWN: 18343421Ssklower socantsendmore(so); 18443421Ssklower break; 18543421Ssklower 18643421Ssklower case PRU_ABORT: 18743421Ssklower soisdisconnected(so); 18843421Ssklower raw_detach(rp); 18943421Ssklower break; 19043421Ssklower 19143421Ssklower case PRU_SENSE: 19243421Ssklower return (0); 19343421Ssklower 19443421Ssklower default: 19543421Ssklower return (EOPNOTSUPP); 19643421Ssklower } 19743421Ssklower release: 19836379Ssklower if (m != NULL) 19936379Ssklower m_freem(m); 20036379Ssklower 20143421Ssklower return (error); 20236379Ssklower } 20336379Ssklower 20436379Ssklower /* 20536379Ssklower * FUNCTION: esis_input 20636379Ssklower * 20736379Ssklower * PURPOSE: Process an incoming esis packet 20836379Ssklower * 20936379Ssklower * RETURNS: nothing 21036379Ssklower * 21136379Ssklower * SIDE EFFECTS: 21236379Ssklower * 21336379Ssklower * NOTES: 21436379Ssklower */ 21536379Ssklower esis_input(m0, shp) 21636379Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 21736379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 21836379Ssklower { 21943421Ssklower register struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 22037469Ssklower register int type; 22136379Ssklower 22236379Ssklower /* 22336379Ssklower * check checksum if necessary 22436379Ssklower */ 22537469Ssklower if (ESIS_CKSUM_REQUIRED(pdu) && iso_check_csum(m0, (int)pdu->esis_hdr_len)) { 22636379Ssklower esis_stat.es_badcsum++; 22736379Ssklower goto bad; 22836379Ssklower } 22936379Ssklower 23036379Ssklower /* check version */ 23136379Ssklower if (pdu->esis_vers != ESIS_VERSION) { 23236379Ssklower esis_stat.es_badvers++; 23336379Ssklower goto bad; 23436379Ssklower } 23537469Ssklower type = pdu->esis_type & 0x1f; 23637469Ssklower switch (type) { 23736379Ssklower case ESIS_ESH: 23836379Ssklower esis_eshinput(m0, shp); 23943421Ssklower break; 24036379Ssklower 24136379Ssklower case ESIS_ISH: 24236379Ssklower esis_ishinput(m0, shp); 24343421Ssklower break; 24436379Ssklower 24536379Ssklower case ESIS_RD: 24636379Ssklower esis_rdinput(m0, shp); 24743421Ssklower break; 24836379Ssklower 24943421Ssklower default: 25036379Ssklower esis_stat.es_badtype++; 25136379Ssklower } 25236379Ssklower 25336379Ssklower bad: 25443421Ssklower if (esis_pcb.rcb_next != &esis_pcb) 25543421Ssklower isis_input(m0, shp); 25643421Ssklower else 25743421Ssklower m_freem(m0); 25836379Ssklower } 25936379Ssklower 26036379Ssklower /* 26136379Ssklower * FUNCTION: esis_rdoutput 26236379Ssklower * 26336379Ssklower * PURPOSE: Transmit a redirect pdu 26436379Ssklower * 26536379Ssklower * RETURNS: nothing 26636379Ssklower * 26736379Ssklower * SIDE EFFECTS: 26836379Ssklower * 26936379Ssklower * NOTES: Assumes there is enough space for fixed part of header, 27036379Ssklower * DA, BSNPA and NET in first mbuf. 27136379Ssklower */ 27243332Ssklower esis_rdoutput(inbound_shp, inbound_m, inbound_oidx, rd_dstnsap, rt) 27336379Ssklower struct snpa_hdr *inbound_shp; /* snpa hdr from incoming packet */ 27436379Ssklower struct mbuf *inbound_m; /* incoming pkt itself */ 27536379Ssklower struct clnp_optidx *inbound_oidx; /* clnp options assoc with incoming pkt */ 27636379Ssklower struct iso_addr *rd_dstnsap; /* ultimate destination of pkt */ 27743332Ssklower struct rtentry *rt; /* snpa cache info regarding next hop of 27836379Ssklower pkt */ 27936379Ssklower { 28036379Ssklower struct mbuf *m, *m0; 28136379Ssklower caddr_t cp; 28236379Ssklower struct esis_fixed *pdu; 28336379Ssklower int len, total_len = 0; 28436379Ssklower struct sockaddr_iso siso; 28536379Ssklower struct ifnet *ifp = inbound_shp->snh_ifp; 28643332Ssklower struct sockaddr_dl *sdl; 28743332Ssklower struct iso_addr *rd_gwnsap; 28836379Ssklower 28943332Ssklower if (rt->rt_flags & RTF_GATEWAY) { 29043332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt->rt_gateway)->siso_addr; 29143332Ssklower rt = rtalloc1(rt->rt_gateway, 0); 29243332Ssklower } else 29343332Ssklower rd_gwnsap = &((struct sockaddr_iso *)rt_key(rt))->siso_addr; 29443332Ssklower if (rt == 0 || (sdl = (struct sockaddr_dl *)rt->rt_gateway) == 0 || 29543332Ssklower sdl->sdl_family != AF_LINK) { 29643332Ssklower /* maybe we should have a function that you 29743332Ssklower could put in the iso_ifaddr structure 29843332Ssklower which could translate iso_addrs into snpa's 29943332Ssklower where there is a known mapping for that address type */ 30043332Ssklower esis_stat.es_badtype++; 30143332Ssklower return; 30243332Ssklower } 30336379Ssklower esis_stat.es_rdsent++; 30436379Ssklower IFDEBUG(D_ESISOUTPUT) 30536379Ssklower printf("esis_rdoutput: ifp x%x (%s%d), ht %d, m x%x, oidx x%x\n", 30636379Ssklower ifp, ifp->if_name, ifp->if_unit, esis_holding_time, inbound_m, 30736379Ssklower inbound_oidx); 30836379Ssklower printf("\tdestination: %s\n", clnp_iso_addrp(rd_dstnsap)); 30943332Ssklower printf("\tredirected toward:%s\n", clnp_iso_addrp(rd_gwnsap)); 31036379Ssklower ENDDEBUG 31136379Ssklower 31237469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 31336379Ssklower esis_stat.es_nomem++; 31436379Ssklower return; 31536379Ssklower } 31637469Ssklower bzero(mtod(m, caddr_t), MHLEN); 31736379Ssklower 31836379Ssklower pdu = mtod(m, struct esis_fixed *); 31937469Ssklower cp = (caddr_t)(pdu + 1); /*pointer arith.; 1st byte after header */ 32036379Ssklower len = sizeof(struct esis_fixed); 32136379Ssklower 32236379Ssklower /* 32336379Ssklower * Build fixed part of header 32436379Ssklower */ 32536379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 32636379Ssklower pdu->esis_vers = ESIS_VERSION; 32736379Ssklower pdu->esis_type = ESIS_RD; 32836379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, esis_holding_time); 32936379Ssklower 33036379Ssklower /* Insert destination address */ 33143072Ssklower (void) esis_insert_addr(&cp, &len, rd_dstnsap, m, 0); 33236379Ssklower 33336379Ssklower /* Insert the snpa of better next hop */ 33443332Ssklower *cp++ = sdl->sdl_alen; 33543332Ssklower bcopy(LLADDR(sdl), cp, sdl->sdl_alen); 33643332Ssklower cp += sdl->sdl_alen; 33743332Ssklower len += (sdl->sdl_alen + 1); 33836379Ssklower 33936379Ssklower /* 34036379Ssklower * If the next hop is not the destination, then it ought to be 34136379Ssklower * an IS and it should be inserted next. Else, set the 34236379Ssklower * NETL to 0 34336379Ssklower */ 34436379Ssklower /* PHASE2 use mask from ifp of outgoing interface */ 34543332Ssklower if (!iso_addrmatch1(rd_dstnsap, rd_gwnsap)) { 34643332Ssklower /* this should not happen: 34736379Ssklower if ((nhop_sc->sc_flags & SNPA_IS) == 0) { 34836379Ssklower printf("esis_rdoutput: next hop is not dst and not an IS\n"); 34936379Ssklower m_freem(m0); 35036379Ssklower return; 35143332Ssklower } */ 35243332Ssklower (void) esis_insert_addr(&cp, &len, rd_gwnsap, m, 0); 35336379Ssklower } else { 35436379Ssklower *cp++ = 0; /* NETL */ 35536379Ssklower len++; 35636379Ssklower } 35737469Ssklower m->m_len = len; 35836379Ssklower 35936379Ssklower /* 36036379Ssklower * PHASE2 36136379Ssklower * If redirect is to an IS, add an address mask. The mask to be 36236379Ssklower * used should be the mask present in the routing entry used to 36336379Ssklower * forward the original data packet. 36436379Ssklower */ 36536379Ssklower 36636379Ssklower /* 36736379Ssklower * Copy Qos, priority, or security options present in original npdu 36836379Ssklower */ 36936379Ssklower if (inbound_oidx) { 37043332Ssklower /* THIS CODE IS CURRENTLY (mostly) UNTESTED */ 37136379Ssklower int optlen = 0; 37236379Ssklower if (inbound_oidx->cni_qos_formatp) 37336379Ssklower optlen += (inbound_oidx->cni_qos_len + 2); 37436379Ssklower if (inbound_oidx->cni_priorp) /* priority option is 1 byte long */ 37536379Ssklower optlen += 3; 37636379Ssklower if (inbound_oidx->cni_securep) 37736379Ssklower optlen += (inbound_oidx->cni_secure_len + 2); 37837469Ssklower if (M_TRAILINGSPACE(m) < optlen) { 37937469Ssklower EXTEND_PACKET(m, m0, cp); 38037469Ssklower m->m_len = 0; 38136379Ssklower /* assumes MLEN > optlen */ 38236379Ssklower } 38336379Ssklower /* assume MLEN-len > optlen */ 38436379Ssklower /* 38536379Ssklower * When copying options, copy from ptr - 2 in order to grab 38636379Ssklower * the option code and length 38736379Ssklower */ 38836379Ssklower if (inbound_oidx->cni_qos_formatp) { 38943332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_qos_formatp - 2, 39043332Ssklower cp, (unsigned)(inbound_oidx->cni_qos_len + 2)); 39143332Ssklower cp += inbound_oidx->cni_qos_len + 2; 39236379Ssklower } 39336379Ssklower if (inbound_oidx->cni_priorp) { 39443332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_priorp - 2, 39543332Ssklower cp, 3); 39643332Ssklower cp += 3; 39736379Ssklower } 39836379Ssklower if (inbound_oidx->cni_securep) { 39943332Ssklower bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_securep - 2, cp, 40037469Ssklower (unsigned)(inbound_oidx->cni_secure_len + 2)); 40143332Ssklower cp += inbound_oidx->cni_secure_len + 2; 40236379Ssklower } 40337469Ssklower m->m_len += optlen; 40443332Ssklower len += optlen; 40536379Ssklower } 40636379Ssklower 40737469Ssklower pdu->esis_hdr_len = m0->m_pkthdr.len = len; 40836379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 40936379Ssklower 41037469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 41136379Ssklower siso.siso_family = AF_ISO; 41237469Ssklower siso.siso_data[0] = AFI_SNA; 41337469Ssklower siso.siso_nlen = 6 + 1; /* should be taken from snpa_hdr */ 41436379Ssklower /* +1 is for AFI */ 41537469Ssklower bcopy(inbound_shp->snh_shost, siso.siso_data + 1, 6); 41640775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 41736379Ssklower } 41836379Ssklower 41936379Ssklower /* 42036379Ssklower * FUNCTION: esis_insert_addr 42136379Ssklower * 42236379Ssklower * PURPOSE: Insert an iso_addr into a buffer 42336379Ssklower * 42436379Ssklower * RETURNS: true if buffer was big enough, else false 42536379Ssklower * 42636379Ssklower * SIDE EFFECTS: Increment buf & len according to size of iso_addr 42736379Ssklower * 42836379Ssklower * NOTES: Plus 1 here is for length byte 42936379Ssklower */ 43043072Ssklower esis_insert_addr(buf, len, isoa, m, nsellen) 43143332Ssklower register caddr_t *buf; /* ptr to buffer to put address into */ 43243332Ssklower int *len; /* ptr to length of buffer so far */ 43343332Ssklower register struct iso_addr *isoa; /* ptr to address */ 43443332Ssklower register struct mbuf *m; /* determine if there remains space */ 43543332Ssklower int nsellen; 43636379Ssklower { 43743332Ssklower register int newlen, result = 0; 43836379Ssklower 43943332Ssklower isoa->isoa_len -= nsellen; 44043332Ssklower newlen = isoa->isoa_len + 1; 44143332Ssklower if (newlen <= M_TRAILINGSPACE(m)) { 44243332Ssklower bcopy((caddr_t)isoa, *buf, newlen); 44343332Ssklower *len += newlen; 44443332Ssklower *buf += newlen; 44543332Ssklower m->m_len += newlen; 44643332Ssklower result = 1; 44743332Ssklower } 44843332Ssklower isoa->isoa_len += nsellen; 44943332Ssklower return (result); 45036379Ssklower } 45136379Ssklower 45239950Ssklower #define ESIS_EXTRACT_ADDR(d, b) { d = (struct iso_addr *)(b); b += (1 + *b); \ 45339950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45439950Ssklower #define ESIS_NEXT_OPTION(b) { b += (2 + b[1]); \ 45539950Ssklower if (b > buflim) {esis_stat.es_toosmall++; goto bad;}} 45643430Ssklower int ESHonly = 0; 45736379Ssklower /* 45836379Ssklower 45936379Ssklower /* 46036379Ssklower * FUNCTION: esis_eshinput 46136379Ssklower * 46236379Ssklower * PURPOSE: Process an incoming ESH pdu 46336379Ssklower * 46436379Ssklower * RETURNS: nothing 46536379Ssklower * 46636379Ssklower * SIDE EFFECTS: 46736379Ssklower * 46836379Ssklower * NOTES: 46936379Ssklower */ 47036379Ssklower esis_eshinput(m, shp) 47136379Ssklower struct mbuf *m; /* esh pdu */ 47236379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 47336379Ssklower { 47443072Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 47536379Ssklower u_short ht; /* holding time */ 47643072Ssklower struct iso_addr *nsap; 47739950Ssklower int naddr; 47837469Ssklower u_char *buf = (u_char *)(pdu + 1); 47939950Ssklower u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 48043332Ssklower int new_entry = 0; 48136379Ssklower 48236379Ssklower esis_stat.es_eshrcvd++; 48336379Ssklower 48436379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 48536379Ssklower 48639950Ssklower naddr = *buf++; 48739950Ssklower if (buf >= buflim) 48836379Ssklower goto bad; 48943332Ssklower if (naddr == 1) { 49039950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 49143332Ssklower new_entry = snpac_add(shp->snh_ifp, 49243332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, 0); 49343332Ssklower } else { 49443332Ssklower int nsellength = 0, nlen = 0; 49543332Ssklower { 49643332Ssklower /* See if we want to compress out multiple nsaps differing 49743332Ssklower only by nsel */ 49843332Ssklower register struct ifaddr *ifa = shp->snh_ifp->if_addrlist; 49943332Ssklower for (; ifa; ifa = ifa->ifa_next) 50043332Ssklower if (ifa->ifa_addr->sa_family == AF_ISO) { 50143332Ssklower nsellength = ((struct iso_ifaddr *)ifa)->ia_addr.siso_tlen; 50243332Ssklower break; 50343332Ssklower } 50443332Ssklower } 50539950Ssklower IFDEBUG(D_ESISINPUT) 50643332Ssklower printf("esis_eshinput: esh: ht %d, naddr %d nsellength %d\n", 50743332Ssklower ht, naddr, nsellength); 50839950Ssklower ENDDEBUG 50943332Ssklower while (naddr-- > 0) { 51043332Ssklower struct iso_addr *nsap2; u_char *buf2; 51143332Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 51243332Ssklower /* see if there is at least one more nsap in ESH differing 51343332Ssklower only by nsel */ 51443332Ssklower if (nsellength != 0) for (buf2 = buf; buf2 < buflim;) { 51543332Ssklower ESIS_EXTRACT_ADDR(nsap2, buf2); 51643332Ssklower IFDEBUG(D_ESISINPUT) 51743332Ssklower printf("esis_eshinput: comparing %s ", 51843332Ssklower clnp_iso_addrp(nsap)); 51943332Ssklower printf("and %s\n", clnp_iso_addrp(nsap2)); 52043332Ssklower ENDDEBUG 52143332Ssklower if (Bcmp(nsap->isoa_genaddr, nsap2->isoa_genaddr, 52243332Ssklower nsap->isoa_len - nsellength) == 0) { 52343332Ssklower nlen = nsellength; 52443332Ssklower break; 52543332Ssklower } 52643332Ssklower } 52743332Ssklower new_entry |= snpac_add(shp->snh_ifp, 52843332Ssklower nsap, shp->snh_shost, SNPA_ES, ht, nlen); 52943332Ssklower nlen = 0; 53043332Ssklower } 53139950Ssklower } 53243332Ssklower IFDEBUG(D_ESISINPUT) 53343332Ssklower printf("esis_eshinput: nsap %s is %s\n", 53443332Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 53543332Ssklower ENDDEBUG 53643332Ssklower if (new_entry && (iso_systype & SNPA_IS)) 53743332Ssklower esis_shoutput(shp->snh_ifp, ESIS_ISH, esis_holding_time, 53843332Ssklower shp->snh_shost, 6, (struct iso_addr *)0); 53937469Ssklower bad: 54039950Ssklower return; 54136379Ssklower } 54236379Ssklower 54336379Ssklower /* 54436379Ssklower * FUNCTION: esis_ishinput 54536379Ssklower * 54636379Ssklower * PURPOSE: process an incoming ISH pdu 54736379Ssklower * 54836379Ssklower * RETURNS: 54936379Ssklower * 55036379Ssklower * SIDE EFFECTS: 55136379Ssklower * 55236379Ssklower * NOTES: 55336379Ssklower */ 55436379Ssklower esis_ishinput(m, shp) 55536379Ssklower struct mbuf *m; /* esh pdu */ 55636379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 55736379Ssklower { 55836379Ssklower struct esis_fixed *pdu = mtod(m, struct esis_fixed *); 55943430Ssklower u_short ht, newct; /* holding time */ 56039950Ssklower struct iso_addr *nsap; /* Network Entity Title */ 56139950Ssklower register u_char *buf = (u_char *) (pdu + 1); 56239950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 56339950Ssklower int new_entry; 56436379Ssklower 56536379Ssklower esis_stat.es_ishrcvd++; 56636379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 56736379Ssklower 56836379Ssklower IFDEBUG(D_ESISINPUT) 56936379Ssklower printf("esis_ishinput: ish: ht %d\n", ht); 57036379Ssklower ENDDEBUG 57139950Ssklower if (ESHonly) 57237469Ssklower goto bad; 57336379Ssklower 57439950Ssklower ESIS_EXTRACT_ADDR(nsap, buf); 57539950Ssklower 57639950Ssklower while (buf < buflim) { 57739950Ssklower switch (*buf) { 57837469Ssklower case ESISOVAL_ESCT: 57944946Ssklower if (iso_systype & SNPA_IS) 58044946Ssklower break; 58139950Ssklower if (buf[1] != 2) 58237469Ssklower goto bad; 58343430Ssklower CTOH(buf[2], buf[3], newct); 58443430Ssklower if (esis_config_time != newct) { 58543430Ssklower untimeout(esis_config,0); 58643430Ssklower esis_config_time = newct; 58743430Ssklower esis_config(); 58843430Ssklower } 58939950Ssklower break; 59039950Ssklower 59139950Ssklower default: 59239950Ssklower printf("Unknown ISH option: %x\n", *buf); 59337469Ssklower } 59439950Ssklower ESIS_NEXT_OPTION(buf); 59537469Ssklower } 59643332Ssklower new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_IS, ht, 0); 59737469Ssklower IFDEBUG(D_ESISINPUT) 59837469Ssklower printf("esis_ishinput: nsap %s is %s\n", 59937469Ssklower clnp_iso_addrp(nsap), new_entry ? "new" : "old"); 60037469Ssklower ENDDEBUG 60137469Ssklower 60237469Ssklower if (new_entry) 60337469Ssklower esis_shoutput(shp->snh_ifp, 60437469Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 60543332Ssklower esis_holding_time, shp->snh_shost, 6, (struct iso_addr *)0); 60639950Ssklower bad: 60739950Ssklower return; 60836379Ssklower } 60936379Ssklower 61036379Ssklower /* 61136379Ssklower * FUNCTION: esis_rdinput 61236379Ssklower * 61336379Ssklower * PURPOSE: Process an incoming RD pdu 61436379Ssklower * 61536379Ssklower * RETURNS: 61636379Ssklower * 61736379Ssklower * SIDE EFFECTS: 61836379Ssklower * 61936379Ssklower * NOTES: 62036379Ssklower */ 62136379Ssklower esis_rdinput(m0, shp) 62236379Ssklower struct mbuf *m0; /* esh pdu */ 62336379Ssklower struct snpa_hdr *shp; /* subnetwork header */ 62436379Ssklower { 62536379Ssklower struct esis_fixed *pdu = mtod(m0, struct esis_fixed *); 62636379Ssklower u_short ht; /* holding time */ 62739950Ssklower struct iso_addr *da, *net = 0, *netmask = 0, *snpamask = 0; 62839950Ssklower register struct iso_addr *bsnpa; 62939950Ssklower register u_char *buf = (u_char *)(pdu + 1); 63039950Ssklower register u_char *buflim = pdu->esis_hdr_len + (u_char *)pdu; 63136379Ssklower 63236379Ssklower esis_stat.es_rdrcvd++; 63336379Ssklower 63436379Ssklower /* intermediate systems ignore redirects */ 63536379Ssklower if (iso_systype & SNPA_IS) 63643421Ssklower return; 63739950Ssklower if (ESHonly) 63843421Ssklower return; 63936379Ssklower 64036379Ssklower CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 64139950Ssklower if (buf >= buflim) 64243421Ssklower return; 64336379Ssklower 64436379Ssklower /* Extract DA */ 64539950Ssklower ESIS_EXTRACT_ADDR(da, buf); 64637469Ssklower 64736379Ssklower /* Extract better snpa */ 64839950Ssklower ESIS_EXTRACT_ADDR(bsnpa, buf); 64939950Ssklower 65037469Ssklower /* Extract NET if present */ 65139950Ssklower if (buf < buflim) { 65243332Ssklower if (*buf == 0) 65343332Ssklower buf++; /* no NET present, skip NETL anyway */ 65443332Ssklower else 65543332Ssklower ESIS_EXTRACT_ADDR(net, buf); 65636379Ssklower } 65736379Ssklower 65837469Ssklower /* process options */ 65939950Ssklower while (buf < buflim) { 66039950Ssklower switch (*buf) { 66137469Ssklower case ESISOVAL_SNPAMASK: 66237469Ssklower if (snpamask) /* duplicate */ 66343421Ssklower return; 66439950Ssklower snpamask = (struct iso_addr *)(buf + 1); 66537469Ssklower break; 66637469Ssklower 66737469Ssklower case ESISOVAL_NETMASK: 66837469Ssklower if (netmask) /* duplicate */ 66943421Ssklower return; 67039950Ssklower netmask = (struct iso_addr *)(buf + 1); 67139950Ssklower break; 67239950Ssklower 67339950Ssklower default: 67439950Ssklower printf("Unknown option in ESIS RD (0x%x)\n", buf[-1]); 67537469Ssklower } 67639950Ssklower ESIS_NEXT_OPTION(buf); 67736379Ssklower } 67836379Ssklower 67936379Ssklower IFDEBUG(D_ESISINPUT) 68037469Ssklower printf("esis_rdinput: rd: ht %d, da %s\n", ht, clnp_iso_addrp(da)); 68137469Ssklower if (net) 68237469Ssklower printf("\t: net %s\n", clnp_iso_addrp(net)); 68336379Ssklower ENDDEBUG 68436379Ssklower /* 68536379Ssklower * If netl is zero, then redirect is to an ES. We need to add an entry 68636379Ssklower * to the snpa cache for (destination, better snpa). 68736379Ssklower * If netl is not zero, then the redirect is to an IS. In this 68836379Ssklower * case, add an snpa cache entry for (net, better snpa). 68936379Ssklower * 69036379Ssklower * If the redirect is to an IS, add a route entry towards that 69136379Ssklower * IS. 69236379Ssklower */ 69339950Ssklower if (net == 0 || net->isoa_len == 0 || snpamask) { 69436379Ssklower /* redirect to an ES */ 69539950Ssklower snpac_add(shp->snh_ifp, da, 69643332Ssklower bsnpa->isoa_genaddr, SNPA_ES, ht, 0); 69736379Ssklower } else { 69839950Ssklower snpac_add(shp->snh_ifp, net, 69943332Ssklower bsnpa->isoa_genaddr, SNPA_IS, ht, 0); 70039950Ssklower snpac_addrt(shp->snh_ifp, da, net, netmask); 70136379Ssklower } 70243421Ssklower bad: ; /* Needed by ESIS_NEXT_OPTION */ 70336379Ssklower } 70436379Ssklower 70536379Ssklower /* 70636379Ssklower * FUNCTION: esis_config 70736379Ssklower * 70836379Ssklower * PURPOSE: Report configuration 70936379Ssklower * 71036379Ssklower * RETURNS: 71136379Ssklower * 71236379Ssklower * SIDE EFFECTS: 71336379Ssklower * 71436379Ssklower * NOTES: Called every esis_config_time seconds 71536379Ssklower */ 71636379Ssklower esis_config() 71736379Ssklower { 71836379Ssklower register struct ifnet *ifp; 71936379Ssklower 72036379Ssklower timeout(esis_config, (caddr_t)0, hz * esis_config_time); 72136379Ssklower 72236379Ssklower /* 72336379Ssklower * Report configuration for each interface that 72436379Ssklower * - is UP 725*48963Ssklower * - has BROADCAST capability 72636379Ssklower * - has an ISO address 72736379Ssklower */ 728*48963Ssklower /* Todo: a better way would be to construct the esh or ish 729*48963Ssklower * once and copy it out for all devices, possibly calling 730*48963Ssklower * a method in the iso_ifaddr structure to encapsulate and 731*48963Ssklower * transmit it. This could work to advantage for non-broadcast media 732*48963Ssklower */ 73336379Ssklower 73436379Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) { 73536379Ssklower if ((ifp->if_flags & IFF_UP) && 736*48963Ssklower (ifp->if_flags & IFF_BROADCAST)) { 73736379Ssklower /* search for an ISO address family */ 73836379Ssklower struct ifaddr *ia; 73936379Ssklower 74036379Ssklower for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) { 74137469Ssklower if (ia->ifa_addr->sa_family == AF_ISO) { 74236379Ssklower esis_shoutput(ifp, 74336379Ssklower iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH, 74436379Ssklower esis_holding_time, 74543332Ssklower (caddr_t)(iso_systype & SNPA_ES ? all_is_snpa : 74643332Ssklower all_es_snpa), 6, (struct iso_addr *)0); 74736379Ssklower break; 74836379Ssklower } 74936379Ssklower } 75036379Ssklower } 75136379Ssklower } 75236379Ssklower } 75336379Ssklower 75436379Ssklower /* 75536379Ssklower * FUNCTION: esis_shoutput 75636379Ssklower * 75736379Ssklower * PURPOSE: Transmit an esh or ish pdu 75836379Ssklower * 75936379Ssklower * RETURNS: nothing 76036379Ssklower * 76136379Ssklower * SIDE EFFECTS: 76236379Ssklower * 76336379Ssklower * NOTES: 76436379Ssklower */ 76543332Ssklower esis_shoutput(ifp, type, ht, sn_addr, sn_len, isoa) 76636379Ssklower struct ifnet *ifp; 76736379Ssklower int type; 76836379Ssklower short ht; 76936379Ssklower caddr_t sn_addr; 77036379Ssklower int sn_len; 77143332Ssklower struct iso_addr *isoa; 77236379Ssklower { 77336379Ssklower struct mbuf *m, *m0; 77436379Ssklower caddr_t cp, naddrp; 77536379Ssklower int naddr = 0; 77636379Ssklower struct esis_fixed *pdu; 77743332Ssklower struct iso_ifaddr *ia; 77837469Ssklower int len; 77936379Ssklower struct sockaddr_iso siso; 78036379Ssklower 78136379Ssklower if (type == ESIS_ESH) 78236379Ssklower esis_stat.es_eshsent++; 78336379Ssklower else if (type == ESIS_ISH) 78436379Ssklower esis_stat.es_ishsent++; 78536379Ssklower else { 78636379Ssklower printf("esis_shoutput: bad pdu type\n"); 78736379Ssklower return; 78836379Ssklower } 78936379Ssklower 79036379Ssklower IFDEBUG(D_ESISOUTPUT) 79136379Ssklower int i; 79236379Ssklower printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ", 79336379Ssklower ifp, ifp->if_name, ifp->if_unit, type == ESIS_ESH ? "esh" : "ish", 79436379Ssklower ht, sn_len); 79536379Ssklower for (i=0; i<sn_len; i++) 79636379Ssklower printf("%x%c", *(sn_addr+i), i < (sn_len-1) ? ':' : ' '); 79736379Ssklower printf("\n"); 79836379Ssklower ENDDEBUG 79936379Ssklower 80037469Ssklower if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) { 80136379Ssklower esis_stat.es_nomem++; 80236379Ssklower return; 80336379Ssklower } 80437469Ssklower bzero(mtod(m, caddr_t), MHLEN); 80536379Ssklower 80636379Ssklower pdu = mtod(m, struct esis_fixed *); 80737469Ssklower naddrp = cp = (caddr_t)(pdu + 1); 80836379Ssklower len = sizeof(struct esis_fixed); 80936379Ssklower 81036379Ssklower /* 81136379Ssklower * Build fixed part of header 81236379Ssklower */ 81336379Ssklower pdu->esis_proto_id = ISO9542_ESIS; 81436379Ssklower pdu->esis_vers = ESIS_VERSION; 81536379Ssklower pdu->esis_type = type; 81636379Ssklower HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht); 81736379Ssklower 81836379Ssklower if (type == ESIS_ESH) { 81936379Ssklower cp++; 82036379Ssklower len++; 82136379Ssklower } 82236379Ssklower 82337469Ssklower m->m_len = len; 82443332Ssklower if (isoa) { 82543332Ssklower /* 82643332Ssklower * Here we are responding to a clnp packet sent to an NSAP 82743332Ssklower * that is ours which was sent to the MAC addr all_es's. 82843332Ssklower * It is possible that we did not specifically advertise this 82943332Ssklower * NSAP, even though it is ours, so we will respond 83043332Ssklower * directly to the sender that we are here. If we do have 83143332Ssklower * multiple NSEL's we'll tack them on so he can compress them out. 83243332Ssklower */ 83343332Ssklower (void) esis_insert_addr(&cp, &len, isoa, m, 0); 83443332Ssklower naddr = 1; 83543332Ssklower } 83643332Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 83743332Ssklower int nsellen = (type == ESIS_ISH ? ia->ia_addr.siso_tlen : 0); 83843332Ssklower int n = ia->ia_addr.siso_nlen; 83943332Ssklower register struct iso_ifaddr *ia2; 84043332Ssklower 84143332Ssklower if (type == ESIS_ISH && naddr > 0) 84243332Ssklower break; 84343332Ssklower for (ia2 = iso_ifaddr; ia2 != ia; ia2 = ia2->ia_next) 84443332Ssklower if (Bcmp(ia->ia_addr.siso_data, ia2->ia_addr.siso_data, n) == 0) 84543332Ssklower break; 84643332Ssklower if (ia2 != ia) 84743332Ssklower continue; /* Means we have previously copied this nsap */ 84843332Ssklower if (isoa && Bcmp(ia->ia_addr.siso_data, isoa->isoa_genaddr, n) == 0) { 84943332Ssklower isoa = 0; 85043332Ssklower continue; /* Ditto */ 85136379Ssklower } 85243332Ssklower IFDEBUG(D_ESISOUTPUT) 85343332Ssklower printf("esis_shoutput: adding NSAP %s\n", 85443332Ssklower clnp_iso_addrp(&ia->ia_addr.siso_addr)); 85543332Ssklower ENDDEBUG 85643332Ssklower if (!esis_insert_addr(&cp, &len, 85743332Ssklower &ia->ia_addr.siso_addr, m, nsellen)) { 85843332Ssklower EXTEND_PACKET(m, m0, cp); 85943332Ssklower (void) esis_insert_addr(&cp, &len, &ia->ia_addr.siso_addr, m, 86043332Ssklower nsellen); 86143332Ssklower } 86243332Ssklower naddr++; 86336379Ssklower } 86436379Ssklower 86536379Ssklower if (type == ESIS_ESH) 86636379Ssklower *naddrp = naddr; 86744254Ssklower else { 86844254Ssklower /* add suggested es config timer option to ISH */ 86944254Ssklower if (M_TRAILINGSPACE(m) < 4) { 87044254Ssklower printf("esis_shoutput: extending packet\n"); 87144254Ssklower EXTEND_PACKET(m, m0, cp); 87244254Ssklower } 87344254Ssklower *cp++ = ESISOVAL_ESCT; 87444254Ssklower *cp++ = 2; 87544254Ssklower HTOC(*cp, *(cp+1), esis_esconfig_time); 87644254Ssklower len += 4; 87744254Ssklower m->m_len += 4; 87844254Ssklower IFDEBUG(D_ESISOUTPUT) 87944254Ssklower printf("m0 0x%x, m 0x%x, data 0x%x, len %d, cp 0x%x\n", 88044254Ssklower m0, m, m->m_data, m->m_len, cp); 88144254Ssklower ENDDEBUG 88244254Ssklower } 88336379Ssklower 88437469Ssklower m0->m_pkthdr.len = len; 88537469Ssklower pdu->esis_hdr_len = len; 88636379Ssklower iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len); 88736379Ssklower 88837469Ssklower bzero((caddr_t)&siso, sizeof(siso)); 88936379Ssklower siso.siso_family = AF_ISO; 89037469Ssklower siso.siso_data[0] = AFI_SNA; 89137469Ssklower siso.siso_nlen = sn_len + 1; 89237469Ssklower bcopy(sn_addr, siso.siso_data + 1, (unsigned)sn_len); 89340775Ssklower (ifp->if_output)(ifp, m0, &siso, 0); 89436379Ssklower } 89536379Ssklower 89636379Ssklower /* 89743421Ssklower * FUNCTION: isis_input 89843421Ssklower * 89943421Ssklower * PURPOSE: Process an incoming isis packet 90043421Ssklower * 90143421Ssklower * RETURNS: nothing 90243421Ssklower * 90343421Ssklower * SIDE EFFECTS: 90443421Ssklower * 90543421Ssklower * NOTES: 90643421Ssklower */ 90743421Ssklower isis_input(m0, shp) 90843421Ssklower struct mbuf *m0; /* ptr to first mbuf of pkt */ 90943421Ssklower struct snpa_hdr *shp; /* subnetwork header */ 91043421Ssklower { 91143421Ssklower register int type; 91243961Ssklower register struct rawcb *rp, *first_rp = 0; 91343421Ssklower struct ifnet *ifp = shp->snh_ifp; 91443421Ssklower char workbuf[16]; 91543421Ssklower struct mbuf *mm; 91643421Ssklower 91743421Ssklower IFDEBUG(D_ISISINPUT) 91843421Ssklower int i; 91943421Ssklower 92043421Ssklower printf("isis_input: pkt on ifp x%x (%s%d): from:", ifp, 92143421Ssklower ifp->if_name, ifp->if_unit); 92243421Ssklower for (i=0; i<6; i++) 92343421Ssklower printf("%x%c", shp->snh_shost[i]&0xff, (i<5) ? ':' : ' '); 92443421Ssklower printf(" to:"); 92543421Ssklower for (i=0; i<6; i++) 92643421Ssklower printf("%x%c", shp->snh_dhost[i]&0xff, (i<5) ? ':' : ' '); 92743421Ssklower printf("\n"); 92843421Ssklower ENDDEBUG 92943421Ssklower esis_dl.sdl_alen = ifp->if_addrlen; 93043421Ssklower esis_dl.sdl_index = ifp->if_index; 93143421Ssklower bcopy(shp->snh_shost, (caddr_t)esis_dl.sdl_data, esis_dl.sdl_alen); 93243421Ssklower for (rp = esis_pcb.rcb_next; rp != &esis_pcb; rp = rp->rcb_next) { 93343961Ssklower if (first_rp == 0) { 93443961Ssklower first_rp = rp; 93543421Ssklower continue; 93643421Ssklower } 93743421Ssklower if (mm = m_copy(m0, 0, M_COPYALL)) { /*can't block at interrupt level */ 93843421Ssklower if (sbappendaddr(&rp->rcb_socket->so_rcv, 93943421Ssklower &esis_dl, mm, (struct mbuf *)0) != 0) 94043421Ssklower sorwakeup(rp->rcb_socket); 94143421Ssklower else { 94243421Ssklower IFDEBUG(D_ISISINPUT) 94343421Ssklower printf("Error in sbappenaddr, mm = 0x%x\n", mm); 94443421Ssklower ENDDEBUG 94543421Ssklower m_freem(mm); 94643421Ssklower } 94743421Ssklower } 94843421Ssklower } 94943961Ssklower if (first_rp && sbappendaddr(&first_rp->rcb_socket->so_rcv, 95044946Ssklower &esis_dl, m0, (struct mbuf *)0) != 0) { 95143961Ssklower sorwakeup(first_rp->rcb_socket); 95243961Ssklower return; 95343421Ssklower } 95443961Ssklower m_freem(m0); 95543421Ssklower } 95643421Ssklower 95743421Ssklower isis_output(sdl, m) 95843421Ssklower register struct sockaddr_dl *sdl; 95943421Ssklower struct mbuf *m; 96043421Ssklower { 96143421Ssklower register struct ifnet *ifp; 96243421Ssklower struct ifaddr *ifa, *ifa_ifwithnet(); 96343421Ssklower struct sockaddr_iso siso; 96443421Ssklower int error = 0; 96543421Ssklower unsigned sn_len; 96643421Ssklower 96743421Ssklower ifa = ifa_ifwithnet(sdl); /* extract ifp from sockaddr_dl */ 96843421Ssklower if (ifa == 0) { 96943421Ssklower IFDEBUG(D_ISISOUTPUT) 97043421Ssklower printf("isis_output: interface not found\n"); 97143421Ssklower ENDDEBUG 97243421Ssklower error = EINVAL; 97343421Ssklower goto release; 97443421Ssklower } 97543421Ssklower ifp = ifa->ifa_ifp; 97645896Ssklower sn_len = sdl->sdl_alen; 97743421Ssklower IFDEBUG(D_ISISOUTPUT) 97843421Ssklower u_char *cp = (u_char *)LLADDR(sdl), *cplim = cp + sn_len; 97943421Ssklower printf("isis_output: ifp 0x%x (%s%d), to: ", 98043421Ssklower ifp, ifp->if_name, ifp->if_unit); 98143421Ssklower while (cp < cplim) { 98243421Ssklower printf("%x", *cp++); 98343421Ssklower printf("%c", (cp < cplim) ? ':' : ' '); 98443421Ssklower } 98543421Ssklower printf("\n"); 98643421Ssklower ENDDEBUG 98743421Ssklower bzero((caddr_t)&siso, sizeof(siso)); 98843421Ssklower siso.siso_family = AF_ISO; /* This convention may be useful for X.25 */ 98943421Ssklower siso.siso_data[0] = AFI_SNA; 99043421Ssklower siso.siso_nlen = sn_len + 1; 99143421Ssklower bcopy(LLADDR(sdl), siso.siso_data + 1, sn_len); 99243421Ssklower error = (ifp->if_output)(ifp, m, (struct sockaddr *)&siso, 0); 99343421Ssklower if (error) { 99443421Ssklower IFDEBUG(D_ISISOUTPUT) 99543421Ssklower printf("isis_output: error from ether_output is %d\n", error); 99643421Ssklower ENDDEBUG 99743421Ssklower } 99843421Ssklower return (error); 99943421Ssklower 100043421Ssklower release: 100143421Ssklower if (m != NULL) 100243421Ssklower m_freem(m); 100343421Ssklower return(error); 100443421Ssklower } 100543421Ssklower 100643421Ssklower 100743421Ssklower /* 100836379Ssklower * FUNCTION: esis_ctlinput 100936379Ssklower * 101036379Ssklower * PURPOSE: Handle the PRC_IFDOWN transition 101136379Ssklower * 101236379Ssklower * RETURNS: nothing 101336379Ssklower * 101436379Ssklower * SIDE EFFECTS: 101536379Ssklower * 101636379Ssklower * NOTES: Calls snpac_flush for interface specified. 101736379Ssklower * The loop through iso_ifaddr is stupid because 101836379Ssklower * back in if_down, we knew the ifp... 101936379Ssklower */ 102036379Ssklower esis_ctlinput(req, siso) 102136379Ssklower int req; /* request: we handle only PRC_IFDOWN */ 102236379Ssklower struct sockaddr_iso *siso; /* address of ifp */ 102336379Ssklower { 102436379Ssklower register struct iso_ifaddr *ia; /* scan through interface addresses */ 102536379Ssklower 102637469Ssklower if (req == PRC_IFDOWN) 102737469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) { 102837469Ssklower if (iso_addrmatch(IA_SIS(ia), siso)) 102937469Ssklower snpac_flushifp(ia->ia_ifp); 103037469Ssklower } 103136379Ssklower } 103236379Ssklower 103336379Ssklower #endif ISO 1034