ctrlpacket.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. /*
  2. * ctrlpacket.c
  3. *
  4. * PPTP Control Message packet reading, formatting and writing.
  5. *
  6. * $Id: ctrlpacket.c,v 1.6 2005/08/03 09:10:59 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. size_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. size_t send_pptp_packet(int clientFd, unsigned char *packet, size_t packet_size)
  116. {
  117. size_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 %d bytes to the client.", 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=%d): %s", 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=%d,length=%d): %s", 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. bzero(start_ctrl_conn_rply.hostname, MAX_HOSTNAME_SIZE);
  340. strncpy((char *)start_ctrl_conn_rply.hostname, PPTP_HOSTNAME, MAX_HOSTNAME_SIZE);
  341. bzero(start_ctrl_conn_rply.vendor, 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. syslog(LOG_ERR, "CTRL: Ignored a SET LINK INFO packet with real ACCMs!");
  492. else if(pptpctrl_debug)
  493. syslog(LOG_DEBUG, "CTRL: Got a SET LINK INFO packet with standard ACCMs");
  494. }
  495. void make_echo_req_packet(unsigned char *rply_packet, ssize_t * rply_size, u_int32_t echo_id)
  496. {
  497. struct pptp_echo_rqst echo_packet;
  498. MAKE_CTRL_HEADER(echo_packet, ECHO_RQST);
  499. echo_packet.identifier = echo_id;
  500. COPY_CTRL_PACKET(echo_packet, rply_packet, rply_size);
  501. DEBUG_PACKET("ECHO REQ");
  502. }
  503. void make_stop_ctrl_req(unsigned char *rply_packet, ssize_t * rply_size)
  504. {
  505. struct pptp_stop_ctrl_conn_rqst stop_ctrl;
  506. MAKE_CTRL_HEADER(stop_ctrl, STOP_CTRL_CONN_RQST);
  507. stop_ctrl.reason = GENERAL_STOP_CTRL;
  508. stop_ctrl.reserved1 = RESERVED;
  509. stop_ctrl.reserved2 = htons(RESERVED);
  510. COPY_CTRL_PACKET(stop_ctrl, rply_packet, rply_size);
  511. DEBUG_PACKET("STOP CTRL REQ");
  512. }
  513. void make_call_admin_shutdown(unsigned char *rply_packet, ssize_t * rply_size)
  514. {
  515. struct pptp_call_disconn_ntfy call_disconn_ntfy;
  516. u_int16_t pac_call_id;
  517. /* Form a reply
  518. * The reply packet is a CALL-DISCONECT-NOTIFY
  519. * In single call mode we don't care what peer's call ID is, so don't even bother looking
  520. */
  521. if ((pac_call_id = freecall()) == htons(-1)) {
  522. /* XXX should return an error */
  523. syslog(LOG_ERR, "CTRL: Could not free Call ID [admin shutdown]!");
  524. }
  525. MAKE_CTRL_HEADER(call_disconn_ntfy, CALL_DISCONN_NTFY);
  526. call_disconn_ntfy.call_id = pac_call_id;
  527. call_disconn_ntfy.result_code = ADMIN_SHUTDOWN; /* disconnected by admin shutdown */
  528. call_disconn_ntfy.error_code = NO_ERROR;
  529. call_disconn_ntfy.cause_code = htons(NO_ERROR);
  530. call_disconn_ntfy.reserved1 = htons(RESERVED);
  531. memset(call_disconn_ntfy.call_stats, 0, 128);
  532. COPY_CTRL_PACKET(call_disconn_ntfy, rply_packet, rply_size);
  533. DEBUG_PACKET("CALL DISCONNECT RPLY");
  534. }
  535. #if PNS_MODE
  536. /* out of date. really PNS isn't 'trivially different', it's quite different */
  537. #define C_BITS (sizeof(unsigned int) * 8)
  538. #define C_SEG(x) (x/C_BITS)
  539. #define C_BIT(x) ((1U)<<(x%C_BITS))
  540. static unsigned int activeCalls[(MAX_CALLS / C_BITS) + 1];
  541. /*
  542. * get_call_id
  543. *
  544. * Assigns a call ID and peer call ID to the session.
  545. *
  546. * args: call_id (OUT) - the call ID for the session
  547. * retn: 0 on success, -1 on failure
  548. */
  549. int get_call_id(u_int16_t * loc)
  550. {
  551. for (i = 0; i < MAX_CALLS; i++) {
  552. if (!(activeCalls[C_SEG(i)] & C_BIT(i))) {
  553. activeCalls[C_SEG(i)] |= C_BIT(i);
  554. *loc = i;
  555. return 0;
  556. }
  557. }
  558. return -1;
  559. }
  560. /*
  561. * free_call_id
  562. *
  563. * args: call_id (IN) - the call ID for a terminated session
  564. * retn: 0 on success, -1 on failure
  565. */
  566. int free_call_id(u_int16_t call_id)
  567. {
  568. if (!(activeCalls[C_SEG(i)] & C_BIT(i)))
  569. return -1;
  570. activeCalls[C_SEG(i)] &= ~C_BIT(i);
  571. return 0;
  572. }
  573. #else
  574. static int _pac_call_id;
  575. static u_int16_t _pac_init = 0;
  576. /*
  577. * getcall
  578. *
  579. * Assigns a call ID to the session and stores/returns it
  580. *
  581. * we only permit one call at a time, so the chance of wrapping 65k on one
  582. * control connection is zero to none...
  583. */
  584. u_int16_t getcall()
  585. {
  586. static u_int16_t i = 0;
  587. extern u_int16_t unique_call_id;
  588. /* Start with a random Call ID. This is to allocate unique
  589. * Call ID's across multiple TCP PPTP connections. In this
  590. * way remote clients masqueraded by a firewall will put
  591. * unique peer call ID's into GRE packets that will have the
  592. * same source IP address of the firewall. */
  593. if (!i) {
  594. if (unique_call_id == 0xFFFF) {
  595. struct timeval tv;
  596. if (gettimeofday(&tv, NULL) == 0) {
  597. i = ((tv.tv_sec & 0x0FFF) << 4) +
  598. (tv.tv_usec >> 16);
  599. }
  600. } else {
  601. i = unique_call_id;
  602. }
  603. }
  604. if(!_pac_init) {
  605. _pac_call_id = htons(-1);
  606. _pac_init = 1;
  607. }
  608. if(_pac_call_id != htons(-1))
  609. syslog(LOG_ERR, "CTRL: Asked to allocate call id when call open, not handled well");
  610. _pac_call_id = htons(i);
  611. i++;
  612. return _pac_call_id;
  613. }
  614. /*
  615. * freecall
  616. *
  617. * Notes termination of current call
  618. *
  619. * retn: -1 on failure, PAC call ID on success
  620. */
  621. u_int16_t freecall()
  622. {
  623. u_int16_t ret;
  624. if(!_pac_init) {
  625. _pac_call_id = htons(-1);
  626. _pac_init = 1;
  627. }
  628. ret = _pac_call_id;
  629. if(_pac_call_id == htons(-1))
  630. syslog(LOG_ERR, "CTRL: Asked to free call when no call open, not handled well");
  631. _pac_call_id = htons(-1);
  632. return ret;
  633. }
  634. #endif