📄 if_x25subr.c
字号:
/* * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_x25subr.c 8.1 (Berkeley) 6/10/93 */#include <sys/param.h>#include <sys/systm.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/ioctl.h>#include <sys/errno.h>#include <sys/syslog.h>#include <machine/mtpr.h>#include <net/if.h>#include <net/if_types.h>#include <net/netisr.h>#include <net/route.h>#include <netccitt/x25.h>#include <netccitt/x25err.h>#include <netccitt/pk.h>#include <netccitt/pk_var.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_var.h>#endif#ifdef NS#include <netns/ns.h>#include <netns/ns_if.h>#endif#ifdef ISOint tp_incoming();#include <netiso/argo_debug.h>#include <netiso/iso.h>#include <netiso/iso_var.h>#endifextern struct ifnet loif;struct llinfo_x25 llinfo_x25 = {&llinfo_x25, &llinfo_x25};#ifndef _offsetof#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))#endifstruct sockaddr *x25_dgram_sockmask;struct sockaddr_x25 x25_dgmask = { _offsetof(struct sockaddr_x25, x25_udata[1]), /* _len */ 0, /* _family */ 0, /* _net */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* _addr */ {0}, /* opts */ -1, /* _udlen */ {-1} /* _udata */}; struct if_x25stats { int ifx_wrongplen; int ifx_nophdr;} if_x25stats;int x25_autoconnect = 0;#define senderr(x) {error = x; goto bad;}/* * Ancillary routines */static struct llinfo_x25 *x25_lxalloc(rt)register struct rtentry *rt;{ register struct llinfo_x25 *lx; register struct sockaddr *dst = rt_key(rt); register struct ifaddr *ifa; MALLOC(lx, struct llinfo_x25 *, sizeof (*lx), M_PCB, M_NOWAIT); if (lx == 0) return lx; Bzero(lx, sizeof(*lx)); lx->lx_rt = rt; lx->lx_family = dst->sa_family; rt->rt_refcnt++; if (rt->rt_llinfo) insque(lx, (struct llinfo_x25 *)rt->rt_llinfo); else { rt->rt_llinfo = (caddr_t)lx; insque(lx, &llinfo_x25); } for (ifa = rt->rt_ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family == AF_CCITT) lx->lx_ia = (struct x25_ifaddr *)ifa; } return lx;}x25_lxfree(lx)register struct llinfo_x25 *lx;{ register struct rtentry *rt = lx->lx_rt; register struct pklcd *lcp = lx->lx_lcd; if (lcp) { lcp->lcd_upper = 0; pk_disconnect(lcp); } if ((rt->rt_llinfo == (caddr_t)lx) && (lx->lx_next->lx_rt == rt)) rt->rt_llinfo = (caddr_t)lx->lx_next; else rt->rt_llinfo = 0; RTFREE(rt); remque(lx); FREE(lx, M_PCB);}/* * Process a x25 packet as datagram; */x25_ifinput(lcp, m)struct pklcd *lcp;register struct mbuf *m;{ struct llinfo_x25 *lx = (struct llinfo_x25 *)lcp->lcd_upnext; register struct ifnet *ifp; struct ifqueue *inq; extern struct timeval time; int s, len, isr; if (m == 0 || lcp->lcd_state != DATA_TRANSFER) { x25_connect_callback(lcp, 0); return; } pk_flowcontrol(lcp, 0, 1); /* Generate RR */ ifp = m->m_pkthdr.rcvif; ifp->if_lastchange = time; switch (m->m_type) { default: if (m) m_freem(m); return; case MT_DATA: /* FALLTHROUGH */; } switch (lx->lx_family) {#ifdef INET case AF_INET: isr = NETISR_IP; inq = &ipintrq; break;#endif#ifdef NS case AF_NS: isr = NETISR_NS; inq = &nsintrq; break;#endif#ifdef ISO case AF_ISO: isr = NETISR_ISO; inq = &clnlintrq; break;#endif default: m_freem(m); ifp->if_noproto++; return; } s = splimp(); schednetisr(isr); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else { IF_ENQUEUE(inq, m); ifp->if_ibytes += m->m_pkthdr.len; } splx(s);}x25_connect_callback(lcp, m)register struct pklcd *lcp;register struct mbuf *m;{ register struct llinfo_x25 *lx = (struct llinfo_x25 *)lcp->lcd_upnext; int do_clear = 1; if (m == 0) goto refused; if (m->m_type != MT_CONTROL) { printf("x25_connect_callback: should panic\n"); goto refused; } switch (pk_decode(mtod(m, struct x25_packet *))) { case CALL_ACCEPTED: lcp->lcd_upper = x25_ifinput; if (lcp->lcd_sb.sb_mb) lcp->lcd_send(lcp); /* XXX start queued packets */ return; default: do_clear = 0; refused: lcp->lcd_upper = 0; lx->lx_lcd = 0; if (do_clear) pk_disconnect(lcp); return; }}#define SA(p) ((struct sockaddr *)(p))#define RT(p) ((struct rtentry *)(p))x25_dgram_incoming(lcp, m0)register struct pklcd *lcp;struct mbuf *m0;{ register struct rtentry *rt, *nrt; register struct mbuf *m = m0->m_next; /* m0 has calling sockaddr_x25 */ void x25_rtrequest(); rt = rtalloc1(SA(&lcp->lcd_faddr), 0); if (rt == 0) {refuse: lcp->lcd_upper = 0; pk_close(lcp); return; } rt->rt_refcnt--; if ((nrt = RT(rt->rt_llinfo)) == 0 || rt_mask(rt) != x25_dgram_sockmask) goto refuse; if ((nrt->rt_flags & RTF_UP) == 0) { rt->rt_llinfo = (caddr_t)rtalloc1(rt->rt_gateway, 0); rtfree(nrt); if ((nrt = RT(rt->rt_llinfo)) == 0) goto refuse; nrt->rt_refcnt--; } if (nrt->rt_ifa == 0 || nrt->rt_ifa->ifa_rtrequest != x25_rtrequest) goto refuse; lcp->lcd_send(lcp); /* confirm call */ x25_rtattach(lcp, nrt); m_freem(m);}/* * X.25 output routine. */x25_ifoutput(ifp, m0, dst, rt)struct ifnet *ifp;struct mbuf *m0;struct sockaddr *dst;register struct rtentry *rt;{ register struct mbuf *m = m0; register struct llinfo_x25 *lx; struct pklcd *lcp; int s, error = 0;int plen;for (plen = 0; m; m = m->m_next) plen += m->m_len;m = m0; if ((ifp->if_flags & IFF_UP) == 0) senderr(ENETDOWN); while (rt == 0 || (rt->rt_flags & RTF_GATEWAY)) { if (rt) { if (rt->rt_llinfo) { rt = (struct rtentry *)rt->rt_llinfo; continue; } dst = rt->rt_gateway; } if ((rt = rtalloc1(dst, 1)) == 0) senderr(EHOSTUNREACH); rt->rt_refcnt--; } /* * Sanity checks. */ if ((rt->rt_ifp != ifp) || (rt->rt_flags & (RTF_CLONING | RTF_GATEWAY)) || ((lx = (struct llinfo_x25 *)rt->rt_llinfo) == 0)) { senderr(ENETUNREACH); }if ((m->m_flags & M_PKTHDR) == 0) { if_x25stats.ifx_nophdr++; m = m_gethdr(M_NOWAIT, MT_HEADER); if (m == 0) senderr(ENOBUFS); m->m_pkthdr.len = plen; m->m_next = m0;}if (plen != m->m_pkthdr.len) { if_x25stats.ifx_wrongplen++; m->m_pkthdr.len = plen;}next_circuit: lcp = lx->lx_lcd; if (lcp == 0) { lx->lx_lcd = lcp = pk_attach((struct socket *)0); if (lcp == 0) senderr(ENOBUFS); lcp->lcd_upper = x25_connect_callback; lcp->lcd_upnext = (caddr_t)lx; lcp->lcd_packetsize = lx->lx_ia->ia_xc.xc_psize; lcp->lcd_flags = X25_MBS_HOLD; } switch (lcp->lcd_state) { case READY: if (dst->sa_family == AF_INET && ifp->if_type == IFT_X25DDN && rt->rt_gateway->sa_family != AF_CCITT) x25_ddnip_to_ccitt(dst, rt); if (rt->rt_gateway->sa_family != AF_CCITT) { if ((rt->rt_flags & RTF_XRESOLVE) == 0) senderr(EHOSTUNREACH); } else if (x25_autoconnect) error = pk_connect(lcp, (struct sockaddr_x25 *)rt->rt_gateway); if (error) senderr(error); /* FALLTHROUGH */ case SENT_CALL: case DATA_TRANSFER: if (sbspace(&lcp->lcd_sb) < 0) { lx = lx->lx_next; if (lx->lx_rt != rt) senderr(ENOSPC); goto next_circuit; } if (lx->lx_ia) lcp->lcd_dg_timer = lx->lx_ia->ia_xc.xc_dg_idletimo; pk_send(lcp, m); break; default: /* * We count on the timer routine to close idle * connections, if there are not enough circuits to go * around. * * So throw away data for now. * After we get it all working, we'll rewrite to handle * actively closing connections (other than by timers), * when circuits get tight. * * In the DDN case, the imp itself closes connections * under heavy load. */ error = ENOBUFS; bad: if (m) m_freem(m); } return (error);}/* * Simpleminded timer routine. */x25_iftimeout(ifp)struct ifnet *ifp;{ register struct pkcb *pkcb = 0; register struct pklcd **lcpp, *lcp; int s = splimp(); FOR_ALL_PKCBS(pkcb) if (pkcb->pk_ia->ia_ifp == ifp) for (lcpp = pkcb->pk_chan + pkcb->pk_maxlcn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -