123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873 |
- #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_metric
- static 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 0x8021
- static 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;
- #define DBGLOG 1
- static int if_ppp_count;
- static int ppp_nalloc;
- static struct ifnet **ifs;
- static if_ppp_t **states;
- 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
- static struct ether_header snit_ehdr = {{0}, {0}, ETHERTYPE_IP};
- #endif
- #ifndef __osf__
- static void ppp_if_detach __P((struct ifnet *));
- int
- if_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
- static int
- if_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;
- sp->q = WR(q);
- sp->flags = 0;
- ++if_ppp_count;
- }
- return 0;
- }
- static int
- if_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 int
- if_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:
-
- 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:
- if (iop->ioc_count != sizeof(int) || sp->unit >= 0)
- break;
- if ((error = NOTSUSER()) != 0)
- break;
- unit = *(int *)mp->b_cont->b_rptr;
-
- if (unit < ppp_nalloc && states[unit] != 0) {
- error = EADDRINUSE;
- break;
- }
-
- 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;
- }
-
- 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
- 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 int
- if_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:
-
- 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;
- snit_intr(ifp, mb, &nif);
- }
- #endif
- #ifdef __osf__
- mb->m_pkthdr.rcvif = ifp;
- mb->m_pkthdr.len = len;
- #else
- mb->m_off -= sizeof(struct ifnet *);
- mb->m_len += sizeof(struct ifnet *);
- *mtod(mb, struct ifnet **) = ifp;
- #endif
- inq = 0;
- switch (proto) {
- case PPP_IP:
- inq = &ipintrq;
- schednetisr(NETISR_IP);
- }
- if (inq != 0) {
- s = splhigh();
- if (IF_QFULL(inq)) {
- IF_DROP(inq);
- ++ifp->if_ierrors;
- if (sp->flags & DBGLOG)
- printf("if_ppp: inq full, proto=%x\n", proto);
- m_freem(mb);
- } else {
- IF_ENQUEUE(inq, mb);
- }
- splx(s);
- } else {
- if (sp->flags & DBGLOG)
- printf("if_ppp%d: proto=%x?\n", ifp->if_unit, proto);
- ++ifp->if_ierrors;
- m_freem(mb);
- }
- break;
- default:
- putnext(q, mp);
- }
- return 0;
- }
- static int
- if_ppp_output(ifp, m0, dst)
- struct ifnet *ifp;
- struct mbuf *m0;
- struct sockaddr *dst;
- {
- mblk_t *mp;
- int proto, s;
- if_ppp_t *sp;
- u_char *p;
- if ((ifp->if_flags & IFF_UP) == 0) {
- m_freem(m0);
- return ENETDOWN;
- }
- if ((unsigned)ifp->if_unit >= ppp_nalloc) {
- #ifdef DEBUG
- printf("if_ppp_output: unit %d?\n", ifp->if_unit);
- #endif
- m_freem(m0);
- return EINVAL;
- }
- sp = states[ifp->if_unit];
- if (sp == 0) {
- #ifdef DEBUG
- printf("if_ppp_output: no queue?\n");
- #endif
- m_freem(m0);
- return ENETDOWN;
- }
- if (sp->flags & DBGLOG) {
- p = mtod(m0, u_char *);
- printf("if_ppp_output%d: af=%d data=%x %x %x %x %x %x %x %x q=%x\n",
- ifp->if_unit, dst->sa_family, p[0], p[1], p[2], p[3], p[4],
- p[5], p[6], p[7], sp->q);
- }
- switch (dst->sa_family) {
- case AF_INET:
- proto = PPP_IP;
- #ifdef SNIT_SUPPORT
- if (ifp->if_flags & IFF_PROMISC) {
- struct nit_if nif;
- struct mbuf *m;
- int len;
- for (len = 0, m = m0; m != NULL; m = m->m_next)
- len += m->m_len;
- nif.nif_header = (caddr_t) &snit_ehdr;
- nif.nif_hdrlen = sizeof(snit_ehdr);
- nif.nif_bodylen = len;
- nif.nif_promisc = 0;
- snit_intr(ifp, m0, &nif);
- }
- #endif
- break;
- default:
- m_freem(m0);
- return EAFNOSUPPORT;
- }
- ++ifp->if_opackets;
- mp = make_message(m0, PPP_HDRLEN);
- m_freem(m0);
- if (mp == 0) {
- ++ifp->if_oerrors;
- return ENOBUFS;
- }
- mp->b_rptr -= PPP_HDRLEN;
- mp->b_rptr[0] = PPP_ALLSTATIONS;
- mp->b_rptr[1] = PPP_UI;
- mp->b_rptr[2] = proto >> 8;
- mp->b_rptr[3] = proto;
- s = splstr();
- if (sp->flags & DBGLOG)
- printf("if_ppp: putnext(%x, %x), r=%x w=%x p=%x\n",
- sp->q, mp, mp->b_rptr, mp->b_wptr, proto);
- putnext(sp->q, mp);
- splx(s);
- return 0;
- }
- static int
- if_ppp_ioctl(ifp, cmd, data)
- struct ifnet *ifp;
- u_int cmd;
- caddr_t data;
- {
- int s, error;
- struct ifreq *ifr = (struct ifreq *) data;
- struct ifaddr *ifa = (struct ifaddr *) data;
- u_short mtu;
- error = 0;
- s = splimp();
- switch (cmd) {
- case SIOCSIFFLAGS:
- if ((ifp->if_flags & IFF_RUNNING) == 0)
- ifp->if_flags &= ~IFF_UP;
- break;
- case SIOCSIFADDR:
- if (IFA_ADDR(ifa).sa_family != AF_INET)
- error = EAFNOSUPPORT;
- break;
- case SIOCSIFDSTADDR:
- if (IFA_ADDR(ifa).sa_family != AF_INET)
- error = EAFNOSUPPORT;
- break;
- case SIOCSIFMTU:
- if ((error = NOTSUSER()) != 0)
- break;
- #ifdef __osf__
-
- bcopy(ifr->ifr_data, &mtu, sizeof (u_short));
- ifr->ifr_mtu = mtu;
- #endif
- if (ifr->ifr_mtu < PPP_MINMTU || ifr->ifr_mtu > PPP_MAXMTU) {
- error = EINVAL;
- break;
- }
- ifp->if_mtu = ifr->ifr_mtu;
- break;
- case SIOCGIFMTU:
- ifr->ifr_mtu = ifp->if_mtu;
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- switch(ifr->ifr_addr.sa_family) {
- case AF_INET:
- break;
- default:
- error = EAFNOSUPPORT;
- break;
- }
- break;
- default:
- error = EINVAL;
- }
- splx(s);
- return (error);
- }
- static struct mbuf *
- make_mbufs(mp, off)
- mblk_t *mp;
- int off;
- {
- struct mbuf *head, **prevp, *m;
- int len, space, n;
- unsigned char *cp, *dp;
- len = msgdsize(mp);
- if (len == 0)
- return 0;
- prevp = &head;
- space = 0;
- cp = mp->b_rptr;
- #ifdef __osf__
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- m->m_len = 0;
- space = MHLEN;
- *prevp = m;
- prevp = &m->m_next;
- dp = mtod(m, unsigned char *);
- len -= space;
- off = 0;
- #endif
- for (;;) {
- while (cp >= mp->b_wptr) {
- mp = mp->b_cont;
- if (mp == 0) {
- *prevp = 0;
- return head;
- }
- cp = mp->b_rptr;
- }
- n = mp->b_wptr - cp;
- if (space == 0) {
- MGET(m, M_DONTWAIT, MT_DATA);
- *prevp = m;
- if (m == 0) {
- if (head != 0)
- m_freem(head);
- return 0;
- }
- if (len + off > 2 * MLEN) {
- #ifdef __osf__
- MCLGET(m, M_DONTWAIT);
- #else
- MCLGET(m);
- #endif
- }
- #ifdef __osf__
- space = ((m->m_flags & M_EXT) ? MCLBYTES : MLEN);
- #else
- space = (m->m_off > MMAXOFF? MCLBYTES: MLEN) - off;
- m->m_off += off;
- #endif
- m->m_len = 0;
- len -= space;
- dp = mtod(m, unsigned char *);
- off = 0;
- prevp = &m->m_next;
- }
- if (n > space)
- n = space;
- bcopy(cp, dp, n);
- cp += n;
- dp += n;
- space -= n;
- m->m_len += n;
- }
- }
- #define ALLOCB_MAX 4096
- static mblk_t *
- make_message(m, off)
- struct mbuf *m;
- int off;
- {
- mblk_t *head, **prevp, *mp;
- int len, space, n, nb;
- unsigned char *cp, *dp;
- struct mbuf *nm;
- len = 0;
- for (nm = m; nm != 0; nm = nm->m_next)
- len += nm->m_len;
- prevp = &head;
- space = 0;
- cp = mtod(m, unsigned char *);
- nb = m->m_len;
- for (;;) {
- while (nb <= 0) {
- m = m->m_next;
- if (m == 0) {
- *prevp = 0;
- return head;
- }
- cp = mtod(m, unsigned char *);
- nb = m->m_len;
- }
- if (space == 0) {
- space = len + off;
- if (space > ALLOCB_MAX)
- space = ALLOCB_MAX;
- mp = allocb(space, BPRI_LO);
- *prevp = mp;
- if (mp == 0) {
- if (head != 0)
- freemsg(head);
- return 0;
- }
- dp = mp->b_rptr += off;
- space -= off;
- len -= space;
- off = 0;
- prevp = &mp->b_cont;
- }
- n = nb < space? nb: space;
- bcopy(cp, dp, n);
- cp += n;
- dp += n;
- nb -= n;
- space -= n;
- mp->b_wptr = dp;
- }
- }
- #ifndef __osf__
- #include <net/route.h>
- #include <netinet/in_pcb.h>
- #include <netinet/ip_var.h>
- #include <netinet/tcp.h>
- #include <netinet/tcp_timer.h>
- #include <netinet/tcp_var.h>
- #include <netinet/udp.h>
- #include <netinet/udp_var.h>
- static void
- ppp_if_detach(ifp)
- struct ifnet *ifp;
- {
- int s;
- struct inpcb *pcb;
- struct ifaddr *ifa;
- struct in_ifaddr **inap;
- struct ifnet **ifpp;
- s = splhigh();
-
- for (pcb = tcb.inp_next; pcb != &tcb; pcb = pcb->inp_next)
- if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
- in_losing(pcb);
- for (pcb = udb.inp_next; pcb != &udb; pcb = pcb->inp_next)
- if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
- in_losing(pcb);
-
- for (ifa = ifp->if_addrlist; ifa != 0; ifa = ifa->ifa_next) {
- rtinit(ifa, ifa, SIOCDELRT, RTF_HOST);
- rtinit(ifa, ifa, SIOCDELRT, 0);
- }
-
- for (inap = &in_ifaddr; *inap != 0; ) {
- if ((*inap)->ia_ifa.ifa_ifp == ifp)
- *inap = (*inap)->ia_next;
- else
- inap = &(*inap)->ia_next;
- }
-
- for (ifpp = &ifnet; (*ifpp) != 0; ) {
- if (*ifpp == ifp)
- break;
- ifpp = &(*ifpp)->if_next;
- }
- if (*ifpp == 0)
- printf("couldn't find interface ppp%d in ifnet list\n", ifp->if_unit);
- else
- *ifpp = ifp->if_next;
- splx(s);
- }
- #endif
|