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/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 "PPTP.h" 43#include "pptp_proto.h" 44#include "pptp_rfc.h" 45#include "pptp_wan.h" 46 47 48/* ----------------------------------------------------------------------------- 49Definitions 50----------------------------------------------------------------------------- */ 51/* Wcast-align fix - cast away alignment warning when buffer is aligned */ 52#define ALIGNED_CAST(type) (type)(void *) 53 54 55/* ----------------------------------------------------------------------------- 56Declarations 57----------------------------------------------------------------------------- */ 58 59void pptp_init(); 60int pptp_ctloutput(struct socket *so, struct sockopt *sopt); 61int pptp_usrreq(); 62 63int pptp_attach(struct socket *, int, struct proc *); 64int pptp_detach(struct socket *); 65int pptp_control(struct socket *so, u_long cmd, caddr_t data, 66 struct ifnet *ifp, struct proc *p); 67 68// callback from rfc layer 69int pptp_input(void *data, mbuf_t m); 70void pptp_event(void *data, u_int32_t event, u_int32_t msg); 71 72/* ----------------------------------------------------------------------------- 73Globals 74----------------------------------------------------------------------------- */ 75struct pr_usrreqs pptp_usr; /* pr_usrreqs extension to the protosw */ 76struct protosw pptp; /* describe the protocol switch */ 77 78extern lck_mtx_t *ppp_domain_mutex; 79 80/* ----------------------------------------------------------------------------- 81-------------------------------------------------------------------------------- 82-------------------------------------------------------------------------------- 83----------- Admistrative functions, called by ppp_domain ----------------------- 84-------------------------------------------------------------------------------- 85-------------------------------------------------------------------------------- 86----------------------------------------------------------------------------- */ 87 88/* ----------------------------------------------------------------------------- 89 PPTP Timer, at 500 ms. Replaces pptp_slowtimo, which is deprecated. 90 ----------------------------------------------------------------------------- */ 91static uint8_t pptp_timer_thread_is_dying = 0; /* > 0 if dying */ 92static uint8_t pptp_timer_thread_is_dead = 0; /* > 0 if dead */ 93 94static void pptp_timer() 95{ 96 struct timespec ts = {0}; 97 98 /* timeout of 500 ms */ 99 ts.tv_nsec = 500 * 1000 * 1000; 100 ts.tv_sec = 0; 101 102 lck_mtx_lock(ppp_domain_mutex); 103 while (TRUE) { 104 if (pptp_timer_thread_is_dying > 0) { 105 break; 106 } 107 108 pptp_rfc_slowtimer(); 109 110 msleep(&pptp_timer_thread_is_dying, ppp_domain_mutex, PSOCK, "pptp_timer_sleep", &ts); 111 } 112 113 pptp_timer_thread_is_dead++; 114 wakeup(&pptp_timer_thread_is_dead); 115 lck_mtx_unlock(ppp_domain_mutex); 116 117 thread_terminate(current_thread()); 118} 119 120/* ----------------------------------------------------------------------------- 121Called when we need to add the PPTP protocol to the domain 122Typically, ppp_add is called by ppp_domain when we add the domain, 123but we can add the protocol anytime later, if the domain is present 124----------------------------------------------------------------------------- */ 125int pptp_add(struct domain *domain) 126{ 127 int err; 128 thread_t pptp_timer_thread = NULL; 129 130 bzero(&pptp_usr, sizeof(struct pr_usrreqs)); 131 pptp_usr.pru_abort = pru_abort_notsupp; 132 pptp_usr.pru_accept = pru_accept_notsupp; 133 pptp_usr.pru_attach = pptp_attach; 134 pptp_usr.pru_bind = pru_bind_notsupp; 135 pptp_usr.pru_connect = pru_connect_notsupp; 136 pptp_usr.pru_connect2 = pru_connect2_notsupp; 137 pptp_usr.pru_control = pptp_control; 138 pptp_usr.pru_detach = pptp_detach; 139 pptp_usr.pru_disconnect = pru_disconnect_notsupp; 140 pptp_usr.pru_listen = pru_listen_notsupp; 141 pptp_usr.pru_peeraddr = pru_peeraddr_notsupp; 142 pptp_usr.pru_rcvd = pru_rcvd_notsupp; 143 pptp_usr.pru_rcvoob = pru_rcvoob_notsupp; 144 pptp_usr.pru_send = pru_send_notsupp; 145 pptp_usr.pru_sense = pru_sense_null; 146 pptp_usr.pru_shutdown = pru_shutdown_notsupp; 147 pptp_usr.pru_sockaddr = pru_sockaddr_notsupp; 148 pptp_usr.pru_sosend = sosend; 149 pptp_usr.pru_soreceive = soreceive; 150 pptp_usr.pru_sopoll = pru_sopoll_notsupp; 151 152 153 bzero(&pptp, sizeof(struct protosw)); 154 pptp.pr_type = SOCK_DGRAM; 155 pptp.pr_domain = domain; 156 pptp.pr_protocol = PPPPROTO_PPTP; 157 pptp.pr_flags = PR_ATOMIC | PR_PROTOLOCK; 158 pptp.pr_ctloutput = pptp_ctloutput; 159 pptp.pr_init = pptp_init; 160 pptp.pr_usrreqs = &pptp_usr; 161 162 pptp_timer_thread_is_dying = 0; 163 if (kernel_thread_start((thread_continue_t)pptp_timer, NULL, &pptp_timer_thread) == KERN_SUCCESS) { 164 thread_deallocate(pptp_timer_thread); 165 } 166 167 err = net_add_proto(&pptp, domain); 168 if (err) 169 return err; 170 171 return KERN_SUCCESS; 172} 173 174/* ----------------------------------------------------------------------------- 175Called when we need to remove the PPTP protocol from the domain 176----------------------------------------------------------------------------- */ 177int pptp_remove(struct domain *domain) 178{ 179 int err; 180 181 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 182 183 /* Cleanup timer thread */ 184 if (pptp_timer_thread_is_dead == 0) { 185 pptp_timer_thread_is_dying++; /* Tell thread to die */ 186 wakeup(&pptp_timer_thread_is_dying); /* Wake thread */ 187 msleep(&pptp_timer_thread_is_dying, ppp_domain_mutex, PSOCK, "pptp_timer_sleep", 0); 188 } 189 190 err = net_del_proto(pptp.pr_type, pptp.pr_protocol, domain); 191 if (err) 192 return err; 193 194 // shall we test that all the pcbs have been freed ? 195 196 return KERN_SUCCESS; 197} 198 199/* ----------------------------------------------------------------------------- 200-------------------------------------------------------------------------------- 201-------------------------------------------------------------------------------- 202--------------------------- protosw functions ---------------------------------- 203-------------------------------------------------------------------------------- 204-------------------------------------------------------------------------------- 205----------------------------------------------------------------------------- */ 206 207/* ----------------------------------------------------------------------------- 208This function is called by socket layer when the protocol is added 209----------------------------------------------------------------------------- */ 210void pptp_init() 211{ 212 //IOLog("pptp_init\n"); 213} 214 215/* ----------------------------------------------------------------------------- 216This function is called by socket layer to handle get/set-socketoption 217----------------------------------------------------------------------------- */ 218int pptp_ctloutput(struct socket *so, struct sockopt *sopt) 219{ 220 int error, optval; 221 u_int32_t lval, cmd = 0; 222 u_int16_t val; 223 224 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 225 226 //IOLog("pptp_ctloutput, so = %p\n", so); 227 228 error = optval = 0; 229 if (sopt->sopt_level != PPPPROTO_PPTP) { 230 return EINVAL; 231 } 232 233 switch (sopt->sopt_dir) { 234 case SOPT_SET: 235 switch (sopt->sopt_name) { 236 case PPTP_OPT_FLAGS: 237 case PPTP_OPT_OURADDRESS: 238 case PPTP_OPT_PEERADDRESS: 239 case PPTP_OPT_BAUDRATE: 240 if (sopt->sopt_valsize != 4) 241 error = EMSGSIZE; 242 else if ((error = sooptcopyin(sopt, &lval, 4, 4)) == 0) { 243 switch (sopt->sopt_name) { 244 case PPTP_OPT_OURADDRESS: cmd = PPTP_CMD_SETOURADDR; break; 245 case PPTP_OPT_PEERADDRESS: cmd = PPTP_CMD_SETPEERADDR; break; 246 case PPTP_OPT_FLAGS: cmd = PPTP_CMD_SETFLAGS; break; 247 case PPTP_OPT_BAUDRATE: cmd = PPTP_CMD_SETBAUDRATE; break; 248 } 249 pptp_rfc_command(so->so_pcb, cmd , &lval); 250 } 251 break; 252 case PPTP_OPT_CALL_ID: 253 case PPTP_OPT_PEER_CALL_ID: 254 case PPTP_OPT_WINDOW: 255 case PPTP_OPT_PEER_WINDOW: 256 case PPTP_OPT_PEER_PPD: 257 case PPTP_OPT_MAXTIMEOUT: 258 if (sopt->sopt_valsize != 2) 259 error = EMSGSIZE; 260 else if ((error = sooptcopyin(sopt, &val, 2, 2)) == 0) { 261 switch (sopt->sopt_name) { 262 case PPTP_OPT_CALL_ID: cmd = PPTP_CMD_SETCALLID; break; 263 case PPTP_OPT_PEER_CALL_ID: cmd = PPTP_CMD_SETPEERCALLID; break; 264 case PPTP_OPT_WINDOW: cmd = PPTP_CMD_SETWINDOW; break; 265 case PPTP_OPT_PEER_WINDOW: cmd = PPTP_CMD_SETPEERWINDOW; break; 266 case PPTP_OPT_PEER_PPD: cmd = PPTP_CMD_SETPEERPPD; break; 267 case PPTP_OPT_MAXTIMEOUT: cmd = PPTP_CMD_SETMAXTIMEOUT; break; 268 } 269 pptp_rfc_command(so->so_pcb, cmd , &val); 270 } 271 break; 272 default: 273 error = ENOPROTOOPT; 274 } 275 break; 276 277 case SOPT_GET: 278 error = ENOPROTOOPT; 279 break; 280 281 } 282 return error; 283} 284 285/* ----------------------------------------------------------------------------- 286-------------------------------------------------------------------------------- 287-------------------------------------------------------------------------------- 288------------------------- pr_usrreqs functions --------------------------------- 289-------------------------------------------------------------------------------- 290-------------------------------------------------------------------------------- 291----------------------------------------------------------------------------- */ 292 293/* ----------------------------------------------------------------------------- 294Called by socket layer when a new socket is created 295Should create all the structures and prepare for pptp dialog 296----------------------------------------------------------------------------- */ 297int pptp_attach (struct socket *so, int proto, struct proc *p) 298{ 299 int error; 300 301 //IOLog("pptp_attach, so = %p, dom_ref = %d\n", so, so->so_proto->pr_domain->dom_refs); 302 if (so->so_pcb) 303 return EINVAL; 304 305 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 306 error = soreserve(so, 8192, 8192); 307 if (error) 308 return error; 309 } 310 311 // call pptp init with the rfc specific structure 312 lck_mtx_lock(ppp_domain_mutex); 313 if (pptp_rfc_new_client(so, (void**)&(so->so_pcb), pptp_input, pptp_event)) { 314 lck_mtx_unlock(ppp_domain_mutex); 315 return ENOMEM; 316 } 317 318 lck_mtx_unlock(ppp_domain_mutex); 319 return 0; 320} 321 322/* ----------------------------------------------------------------------------- 323Called by socket layer when the socket is closed 324Should free all the pptp structures 325----------------------------------------------------------------------------- */ 326int pptp_detach(struct socket *so) 327{ 328 329 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 330 331 //IOLog("pptp_detach, so = %p, dom_ref = %d\n", so, so->so_proto->pr_domain->dom_refs); 332 333 if (so->so_tpcb) { 334 pptp_wan_detach(ALIGNED_CAST(struct ppp_link *)so->so_tpcb); 335 so->so_tpcb = 0; 336 } 337 if (so->so_pcb) { 338 pptp_rfc_free_client(so->so_pcb); 339 so->so_pcb = 0; 340 } 341 so->so_flags |= SOF_PCBCLEARING; 342 return 0; 343} 344 345/* ----------------------------------------------------------------------------- 346Called by socket layer to handle ioctl 347----------------------------------------------------------------------------- */ 348int pptp_control(struct socket *so, u_long cmd, caddr_t data, 349 struct ifnet *ifp, struct proc *p) 350{ 351 int error = 0; 352 u_int32_t aligned_data; 353 354 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 355 356 //IOLog("pptp_control : so = %p, cmd = %d\n", so, cmd); 357 358 switch (cmd) { 359 case PPPIOCGCHAN: 360 //IOLog("pptp_control : PPPIOCGCHAN\n"); 361 if (!so->so_tpcb) 362 return EINVAL;// not attached 363 aligned_data = (ALIGNED_CAST(struct ppp_link *)so->so_tpcb)->lk_index; // Wcast-align fix - we malloc so->so_tpcb - lk_index is u_1616_t copying to u_int32_t 364 memcpy(data, &aligned_data, sizeof(u_int32_t)); // Wcast-align fix - memcpy for unaligned move 365 break; 366 case PPPIOCATTACH: 367 //IOLog("pptp_control : PPPIOCATTACH\n"); 368 if (so->so_tpcb) 369 return EINVAL;// already attached 370 error = pptp_wan_attach(so->so_pcb, ALIGNED_CAST(struct ppp_link **)&so->so_tpcb); 371 break; 372 case PPPIOCDETACH: 373 //IOLog("pptp_control : PPPIOCDETACH\n"); 374 if (!so->so_tpcb) 375 return EINVAL;// already detached 376 pptp_wan_detach(ALIGNED_CAST(struct ppp_link *)so->so_tpcb); 377 so->so_tpcb = 0; 378 break; 379 default: 380 ; 381 } 382 383 return error; 384} 385 386/* ----------------------------------------------------------------------------- 387-------------------------------------------------------------------------------- 388-------------------------------------------------------------------------------- 389------------------------- callbacks from pptp rfc or from dlil ---------------- 390-------------------------------------------------------------------------------- 391-------------------------------------------------------------------------------- 392----------------------------------------------------------------------------- */ 393 394 395/* ----------------------------------------------------------------------------- 396called from pptp_rfc when data are present 397----------------------------------------------------------------------------- */ 398int pptp_input(void *data, mbuf_t m) 399{ 400 struct socket *so = (struct socket *)data; 401 402 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 403 404 if (so->so_tpcb) { 405 // we are hooked to ppp 406 return pptp_wan_input(ALIGNED_CAST(struct ppp_link *)so->so_tpcb, m); 407 } 408 409 mbuf_freem(m); 410 IOLog("pptp_input unexpected, so = %p, len = %lu\n", so, mbuf_pkthdr_len(m)); 411 return 0; 412} 413 414/* ----------------------------------------------------------------------------- 415----------------------------------------------------------------------------- */ 416void pptp_event(void *data, u_int32_t event, u_int32_t msg) 417{ 418 struct socket *so = (struct socket *)data; 419 420 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 421 422 if (so->so_tpcb) { 423 switch (event) { 424 case PPTP_EVT_XMIT_FULL: 425 pptp_wan_xmit_full(ALIGNED_CAST(struct ppp_link *)so->so_tpcb); // Wcast-align fix - we malloc so->so_tpcb 426 break; 427 case PPTP_EVT_XMIT_OK: 428 pptp_wan_xmit_ok(ALIGNED_CAST(struct ppp_link *)so->so_tpcb); 429 break; 430 case PPTP_EVT_INPUTERROR: 431 pptp_wan_input_error(ALIGNED_CAST(struct ppp_link *)so->so_tpcb); 432 break; 433 } 434 } 435} 436