1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25#include <sys/systm.h>
26#include <sys/malloc.h>
27#include <sys/kpi_mbuf.h>
28#include <sys/socket.h>
29#include <sys/syslog.h>
30#include <sys/protosw.h>
31#include <kern/locks.h>
32
33#include <net/if_types.h>
34#include <net/if.h>
35
36#include "../../../Family/ppp_defs.h"
37#include "../../../Family/if_ppplink.h"
38#include "../../../Family/if_ppp.h"
39#include "../../../Family/ppp_domain.h"
40
41
42#include "PPPoE.h"
43#include "pppoe_proto.h"
44#include "pppoe_rfc.h"
45#include "pppoe_wan.h"
46
47
48/* -----------------------------------------------------------------------------
49Definitions
50----------------------------------------------------------------------------- */
51
52
53/* -----------------------------------------------------------------------------
54Declarations
55----------------------------------------------------------------------------- */
56
57void pppoe_init();
58int pppoe_ctloutput(struct socket *so, struct sockopt *sopt);
59int pppoe_usrreq();
60void pppoe_slowtimo();
61
62int pppoe_attach(struct socket *, int, struct proc *);
63int pppoe_detach(struct socket *);
64int pppoe_shutdown(struct socket *);
65int pppoe_control(struct socket *so, u_long cmd, caddr_t data,
66                  struct ifnet *ifp, struct proc *p);
67int pppoe_connect(struct socket *so, struct sockaddr *nam, struct proc *p);
68int pppoe_disconnect(struct socket *so);
69int pppoe_send(struct socket *so, int flags, struct mbuf *m,
70               struct sockaddr *nam, struct mbuf *control, struct proc *p);
71int pppoe_bind(struct socket *so, struct sockaddr *nam, struct proc *p);
72int pppoe_accept(struct socket *so, struct sockaddr **nam);
73int pppoe_listen(struct socket *so, struct proc *p);
74
75// callback from rfc layer
76void pppoe_event(void *data, u_int32_t event, u_int32_t msg);
77int pppoe_input(void *data, mbuf_t m);
78
79/* -----------------------------------------------------------------------------
80Globals
81----------------------------------------------------------------------------- */
82struct pr_usrreqs 	pppoe_usr;	/* pr_usrreqs extension to the protosw */
83struct protosw 		pppoe;		/* describe the protocol switch */
84
85extern lck_mtx_t	*ppp_domain_mutex;
86
87/* -----------------------------------------------------------------------------
88--------------------------------------------------------------------------------
89--------------------------------------------------------------------------------
90----------- Admistrative functions, called by ppp_domain -----------------------
91--------------------------------------------------------------------------------
92--------------------------------------------------------------------------------
93----------------------------------------------------------------------------- */
94
95/* -----------------------------------------------------------------------------
96 PPPOE Timer, at 100 ms. Replaces pppoe_slowtimo, which is deprecated.
97 ----------------------------------------------------------------------------- */
98static uint8_t pppoe_timer_thread_is_dying = 0; /* > 0 if dying */
99static uint8_t pppoe_timer_thread_is_dead = 0; /* > 0 if dead */
100
101static void pppoe_timer()
102{
103    struct timespec ts = {0};
104
105    /* timeout of 1000 ms */
106    ts.tv_nsec = 1000 * 1000 * 1000;
107    ts.tv_sec = 0;
108
109    lck_mtx_lock(ppp_domain_mutex);
110    while (TRUE) {
111        if (pppoe_timer_thread_is_dying > 0) {
112            break;
113        }
114
115        pppoe_rfc_timer();
116
117        msleep(&pppoe_timer_thread_is_dying, ppp_domain_mutex, PSOCK, "pppoe_timer_sleep", &ts);
118    }
119
120    pppoe_timer_thread_is_dead++;
121    wakeup(&pppoe_timer_thread_is_dead);
122    lck_mtx_unlock(ppp_domain_mutex);
123
124    thread_terminate(current_thread());
125}
126
127/* -----------------------------------------------------------------------------
128Called when we need to add the PPPoE protocol to the domain
129Typically, ppp_add is called by ppp_domain when we add the domain,
130but we can add the protocol anytime later, if the domain is present
131----------------------------------------------------------------------------- */
132int pppoe_add(struct domain *domain)
133{
134    int 	 err;
135    thread_t pppoe_timer_thread = NULL;
136
137    bzero(&pppoe_usr, sizeof(struct pr_usrreqs));
138    pppoe_usr.pru_abort 	= pru_abort_notsupp;
139    pppoe_usr.pru_accept 	= pppoe_accept;
140    pppoe_usr.pru_attach 	= pppoe_attach;
141    pppoe_usr.pru_bind 		= pppoe_bind;
142    pppoe_usr.pru_connect 	= pppoe_connect;
143    pppoe_usr.pru_connect2 	= pru_connect2_notsupp;
144    pppoe_usr.pru_control 	= pppoe_control;
145    pppoe_usr.pru_detach 	= pppoe_detach;
146    pppoe_usr.pru_disconnect 	= pppoe_disconnect;
147    pppoe_usr.pru_listen 	= pppoe_listen;
148    pppoe_usr.pru_peeraddr 	= pru_peeraddr_notsupp;
149    pppoe_usr.pru_rcvd 		= pru_rcvd_notsupp;
150    pppoe_usr.pru_rcvoob 	= pru_rcvoob_notsupp;
151    pppoe_usr.pru_send 		= pppoe_send;
152    pppoe_usr.pru_sense 	= pru_sense_null;
153    pppoe_usr.pru_shutdown 	= pppoe_shutdown;
154    pppoe_usr.pru_sockaddr 	= pru_sockaddr_notsupp;
155    pppoe_usr.pru_sosend 	= sosend;
156    pppoe_usr.pru_soreceive = soreceive;
157    pppoe_usr.pru_sopoll 	= pru_sopoll_notsupp;
158
159
160    bzero(&pppoe, sizeof(struct protosw));
161    pppoe.pr_type		= SOCK_DGRAM;
162    pppoe.pr_domain 	= domain;
163    pppoe.pr_protocol 	= PPPPROTO_PPPOE;
164    pppoe.pr_flags		= PR_ATOMIC|PR_CONNREQUIRED|PR_PROTOLOCK;
165    pppoe.pr_ctloutput 	= pppoe_ctloutput;
166    pppoe.pr_init		= pppoe_init;
167    pppoe.pr_usrreqs 	= &pppoe_usr;
168
169    pppoe_timer_thread_is_dying = 0;
170    if (kernel_thread_start((thread_continue_t)pppoe_timer, NULL, &pppoe_timer_thread) == KERN_SUCCESS) {
171        thread_deallocate(pppoe_timer_thread);
172    }
173
174    err = net_add_proto(&pppoe, domain);
175    if (err)
176        return err;
177
178    return KERN_SUCCESS;
179}
180
181/* -----------------------------------------------------------------------------
182Called when we need to remove the PPPoE protocol from the domain
183----------------------------------------------------------------------------- */
184int pppoe_remove(struct domain *domain)
185{
186    int err;
187
188    lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
189
190    /* Cleanup timer thread */
191    if (pppoe_timer_thread_is_dead == 0) {
192        pppoe_timer_thread_is_dying++;           /* Tell thread to die */
193        wakeup(&pppoe_timer_thread_is_dying);    /* Wake thread */
194        msleep(&pppoe_timer_thread_is_dying, ppp_domain_mutex, PSOCK, "pppoe_timer_sleep", 0);
195    }
196
197    err = net_del_proto(pppoe.pr_type, pppoe.pr_protocol, domain);
198    if (err)
199        return err;
200
201    // shall we test that all the pcbs have been freed ?
202
203    return KERN_SUCCESS;
204}
205
206/* -----------------------------------------------------------------------------
207--------------------------------------------------------------------------------
208--------------------------------------------------------------------------------
209--------------------------- protosw functions ----------------------------------
210--------------------------------------------------------------------------------
211--------------------------------------------------------------------------------
212----------------------------------------------------------------------------- */
213
214/* -----------------------------------------------------------------------------
215This function is called by socket layer when the protocol is added
216----------------------------------------------------------------------------- */
217void pppoe_init()
218{
219    //IOLog("pppoe_init\n");
220}
221
222/* -----------------------------------------------------------------------------
223This function is called by socket layer to handle get/set-socketoption
224----------------------------------------------------------------------------- */
225int pppoe_ctloutput(struct socket *so, struct sockopt *sopt)
226{
227    int		error, optval, i, mult;
228    u_int16_t	val;
229    u_int32_t	lval;
230    u_char 	str[IFNAMSIZ];
231
232	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
233
234    //IOLog("pppoe_ctloutput, so = %p\n", so);
235
236    error = optval = 0;
237    if (sopt->sopt_level != PPPPROTO_PPPOE) {
238        return EINVAL;
239    }
240
241    switch (sopt->sopt_dir) {
242        case SOPT_SET:
243            switch (sopt->sopt_name) {
244                case PPPOE_OPT_FLAGS:
245                    if (sopt->sopt_valsize != 4)
246                        error = EMSGSIZE;
247                    else if ((error = sooptcopyin(sopt, &lval, 4, 4)) == 0)
248                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_SETFLAGS, &lval);
249                    break;
250                case PPPOE_OPT_INTERFACE:
251                    if (sopt->sopt_valsize > IFNAMSIZ) {
252                        error = EMSGSIZE;
253                        break;
254                    }
255                    bzero(str, sizeof(str));
256                    if ((error = sooptcopyin(sopt, str, sopt->sopt_valsize, 0)))
257                        break;
258                    val = 0;
259                    for (i = IFNAMSIZ - 1; i && !str[i]; i--);
260                    for (mult = 1; i && (str[i] >= '0' && str[i] <= '9'); i--) {
261                        val += (str[i] - '0') * mult;
262                        mult *= 10;
263                    }
264                    //IOLog("pppoe_ctloutput (set) : PPPOE_OPT_INTERFACE = %s, %d\n", ifname, val);
265                    pppoe_rfc_command(so->so_pcb, PPPOE_CMD_SETUNIT, &val);
266                    break;
267                case PPPOE_OPT_CONNECT_TIMER:
268                    if (sopt->sopt_valsize != 2)
269                        error = EMSGSIZE;
270                    else if ((error = sooptcopyin(sopt, &val, 2, 2)) == 0)
271                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_SETCONNECTTIMER , &val);
272                    break;
273                case PPPOE_OPT_RING_TIMER:
274                    if (sopt->sopt_valsize != 2)
275                        error = EMSGSIZE;
276                    else if ((error = sooptcopyin(sopt, &val, 2, 2)) == 0)
277                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_SETRINGTIMER , &val);
278                    break;
279                case PPPOE_OPT_RETRY_TIMER:
280                    if (sopt->sopt_valsize != 2)
281                        error = EMSGSIZE;
282                    else if ((error = sooptcopyin(sopt, &val, 2, 2)) == 0)
283                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_SETRETRYTIMER , &val);
284                    break;
285                case PPPOE_OPT_PEER_ENETADDR:
286                    if (sopt->sopt_valsize != 6)
287                        error = EMSGSIZE;
288                    else if ((error = sooptcopyin(sopt, &str, 2, 2)) == 0)
289                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_SETPEERADDR , &str);
290                    break;
291                default:
292                    error = ENOPROTOOPT;
293            }
294            break;
295
296        case SOPT_GET:
297            switch (sopt->sopt_name) {
298                case PPPOE_OPT_FLAGS:
299                    if (sopt->sopt_valsize != 4)
300                        error = EMSGSIZE;
301                    else {
302                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_GETFLAGS, &lval);
303                        error = sooptcopyout(sopt, &lval, 4);
304                    }
305                    break;
306                case PPPOE_OPT_INTERFACE:
307                    if (sopt->sopt_valsize < IFNAMSIZ)
308                        error = EMSGSIZE;
309                    else {
310                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_GETUNIT, &val);
311                        // Fix Me : should get the name from ifnet
312                        snprintf((char*)str, sizeof(str), "en%d", val);
313                        error = sooptcopyout(sopt, str, strlen((char*)str));
314                    }
315                    break;
316                case PPPOE_OPT_CONNECT_TIMER:
317                    if (sopt->sopt_valsize != 2)
318                        error = EMSGSIZE;
319                    else {
320                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_GETCONNECTTIMER, &val);
321                        error = sooptcopyout(sopt, &val, 2);
322                    }
323                    break;
324                case PPPOE_OPT_RING_TIMER:
325                     if (sopt->sopt_valsize != 2)
326                        error = EMSGSIZE;
327                    else {
328                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_GETRINGTIMER, &val);
329                        error = sooptcopyout(sopt, &val, 2);
330                    }
331                    break;
332                case PPPOE_OPT_RETRY_TIMER:
333                     if (sopt->sopt_valsize != 2)
334                        error = EMSGSIZE;
335                    else {
336                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_GETRETRYTIMER, &val);
337                        error = sooptcopyout(sopt, &val, 2);
338                    }
339                    break;
340                case PPPOE_OPT_PEER_ENETADDR:
341                    if (sopt->sopt_valsize != 6)
342                        error = EMSGSIZE;
343                    else {
344                        pppoe_rfc_command(so->so_pcb, PPPOE_CMD_GETPEERADDR, &str);
345                        error = sooptcopyout(sopt, &str, 6);
346                    }
347                    break;
348                default:
349                    error = ENOPROTOOPT;
350            }
351            break;
352
353    }
354    return error;
355}
356
357/* -----------------------------------------------------------------------------
358--------------------------------------------------------------------------------
359--------------------------------------------------------------------------------
360------------------------- pr_usrreqs functions ---------------------------------
361--------------------------------------------------------------------------------
362--------------------------------------------------------------------------------
363----------------------------------------------------------------------------- */
364
365/* -----------------------------------------------------------------------------
366Called by socket layer when a new socket is created
367Should create all the structures and prepare for pppoe dialog
368----------------------------------------------------------------------------- */
369int pppoe_attach (struct socket *so, int proto, struct proc *p)
370{
371    int			error;
372    u_short 		unit;
373
374    //IOLog("pppoe_attach, so = %p, dom_ref = %d\n", so, so->so_proto->pr_domain->dom_refs);
375    if (so->so_pcb)
376        return EINVAL;
377
378    if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
379        error = soreserve(so, 8192, 8192);
380        if (error)
381            return error;
382    }
383
384    // fix me : change association between socket and dltag to support multiple interface
385    //pcb->dl_tag = pppoe_domain_find_dl_tag();
386    unit = 0;
387
388    // call pppoe init with the rfc specific structure
389	lck_mtx_lock(ppp_domain_mutex);
390    if (pppoe_rfc_new_client(so, (void**)&(so->so_pcb), pppoe_input, pppoe_event)) {
391		lck_mtx_unlock(ppp_domain_mutex);
392        return ENOMEM;
393    }
394	lck_mtx_unlock(ppp_domain_mutex);
395
396    return 0;
397}
398
399/* -----------------------------------------------------------------------------
400Called by socket layer when the socket is closed
401Should free all the pppoe structures
402----------------------------------------------------------------------------- */
403int pppoe_detach(struct socket *so)
404{
405
406    //IOLog("pppoe_detach, so = %p, dom_ref = %d\n", so, so->so_proto->pr_domain->dom_refs);
407
408	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
409
410    if (so->so_tpcb) {
411        pppoe_wan_detach((struct ppp_link *)so->so_tpcb);
412        so->so_tpcb = 0;
413    }
414    if (so->so_pcb) {
415        pppoe_rfc_free_client(so->so_pcb);
416        so->so_pcb = 0;
417    }
418	so->so_flags |= SOF_PCBCLEARING;
419    return 0;
420}
421
422/* -----------------------------------------------------------------------------
423this function is not yet complete
424----------------------------------------------------------------------------- */
425int pppoe_shutdown(struct socket *so)
426{
427    int 	error = 0;
428
429	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
430
431    //IOLog("pppoe_shutdown, so = %p\n", so);
432
433    socantsendmore(so);
434    pppoe_disconnect(so);
435    return error;
436}
437
438/* -----------------------------------------------------------------------------
439Called by socket layer to bind to the protocol
440----------------------------------------------------------------------------- */
441int pppoe_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
442{
443    int 		error = 0;
444    struct sockaddr_pppoe *adr = (struct sockaddr_pppoe *)nam;
445
446	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
447
448    //IOLog("pppoe_bind, so = %p\n", so);
449
450    // bind pppoe protocol
451    if (pppoe_rfc_bind(so->so_pcb, (u_char*)&adr->pppoe_ac_name[0], (u_char*)&adr->pppoe_service[0]))
452        error = EINVAL;		/* XXX ??? */
453
454    return error;
455}
456
457/* -----------------------------------------------------------------------------
458Called by socket layer to connect the protocol (PR_CONNREQUIRED)
459----------------------------------------------------------------------------- */
460int pppoe_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
461{
462    int 		error = 0;
463    struct sockaddr_pppoe *adr = (struct sockaddr_pppoe *)nam;
464
465	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
466
467    //IOLog("pppoe_connect, so = %p\n", so);
468
469    // connect pppoe protocol
470    if (pppoe_rfc_connect(so->so_pcb, (u_char*)adr->pppoe_ac_name, (u_char*)adr->pppoe_service))
471        error = EINVAL;		/* XXX ??? */
472    else {
473        soisconnecting(so);
474    }
475
476    return error;
477}
478
479/* -----------------------------------------------------------------------------
480Called by socket layer to disconnect the protocol (PR_CONNREQUIRED)
481----------------------------------------------------------------------------- */
482int pppoe_disconnect(struct socket *so)
483{
484
485    //IOLog("pppoe_disconnect, so = %p\n", so);
486
487	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
488
489    // disconnect pppoe protocol
490    if (pppoe_rfc_disconnect(so->so_pcb)) {
491        // ???
492    }
493
494    soisdisconnected(so); // let's say we are disconnected anyway...
495    return 0;
496}
497
498/* -----------------------------------------------------------------------------
499Prepare to accept connections
500----------------------------------------------------------------------------- */
501int pppoe_listen(struct socket *so, struct proc *p)
502{
503    int 		error = 0;
504
505	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
506
507    //IOLog("pppoe_listen, so = %p\n", so);
508
509    if (pppoe_rfc_listen(so->so_pcb))
510        error = EINVAL; // XXX ???
511
512    return error;
513}
514
515/* -----------------------------------------------------------------------------
516Accept connection
517----------------------------------------------------------------------------- */
518int pppoe_accept(struct socket *so, struct sockaddr **nam)
519{
520    int 		error = 0;
521    struct sockaddr_pppoe *addr;
522
523    //IOLog("pppoe_accept, so = %p\n", so);
524
525	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
526
527    *nam = 0;
528    if (pppoe_rfc_accept(so->so_pcb))
529        error = EINVAL; // XXX ???
530    else {
531        // pppoe_rfc_getboundaddr(pcb->rfc, addr.ac_name, addr.service);
532        addr = (struct sockaddr_pppoe *)_MALLOC(sizeof (struct sockaddr_pppoe), M_SONAME, M_WAITOK);
533        if (addr) {
534            addr->ppp.ppp_len = sizeof(struct sockaddr_pppoe);
535            addr->ppp.ppp_family = AF_PPP;
536            addr->ppp.ppp_proto = PPPPROTO_PPPOE;
537            addr->ppp.ppp_cookie = 0;
538            addr->pppoe_ac_name[0] = 0;
539            addr->pppoe_service[0] = 0;
540            *nam = (struct sockaddr *)addr;
541        }
542    }
543
544    return error;
545}
546
547/* -----------------------------------------------------------------------------
548Called by socket layer to abort call
549----------------------------------------------------------------------------- */
550int pppoe_abort(struct socket *so)
551{
552    int 		error = 0;
553
554	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
555
556    //IOLog("pppoe_abort, so = %p\n", so);
557
558    if (pppoe_rfc_abort(so->so_pcb, 1))
559        error = EINVAL; // XXX ???
560
561    soisdisconnected(so); // let's say we are disconnected anyway...
562    return error;
563}
564
565/* -----------------------------------------------------------------------------
566Called by socket layer to handle ioctl
567----------------------------------------------------------------------------- */
568int pppoe_control(struct socket *so, u_long cmd, caddr_t data,
569                  struct ifnet *ifp, struct proc *p)
570{
571    int 		error = 0;
572
573	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
574
575    //IOLog("pppoe_control : so = %p, cmd = %d\n", so, cmd);
576
577    switch (cmd) {
578	case PPPIOCGCHAN:
579            //IOLog("pppoe_control : PPPIOCGCHAN\n");
580            if (!so->so_tpcb)
581                return EINVAL;// not attached
582            *(u_int32_t *)data = ((struct ppp_link *)so->so_tpcb)->lk_index;
583            break;
584	case PPPIOCATTACH:
585            //IOLog("pppoe_control : PPPIOCATTACH\n");
586           if (so->so_tpcb)
587                return EINVAL;// already attached
588            sbflush(&so->so_rcv);	// flush all data received
589            error = pppoe_wan_attach(so->so_pcb, (struct ppp_link **)&so->so_tpcb);
590            break;
591	case PPPIOCDETACH:
592            //IOLog("pppoe_control : PPPIOCDETACH\n");
593            if (!so->so_tpcb)
594                return EINVAL;// already detached
595            pppoe_wan_detach((struct ppp_link *)so->so_tpcb);
596            so->so_tpcb = 0;
597            break;
598        default:
599            ;
600    }
601
602    return error;
603}
604
605/* -----------------------------------------------------------------------------
606Called by socket layer to send data out
607----------------------------------------------------------------------------- */
608int pppoe_send(struct socket *so, int flags, struct mbuf *m,
609               struct sockaddr *nam, struct mbuf *control, struct proc *p)
610{
611
612    int 		error = 0;
613
614	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
615
616    //IOLog("pppoe_send, so = %p\n", so);
617
618    if ((error = pppoe_rfc_output(so->so_pcb, (mbuf_t)m))) {
619        mbuf_freem((mbuf_t)m);
620    }
621
622    return error;
623}
624
625/* -----------------------------------------------------------------------------
626--------------------------------------------------------------------------------
627--------------------------------------------------------------------------------
628------------------------- callbacks from pppoe rfc or from dlil ----------------
629--------------------------------------------------------------------------------
630--------------------------------------------------------------------------------
631----------------------------------------------------------------------------- */
632
633/* -----------------------------------------------------------------------------
634called from pppoe_rfc when change state occurs
635----------------------------------------------------------------------------- */
636void pppoe_event(void *data, u_int32_t event, u_int32_t msg)
637{
638    struct socket 	*so = (struct socket *)data, *so2;
639	struct sockaddr_pppoe addr;
640
641	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
642
643    switch (event) {
644        case PPPOE_EVT_RINGING:
645            /*
646             at this point, we need to introduce our semantic about how ring/accept will work.
647             when there is an incoming call, we create a new socket with sonewconn, so socket layer is happy.
648             the sonewconn will wake up the original listening app with the ogirinal socket.
649             the app will decide wether it wants to accept or refuse the call.
650             if the app decides to accept it, il will call accept with the original listening socket,
651             which will be turned by the socket layer into a call to the accept function to our protocol
652             with the second socket (created with sonewconn). [the socket layer knows that
653                 those two sockets are related, because sonewconn had linked them together]
654             when we enter into our accept function, we will then physically answer the call.
655             (that's a difference with tcp, where the call has already be answer at ring time)
656             the original listening socket will still be listening (probably for nothing if the protocol
657                                                                    can only accept one call)
658             then, when later the app close the socket (the one returned by accept) the protocol can listen again
659             it's up to this protocol to know what's really happening here, and to do the correct work,
660             wether we have only one active listening socket, or whatever makes sense.
661             in case of PPPoE, let's say we can continue listening....
662             */
663
664			addr.ppp.ppp_len = sizeof(struct sockaddr_pppoe);
665			addr.ppp.ppp_family = AF_PPP;
666			addr.ppp.ppp_proto = PPPPROTO_PPPOE;
667			addr.ppp.ppp_cookie = 0;
668			addr.pppoe_ac_name[0] = 0;
669			addr.pppoe_service[0] = 0;
670
671            so2 = sonewconn(so, SS_ISCONFIRMING, (struct sockaddr*)(&addr));	// create the accepting connection
672            //IOLog("pppoe_event, so = %p, so2 = %p, evt = PPPOE_EVT_RINGING\n", so, so2);
673
674			if (so2)
675				pppoe_rfc_clone(so->so_pcb, so2->so_pcb);	// transfer all the RFC info to the new connection, including ringing state
676
677            pppoe_rfc_abort(so->so_pcb, 0);		// abort the ring on the listening connection
678            pppoe_rfc_listen(so->so_pcb);		// relisten again, because pppoe can handle multiple connections
679            break;
680
681        case PPPOE_EVT_CONNECTED:
682            //IOLog("pppoe_event, so = %p, evt = PPPOE_EVT_CONNECTED\n", so);
683            soisconnected(so);
684            break;
685
686        case PPPOE_EVT_DISCONNECTED:
687            //IOLog("pppoe_event, so = %p, evt = PPPOE_EVT_DISCONNECTED\n", so);
688            so->so_error = msg;
689
690            //if (so->so_tpcb) {
691             //   pppoe_wan_detach((struct ppp_link *)so->so_tpcb);
692            //    so->so_tpcb = 0;
693            //}
694            soisdisconnected(so);
695            break;
696    }
697}
698
699/* -----------------------------------------------------------------------------
700called from pppoe_rfc when data are present
701----------------------------------------------------------------------------- */
702int pppoe_input(void *data, mbuf_t m)
703{
704    struct socket 	*so = (struct socket *)data;
705
706	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
707
708    if (so->so_tpcb) {
709        // we are hooked to ppp
710	return pppoe_wan_input((struct ppp_link *)so->so_tpcb, m);
711    }
712
713    //IOLog("pppoe_input, so = %p, len = %d\n", so, m_pkthdr.len);
714
715    if (sbspace(&so->so_rcv) < mbuf_pkthdr_len(m)) {
716        mbuf_freem(m);
717        IOLog("pppoe_input no space, so = %p, len = %d\n", so, mbuf_pkthdr_len(m));
718        return 0;
719    }
720
721    sbappendrecord(&so->so_rcv, (struct mbuf*)m);
722    sorwakeup(so);
723    return 0;
724}
725
726
727