📄 if_ppp.c
字号:
/* * if_ppp.c - a network interface connected to a STREAMS module. * * Copyright (c) 1994 The Australian National University. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation is hereby granted, provided that the above copyright * notice appears in all copies. This software is provided without any * warranty, express or implied. The Australian National University * makes no representations about the suitability of this software for * any purpose. * * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * * $Id: if_ppp.c,v 1.17 1999/12/23 01:48:45 paulus Exp $ *//* * This file is used under SunOS 4 and Digital UNIX. * * This file provides the glue between PPP and IP. */#define INET 1#include <sys/types.h>#include <sys/param.h>#include <sys/errno.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <net/if.h>#include <net/netisr.h>#include <net/ppp_defs.h>#include <net/pppio.h>#include <netinet/in.h>#include <netinet/in_var.h>#ifdef __osf__#include <sys/ioctl.h>#include <net/if_types.h>#else#include <sys/sockio.h>#endif#include "ppp_mod.h"#include <sys/stream.h>#ifdef SNIT_SUPPORT#include <sys/time.h>#include <net/nit_if.h>#include <netinet/if_ether.h>#endif#ifdef __osf__#define SIOCSIFMTU SIOCSIPMTU#define SIOCGIFMTU SIOCRIPMTU#define IFA_ADDR(ifa) (*(ifa)->ifa_addr)#else#define IFA_ADDR(ifa) ((ifa)->ifa_addr)#endif#define ifr_mtu ifr_metricstatic int if_ppp_open __P((queue_t *, int, int, int));static int if_ppp_close __P((queue_t *, int));static int if_ppp_wput __P((queue_t *, mblk_t *));static int if_ppp_rput __P((queue_t *, mblk_t *));#define PPP_IF_ID 0x8021static struct module_info minfo = { PPP_IF_ID, "if_ppp", 0, INFPSZ, 4096, 128};static struct qinit rinit = { if_ppp_rput, NULL, if_ppp_open, if_ppp_close, NULL, &minfo, NULL};static struct qinit winit = { if_ppp_wput, NULL, NULL, NULL, NULL, &minfo, NULL};struct streamtab if_pppinfo = { &rinit, &winit, NULL, NULL};typedef struct if_ppp_state { int unit; queue_t *q; int flags;} if_ppp_t;/* Values for flags */#define DBGLOG 1static int if_ppp_count; /* Number of currently-active streams */static int ppp_nalloc; /* Number of elements of ifs and states */static struct ifnet **ifs; /* Array of pointers to interface structs */static if_ppp_t **states; /* Array of pointers to state structs */static int if_ppp_output __P((struct ifnet *, struct mbuf *, struct sockaddr *));static int if_ppp_ioctl __P((struct ifnet *, u_int, caddr_t));static struct mbuf *make_mbufs __P((mblk_t *, int));static mblk_t *make_message __P((struct mbuf *, int));#ifdef SNIT_SUPPORT/* Fake ether header for SNIT */static struct ether_header snit_ehdr = {{0}, {0}, ETHERTYPE_IP};#endif#ifndef __osf__static void ppp_if_detach __P((struct ifnet *));/* * Detach all the interfaces before unloading. * Not sure this works. */intif_ppp_unload(){ int i; if (if_ppp_count > 0) return EBUSY; for (i = 0; i < ppp_nalloc; ++i) if (ifs[i] != 0) ppp_if_detach(ifs[i]); if (ifs) { FREE(ifs, ppp_nalloc * sizeof (struct ifnet *)); FREE(states, ppp_nalloc * sizeof (struct if_ppp_t *)); } ppp_nalloc = 0; return 0;}#endif /* __osf__ *//* * STREAMS module entry points. */static intif_ppp_open(q, dev, flag, sflag) queue_t *q; int dev; int flag, sflag;{ if_ppp_t *sp; if (q->q_ptr == 0) { sp = (if_ppp_t *) ALLOC_SLEEP(sizeof (if_ppp_t)); if (sp == 0) return OPENFAIL; bzero(sp, sizeof (if_ppp_t)); q->q_ptr = (caddr_t) sp; WR(q)->q_ptr = (caddr_t) sp; sp->unit = -1; /* no interface unit attached at present */ sp->q = WR(q); sp->flags = 0; ++if_ppp_count; } return 0;}static intif_ppp_close(q, flag) queue_t *q; int flag;{ if_ppp_t *sp; struct ifnet *ifp; sp = (if_ppp_t *) q->q_ptr; if (sp != 0) { if (sp->flags & DBGLOG) printf("if_ppp closed, q=%x sp=%x\n", q, sp); if (sp->unit >= 0) { if (sp->unit < ppp_nalloc) { states[sp->unit] = 0; ifp = ifs[sp->unit]; if (ifp != 0) ifp->if_flags &= ~(IFF_UP | IFF_RUNNING);#ifdef DEBUG } else { printf("if_ppp: unit %d nonexistent!\n", sp->unit);#endif } } FREE(sp, sizeof (if_ppp_t)); --if_ppp_count; } return 0;}static intif_ppp_wput(q, mp) queue_t *q; mblk_t *mp;{ if_ppp_t *sp; struct iocblk *iop; int error, unit; struct ifnet *ifp; sp = (if_ppp_t *) q->q_ptr; switch (mp->b_datap->db_type) { case M_DATA: /* * Now why would we be getting data coming in here?? */ if (sp->flags & DBGLOG) printf("if_ppp: got M_DATA len=%d\n", msgdsize(mp)); freemsg(mp); break; case M_IOCTL: iop = (struct iocblk *) mp->b_rptr; error = EINVAL; if (sp->flags & DBGLOG) printf("if_ppp: got ioctl cmd=%x count=%d\n", iop->ioc_cmd, iop->ioc_count); switch (iop->ioc_cmd) { case PPPIO_NEWPPA: /* well almost */ if (iop->ioc_count != sizeof(int) || sp->unit >= 0) break; if ((error = NOTSUSER()) != 0) break; unit = *(int *)mp->b_cont->b_rptr; /* Check that this unit isn't already in use */ if (unit < ppp_nalloc && states[unit] != 0) { error = EADDRINUSE; break; } /* Extend ifs and states arrays if necessary. */ error = ENOSR; if (unit >= ppp_nalloc) { int newn; struct ifnet **newifs; if_ppp_t **newstates; newn = unit + 4; if (sp->flags & DBGLOG) printf("if_ppp: extending ifs to %d\n", newn); newifs = (struct ifnet **) ALLOC_NOSLEEP(newn * sizeof (struct ifnet *)); if (newifs == 0) break; bzero(newifs, newn * sizeof (struct ifnet *)); newstates = (if_ppp_t **) ALLOC_NOSLEEP(newn * sizeof (struct if_ppp_t *)); if (newstates == 0) { FREE(newifs, newn * sizeof (struct ifnet *)); break; } bzero(newstates, newn * sizeof (struct if_ppp_t *)); bcopy(ifs, newifs, ppp_nalloc * sizeof(struct ifnet *)); bcopy(states, newstates, ppp_nalloc * sizeof(if_ppp_t *)); if (ifs) { FREE(ifs, ppp_nalloc * sizeof(struct ifnet *)); FREE(states, ppp_nalloc * sizeof(if_ppp_t *)); } ifs = newifs; states = newstates; ppp_nalloc = newn; } /* Allocate a new ifnet struct if necessary. */ ifp = ifs[unit]; if (ifp == 0) { ifp = (struct ifnet *) ALLOC_NOSLEEP(sizeof (struct ifnet)); if (ifp == 0) break; bzero(ifp, sizeof (struct ifnet)); ifs[unit] = ifp; ifp->if_name = "ppp"; ifp->if_unit = unit; ifp->if_mtu = PPP_MTU; ifp->if_flags = IFF_POINTOPOINT | IFF_RUNNING;#ifndef __osf__#ifdef IFF_MULTICAST ifp->if_flags |= IFF_MULTICAST;#endif#endif /* __osf__ */ ifp->if_output = if_ppp_output;#ifdef __osf__ ifp->if_version = "Point-to-Point Protocol, version 2.3.11"; ifp->if_mediamtu = PPP_MTU; ifp->if_type = IFT_PPP; ifp->if_hdrlen = PPP_HDRLEN; ifp->if_addrlen = 0; ifp->if_flags |= IFF_NOARP | IFF_SIMPLEX | IFF_NOTRAILERS;#ifdef IFF_VAR_MTU ifp->if_flags |= IFF_VAR_MTU;#endif#ifdef NETMASTERCPU ifp->if_affinity = NETMASTERCPU;#endif#endif ifp->if_ioctl = if_ppp_ioctl; ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; if_attach(ifp); if (sp->flags & DBGLOG) printf("if_ppp: created unit %d\n", unit); } else { ifp->if_mtu = PPP_MTU; ifp->if_flags |= IFF_RUNNING; } states[unit] = sp; sp->unit = unit; error = 0; iop->ioc_count = 0; if (sp->flags & DBGLOG) printf("if_ppp: attached unit %d, sp=%x q=%x\n", unit, sp, sp->q); break; case PPPIO_DEBUG: error = -1; if (iop->ioc_count == sizeof(int)) { if (*(int *)mp->b_cont->b_rptr == PPPDBG_LOG + PPPDBG_IF) { printf("if_ppp: debug log enabled, q=%x sp=%x\n", q, sp); sp->flags |= DBGLOG; error = 0; iop->ioc_count = 0; } } break; default: error = -1; break; } if (sp->flags & DBGLOG) printf("if_ppp: ioctl result %d\n", error); if (error < 0) putnext(q, mp); else if (error == 0) { mp->b_datap->db_type = M_IOCACK; qreply(q, mp); } else { mp->b_datap->db_type = M_IOCNAK; iop->ioc_count = 0; iop->ioc_error = error; qreply(q, mp); } break; default: putnext(q, mp); } return 0;}static intif_ppp_rput(q, mp) queue_t *q; mblk_t *mp;{ if_ppp_t *sp; int proto, s; struct mbuf *mb; struct ifqueue *inq; struct ifnet *ifp; int len; sp = (if_ppp_t *) q->q_ptr; switch (mp->b_datap->db_type) { case M_DATA: /* * Convert the message into an mbuf chain * and inject it into the network code. */ if (sp->flags & DBGLOG) printf("if_ppp: rput pkt len %d data %x %x %x %x %x %x %x %x\n", msgdsize(mp), mp->b_rptr[0], mp->b_rptr[1], mp->b_rptr[2], mp->b_rptr[3], mp->b_rptr[4], mp->b_rptr[5], mp->b_rptr[6], mp->b_rptr[7]); if (sp->unit < 0) { freemsg(mp); break; } if (sp->unit >= ppp_nalloc || (ifp = ifs[sp->unit]) == 0) {#ifdef DEBUG printf("if_ppp: no unit %d!\n", sp->unit);#endif freemsg(mp); break; } if ((ifp->if_flags & IFF_UP) == 0) { freemsg(mp); break; } ++ifp->if_ipackets; proto = PPP_PROTOCOL(mp->b_rptr); adjmsg(mp, PPP_HDRLEN); len = msgdsize(mp); mb = make_mbufs(mp, sizeof(struct ifnet *)); freemsg(mp); if (mb == NULL) { if (sp->flags & DBGLOG) printf("if_ppp%d: make_mbufs failed\n", ifp->if_unit); ++ifp->if_ierrors; break; }#ifdef SNIT_SUPPORT if (proto == PPP_IP && (ifp->if_flags & IFF_PROMISC)) { struct nit_if nif; nif.nif_header = (caddr_t) &snit_ehdr; nif.nif_hdrlen = sizeof(snit_ehdr); nif.nif_bodylen = len; nif.nif_promisc = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -