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