ctrlpacket.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. /*
  2. * ctrlpacket.c
  3. *
  4. * PPTP Control Message packet reading, formatting and writing.
  5. *
  6. * $Id: ctrlpacket.c,v 1.8 2008/11/13 23:49:22 quozl Exp $
  7. */
  8. #ifdef HAVE_CONFIG_H
  9. #include "config.h"
  10. #endif
  11. #if HAVE_SYSLOG_H
  12. #include <syslog.h>
  13. #else
  14. #include "our_syslog.h"
  15. #endif
  16. #include <signal.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <sys/types.h>
  20. #include <time.h>
  21. #include <sys/time.h>
  22. #include <netinet/in.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <errno.h>
  26. #include "pptpdefs.h"
  27. #include "pptpctrl.h"
  28. #include "ctrlpacket.h"
  29. #ifndef HAVE_STRERROR
  30. #include "compat.h"
  31. #endif
  32. /* Local function prototypes */
  33. static ssize_t read_pptp_header(int clientFd, unsigned char *packet, int *ctrl_message_type);
  34. static void deal_start_ctrl_conn(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
  35. static void deal_stop_ctrl_conn(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
  36. static void deal_out_call(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
  37. static void deal_echo(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
  38. static void deal_call_clr(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
  39. static void deal_set_link_info(unsigned char *packet);
  40. static u_int16_t getcall();
  41. static u_int16_t freecall();
  42. #if notyet
  43. static int make_out_call_rqst(unsigned char *rply_packet, ssize_t * rply_size);
  44. #endif
  45. /*
  46. * read_pptp_packet
  47. *
  48. * Sees if a packet can be read and if so what type of packet it is. The
  49. * method then calls the appropriate function to examine the details of the
  50. * packet and form a suitable reply packet.
  51. *
  52. * args: clientFd (IN) - Client socket to read from.
  53. * packet (OUT) - Packet read from the client.
  54. * rply_packet (OUT) - Reply packet for the client.
  55. * rply_size (OUT) - Size of the reply packet.
  56. *
  57. * retn: PPTP control message type of the packet on success.
  58. * -1 on retryable error.
  59. * 0 on error to abort on.
  60. */
  61. int read_pptp_packet(int clientFd, unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
  62. {
  63. ssize_t bytes_read;
  64. int pptp_ctrl_type = 0; /* Control Message Type */
  65. /* read a packet and parse header */
  66. if ((bytes_read = read_pptp_header(clientFd, packet, &pptp_ctrl_type)) <= 0) {
  67. /* error reading packet */
  68. syslog(LOG_ERR, "CTRL: couldn't read packet header (%s)", bytes_read ? "retry" : "exit");
  69. return bytes_read;
  70. }
  71. /* launch appropriate method to form suitable reply to the packet */
  72. switch (pptp_ctrl_type) {
  73. case START_CTRL_CONN_RQST: /* Start Control Connection Request */
  74. deal_start_ctrl_conn(packet, rply_packet, rply_size);
  75. break;
  76. case STOP_CTRL_CONN_RQST:
  77. deal_stop_ctrl_conn(packet, rply_packet, rply_size);
  78. break;
  79. case OUT_CALL_RQST: /* Outgoing Call Request */
  80. deal_out_call(packet, rply_packet, rply_size);
  81. break;
  82. case ECHO_RQST: /* Echo Request */
  83. deal_echo(packet, rply_packet, rply_size);
  84. break;
  85. case CALL_CLR_RQST: /* Call Clear Request (Disconnect Request) */
  86. deal_call_clr(packet, rply_packet, rply_size);
  87. break;
  88. case SET_LINK_INFO: /* Set Link Info */
  89. /* no reply packet but process it */
  90. deal_set_link_info(packet);
  91. break;
  92. case ECHO_RPLY: /* Echo Reply */
  93. case STOP_CTRL_CONN_RPLY: /* Stop Control Connection Reply */
  94. case CALL_DISCONN_NTFY: /* Call Disconnect Notify */
  95. /* no reply packet */
  96. break;
  97. default:
  98. syslog(LOG_ERR, "CTRL: PPTP Control Message type %d not supported.", pptp_ctrl_type);
  99. pptp_ctrl_type = -1;
  100. }
  101. return pptp_ctrl_type;
  102. }
  103. /*
  104. * send_pptp_packet
  105. *
  106. * Sends a PPTP packet to a file descriptor.
  107. *
  108. * args: clientFd (IN) - file descriptor to write the packet to.
  109. * packet (IN) - the packet data to write.
  110. * packet_size (IN) - the packet size.
  111. *
  112. * retn: Number of bytes written on success.
  113. * -1 on write failure.
  114. */
  115. ssize_t send_pptp_packet(int clientFd, unsigned char *packet, size_t packet_size)
  116. {
  117. ssize_t bytes_written;
  118. if ((bytes_written = write(clientFd, packet, packet_size)) == -1) {
  119. /* write failed */
  120. syslog(LOG_ERR, "CTRL: Couldn't write packet to client.");
  121. return -1;
  122. } else {
  123. /* debugging */
  124. if (pptpctrl_debug) {
  125. syslog(LOG_DEBUG, "CTRL: I wrote %lu bytes to the client.", (unsigned long) packet_size);
  126. syslog(LOG_DEBUG, "CTRL: Sent packet to client");
  127. }
  128. return bytes_written;
  129. }
  130. }
  131. /*
  132. * ignoreErrno
  133. *
  134. * Check if an errno represents a read error which should be ignored, and
  135. * put back to be select()ed on again later.
  136. *
  137. * Very similar to the function in Squid by Duane Wessels (under GPL).
  138. *
  139. * args: an errno value
  140. *
  141. * retn: 1 if the error is unimportant
  142. * 0 if the error is important
  143. */
  144. static int ignoreErrno(int ierrno) {
  145. switch (ierrno) {
  146. case EAGAIN: /* nothing to read */
  147. case EINTR: /* signal received */
  148. #ifdef ERESTART
  149. #if ERESTART != EINTR
  150. case ERESTART: /* signal received, should restart syscall */
  151. #endif
  152. #endif
  153. #if EWOULDBLOCK != EAGAIN
  154. case EWOULDBLOCK: /* shouldn't get this one but anyway, just in case */
  155. #endif
  156. return 1;
  157. default:
  158. return 0;
  159. }
  160. }
  161. /*
  162. * read_pptp_header
  163. *
  164. * Reads a packet from a file descriptor and determines whether it is a
  165. * valid PPTP Control Message. If a valid PPTP Control Message is detected
  166. * it extracts the Control Message type from the packet header.
  167. *
  168. * args: clientFd (IN) - Clients file descriptor.
  169. * packet (OUT) - Packet we read from the client.
  170. * pptp_ctrl_type (OUT) - PPTP Control Message type of the packet.
  171. *
  172. * retn: Number of bytes read on success.
  173. * -1 on retryable error.
  174. * 0 on error to exit on.
  175. */
  176. ssize_t read_pptp_header(int clientFd, unsigned char *packet, int *pptp_ctrl_type)
  177. {
  178. ssize_t bytes_ttl, bytes_this; /* quantities read (total and this read) */
  179. u_int16_t length; /* length of this packet */
  180. struct pptp_header *header; /* the received header */
  181. static char *buffer = NULL; /* buffer between calls */
  182. static int buffered = 0; /* size of buffer */
  183. *pptp_ctrl_type = 0; /* initialise return arg */
  184. /* read any previously buffered data */
  185. if (buffered) {
  186. memcpy(packet, buffer, buffered);
  187. free(buffer);
  188. buffer = NULL;
  189. bytes_ttl = buffered;
  190. buffered = 0;
  191. if (pptpctrl_debug)
  192. syslog(LOG_DEBUG, "CTRL: Read in previous incomplete ctrl packet");
  193. } else
  194. bytes_ttl = 0;
  195. /* try and get the length in */
  196. if (bytes_ttl < 2) {
  197. bytes_this = read(clientFd, packet + bytes_ttl, 2 - bytes_ttl);
  198. switch (bytes_this) {
  199. case -1:
  200. if (ignoreErrno(errno)) {
  201. /* re-tryable error, re-buffer and return */
  202. if (bytes_ttl) {
  203. buffered = bytes_ttl;
  204. buffer = malloc(bytes_ttl);
  205. if (!buffer)
  206. return(0);
  207. memcpy(buffer, packet, bytes_ttl);
  208. }
  209. syslog(LOG_ERR, "CTRL: Error reading ctrl packet length (bytes_ttl=%lu): %s", (unsigned long) bytes_ttl, strerror(errno));
  210. return -1;
  211. }
  212. /* FALLTHRU */
  213. case 0:
  214. syslog(LOG_ERR, "CTRL: EOF or bad error reading ctrl packet length.");
  215. return 0;
  216. default:
  217. bytes_ttl += bytes_this;
  218. /* Not enough data to proceed */
  219. if (bytes_ttl == 1) {
  220. buffered = bytes_ttl;
  221. buffer = malloc(bytes_ttl);
  222. if (!buffer)
  223. return(0);
  224. memcpy(buffer, packet, bytes_ttl);
  225. if (pptpctrl_debug)
  226. syslog(LOG_DEBUG, "CTRL: Incomplete ctrl packet length, retry later");
  227. return -1;
  228. }
  229. }
  230. }
  231. /* OK, we have (at least) the first 2 bytes, and there is data waiting
  232. *
  233. * length includes the header, so a length less than 2 is someone
  234. * trying to hack into us or a badly corrupted packet.
  235. * Why not require length to be at least 10? Since we later cast
  236. * packet to struct pptp_header and use at least the 10 first bytes..
  237. * Thanks to Timo Sirainen for mentioning this.
  238. */
  239. length = htons(*(u_int16_t *) packet);
  240. if (length <= 10 || length > PPTP_MAX_CTRL_PCKT_SIZE) {
  241. syslog(LOG_ERR, "CTRL: 11 < Control packet (length=%d) < "
  242. "PPTP_MAX_CTRL_PCKT_SIZE (%d)",
  243. length, PPTP_MAX_CTRL_PCKT_SIZE);
  244. /* we loose sync (unless we malloc something big, which isn't a good
  245. * idea - potential DoS) so we must close connection (draft states that
  246. * if you loose sync you must close the control connection immediately)
  247. */
  248. return 0;
  249. }
  250. /* Now read the actual control packet */
  251. bytes_this = read(clientFd, packet + bytes_ttl, length - bytes_ttl);
  252. switch (bytes_this) {
  253. case -1:
  254. if(ignoreErrno(errno)) {
  255. /* re-tryable error, re-buffer and return */
  256. if (bytes_ttl) {
  257. buffered = bytes_ttl;
  258. buffer = malloc(bytes_ttl);
  259. if (!buffer)
  260. return(0);
  261. memcpy(buffer, packet, bytes_ttl);
  262. }
  263. syslog(LOG_ERR, "CTRL: Error reading ctrl packet (bytes_ttl=%lu,length=%d): %s", (unsigned long) bytes_ttl, length, strerror(errno));
  264. return -1;
  265. }
  266. /* FALLTHRU */
  267. case 0:
  268. syslog(LOG_ERR, "CTRL: EOF or bad error reading ctrl packet.");
  269. return 0;
  270. default:
  271. bytes_ttl += bytes_this;
  272. /* not enough data to proceed */
  273. if (bytes_ttl != length) {
  274. buffered = bytes_ttl;
  275. buffer = malloc(bytes_ttl);
  276. if (!buffer)
  277. return(0);
  278. memcpy(buffer, packet, bytes_ttl);
  279. if (pptpctrl_debug)
  280. syslog(LOG_DEBUG, "CTRL: Incomplete ctrl packet, retry later");
  281. return -1;
  282. }
  283. }
  284. /* We got one :-) */
  285. /* Cast the packet into the PPTP Control Message format */
  286. header = (struct pptp_header *) packet;
  287. /* Packet sanity check on magic cookie */
  288. if (ntohl(header->magic) != PPTP_MAGIC_COOKIE) {
  289. /* Oops! Not a valid Control Message */
  290. syslog(LOG_ERR, "CTRL: Bad magic cookie - lost syncronization, closing control connection.");
  291. /* draft states loss of syncronization must result in
  292. * immediate closing of the control connection
  293. */
  294. return 0;
  295. }
  296. /* Woohoo! Looks like we got a valid PPTP packet */
  297. *pptp_ctrl_type = (int) (ntohs(header->ctrl_type));
  298. if (pptpctrl_debug)
  299. syslog(LOG_DEBUG, "CTRL: Received PPTP Control Message (type: %d)", *pptp_ctrl_type);
  300. return bytes_ttl;
  301. }
  302. /* Macros to use in making response packets */
  303. #define MAKE_CTRL_HEADER(where, what) \
  304. where.header.length = htons(sizeof(where)); \
  305. where.header.pptp_type = htons(PPTP_CTRL_MESSAGE); \
  306. where.header.magic = htonl(PPTP_MAGIC_COOKIE); \
  307. where.header.ctrl_type = htons(what); \
  308. where.header.reserved0 = htons(RESERVED)
  309. #define COPY_CTRL_PACKET(from, to, size) \
  310. memcpy(to, &from, ((*size) = sizeof(from)))
  311. #define DEBUG_PACKET(what) \
  312. if(pptpctrl_debug) \
  313. syslog(LOG_DEBUG, "CTRL: Made a " what " packet")
  314. /*
  315. * deal_start_ctrl_conn
  316. *
  317. * This method 'deals' with a START-CONTROL-CONNECTION-REQUEST. After
  318. * stripping down the connection request a suitable reply is formed and
  319. * stored in 'rply_packet' ready for sending.
  320. *
  321. * args: packet (IN) - the packet that we have to deal with (should be a
  322. * START-CONTROL-CONNECTION-REQUEST packet)
  323. * rply_packet (OUT) - suitable reply to the 'packet' we got.
  324. * rply_size (OUT) - size of the reply packet
  325. */
  326. void deal_start_ctrl_conn(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
  327. {
  328. struct pptp_start_ctrl_conn_rqst *start_ctrl_conn_rqst;
  329. struct pptp_start_ctrl_conn_rply start_ctrl_conn_rply;
  330. start_ctrl_conn_rqst = (struct pptp_start_ctrl_conn_rqst *) packet;
  331. MAKE_CTRL_HEADER(start_ctrl_conn_rply, START_CTRL_CONN_RPLY);
  332. start_ctrl_conn_rply.version = htons(PPTP_VERSION);
  333. start_ctrl_conn_rply.result_code = CONNECTED;
  334. start_ctrl_conn_rply.error_code = NO_ERROR;
  335. start_ctrl_conn_rply.framing_cap = htons(OUR_FRAMING);
  336. start_ctrl_conn_rply.bearer_cap = htons(OUR_BEARER);
  337. start_ctrl_conn_rply.max_channels = htons(MAX_CHANNELS);
  338. start_ctrl_conn_rply.firmware_rev = htons(PPTP_FIRMWARE_VERSION);
  339. memset(start_ctrl_conn_rply.hostname, 0, MAX_HOSTNAME_SIZE);
  340. strncpy((char *)start_ctrl_conn_rply.hostname, PPTP_HOSTNAME, MAX_HOSTNAME_SIZE);
  341. memset(start_ctrl_conn_rply.vendor, 0, MAX_VENDOR_SIZE);
  342. strncpy((char *)start_ctrl_conn_rply.vendor, PPTP_VENDOR, MAX_VENDOR_SIZE);
  343. COPY_CTRL_PACKET(start_ctrl_conn_rply, rply_packet, rply_size);
  344. DEBUG_PACKET("START CTRL CONN RPLY");
  345. }
  346. /*
  347. * deal_stop_ctrl_conn
  348. *
  349. * This method response to a STOP-CONTROL-CONNECTION-REQUEST with a
  350. * STOP-CONTROL-CONNECTION-REPLY.
  351. */
  352. void deal_stop_ctrl_conn(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
  353. {
  354. struct pptp_stop_ctrl_conn_rply stop_ctrl_conn_rply;
  355. MAKE_CTRL_HEADER(stop_ctrl_conn_rply, STOP_CTRL_CONN_RPLY);
  356. stop_ctrl_conn_rply.result_code = DISCONNECTED;
  357. stop_ctrl_conn_rply.error_code = NO_ERROR;
  358. stop_ctrl_conn_rply.reserved1 = htons(RESERVED);
  359. COPY_CTRL_PACKET(stop_ctrl_conn_rply, rply_packet, rply_size);
  360. DEBUG_PACKET("STOP CTRL CONN RPLY");
  361. }
  362. /*
  363. * deal_out_call
  364. *
  365. * This method 'deals' with a OUT-GOING-CALL-REQUEST. After
  366. * stripping down the request a suitable reply is formed and stored in
  367. * 'rply_packet' ready for sending.
  368. *
  369. * args: packet (IN) - the packet that we have to deal with (should be a
  370. * OUT-GOING-CALL-REQUEST packet)
  371. * rply_packet (OUT) - suitable reply to the 'packet' we got.
  372. * rply_size (OUT) - size of the reply packet
  373. *
  374. */
  375. void deal_out_call(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
  376. {
  377. u_int16_t pac_call_id;
  378. struct pptp_out_call_rqst *out_call_rqst;
  379. struct pptp_out_call_rply out_call_rply;
  380. out_call_rqst = (struct pptp_out_call_rqst *) packet;
  381. if ((pac_call_id = getcall()) == htons(-1)) {
  382. /* XXX should reject call */
  383. syslog(LOG_ERR, "CTRL: No free Call IDs!");
  384. pac_call_id = 0;
  385. }
  386. MAKE_CTRL_HEADER(out_call_rply, OUT_CALL_RPLY);
  387. /* call_id is used for ctrl, call_id_peer is used for GRE
  388. * call_id_peer is what we were sent by the other end in ctrl initilization
  389. */
  390. out_call_rply.call_id = pac_call_id;
  391. out_call_rply.call_id_peer = out_call_rqst->call_id;
  392. out_call_rply.result_code = CONNECTED;
  393. out_call_rply.error_code = NO_ERROR;
  394. out_call_rply.cause_code = NO_ERROR;
  395. /* maybe limit to pppd speed? but pppd doesn't accept 10Mbps as a speed and yet
  396. * still performs at over 115200, eg, 60kbyte/sec and higher observed.
  397. */
  398. out_call_rply.speed = out_call_rqst->max_bps;
  399. /* lets match their window size for now... was htons(PCKT_RECV_WINDOW_SIZE)
  400. */
  401. out_call_rply.pckt_recv_size = out_call_rqst->pckt_recv_size;
  402. if(pptpctrl_debug)
  403. syslog(LOG_DEBUG, "CTRL: Set parameters to %d maxbps, %d window size",
  404. ntohl(out_call_rply.speed), ntohs(out_call_rply.pckt_recv_size));
  405. out_call_rply.pckt_delay = htons(PCKT_PROCESS_DELAY);
  406. out_call_rply.channel_id = htonl(CHANNEL_ID);
  407. COPY_CTRL_PACKET(out_call_rply, rply_packet, rply_size);
  408. DEBUG_PACKET("OUT CALL RPLY");
  409. }
  410. /*
  411. * deal_echo
  412. *
  413. * This method 'deals' with a ECHO-REQUEST. After stripping down the
  414. * connection request a suitable reply is formed and stored in
  415. * 'rply_packet' ready for sending.
  416. *
  417. * args: packet (IN) - the packet that we have to deal with (should be a
  418. * ECHO-REQUEST packet)
  419. * rply_packet (OUT) - suitable reply to the 'packet' we got.
  420. * rply_size (OUT) - size of the reply packet
  421. *
  422. */
  423. void deal_echo(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
  424. {
  425. struct pptp_echo_rqst *echo_rqst;
  426. struct pptp_echo_rply echo_rply;
  427. echo_rqst = (struct pptp_echo_rqst *) packet;
  428. MAKE_CTRL_HEADER(echo_rply, ECHO_RPLY);
  429. echo_rply.identifier = echo_rqst->identifier;
  430. echo_rply.result_code = CONNECTED;
  431. echo_rply.error_code = NO_ERROR;
  432. echo_rply.reserved1 = htons(RESERVED);
  433. COPY_CTRL_PACKET(echo_rply, rply_packet, rply_size);
  434. DEBUG_PACKET("ECHO RPLY");
  435. }
  436. /*
  437. * deal_call_clr
  438. *
  439. * This method 'deals' with a CALL-CLEAR-REQUEST. After stripping down the
  440. * connection request a suitable reply is formed and stored in
  441. * 'rply_packet' ready for sending.
  442. *
  443. * args: packet (IN) - the packet that we have to deal with (should be a
  444. * CALL-CLEAR-REQUEST packet)
  445. * rply_packet (OUT) - suitable reply to the 'packet' we got.
  446. * rply_size (OUT) - size of the reply packet
  447. *
  448. */
  449. void deal_call_clr(unsigned char *packet, unsigned char *rply_packet, ssize_t *rply_size)
  450. {
  451. struct pptp_call_disconn_ntfy call_disconn_ntfy;
  452. u_int16_t pac_call_id;
  453. /* Form a reply
  454. * The reply packet is a CALL-DISCONECT-NOTIFY
  455. * In single call mode we don't care what peer's call ID is, so don't even bother looking
  456. */
  457. if ((pac_call_id = freecall()) == htons(-1)) {
  458. /* XXX should return an error */
  459. syslog(LOG_ERR, "CTRL: Could not free Call ID [call clear]!");
  460. }
  461. MAKE_CTRL_HEADER(call_disconn_ntfy, CALL_DISCONN_NTFY);
  462. call_disconn_ntfy.call_id = pac_call_id;
  463. call_disconn_ntfy.result_code = CALL_CLEAR_REQUEST; /* disconnected by call_clr_rqst */
  464. call_disconn_ntfy.error_code = NO_ERROR;
  465. call_disconn_ntfy.cause_code = htons(NO_ERROR);
  466. call_disconn_ntfy.reserved1 = htons(RESERVED);
  467. memset(call_disconn_ntfy.call_stats, 0, 128);
  468. COPY_CTRL_PACKET(call_disconn_ntfy, rply_packet, rply_size);
  469. DEBUG_PACKET("CALL DISCONNECT RPLY");
  470. }
  471. /*
  472. * deal_set_link_info
  473. *
  474. * @FIXME This function is *not* completed
  475. *
  476. * This method 'deals' with a SET-LINK-INFO. After stripping down the
  477. * connection request a suitable reply is formed and stored in
  478. * 'rply_packet' ready for sending.
  479. *
  480. * args: packet (IN) - the packet that we have to deal with (should be a
  481. * SET-LINK-INFO packet)
  482. * rply_packet (OUT) - suitable reply to the 'packet' we got.
  483. * rply_size (OUT) - size of the reply packet
  484. *
  485. */
  486. void deal_set_link_info(unsigned char *packet)
  487. {
  488. struct pptp_set_link_info *set_link_info;
  489. set_link_info = (struct pptp_set_link_info *) packet;
  490. if (set_link_info->send_accm != 0xffffffff || set_link_info->recv_accm != 0xffffffff) {
  491. /* Async-Control-Character-Map (ACCM) are bits that
  492. show which control characters should be escaped by the
  493. PPP implementation ... pptpd leaves pppd to negotiate
  494. that via LCP and does not process SET LINK INFO
  495. packets ... this is not complaint with the RFC but
  496. still works. */
  497. if (pptpctrl_debug)
  498. syslog(LOG_DEBUG, "CTRL: Ignored a SET LINK INFO packet with real ACCMs! (intentional non-compliance with section 2.15 of RFC 2637, ACCM is negotiated by PPP LCP asyncmap)");
  499. } else if (pptpctrl_debug)
  500. syslog(LOG_DEBUG, "CTRL: Got a SET LINK INFO packet with standard ACCMs");
  501. }
  502. void make_echo_req_packet(unsigned char *rply_packet, ssize_t * rply_size, u_int32_t echo_id)
  503. {
  504. struct pptp_echo_rqst echo_packet;
  505. MAKE_CTRL_HEADER(echo_packet, ECHO_RQST);
  506. echo_packet.identifier = echo_id;
  507. COPY_CTRL_PACKET(echo_packet, rply_packet, rply_size);
  508. DEBUG_PACKET("ECHO REQ");
  509. }
  510. void make_stop_ctrl_req(unsigned char *rply_packet, ssize_t * rply_size)
  511. {
  512. struct pptp_stop_ctrl_conn_rqst stop_ctrl;
  513. MAKE_CTRL_HEADER(stop_ctrl, STOP_CTRL_CONN_RQST);
  514. stop_ctrl.reason = GENERAL_STOP_CTRL;
  515. stop_ctrl.reserved1 = RESERVED;
  516. stop_ctrl.reserved2 = htons(RESERVED);
  517. COPY_CTRL_PACKET(stop_ctrl, rply_packet, rply_size);
  518. DEBUG_PACKET("STOP CTRL REQ");
  519. }
  520. void make_call_admin_shutdown(unsigned char *rply_packet, ssize_t * rply_size)
  521. {
  522. struct pptp_call_disconn_ntfy call_disconn_ntfy;
  523. u_int16_t pac_call_id;
  524. /* Form a reply
  525. * The reply packet is a CALL-DISCONECT-NOTIFY
  526. * In single call mode we don't care what peer's call ID is, so don't even bother looking
  527. */
  528. if ((pac_call_id = freecall()) == htons(-1)) {
  529. /* XXX should return an error */
  530. syslog(LOG_ERR, "CTRL: Could not free Call ID [admin shutdown]!");
  531. }
  532. MAKE_CTRL_HEADER(call_disconn_ntfy, CALL_DISCONN_NTFY);
  533. call_disconn_ntfy.call_id = pac_call_id;
  534. call_disconn_ntfy.result_code = ADMIN_SHUTDOWN; /* disconnected by admin shutdown */
  535. call_disconn_ntfy.error_code = NO_ERROR;
  536. call_disconn_ntfy.cause_code = htons(NO_ERROR);
  537. call_disconn_ntfy.reserved1 = htons(RESERVED);
  538. memset(call_disconn_ntfy.call_stats, 0, 128);
  539. COPY_CTRL_PACKET(call_disconn_ntfy, rply_packet, rply_size);
  540. DEBUG_PACKET("CALL DISCONNECT RPLY");
  541. }
  542. #if PNS_MODE
  543. /* out of date. really PNS isn't 'trivially different', it's quite different */
  544. #define C_BITS (sizeof(unsigned int) * 8)
  545. #define C_SEG(x) (x/C_BITS)
  546. #define C_BIT(x) ((1U)<<(x%C_BITS))
  547. static unsigned int activeCalls[(MAX_CALLS / C_BITS) + 1];
  548. /*
  549. * get_call_id
  550. *
  551. * Assigns a call ID and peer call ID to the session.
  552. *
  553. * args: call_id (OUT) - the call ID for the session
  554. * retn: 0 on success, -1 on failure
  555. */
  556. int get_call_id(u_int16_t * loc)
  557. {
  558. for (i = 0; i < MAX_CALLS; i++) {
  559. if (!(activeCalls[C_SEG(i)] & C_BIT(i))) {
  560. activeCalls[C_SEG(i)] |= C_BIT(i);
  561. *loc = i;
  562. return 0;
  563. }
  564. }
  565. return -1;
  566. }
  567. /*
  568. * free_call_id
  569. *
  570. * args: call_id (IN) - the call ID for a terminated session
  571. * retn: 0 on success, -1 on failure
  572. */
  573. int free_call_id(u_int16_t call_id)
  574. {
  575. if (!(activeCalls[C_SEG(i)] & C_BIT(i)))
  576. return -1;
  577. activeCalls[C_SEG(i)] &= ~C_BIT(i);
  578. return 0;
  579. }
  580. #else
  581. static int _pac_call_id;
  582. static u_int16_t _pac_init = 0;
  583. /*
  584. * getcall
  585. *
  586. * Assigns a call ID to the session and stores/returns it
  587. *
  588. * we only permit one call at a time, so the chance of wrapping 65k on one
  589. * control connection is zero to none...
  590. */
  591. u_int16_t getcall()
  592. {
  593. static u_int16_t i = 0;
  594. extern u_int16_t unique_call_id;
  595. /* Start with a random Call ID. This is to allocate unique
  596. * Call ID's across multiple TCP PPTP connections. In this
  597. * way remote clients masqueraded by a firewall will put
  598. * unique peer call ID's into GRE packets that will have the
  599. * same source IP address of the firewall. */
  600. if (!i) {
  601. if (unique_call_id == 0xFFFF) {
  602. struct timeval tv;
  603. if (gettimeofday(&tv, NULL) == 0) {
  604. i = ((tv.tv_sec & 0x0FFF) << 4) +
  605. (tv.tv_usec >> 16);
  606. }
  607. } else {
  608. i = unique_call_id;
  609. }
  610. }
  611. if(!_pac_init) {
  612. _pac_call_id = htons(-1);
  613. _pac_init = 1;
  614. }
  615. if(_pac_call_id != htons(-1))
  616. syslog(LOG_ERR, "CTRL: Asked to allocate call id when call open, not handled well");
  617. _pac_call_id = htons(i);
  618. i++;
  619. return _pac_call_id;
  620. }
  621. /*
  622. * freecall
  623. *
  624. * Notes termination of current call
  625. *
  626. * retn: -1 on failure, PAC call ID on success
  627. */
  628. u_int16_t freecall()
  629. {
  630. u_int16_t ret;
  631. if(!_pac_init) {
  632. _pac_call_id = htons(-1);
  633. _pac_init = 1;
  634. }
  635. ret = _pac_call_id;
  636. if(_pac_call_id == htons(-1))
  637. syslog(LOG_ERR, "CTRL: Asked to free call when no call open, not handled well");
  638. _pac_call_id = htons(-1);
  639. return ret;
  640. }
  641. #endif