/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "pppd.h" #include "fsm.h" #include "lcp.h" #include <unistd.h> #include <sys/ioctl.h> #include <linux/if_ppp.h> char pppd_version[] = VERSION; static struct channel pppol2tp_channel; /* Options variables */ static int session_fd = -1; static int tunnel_fd = -1; static int session_id = 0; static int tunnel_id = 0; static int pppol2tp_set_session_fd(char **argv); static option_t pppol2tp_options[] = { { "session_fd", o_special, pppol2tp_set_session_fd, "Session PPPoX data socket", OPT_DEVNAM }, { "tunnel_fd", o_int, &tunnel_fd, "Tunnel management PPPoX socket", OPT_PRIO }, { "session_id", o_int, &session_id, "Session ID", OPT_PRIO }, { "tunnel_id", o_int, &tunnel_id, "Tunnel ID", OPT_PRIO }, { NULL } }; static int pppol2tp_set_session_fd(char **argv) { if (!int_option(*argv, &session_fd)) return 0; info("Using PPPoL2TP (socket = %d)", session_fd); the_channel = &pppol2tp_channel; return 1; } /** * Set the MRU on the PPP network interface. * * @param mru New MRU value * * @note netif_set_mru() is missing in sys-linux.c, so implement it manually * @note See net/l2tp/l2tp_ppp.c:pppol2tp_session_ioctl() in kernel for details */ static void pppol2tp_set_mru(int mru) { int res; if (ifunit < 0) return; res = ioctl(session_fd, PPPIOCSMRU, (caddr_t)&mru); if (res < 0) error("ioctl(PPPIOCSMRU): %m (line %d)", __LINE__); } /* Set the transmit-side PPP parameters of the channel */ static void pppol2tp_send_config(int mtu, u_int32_t accm, int pcomp, int accomp) { int new_mtu = lcp_allowoptions[0].mru; /* "mtu" pppd option */ if (new_mtu <= PPP_MAXMTU && new_mtu >= PPP_MINMTU) netif_set_mtu(ifunit, new_mtu); } /* Set the receive-side PPP parameters of the channel */ static void pppol2tp_recv_config(int mru, u_int32_t accm, int pcomp, int accomp) { int new_mru = lcp_wantoptions[0].mru; /* "mru" pppd option */ if (new_mru <= PPP_MAXMRU && new_mru >= PPP_MINMRU) pppol2tp_set_mru(new_mru); } static int pppol2tp_connect(void) { return session_fd; } static void pppol2tp_disconnect(void) { if (session_fd != -1) { close(session_fd); session_fd = -1; } if (tunnel_fd != -1) { close(tunnel_fd); tunnel_fd = -1; } } void plugin_init(void) { add_options(pppol2tp_options); } static struct channel pppol2tp_channel = { .options = pppol2tp_options, .process_extra_options = NULL, .check_options = NULL, .connect = pppol2tp_connect, .disconnect = pppol2tp_disconnect, .establish_ppp = generic_establish_ppp, .disestablish_ppp = generic_disestablish_ppp, .send_config = pppol2tp_send_config, .recv_config = pppol2tp_recv_config, .cleanup = NULL, .close = NULL, };