1
0

ctrlpacket.c 26 KB

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