/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* ----------------------------------------------------------------------------- * * History : * * Aug 2000 - Christophe Allie - created. * * Theory of operation : * * this file implements the pptp driver for the ppp family * * it's the responsability of the driver to update the statistics * whenever that makes sense * ifnet.if_lastchange = a packet is present, a packet starts to be sent * ifnet.if_ibytes = nb of correct PPP bytes received * ifnet.if_obytes = nb of correct PPP bytes sent * ifnet.if_ipackets = nb of PPP packet received * ifnet.if_opackets = nb of PPP packet sent * ifnet.if_ierrors = nb on input packets in error * ifnet.if_oerrors = nb on ouptut packets in error * ----------------------------------------------------------------------------- */ /* ----------------------------------------------------------------------------- Includes ----------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include "../../../Family/ppp_domain.h" #include "../../../Family/if_ppplink.h" #include "../../../Family/ppp_defs.h" #include "../../../Family/if_ppp.h" #include "PPTP.h" #include "pptp_rfc.h" #include "pptp_wan.h" /* ----------------------------------------------------------------------------- Definitions ----------------------------------------------------------------------------- */ struct pptp_wan { /* first, the ifnet structure... */ struct ppp_link link; /* ppp link structure */ /* administrative info */ TAILQ_ENTRY(pptp_wan) next; void *rfc; /* pptp protocol structure */ /* settings */ /* output data */ /* input data */ /* log purpose */ }; /* ----------------------------------------------------------------------------- Forward declarations ----------------------------------------------------------------------------- */ static int pptp_wan_output(struct ppp_link *link, struct mbuf *m); static int pptp_wan_ioctl(struct ppp_link *link, u_int32_t cmd, void *data); static int pptp_wan_findfreeunit(u_short *freeunit); /* ----------------------------------------------------------------------------- Globals ----------------------------------------------------------------------------- */ static TAILQ_HEAD(, pptp_wan) pptp_wan_head; /* ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ int pptp_wan_init() { TAILQ_INIT(&pptp_wan_head); return 0; } /* ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ int pptp_wan_dispose() { // don't detach if links are in use if (TAILQ_FIRST(&pptp_wan_head)) return EBUSY; return 0; } /* ----------------------------------------------------------------------------- detach pptp interface dlil layer ----------------------------------------------------------------------------- */ int pptp_wan_attach(void *rfc, struct ppp_link **link) { int ret; struct pptp_wan *wan; struct ppp_link *lk; u_short unit; // Note : we allocate/find number/insert in queue in that specific order // because of funnels and race condition issues MALLOC(wan, struct pptp_wan *, sizeof(struct pptp_wan), M_DEVBUF, M_WAITOK); if (!wan) return ENOMEM; if (pptp_wan_findfreeunit(&unit)) { FREE(wan, M_DEVBUF); return ENOMEM; } bzero(wan, sizeof(struct pptp_wan)); TAILQ_INSERT_TAIL(&pptp_wan_head, wan, next); lk = (struct ppp_link *) wan; // it's time now to register our brand new link lk->lk_name = PPTP_NAME; lk->lk_mtu = PPTP_MTU; lk->lk_mru = PPTP_MTU;; lk->lk_type = PPP_TYPE_PPTP; lk->lk_hdrlen = 80; // ??? //ld->lk_if.link_lk_baudrate = tp->t_ospeed; lk->lk_ioctl = pptp_wan_ioctl; lk->lk_output = pptp_wan_output; lk->lk_unit = unit; lk->lk_support = 0; wan->rfc = rfc; ret = ppp_link_attach((struct ppp_link *)wan); if (ret) { log(LOG_INFO, "pptp_wan_attach, error = %d, (ld = 0x%x)\n", ret, wan); TAILQ_REMOVE(&pptp_wan_head, wan, next); FREE(wan, M_DEVBUF); return ret; } log(LOG_INFO, "pptp_wan_attach, link index = %d, (ld = 0x%x)\n", lk->lk_index, lk); *link = lk; return 0; } /* ----------------------------------------------------------------------------- detach pptp interface dlil layer ----------------------------------------------------------------------------- */ void pptp_wan_detach(struct ppp_link *link) { struct pptp_wan *wan = (struct pptp_wan *)link; ppp_link_detach(link); TAILQ_REMOVE(&pptp_wan_head, wan, next); FREE(wan, M_DEVBUF); } /* ----------------------------------------------------------------------------- find a free unit in the interface list ----------------------------------------------------------------------------- */ int pptp_wan_findfreeunit(u_short *freeunit) { struct pptp_wan *wan = TAILQ_FIRST(&pptp_wan_head); u_short unit = 0; while (wan) { if (wan->link.lk_unit == unit) { unit++; wan = TAILQ_FIRST(&pptp_wan_head); // restart } else wan = TAILQ_NEXT(wan, next); // continue } *freeunit = unit; return 0; } /* ----------------------------------------------------------------------------- called from pptp_rfc when data are present ----------------------------------------------------------------------------- */ int pptp_wan_input(struct ppp_link *link, struct mbuf *m) { link->lk_ipackets++; link->lk_ibytes += m->m_pkthdr.len; link->lk_last_recv = clock_get_system_value().tv_sec; ppp_link_input(link, m); return 0; } /* ----------------------------------------------------------------------------- called from pptp_rfc when xmit is full ----------------------------------------------------------------------------- */ void pptp_wan_xmit_full(struct ppp_link *link) { link->lk_flags |= SC_XMIT_FULL; } /* ----------------------------------------------------------------------------- called from pptp_rfc when there is an input error ----------------------------------------------------------------------------- */ void pptp_wan_input_error(struct ppp_link *link) { ppp_link_event(link, PPP_LINK_EVT_INPUTERROR, 0); } /* ----------------------------------------------------------------------------- called from pptp_rfc when xmit is ok again ----------------------------------------------------------------------------- */ void pptp_wan_xmit_ok(struct ppp_link *link) { link->lk_flags &= ~SC_XMIT_FULL; ppp_link_event(link, PPP_LINK_EVT_XMIT_OK, 0); } /* ----------------------------------------------------------------------------- Process an ioctl request to the ppp interface ----------------------------------------------------------------------------- */ int pptp_wan_ioctl(struct ppp_link *link, u_int32_t cmd, void *data) { //struct pptp_wan *wan = (struct pptp_wan *)link;; int error = 0; //LOGDBG(ifp, (LOGVAL, "pptp_wan_ioctl, cmd = 0x%x\n", cmd)); switch (cmd) { default: error = ENOTSUP; } return error; } /* ----------------------------------------------------------------------------- This gets called at splnet from if_ppp.c at various times when there is data ready to be sent ----------------------------------------------------------------------------- */ int pptp_wan_output(struct ppp_link *link, struct mbuf *m) { struct pptp_wan *wan = (struct pptp_wan *)link; u_int32_t len = m->m_pkthdr.len; // take it now, as output will change the mbuf if (pptp_rfc_output(wan->rfc, m)) { link->lk_oerrors++; return ENOBUFS; } link->lk_opackets++; link->lk_obytes += len; link->lk_last_xmit = clock_get_system_value().tv_sec; return 0; }