Home | History | Annotate | Download | only in pppol2tp-android
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "pppd.h"
     18 #include "fsm.h"
     19 #include "lcp.h"
     20 #include <unistd.h>
     21 #include <sys/ioctl.h>
     22 #include <linux/if_ppp.h>
     23 
     24 char pppd_version[] = VERSION;
     25 
     26 static struct channel pppol2tp_channel;
     27 
     28 /* Options variables */
     29 static int session_fd = -1;
     30 static int tunnel_fd = -1;
     31 static int session_id = 0;
     32 static int tunnel_id = 0;
     33 
     34 static int pppol2tp_set_session_fd(char **argv);
     35 
     36 static option_t pppol2tp_options[] = {
     37 	{ "session_fd", o_special, pppol2tp_set_session_fd,
     38 		"Session PPPoX data socket", OPT_DEVNAM },
     39 	{ "tunnel_fd", o_int, &tunnel_fd,
     40 		"Tunnel management PPPoX socket", OPT_PRIO },
     41 	{ "session_id", o_int, &session_id, "Session ID", OPT_PRIO },
     42 	{ "tunnel_id", o_int, &tunnel_id, "Tunnel ID", OPT_PRIO },
     43 	{ NULL }
     44 };
     45 
     46 static int pppol2tp_set_session_fd(char **argv)
     47 {
     48 	if (!int_option(*argv, &session_fd))
     49 		return 0;
     50 
     51 	info("Using PPPoL2TP (socket = %d)", session_fd);
     52 	the_channel = &pppol2tp_channel;
     53 	return 1;
     54 }
     55 
     56 /**
     57  * Set the MRU on the PPP network interface.
     58  *
     59  * @param mru New MRU value
     60  *
     61  * @note netif_set_mru() is missing in sys-linux.c, so implement it manually
     62  * @note See net/l2tp/l2tp_ppp.c:pppol2tp_session_ioctl() in kernel for details
     63  */
     64 static void pppol2tp_set_mru(int mru)
     65 {
     66 	int res;
     67 
     68 	if (ifunit < 0)
     69 		return;
     70 
     71 	res = ioctl(session_fd, PPPIOCSMRU, (caddr_t)&mru);
     72 	if (res < 0)
     73 		error("ioctl(PPPIOCSMRU): %m (line %d)", __LINE__);
     74 }
     75 
     76 /* Set the transmit-side PPP parameters of the channel */
     77 static void pppol2tp_send_config(int mtu, u_int32_t accm, int pcomp, int accomp)
     78 {
     79 	int new_mtu = lcp_allowoptions[0].mru;	/* "mtu" pppd option */
     80 
     81 	if (new_mtu <= PPP_MAXMTU && new_mtu >= PPP_MINMTU)
     82 		netif_set_mtu(ifunit, new_mtu);
     83 }
     84 
     85 /* Set the receive-side PPP parameters of the channel */
     86 static void pppol2tp_recv_config(int mru, u_int32_t accm, int pcomp, int accomp)
     87 {
     88 	int new_mru = lcp_wantoptions[0].mru;	/* "mru" pppd option */
     89 
     90 	if (new_mru <= PPP_MAXMRU && new_mru >= PPP_MINMRU)
     91 		pppol2tp_set_mru(new_mru);
     92 }
     93 
     94 static int pppol2tp_connect(void)
     95 {
     96 	return session_fd;
     97 }
     98 
     99 static void pppol2tp_disconnect(void)
    100 {
    101 	if (session_fd != -1) {
    102 		close(session_fd);
    103 		session_fd = -1;
    104 	}
    105 
    106 	if (tunnel_fd != -1) {
    107 		close(tunnel_fd);
    108 		tunnel_fd = -1;
    109 	}
    110 }
    111 
    112 void plugin_init(void)
    113 {
    114 	add_options(pppol2tp_options);
    115 }
    116 
    117 static struct channel pppol2tp_channel = {
    118 	.options		= pppol2tp_options,
    119 	.process_extra_options	= NULL,
    120 	.check_options		= NULL,
    121 	.connect		= pppol2tp_connect,
    122 	.disconnect		= pppol2tp_disconnect,
    123 	.establish_ppp		= generic_establish_ppp,
    124 	.disestablish_ppp	= generic_disestablish_ppp,
    125 	.send_config		= pppol2tp_send_config,
    126 	.recv_config		= pppol2tp_recv_config,
    127 	.cleanup		= NULL,
    128 	.close			= NULL,
    129 };
    130