pptpctrl.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. /*
  2. * pptpctrl.c
  3. *
  4. * PPTP control connection between PAC-PNS pair
  5. *
  6. * $Id: pptpctrl.c,v 1.20 2006/12/08 00:01:40 quozl Exp $
  7. */
  8. #ifdef HAVE_CONFIG_H
  9. #include "config.h"
  10. #endif
  11. #ifdef __linux__
  12. #define _GNU_SOURCE 1 /* kill() prototype, broken arpa/inet.h */
  13. #endif
  14. #include "our_syslog.h"
  15. #include <fcntl.h>
  16. #include <errno.h>
  17. #include <signal.h>
  18. #include <unistd.h>
  19. #include <string.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <time.h>
  23. #include <sys/time.h>
  24. #include <dirent.h>
  25. #include <sys/types.h>
  26. #include <sys/wait.h>
  27. #include <sys/socket.h>
  28. #include <netinet/in.h>
  29. #include <arpa/inet.h>
  30. #ifdef HAVE_OPENPTY
  31. #ifdef HAVE_PTY_H
  32. #include <pty.h>
  33. #include <termios.h>
  34. #endif
  35. #ifdef HAVE_LIBUTIL_H
  36. #include <libutil.h>
  37. #endif
  38. #endif
  39. #ifdef __UCLIBC__
  40. #define socklen_t int
  41. #endif
  42. #include "compat.h"
  43. #include "pptpctrl.h"
  44. #include "pptpgre.h"
  45. #include "pptpdefs.h"
  46. #include "ctrlpacket.h"
  47. #include "defaults.h"
  48. // placing net/if.h here fixes build on Solaris
  49. #include <net/if.h>
  50. static char *ppp_binary = PPP_BINARY;
  51. static int pptp_logwtmp;
  52. static int noipparam; /* if true, don't send ipparam to ppp */
  53. static char speed[32];
  54. static char pppdxfig[256];
  55. static pid_t pppfork; /* so we can kill it after disconnect */
  56. /*
  57. * Global to handle dying
  58. *
  59. * I'd be nice if someone could figure out a way to do it
  60. * without the global, but i don't think you can.. -tmk
  61. */
  62. #define clientSocket 0 /* in case it changes back to a variable */
  63. static u_int32_t call_id_pair; /* call id (to terminate call) */
  64. /* Needed by this and ctrlpacket.c */
  65. int pptpctrl_debug = 0; /* specifies if debugging is on or off */
  66. uint16_t unique_call_id = 0xFFFF; /* Start value for our call IDs on this TCP link */
  67. int gargc; /* Command line argument count */
  68. char **gargv; /* Command line argument vector */
  69. /* Local function prototypes */
  70. static void bail(int sigraised);
  71. static void pptp_handle_ctrl_connection(char **pppaddrs, struct in_addr *inetaddrs);
  72. static int startCall(char **pppaddrs, struct in_addr *inetaddrs);
  73. static void launch_pppd(char **pppaddrs, struct in_addr *inetaddrs);
  74. /* Oh the horror.. lets hope this covers all the ones we have to handle */
  75. #if defined(O_NONBLOCK) && !defined(__sun__) && !defined(__sun)
  76. #define OUR_NB_MODE O_NONBLOCK
  77. #else
  78. #define OUR_NB_MODE O_NDELAY
  79. #endif
  80. /* read a command line argument, a flag alone */
  81. #define GETARG_INT(X) \
  82. X = atoi(argv[arg++])
  83. /* read a command line argument, a string alone */
  84. #define GETARG_STRING(X) \
  85. X = strdup(argv[arg++])
  86. /* read a command line argument, a presence flag followed by string */
  87. #define GETARG_VALUE(X) \
  88. if(atoi(argv[arg++]) != 0) \
  89. strlcpy(X, argv[arg++], sizeof(X)); \
  90. else \
  91. *X = '\0'
  92. int main(int argc, char **argv)
  93. {
  94. char pppLocal[16]; /* local IP to pass to pppd */
  95. char pppRemote[16]; /* remote IP address to pass to pppd */
  96. struct sockaddr_in addr; /* client address */
  97. socklen_t addrlen;
  98. int arg = 1;
  99. int flags;
  100. struct in_addr inetaddrs[2];
  101. char *pppaddrs[2] = { pppLocal, pppRemote };
  102. gargc = argc;
  103. gargv = argv;
  104. /* fail if argument count invalid */
  105. if (argc < 7) {
  106. fprintf(stderr, "pptpctrl: insufficient arguments, see man pptpctrl\n");
  107. exit(2);
  108. }
  109. /* open a connection to the syslog daemon */
  110. openlog("pptpd", LOG_PID, PPTP_FACILITY);
  111. /* autoreap if supported */
  112. signal(SIGCHLD, SIG_IGN);
  113. /* note: update pptpctrl.8 if the argument list format is changed */
  114. GETARG_INT(pptpctrl_debug);
  115. GETARG_INT(noipparam);
  116. GETARG_VALUE(pppdxfig);
  117. GETARG_VALUE(speed);
  118. GETARG_VALUE(pppLocal);
  119. GETARG_VALUE(pppRemote);
  120. if (arg < argc) GETARG_INT(unique_call_id);
  121. if (arg < argc) GETARG_STRING(ppp_binary);
  122. if (arg < argc) GETARG_INT(pptp_logwtmp);
  123. if (pptpctrl_debug) {
  124. if (*pppLocal)
  125. syslog(LOG_DEBUG, "CTRL: local address = %s", pppLocal);
  126. if (*pppRemote)
  127. syslog(LOG_DEBUG, "CTRL: remote address = %s", pppRemote);
  128. if (*speed)
  129. syslog(LOG_DEBUG, "CTRL: pppd speed = %s", speed);
  130. if (*pppdxfig)
  131. syslog(LOG_DEBUG, "CTRL: pppd options file = %s", pppdxfig);
  132. }
  133. addrlen = sizeof(addr);
  134. if (getsockname(clientSocket, (struct sockaddr *) &addr, &addrlen) != 0) {
  135. syslog(LOG_ERR, "CTRL: getsockname() failed");
  136. syslog_perror("getsockname");
  137. close(clientSocket);
  138. bail(0); /* NORETURN */
  139. }
  140. inetaddrs[0] = addr.sin_addr;
  141. addrlen = sizeof(addr);
  142. if (getpeername(clientSocket, (struct sockaddr *) &addr, &addrlen) != 0) {
  143. syslog(LOG_ERR, "CTRL: getpeername() failed");
  144. syslog_perror("getpeername");
  145. close(clientSocket);
  146. bail(0); /* NORETURN */
  147. }
  148. inetaddrs[1] = addr.sin_addr;
  149. /* Set non-blocking */
  150. if ((flags = fcntl(clientSocket, F_GETFL, arg /* ignored */)) == -1 ||
  151. fcntl(clientSocket, F_SETFL, flags|OUR_NB_MODE) == -1) {
  152. syslog(LOG_ERR, "CTRL: Failed to set client socket non-blocking");
  153. syslog_perror("fcntl");
  154. close(clientSocket);
  155. bail(0); /* NORETURN */
  156. }
  157. /* Fiddle with argv */
  158. my_setproctitle(gargc, gargv, "pptpd [%s]%20c",
  159. inet_ntoa(addr.sin_addr), ' ');
  160. /* be ready for a grisly death */
  161. sigpipe_create();
  162. sigpipe_assign(SIGTERM);
  163. NOTE_VALUE(PAC, call_id_pair, htons(-1));
  164. NOTE_VALUE(PNS, call_id_pair, htons(-1));
  165. syslog(LOG_INFO, "CTRL: Client %s control connection started", inet_ntoa(addr.sin_addr));
  166. pptp_handle_ctrl_connection(pppaddrs, inetaddrs);
  167. syslog(LOG_DEBUG, "CTRL: Reaping child PPP[%i]", pppfork);
  168. if (pppfork > 0)
  169. waitpid(pppfork, NULL, 0);
  170. syslog(LOG_INFO, "CTRL: Client %s control connection finished", inet_ntoa(addr.sin_addr));
  171. bail(0); /* NORETURN */
  172. return 1; /* make gcc happy */
  173. }
  174. /*
  175. * Local functions only below
  176. */
  177. /*
  178. * pptp_handle_ctrl_connection
  179. *
  180. * 1. read a packet (should be start_ctrl_conn_rqst)
  181. * 2. reply to packet (send a start_ctrl_conn_rply)
  182. * 3. proceed with GRE and CTRL connections
  183. *
  184. * args: pppaddrs - ppp local and remote addresses (strings)
  185. * inetaddrs - local and client socket address
  186. * retn: 0 success, -1 failure
  187. */
  188. static void pptp_handle_ctrl_connection(char **pppaddrs, struct in_addr *inetaddrs)
  189. {
  190. /* For echo requests used to check link is alive */
  191. int echo_wait = FALSE; /* Waiting for echo? */
  192. u_int32_t echo_count = 0; /* Sequence # of echo */
  193. time_t echo_time = 0; /* Time last echo req sent */
  194. struct timeval idleTime; /* How long to select() */
  195. /* General local variables */
  196. ssize_t rply_size; /* Reply packet size */
  197. fd_set fds; /* For select() */
  198. int maxfd = clientSocket; /* For select() */
  199. int send_packet; /* Send a packet this time? */
  200. #if BSDUSER_PPP || SLIRP
  201. /* not needed by stuff which uses socketpair() in startCall() */
  202. #define init 1
  203. #else
  204. int init = 0; /* Has pppd initialized the pty? */
  205. #endif
  206. int pty_fd = -1; /* File descriptor of pty */
  207. int gre_fd = -1; /* Network file descriptor */
  208. int sig_fd = sigpipe_fd(); /* Signal pipe descriptor */
  209. unsigned char packet[PPTP_MAX_CTRL_PCKT_SIZE];
  210. unsigned char rply_packet[PPTP_MAX_CTRL_PCKT_SIZE];
  211. for (;;) {
  212. FD_ZERO(&fds);
  213. FD_SET(sig_fd, &fds);
  214. FD_SET(clientSocket, &fds);
  215. if (pty_fd != -1)
  216. FD_SET(pty_fd, &fds);
  217. if (gre_fd != -1 && init)
  218. FD_SET(gre_fd, &fds);
  219. /* set timeout */
  220. if (encaps_gre(-1, NULL, 0) || decaps_hdlc(-1, NULL, 0)) {
  221. idleTime.tv_sec = 0;
  222. idleTime.tv_usec = 50000; /* don't ack immediately */
  223. } else {
  224. idleTime.tv_sec = IDLE_WAIT;
  225. idleTime.tv_usec = 0;
  226. }
  227. /* default: do nothing */
  228. send_packet = FALSE;
  229. switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
  230. case -1: /* Error with select() */
  231. if (errno != EINTR)
  232. syslog(LOG_ERR, "CTRL: Error with select(), quitting");
  233. goto leave_clear_call;
  234. case 0:
  235. if (decaps_hdlc(-1, NULL, 0)) {
  236. if(decaps_hdlc(-1, encaps_gre, gre_fd))
  237. syslog(LOG_ERR, "CTRL: GRE re-xmit failed");
  238. } else if (encaps_gre(-1, NULL, 0))
  239. /* Pending ack and nothing else to do */
  240. encaps_gre(gre_fd, NULL, 0); /* send ack with no payload */
  241. else if (echo_wait != TRUE) {
  242. /* Timeout. Start idle link detection. */
  243. echo_count++;
  244. if (pptpctrl_debug)
  245. syslog(LOG_DEBUG, "CTRL: Sending ECHO REQ id %d", echo_count);
  246. time(&echo_time);
  247. make_echo_req_packet(rply_packet, &rply_size, echo_count);
  248. echo_wait = TRUE;
  249. send_packet = TRUE;
  250. }
  251. break;
  252. default:
  253. break;
  254. }
  255. /* check for pending SIGTERM delivery */
  256. if (FD_ISSET(sig_fd, &fds)) {
  257. if (sigpipe_read() == SIGTERM)
  258. bail(SIGTERM);
  259. }
  260. /* detect startup of pppd */
  261. #ifndef init
  262. if (!init && pty_fd != -1 && FD_ISSET(pty_fd, &fds))
  263. init = 1;
  264. #endif
  265. /* handle actual packets */
  266. /* send from pty off via GRE */
  267. if (pty_fd != -1 && FD_ISSET(pty_fd, &fds) && decaps_hdlc(pty_fd, encaps_gre, gre_fd) < 0) {
  268. syslog(LOG_ERR, "CTRL: PTY read or GRE write failed (pty,gre)=(%d,%d)", pty_fd, gre_fd);
  269. break;
  270. }
  271. /* send from GRE off to pty */
  272. if (gre_fd != -1 && FD_ISSET(gre_fd, &fds) && decaps_gre(gre_fd, encaps_hdlc, pty_fd) < 0) {
  273. if (gre_fd == 6 && pty_fd == 5) {
  274. syslog(LOG_ERR, "CTRL: GRE-tunnel has collapsed (GRE read or PTY write failed (gre,pty)=(%d,%d))", gre_fd, pty_fd);
  275. } else {
  276. syslog(LOG_ERR, "CTRL: GRE read or PTY write failed (gre,pty)=(%d,%d)", gre_fd, pty_fd);
  277. }
  278. break;
  279. }
  280. /* handle control messages */
  281. if (FD_ISSET(clientSocket, &fds)) {
  282. send_packet = TRUE;
  283. switch (read_pptp_packet(clientSocket, packet, rply_packet, &rply_size)) {
  284. case 0:
  285. syslog(LOG_ERR, "CTRL: CTRL read failed");
  286. goto leave_drop_call;
  287. case -1:
  288. send_packet = FALSE;
  289. break;
  290. case STOP_CTRL_CONN_RQST:
  291. if (pptpctrl_debug)
  292. syslog(LOG_DEBUG, "CTRL: Received STOP CTRL CONN request (disconnecting)");
  293. if (gre_fd != -1 || pty_fd != -1)
  294. syslog(LOG_WARNING, "CTRL: Request to close control connection when call is open, closing");
  295. send_pptp_packet(clientSocket, rply_packet, rply_size);
  296. goto leave_drop_call;
  297. case CALL_CLR_RQST:
  298. if(pptpctrl_debug)
  299. syslog(LOG_DEBUG, "CTRL: Received CALL CLR request (closing call)");
  300. if (gre_fd == -1 || pty_fd == -1)
  301. syslog(LOG_WARNING, "CTRL: Request to close call but call not open");
  302. if (gre_fd != -1) {
  303. FD_CLR(gre_fd, &fds);
  304. close(gre_fd);
  305. gre_fd = -1;
  306. }
  307. if (pty_fd != -1) {
  308. FD_CLR(pty_fd, &fds);
  309. close(pty_fd);
  310. pty_fd = -1;
  311. }
  312. /* violating RFC */
  313. goto leave_drop_call;
  314. case OUT_CALL_RQST:
  315. /* for killing off the link later (ugly) */
  316. NOTE_VALUE(PAC, call_id_pair, ((struct pptp_out_call_rply *) (rply_packet))->call_id);
  317. NOTE_VALUE(PNS, call_id_pair, ((struct pptp_out_call_rply *) (rply_packet))->call_id_peer);
  318. if (gre_fd != -1 || pty_fd != -1) {
  319. syslog(LOG_WARNING, "CTRL: Request to open call when call is already open, closing");
  320. if (gre_fd != -1) {
  321. FD_CLR(gre_fd, &fds);
  322. close(gre_fd);
  323. gre_fd = -1;
  324. }
  325. if (pty_fd != -1) {
  326. FD_CLR(pty_fd, &fds);
  327. close(pty_fd);
  328. pty_fd = -1;
  329. }
  330. }
  331. /* change process title for accounting and status scripts */
  332. my_setproctitle(gargc, gargv,
  333. "pptpd [%s:%04X - %04X]",
  334. inet_ntoa(inetaddrs[1]),
  335. ntohs(((struct pptp_out_call_rply *) (rply_packet))->call_id_peer),
  336. ntohs(((struct pptp_out_call_rply *) (rply_packet))->call_id));
  337. /* start the call, by launching pppd */
  338. syslog(LOG_INFO, "CTRL: Starting call (launching pppd, opening GRE)");
  339. pty_fd = startCall(pppaddrs, inetaddrs);
  340. if (pty_fd > maxfd) maxfd = pty_fd;
  341. if ((gre_fd = pptp_gre_init(call_id_pair, pty_fd, inetaddrs)) > maxfd)
  342. maxfd = gre_fd;
  343. break;
  344. case ECHO_RPLY:
  345. if (echo_wait == TRUE && ((struct pptp_echo_rply *) (packet))->identifier == echo_count)
  346. echo_wait = FALSE;
  347. else
  348. syslog(LOG_WARNING, "CTRL: Unexpected ECHO REPLY packet");
  349. /* FALLTHRU */
  350. case SET_LINK_INFO:
  351. send_packet = FALSE;
  352. break;
  353. #ifdef PNS_MODE
  354. case IN_CALL_RQST:
  355. case IN_CALL_RPLY:
  356. case IN_CALL_CONN:
  357. #endif
  358. case CALL_DISCONN_NTFY:
  359. case STOP_CTRL_CONN_RPLY:
  360. /* These don't generate replies. Also they come from things we don't send in this section. */
  361. syslog(LOG_WARNING, "CTRL: Got a reply to a packet we didn't send");
  362. send_packet = FALSE;
  363. break;
  364. /* Otherwise, the already-formed reply will do fine, so send it */
  365. }
  366. }
  367. /* send reply packet - this may block, but it should be very rare */
  368. if (send_packet == TRUE && send_pptp_packet(clientSocket, rply_packet, rply_size) < 0) {
  369. syslog(LOG_ERR, "CTRL: Error sending GRE, aborting call");
  370. goto leave_clear_call;
  371. }
  372. /* waiting for echo reply and curtime - echo_time > max wait */
  373. if (echo_wait == TRUE && (time(NULL) - echo_time) > MAX_ECHO_WAIT) {
  374. syslog(LOG_INFO, "CTRL: Session timed out, ending call");
  375. goto leave_clear_call;
  376. }
  377. }
  378. /* Finished! :-) */
  379. leave_drop_call:
  380. NOTE_VALUE(PAC, call_id_pair, htons(-1));
  381. NOTE_VALUE(PNS, call_id_pair, htons(-1));
  382. close(clientSocket);
  383. leave_clear_call:
  384. /* leave clientSocket and call_id_pair alone for bail() */
  385. if (gre_fd != -1)
  386. close(gre_fd);
  387. gre_fd = -1;
  388. if (pty_fd != -1)
  389. close(pty_fd);
  390. pty_fd = -1;
  391. return;
  392. #ifdef init
  393. #undef init
  394. #endif
  395. }
  396. /*
  397. * This is the custom exit() for this program.
  398. *
  399. * Updated to also be the default SIGTERM handler, and if
  400. * the link is going down for unnatural reasons, we will close it
  401. * right now, it's only been tested for win98, other tests would be nice
  402. * -tmk
  403. */
  404. static void bail(int sigraised)
  405. {
  406. if (sigraised)
  407. syslog(LOG_INFO, "CTRL: Exiting on signal %d", sigraised);
  408. /* send a disconnect to the other end */
  409. /* ignore any errors */
  410. if (GET_VALUE(PAC, call_id_pair) != htons(-1)) {
  411. fd_set connSet; /* fd_set for select() */
  412. struct timeval tv; /* time to wait for reply */
  413. unsigned char packet[PPTP_MAX_CTRL_PCKT_SIZE];
  414. unsigned char rply_packet[PPTP_MAX_CTRL_PCKT_SIZE];
  415. ssize_t rply_size; /* reply packet size */
  416. int pkt;
  417. int retry = 0;
  418. if (pptpctrl_debug)
  419. syslog(LOG_DEBUG, "CTRL: Exiting with active call");
  420. make_call_admin_shutdown(rply_packet, &rply_size);
  421. if(send_pptp_packet(clientSocket, rply_packet, rply_size) < 0)
  422. goto skip;
  423. make_stop_ctrl_req(rply_packet, &rply_size);
  424. if(send_pptp_packet(clientSocket, rply_packet, rply_size) < 0)
  425. goto skip;
  426. FD_ZERO(&connSet);
  427. FD_SET(clientSocket, &connSet);
  428. tv.tv_sec = 5; /* wait 5 secs for a reply then quit */
  429. tv.tv_usec = 0;
  430. /* Wait for STOP CTRL CONN RQST or RPLY */
  431. while (select(clientSocket + 1, &connSet, NULL, NULL, &tv) == 1) {
  432. switch((pkt = read_pptp_packet(clientSocket, packet, rply_packet, &rply_size))) {
  433. case STOP_CTRL_CONN_RQST:
  434. send_pptp_packet(clientSocket, rply_packet, rply_size);
  435. goto skip;
  436. case CALL_CLR_RQST:
  437. syslog(LOG_WARNING, "CTRL: Got call clear request after call manually shutdown - buggy client");
  438. break;
  439. case STOP_CTRL_CONN_RPLY:
  440. goto skip;
  441. case -1:
  442. syslog(LOG_WARNING, "CTRL: Retryable error in disconnect sequence");
  443. retry++;
  444. break;
  445. case 0:
  446. syslog(LOG_WARNING, "CTRL: Fatal error reading control message in disconnect sequence");
  447. goto skip;
  448. default:
  449. syslog(LOG_WARNING, "CTRL: Unexpected control message %d in disconnect sequence", pkt);
  450. retry++;
  451. break;
  452. }
  453. tv.tv_sec = 5; /* wait 5 secs for another reply then quit */
  454. tv.tv_usec = 0;
  455. if (retry > 100) {
  456. syslog(LOG_WARNING, "CTRL: Too many retries (%d) - giving up", retry);
  457. break;
  458. }
  459. }
  460. skip:
  461. close(clientSocket);
  462. }
  463. if (pptpctrl_debug)
  464. syslog(LOG_DEBUG, "CTRL: Exiting now");
  465. }
  466. /*
  467. * startCall
  468. *
  469. * Launches PPPD for the call.
  470. *
  471. * args: pppaddrs - local/remote IPs or "" for either/both if none
  472. * retn: pty file descriptor
  473. *
  474. */
  475. static int startCall(char **pppaddrs, struct in_addr *inetaddrs)
  476. {
  477. /* PTY/TTY pair for talking to PPPd */
  478. int pty_fd, tty_fd;
  479. /* register pids of children */
  480. #if BSDUSER_PPP || SLIRP
  481. int sockfd[2];
  482. #ifndef AF_LOCAL
  483. #ifdef AF_UNIX
  484. #define AF_LOCAL AF_UNIX /* Old BSD */
  485. #else
  486. #define AF_LOCAL AF_FILE /* POSIX */
  487. #endif
  488. #endif
  489. /* userspace ppp doesn't need to waste a real pty/tty pair */
  490. if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd)) {
  491. syslog(LOG_ERR, "CTRL: socketpair() error");
  492. syslog_perror("socketpair");
  493. exit(1);
  494. }
  495. tty_fd = sockfd[0];
  496. pty_fd = sockfd[1];
  497. #else
  498. /* Finds an open pty/tty pair */
  499. if (openpty(&pty_fd, &tty_fd, NULL, NULL, NULL) != 0) {
  500. syslog(LOG_ERR, "CTRL: openpty() error");
  501. syslog_perror("openpty");
  502. exit(1);
  503. } else {
  504. struct termios tios;
  505. /* Turn off echo in the slave - to prevent loopback.
  506. pppd will do this, but might not do it before we
  507. try to send data. */
  508. if (tcgetattr(tty_fd, &tios) < 0) {
  509. syslog(LOG_ERR, "CTRL: tcgetattr() error");
  510. syslog_perror("tcgetattr");
  511. exit(1);
  512. }
  513. tios.c_lflag &= ~(ECHO | ECHONL);
  514. if (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0) {
  515. syslog(LOG_ERR, "CTRL: tcsetattr() error");
  516. syslog_perror("tcsetattr");
  517. exit(1);
  518. }
  519. }
  520. #endif
  521. if (pptpctrl_debug) {
  522. syslog(LOG_DEBUG, "CTRL: pty_fd = %d", pty_fd);
  523. syslog(LOG_DEBUG, "CTRL: tty_fd = %d", tty_fd);
  524. }
  525. /* Launch the PPPD */
  526. #ifndef HAVE_FORK
  527. switch(pppfork=vfork()){
  528. #else
  529. switch(pppfork=fork()){
  530. #endif
  531. case -1: /* fork() error */
  532. syslog(LOG_ERR, "CTRL: Error forking to exec pppd");
  533. _exit(1);
  534. case 0: /* child */
  535. if (dup2(tty_fd, 0) == -1) {
  536. syslog(LOG_ERR, "CTRL: child tty_fd dup2 to stdin, %s",
  537. strerror(errno));
  538. exit(1);
  539. }
  540. if (dup2(tty_fd, 1) == -1) {
  541. syslog(LOG_ERR, "CTRL: child tty_fd dup2 to stdout, %s",
  542. strerror(errno));
  543. exit(1);
  544. }
  545. #if 0
  546. /* This must never be used if !HAVE_SYSLOG since that logs to stderr.
  547. * Trying just never using it to see if it causes anyone else problems.
  548. * It may let people see the pppd errors, which would be good.
  549. */
  550. dup2(tty_fd, 2);
  551. #endif
  552. if (tty_fd > 1)
  553. close(tty_fd);
  554. if (pty_fd > 1)
  555. close(pty_fd);
  556. /* In case we move clientSocket back off stdin */
  557. #ifndef clientSocket
  558. if (clientSocket > 1)
  559. close(clientSocket);
  560. #elif clientSocket > 1
  561. close(clientSocket);
  562. #endif
  563. launch_pppd(pppaddrs, inetaddrs);
  564. syslog(LOG_ERR, "CTRL: PPPD launch failed! (launch_pppd did not fork)");
  565. _exit(1);
  566. }
  567. close(tty_fd);
  568. return pty_fd;
  569. }
  570. /*
  571. * launch_pppd
  572. *
  573. * Launches the PPP daemon. The PPP daemon is responsible for assigning the
  574. * PPTP client its IP address.. These values are assigned via the command
  575. * line.
  576. *
  577. * Add return of connected ppp interface
  578. *
  579. * retn: 0 on success, -1 on failure.
  580. *
  581. */
  582. static void launch_pppd(char **pppaddrs, struct in_addr *inetaddrs)
  583. {
  584. char *pppd_argv[16];
  585. int an = 0;
  586. sigset_t sigs;
  587. char pppInterfaceIPs[33];
  588. pppd_argv[an++] = ppp_binary;
  589. if (pptpctrl_debug) {
  590. syslog(LOG_DEBUG,
  591. "CTRL (PPPD Launcher): program binary = %s",
  592. pppd_argv[an - 1]);
  593. }
  594. #if BSDUSER_PPP
  595. /* The way that Brian Somers' user-land ppp works is to use the
  596. * system name as a reference for most of the useful options. Hence
  597. * most things can't be defined on the command line. On OpenBSD at
  598. * least the file used for the systems is /etc/ppp/ppp.conf, where
  599. * the pptp stanza should look something like:
  600. pptp:
  601. set speed sync
  602. enable pap
  603. enable chap
  604. set dns a.a.a.a b.b.b.b
  605. set ndbs x.x.x.x y.y.y.y
  606. accept dns
  607. add 10.0.0/24
  608. * To be honest, at the time of writing, I haven't had the thing
  609. * working enough to understand :) I will update this comment and
  610. * make a sample config available when I get there.
  611. */
  612. /* options for BSDUSER_PPP
  613. *
  614. * ignores IP addresses, config file option, speed
  615. * fix usage info in pptpd.c and configure script if this changes
  616. *
  617. * IP addresses can be specified in /etc/ppp/ppp.secret per user
  618. */
  619. pppd_argv[an++] = "-direct";
  620. pppd_argv[an++] = "pptp"; /* XXX this is the system name */
  621. /* should be dynamic - PMG */
  622. #elif SLIRP
  623. /* options for SLIRP
  624. *
  625. * ignores IP addresses from config - SLIRP handles this
  626. */
  627. pppd_argv[an++] = "-P";
  628. pppd_argv[an++] = "+chap";
  629. pppd_argv[an++] = "-b";
  630. /* If a speed has been specified, use it
  631. * if not, use "smart" default (defaults.h)
  632. */
  633. if (*speed) {
  634. pppd_argv[an++] = speed;
  635. } else {
  636. pppd_argv[an++] = PPP_SPEED_DEFAULT;
  637. }
  638. if (*pppdxfig) {
  639. pppd_argv[an++] = "-f";
  640. pppd_argv[an++] = pppdxfig;
  641. }
  642. if (pptpctrl_debug) {
  643. syslog(LOG_DEBUG, "CTRL (PPPD Launcher): Connection speed = %s", pppd_argv[an - 1]);
  644. }
  645. #else
  646. /* options for 'normal' pppd */
  647. pppd_argv[an++] = "local";
  648. /* If a pppd option file is specified, use it
  649. * if not, pppd will default to /etc/ppp/options
  650. */
  651. if (*pppdxfig) {
  652. pppd_argv[an++] = "file";
  653. pppd_argv[an++] = pppdxfig;
  654. }
  655. /* If a speed has been specified, use it
  656. * if not, use "smart" default (defaults.h)
  657. */
  658. if (*speed) {
  659. pppd_argv[an++] = speed;
  660. } else {
  661. pppd_argv[an++] = PPP_SPEED_DEFAULT;
  662. }
  663. if (pptpctrl_debug) {
  664. if (*pppaddrs[0])
  665. syslog(LOG_DEBUG, "CTRL (PPPD Launcher): local address = %s", pppaddrs[0]);
  666. if (*pppaddrs[1])
  667. syslog(LOG_DEBUG, "CTRL (PPPD Launcher): remote address = %s", pppaddrs[1]);
  668. }
  669. if (*pppaddrs[0] || *pppaddrs[1]) {
  670. sprintf(pppInterfaceIPs, "%s:%s", pppaddrs[0], pppaddrs[1]);
  671. pppd_argv[an++] = pppInterfaceIPs;
  672. }
  673. #endif
  674. if (!noipparam) {
  675. pppd_argv[an++] = "ipparam";
  676. pppd_argv[an++] = inet_ntoa(inetaddrs[1]);
  677. }
  678. if (pptp_logwtmp) {
  679. pppd_argv[an++] = "plugin";
  680. pppd_argv[an++] = "/usr/lib/pptpd/pptpd-logwtmp.so";
  681. pppd_argv[an++] = "pptpd-original-ip";
  682. pppd_argv[an++] = inet_ntoa(inetaddrs[1]);
  683. }
  684. pppd_argv[an++] = "remotenumber";
  685. pppd_argv[an++] = inet_ntoa(inetaddrs[1]);
  686. /* argv arrays must always be NULL terminated */
  687. pppd_argv[an++] = NULL;
  688. /* make sure SIGCHLD is unblocked, pppd does not expect it */
  689. sigfillset(&sigs);
  690. sigprocmask(SIG_UNBLOCK, &sigs, NULL);
  691. /* run pppd now */
  692. execvp(pppd_argv[0], pppd_argv);
  693. /* execvp() failed */
  694. syslog(LOG_ERR,
  695. "CTRL (PPPD Launcher): Failed to launch PPP daemon. %s",
  696. strerror(errno));
  697. }