negotiated MTU after decompression. We reserve some extra
space to handle that */
int receive_mtu = MAX(16384, vpninfo->ip_info.mtu);
- struct pkt *new = malloc(sizeof(struct pkt) + receive_mtu);
+ struct pkt *new = alloc_pkt(vpninfo, receive_mtu);
const char *comprname = "";
if (!new)
#ifndef _WIN32
vpninfo->tun_fd = -1;
#endif
+ init_pkt_queue(&vpninfo->free_queue);
init_pkt_queue(&vpninfo->incoming_queue);
init_pkt_queue(&vpninfo->outgoing_queue);
init_pkt_queue(&vpninfo->tcp_control_queue);
free_pkt(vpninfo, vpninfo->tun_pkt);
free_pkt(vpninfo, vpninfo->dtls_pkt);
free_pkt(vpninfo, vpninfo->cstp_pkt);
+ struct pkt *pkt;
+ while ((pkt = dequeue_packet(&vpninfo->free_queue)))
+ free(pkt);
+
free(vpninfo->bearer_token);
free(vpninfo);
}
#include "openconnect-internal.h"
-int queue_new_packet(struct pkt_q *q, void *buf, int len)
+int queue_new_packet(struct openconnect_info *vpninfo,
+ struct pkt_q *q, void *buf, int len)
{
- struct pkt *new = malloc(sizeof(struct pkt) + len);
+ struct pkt *new = alloc_pkt(vpninfo, len);
if (!new)
return -ENOMEM;
static int queue_esp_control(struct openconnect_info *vpninfo, int enable)
{
- struct pkt *new = malloc(sizeof(*new) + 13);
+ struct pkt *new = alloc_pkt(vpninfo, esp_enable_pkt.len);
if (!new)
return -ENOMEM;
- memcpy(new, &esp_enable_pkt, sizeof(*new) + 13);
+ new->oncp = esp_enable_pkt.oncp;
+ new->len = esp_enable_pkt.len;
+
+ memcpy(new->data, esp_enable_pkt.data, esp_enable_pkt.len);
new->data[12] = enable;
+
queue_packet(&vpninfo->tcp_control_queue, new);
return 0;
}
}
/* OK, we have a whole packet, and we have stuff after it */
- queue_new_packet(&vpninfo->incoming_queue, vpninfo->cstp_pkt->data, iplen);
+ queue_new_packet(vpninfo, &vpninfo->incoming_queue,
+ vpninfo->cstp_pkt->data, iplen);
kmplen -= iplen;
if (kmplen) {
/* Still data packets to come in this KMP300 */
/****************************************************************************/
struct pkt {
+ int alloc_len;
int len;
struct pkt *next;
union {
q->tail = &q->head;
}
-
-static inline struct pkt *alloc_pkt(struct openconnect_info *vpninfo, int len)
-{
- return malloc(sizeof(struct pkt) + len);
-}
-
-static inline void free_pkt(struct openconnect_info *vpninfo, struct pkt *pkt)
-{
- free(pkt);
-}
-
#define TLS_OVERHEAD 5 /* packet + header */
#define DTLS_OVERHEAD (1 /* packet + header */ + 13 /* DTLS header */ + \
20 /* biggest supported MAC (SHA1) */ + 32 /* biggest supported IV (AES-256) */ + \
int got_pause_cmd;
char cancel_type;
+ struct pkt_q free_queue;
struct pkt_q incoming_queue;
struct pkt_q outgoing_queue;
struct pkt_q tcp_control_queue; /* Control packets to be sent via TCP */
int (*ssl_write)(struct openconnect_info *vpninfo, char *buf, size_t len);
};
+
+static inline struct pkt *alloc_pkt(struct openconnect_info *vpninfo, int len)
+{
+ int alloc_len = sizeof(struct pkt) + len;
+
+ if (vpninfo->free_queue.head &&
+ vpninfo->free_queue.head->alloc_len >= alloc_len)
+ return dequeue_packet(&vpninfo->free_queue);
+
+ if (alloc_len < 2048)
+ alloc_len = 2048;
+
+ struct pkt *pkt = malloc(alloc_len);
+ if (pkt)
+ pkt->alloc_len = alloc_len;
+ return pkt;
+}
+
+static inline void free_pkt(struct openconnect_info *vpninfo, struct pkt *pkt)
+{
+ if (!pkt)
+ return;
+
+ if (vpninfo->free_queue.count < vpninfo->max_qlen * 2)
+ requeue_packet(&vpninfo->free_queue, pkt);
+ else
+ free(pkt);
+}
+
#ifdef _WIN32
#define monitor_read_fd(_v, _n) _v->_n##_monitored |= FD_READ
#define monitor_write_fd(_v, _n) _v->_n##_monitored |= FD_WRITE
/* mainloop.c */
int tun_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable);
-int queue_new_packet(struct pkt_q *q, void *buf, int len);
+int queue_new_packet(struct openconnect_info *vpninfo,
+ struct pkt_q *q, void *buf, int len);
int keepalive_action(struct keepalive_info *ka, int *timeout);
int ka_stalled_action(struct keepalive_info *ka, int *timeout);
int ka_check_deadline(int *timeout, time_t now, time_t due);
/* Every byte in payload and 2-byte FCS potentially expands to two bytes,
* plus 2 for flag (0x7e) at start and end. We know that we will output
* at least 4 bytes so we can stash those in the header. */
- struct pkt *p = malloc(sizeof(struct pkt) + len*2 + 2);
+ struct pkt *p = alloc_pkt(vpninfo, len*2 + 2);
if (!p)
return NULL;
return buf_append_ppp_tlv(buf, tag, 4, &val_be);
}
-static int queue_config_packet(struct openconnect_info *vpninfo,
- uint16_t proto, int id, int code, int len, const void *payload)
+static int queue_config_packet(struct openconnect_info *vpninfo, uint16_t proto,
+ int id, int code, int len, const void *payload)
{
- struct pkt *p = malloc(sizeof(struct pkt) + len + 4);
+ struct pkt *p = alloc_pkt(vpninfo, len + 4);
if (!p)
return -ENOMEM;