Tim Stewart <t...@stoo.org> writes:

> On 3/30/19 3:11 PM, Tobias Heider wrote:
>> Hi Stuart,
>>
>> I'm glad to see people are using this.
>> There's some smaller fixes that I haven't sent to the list yet, so
>> probably I'll send an updated diff on monday.
>
> I plan to start using this patch this week, likely as soon as you send
> the updated diff.  I started on the same feature in June of 2018, but
> other tasks took priority and it stalled.
>
> I have a pretty good testbed for this, as I have several site-to-site
> links that drop UDP fragments and several road warriors that would
> experience fragment drops depending on the cell network they use.  I
> will report back on this thread with my findings.
>
> Thanks for the patch!
>
> -TimS

I have been using this patch for over a week and it has increased the
reliability of my road warrior VPN as I move across a variety of
networks.  It also allows one of my previously-broken site-to-site VPNs
to function again.  Thanks!


I did have one strange problem today, and I have no idea if it's related
to this patch or not.  One of my site-to-site connections went down and
I saw the following in one of the peer's log:

Apr 16 12:59:05 site-a iked[15114]: ikev2_msg_send: sendtofrom: No buffer space 
available
Apr 16 13:00:07 site-a iked[15114]: ikev2_msg_send: INFORMATIONAL request from 
5.6.7.8:500 to 1.2.3.4:500 msgid 929, 80 bytes
Apr 16 13:00:07 site-a iked[15114]: ikev2_recv: INFORMATIONAL response from 
responder 1.2.3.4:500 to 5.6.7.8:500 policy 'central' id 929, 80 bytes
Apr 16 13:01:07 site-a iked[15114]: ikev2_msg_send: INFORMATIONAL request from 
5.6.7.8:500 to 1.2.3.4:500 msgid 930, 80 bytes
Apr 16 13:01:07 site-a iked[15114]: ikev2_recv: INFORMATIONAL response from 
responder 1.2.3.4:500 to 5.6.7.8:500 policy 'central' id 930, 80 bytes
Apr 16 13:02:07 site-a iked[15114]: ikev2_msg_send: INFORMATIONAL request from 
5.6.7.8:500 to 1.2.3.4:500 msgid 931, 80 bytes
Apr 16 13:02:07 site-a iked[15114]: ikev2_recv: INFORMATIONAL response from 
responder 1.2.3.4:500 to 5.6.7.8:500 policy 'central' id 931, 80 bytes
Apr 16 13:03:00 site-a iked[15114]: ikev2_acquire_sa: flow wasn't found
Apr 16 13:03:07 site-a iked[15114]: pfkey_sa_last_used: message: No such process
Apr 16 13:03:07 site-a iked[15114]: pfkey_sa_last_used: message: No such process
Apr 16 13:03:30 site-a iked[15114]: ikev2_acquire_sa: flow wasn't found
Apr 16 13:04:00 site-a iked[15114]: ikev2_acquire_sa: flow wasn't found
Apr 16 13:04:02 site-a iked[15114]: ikev2_recv: INFORMATIONAL request from 
responder 1.2.3.4:500 to 5.6.7.8:500 policy 'central' id 0, 80 bytes
Apr 16 13:04:02 site-a iked[15114]: ikev2_msg_send: INFORMATIONAL response from 
5.6.7.8:500 to 1.2.3.4:500 msgid 0, 80 bytes
Apr 16 13:04:07 site-a iked[15114]: pfkey_sa_last_used: message: No such process
Apr 16 13:04:07 site-a iked[15114]: pfkey_sa_last_used: message: No such process
Apr 16 13:04:30 site-a iked[15114]: ikev2_acquire_sa: flow wasn't found
Apr 16 13:05:00 site-a iked[15114]: ikev2_acquire_sa: flow wasn't found
Apr 16 13:05:04 site-a iked[15114]: ikev2_recv: INFORMATIONAL request from 
responder 1.2.3.4:500 to 5.6.7.8:500 policy 'central' id 1, 80 bytes
Apr 16 13:05:04 site-a iked[15114]: ikev2_msg_send: INFORMATIONAL response from 
5.6.7.8:500 to 1.2.3.4:500 msgid 1, 80 bytes

I restarted site-a's iked and everything came back up and has been
working fine since.

I see there are some other iked patches in-flight on this list
(including a new version of this one), so I'm happy to punt on this for
now and see if it happens again after I've applied the latest versions
of all patches.

-TimS


>> On 3/30/19 6:43 PM, Stuart Henderson wrote:
>>> This diff hasn't gone anywhere recently - I've been using it since
>>> Tobias posted it with no problems. Any comments on whether it should
>>> go in, and if so, before/after 6.5? The feature is disabled by default.
>>>
>>> Index: config.c
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/config.c,v
>>> retrieving revision 1.49
>>> diff -u -p -r1.49 config.c
>>> --- config.c        27 Nov 2017 18:39:35 -0000      1.49
>>> +++ config.c        30 Mar 2019 17:41:33 -0000
>>> @@ -94,12 +94,30 @@ config_free_kex(struct iked_kex *kex)
>>>   }
>>>     void
>>> +config_free_fragments(struct iked_frag *frag)
>>> +{
>>> +   size_t i;
>>> +   if (frag && frag->frag_arr) {
>>> +           for (i = 0; i < frag->frag_count; i++) {
>>> +                   free(frag->frag_arr[i]->frag_data);
>>> +                   frag->frag_arr[i]->frag_data = NULL;
>>> +                   free(frag->frag_arr[i]);
>>> +                   frag->frag_arr[i] = NULL;
>>> +           }
>>> +           free(frag->frag_arr);
>>> +           frag->frag_arr = NULL;
>>> +           bzero(frag, sizeof(struct iked_frag));
>>> +   }
>>> +}
>>> +
>>> +void
>>>   config_free_sa(struct iked *env, struct iked_sa *sa)
>>>   {
>>>     timer_del(env, &sa->sa_timer);
>>>     timer_del(env, &sa->sa_keepalive);
>>>     timer_del(env, &sa->sa_rekey);
>>>   + config_free_fragments(&sa->sa_fragments);
>>>     config_free_proposals(&sa->sa_proposals, 0);
>>>     config_free_childsas(env, &sa->sa_childsas, NULL, NULL);
>>>     sa_free_flows(env, &sa->sa_flows);
>>> @@ -925,6 +943,29 @@ config_setkeys(struct iked *env)
>>>     EVP_PKEY_free(key);
>>>             return (ret);
>>> +}
>>> +
>>> +int
>>> +config_setfragmentation(struct iked *env)
>>> +{
>>> +   unsigned int boolval;
>>> +
>>> +   boolval = env->sc_frag;
>>> +   proc_compose(&env->sc_ps, PROC_IKEV2, IMSG_CTL_FRAGMENTATION,
>>> +       &boolval, sizeof(boolval));
>>> +   return (0);
>>> +}
>>> +
>>> +int
>>> +config_getfragmentation(struct iked *env, struct imsg *imsg)
>>> +{
>>> +   unsigned int boolval;
>>> +
>>> +   IMSG_SIZE_CHECK(imsg, &boolval);
>>> +   memcpy(&boolval, imsg->data, sizeof(boolval));
>>> +   env->sc_frag = boolval;
>>> +   log_debug("%s: %sfragmentation", __func__, env->sc_frag ? "" : "no ");
>>> +   return (0);
>>>   }
>>>     int
>>> Index: iked.c
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/iked.c,v
>>> retrieving revision 1.36
>>> diff -u -p -r1.36 iked.c
>>> --- iked.c  27 Nov 2017 18:39:35 -0000      1.36
>>> +++ iked.c  30 Mar 2019 17:41:33 -0000
>>> @@ -251,6 +251,7 @@ parent_configure(struct iked *env)
>>>             fatal("pledge");
>>>             config_setmobike(env);
>>> +   config_setfragmentation(env);
>>>     config_setcoupled(env, env->sc_decoupled ? 0 : 1);
>>>     config_setmode(env, env->sc_passive ? 1 : 0);
>>>     config_setocsp(env);
>>> @@ -282,6 +283,7 @@ parent_reload(struct iked *env, int rese
>>>             config_setcompile(env, PROC_IKEV2);
>>>                     config_setmobike(env);
>>> +           config_setfragmentation(env);
>>>             config_setcoupled(env, env->sc_decoupled ? 0 : 1);
>>>             config_setmode(env, env->sc_passive ? 1 : 0);
>>>             config_setocsp(env);
>>> Index: iked.conf.5
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/iked.conf.5,v
>>> retrieving revision 1.53
>>> diff -u -p -r1.53 iked.conf.5
>>> --- iked.conf.5     31 Jan 2018 13:25:55 -0000      1.53
>>> +++ iked.conf.5     30 Mar 2019 17:41:33 -0000
>>> @@ -136,6 +136,12 @@ This is the default.
>>>   .It Ic set decouple
>>>   Don't load the negotiated SAs and flows from the kernel.
>>>   This mode is only useful for testing and debugging.
>>> +.It Ic set fragmentation
>>> +Enable IKEv2 Message Fragmentation (RFC 7383) support.
>>> +This allows IKEv2 to operate in environments that might block IP fragments.
>>> +.It Ic set nofragmentation
>>> +Disables IKEv2 Message Fragmentation support.
>>> +This is the default.
>>>   .It Ic set mobike
>>>   Enable MOBIKE (RFC 4555) support.
>>>   This is the default.
>>> Index: iked.h
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/iked.h,v
>>> retrieving revision 1.119
>>> diff -u -p -r1.119 iked.h
>>> --- iked.h  6 Aug 2018 06:30:06 -0000       1.119
>>> +++ iked.h  30 Mar 2019 17:41:33 -0000
>>> @@ -362,6 +362,21 @@ struct iked_kex {
>>>     struct ibuf                     *kex_dhpeer;    /* pointer to i or r */
>>>   };
>>>   +struct iked_frag_entry {
>>> +   uint8_t *frag_data;
>>> +   size_t   frag_size;
>>> +};
>>> +
>>> +struct iked_frag {
>>> +   struct iked_frag_entry          **frag_arr;     /* list of fragment 
>>> buffers */
>>> +   size_t                            frag_count;   /* number of fragments 
>>> received */
>>> +#define IKED_FRAG_TOTAL_MAX        111     /* upper limit of frag_total 
>>> (64kB / 576B) */
>>> +   size_t                            frag_total;   /* total numbe of 
>>> fragments */
>>> +   size_t                            frag_total_size;
>>> +   uint8_t                           frag_nextpayload;
>>> +
>>> +};
>>> +
>>>   struct iked_sa {
>>>     struct iked_sahdr                sa_hdr;
>>>     uint32_t                         sa_msgid;      /* Last request rcvd */
>>> @@ -377,6 +392,8 @@ struct iked_sa {
>>>     struct iked_addr                 sa_local;
>>>     int                              sa_fd;
>>>   + struct iked_frag                 sa_fragments;
>>> +
>>>     int                              sa_natt;       /* for IKE messages */
>>>     int                              sa_udpencap;   /* for pfkey */
>>>     int                              sa_usekeepalive;/* NAT-T keepalive */
>>> @@ -445,6 +462,7 @@ struct iked_sa {
>>>     uint16_t                         sa_cpi_in;     /* IPcomp incoming*/
>>>             int                              sa_mobike;     /* MOBIKE */
>>> +   int                              sa_frag;       /* fragmentation */
>>>             struct iked_timer                sa_timer;      /* SA timeouts
>>> */
>>>   #define IKED_IKE_SA_EXCHANGE_TIMEOUT       300            /* 5 minutes */
>>> @@ -602,6 +620,7 @@ struct iked {
>>>     uint8_t                          sc_decoupled;
>>>             uint8_t                          sc_mobike;     /* MOBIKE */
>>> +   uint8_t                          sc_frag;       /* fragmentation */
>>>             struct iked_policies             sc_policies;
>>>     struct iked_policy              *sc_defaultcon;
>>> @@ -653,6 +672,7 @@ int      control_listen(struct control_sock
>>>   struct iked_policy *
>>>      config_new_policy(struct iked *);
>>>   void       config_free_kex(struct iked_kex *);
>>> +void        config_free_fragments(struct iked_frag *frag);
>>>   void       config_free_sa(struct iked *, struct iked_sa *);
>>>   struct iked_sa *
>>>      config_new_sa(struct iked *, int);
>>> @@ -701,6 +721,8 @@ int      config_setkeys(struct iked *);
>>>   int        config_getkey(struct iked *, struct imsg *);
>>>   int        config_setmobike(struct iked *);
>>>   int        config_getmobike(struct iked *, struct imsg *);
>>> +int         config_setfragmentation(struct iked *);
>>> +int         config_getfragmentation(struct iked *, struct imsg *);
>>>     /* policy.c */
>>>   void       policy_init(struct iked *);
>>> @@ -859,6 +881,12 @@ void    ikev2_msg_flushqueue(struct iked *
>>>   struct iked_message *
>>>      ikev2_msg_lookup(struct iked *, struct iked_msgqueue *,
>>>         struct iked_message *, struct ike_header *);
>>> +void        ikev2_msg_lookup_dispose_all(struct iked *env,
>>> +       struct iked_msgqueue *queue, struct iked_message *msg,
>>> +       struct ike_header *hdr);
>>> +int         ikev2_msg_lookup_retransmit_all(struct iked *env,
>>> +       struct iked_msgqueue *queue, struct iked_message *msg,
>>> +       struct ike_header *hdr, struct iked_sa *sa);
>>>     /* ikev2_pld.c */
>>>   int        ikev2_pld_parse(struct iked *, struct ike_header *,
>>> Index: ikev2.c
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/ikev2.c,v
>>> retrieving revision 1.168
>>> diff -u -p -r1.168 ikev2.c
>>> --- ikev2.c 27 Feb 2019 06:33:56 -0000      1.168
>>> +++ ikev2.c 30 Mar 2019 17:41:33 -0000
>>> @@ -144,6 +144,8 @@ ssize_t ikev2_add_sighashnotify(struct i
>>>         ssize_t);
>>>   ssize_t ikev2_add_nat_detection(struct iked *, struct ibuf *,
>>>         struct ikev2_payload **, struct iked_message *, ssize_t);
>>> +ssize_t ikev2_add_fragmentation(struct iked *, struct ibuf *,
>>> +       struct ikev2_payload **, struct iked_message *, ssize_t);
>>>     ssize_t  ikev2_add_mobike(struct iked *, struct ibuf *,
>>>         struct ikev2_payload **, ssize_t, struct iked_sa *);
>>> @@ -202,6 +204,8 @@ ikev2_dispatch_parent(int fd, struct pri
>>>             return (0);
>>>     case IMSG_CTL_MOBIKE:
>>>             return (config_getmobike(env, imsg));
>>> +   case IMSG_CTL_FRAGMENTATION:
>>> +           return (config_getfragmentation(env, imsg));
>>>     case IMSG_UDP_SOCKET:
>>>             return (config_getsocket(env, imsg, ikev2_msg_cb));
>>>     case IMSG_PFKEY_SOCKET:
>>> @@ -399,9 +403,9 @@ void
>>>   ikev2_recv(struct iked *env, struct iked_message *msg)
>>>   {
>>>     struct ike_header       *hdr;
>>> -   struct iked_message     *m;
>>>     struct iked_sa          *sa;
>>>     unsigned int             initiator, flag = 0;
>>> +   int                      r;
>>>             hdr = ibuf_seek(msg->msg_data, msg->msg_offset, sizeof(*hdr));
>>>   @@ -442,7 +446,8 @@ ikev2_recv(struct iked *env, struct iked
>>>             if (msg->msg_msgid > sa->sa_reqid)
>>>                     return;
>>>             if (hdr->ike_exchange != IKEV2_EXCHANGE_INFORMATIONAL &&
>>> -               !ikev2_msg_lookup(env, &sa->sa_requests, msg, hdr))
>>> +               !ikev2_msg_lookup(env, &sa->sa_requests, msg, hdr) &&
>>> +               sa->sa_fragments.frag_count == 0)
>>>                     return;
>>>             if (flag) {
>>>                     if ((sa->sa_stateflags & flag) == 0)
>>> @@ -454,10 +459,9 @@ ikev2_recv(struct iked *env, struct iked
>>>                     initiator = 1;
>>>             }
>>>             /*
>>> -            * There's no need to keep the request around anymore
>>> +            * There's no need to keep the request (fragments) around 
>>> anymore
>>>              */
>>> -           if ((m = ikev2_msg_lookup(env, &sa->sa_requests, msg, hdr)))
>>> -                   ikev2_msg_dispose(env, &sa->sa_requests, m);
>>> +           ikev2_msg_lookup_dispose_all(env, &sa->sa_requests, msg, hdr);
>>>     } else {
>>>             /*
>>>              * IKE_SA_INIT is special since it always uses the message id 0.
>>> @@ -483,14 +487,16 @@ ikev2_recv(struct iked *env, struct iked
>>>             /*
>>>              * See if we have responded to this request before
>>>              */
>>> -           if ((m = ikev2_msg_lookup(env, &sa->sa_responses, msg, hdr))) {
>>> -                   if (ikev2_msg_retransmit_response(env, sa, m)) {
>>> +           if ((r = ikev2_msg_lookup_retransmit_all(env, &sa->sa_responses,
>>> +               msg, hdr, sa)) != 0) {
>>> +                   if (r == -1) {
>>>                             log_warn("%s: failed to retransmit a "
>>>                                 "response", __func__);
>>>                             sa_free(env, sa);
>>>                     }
>>>                     return;
>>> -           } else if (sa->sa_msgid_set && msg->msg_msgid == sa->sa_msgid) {
>>> +           } else if (sa->sa_msgid_set && msg->msg_msgid == sa->sa_msgid &&
>>> +                     !(sa->sa_fragments.frag_count)) {
>>>                     /*
>>>                      * Response is being worked on, most likely we're
>>>                      * waiting for the CA process to get back to us
>>> @@ -803,6 +809,9 @@ ikev2_init_recv(struct iked *env, struct
>>>             return;
>>>     }
>>>   + if (sa->sa_fragments.frag_count != 0)
>>> +           return;
>>> +
>>>     if (!ikev2_msg_frompeer(msg))
>>>             return;
>>>   @@ -1022,6 +1031,13 @@ ikev2_init_ike_sa_peer(struct iked *env,
>>>             goto done;
>>>     len = ibuf_size(sa->sa_inonce);
>>>   + /* Fragmentation Notify */
>>> +   if (env->sc_frag) {
>>> +           if ((len = ikev2_add_fragmentation(env, buf, &pld, &req, len))
>>> +               == -1)
>>> +                   goto done;
>>> +   }
>>> +
>>>     if ((env->sc_opts & IKED_OPT_NONATT) == 0) {
>>>             if (ntohs(port) == IKED_NATT_PORT) {
>>>                     /* Enforce NAT-T on the initiator side */
>>> @@ -1973,6 +1989,29 @@ ikev2_add_cp(struct iked *env, struct ik
>>>   }
>>>     ssize_t
>>> +ikev2_add_fragmentation(struct iked *env, struct ibuf *buf,
>>> +    struct ikev2_payload **pld, struct iked_message *msg, ssize_t len)
>>> +{
>>> +   struct ikev2_notify             *n;
>>> +   uint8_t                         *ptr;
>>> +
>>> +   if (*pld != NULL)
>>> +           if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY) == -1)
>>> +                   return (-1);
>>> +   if ((*pld = ikev2_add_payload(buf)) == NULL)
>>> +           return (-1);
>>> +   len = sizeof(*n);
>>> +   if ((ptr = ibuf_advance(buf, len)) == NULL)
>>> +           return (-1);
>>> +   n = (struct ikev2_notify *) ptr;
>>> +   n->n_protoid = 0;
>>> +   n->n_spisize = 0;
>>> +   n->n_type = htobe16(IKEV2_N_FRAGMENTATION_SUPPORTED);
>>> +
>>> +   return (len);
>>> +}
>>> +
>>> +ssize_t
>>>   ikev2_add_proposals(struct iked *env, struct iked_sa *sa, struct ibuf 
>>> *buf,
>>>       struct iked_proposals *proposals, uint8_t protoid, int initiator,
>>>       int sendikespi, int skipdh)
>>> @@ -2283,6 +2322,9 @@ ikev2_resp_recv(struct iked *env, struct
>>>     if ((sa = msg->msg_sa) == NULL)
>>>             return;
>>>   + if (sa->sa_fragments.frag_count !=0)
>>> +           return;
>>> +
>>>     if (msg->msg_natt && sa->sa_natt == 0) {
>>>             log_debug("%s: NAT-T message received, updated SA", __func__);
>>>             sa->sa_natt = 1;
>>> @@ -2407,6 +2449,13 @@ ikev2_resp_ike_sa_init(struct iked *env,
>>>             goto done;
>>>     len = ibuf_size(sa->sa_rnonce);
>>>   + /* Fragmentation Notify*/
>>> +   if (sa->sa_frag) {
>>> +           if ((len = ikev2_add_fragmentation(env, buf, &pld, &resp, len))
>>> +               == -1)
>>> +                   goto done;
>>> +   }
>>> +
>>>     if ((env->sc_opts & IKED_OPT_NONATT) == 0 &&
>>>         msg->msg_local.ss_family != AF_UNSPEC) {
>>>             if ((len = ikev2_add_nat_detection(env, buf, &pld, &resp, len))
>>> @@ -2485,6 +2534,7 @@ ikev2_send_auth_failed(struct iked *env,
>>>     timer_del(env, &sa->sa_timer);
>>>     timer_set(env, &sa->sa_timer, ikev2_ike_sa_timeout, sa);
>>>     timer_add(env, &sa->sa_timer, IKED_IKE_SA_DELETE_TIMEOUT);
>>> +   config_free_fragments(&sa->sa_fragments);
>>>             return (ret);
>>>   }
>>> Index: ikev2.h
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/ikev2.h,v
>>> retrieving revision 1.28
>>> diff -u -p -r1.28 ikev2.h
>>> --- ikev2.h 27 Feb 2019 06:33:57 -0000      1.28
>>> +++ ikev2.h 30 Mar 2019 17:41:33 -0000
>>> @@ -78,6 +78,11 @@ struct ikev2_payload {
>>>     uint16_t         pld_length;            /* Payload length with header */
>>>   } __packed;
>>>   +struct ikev2_frag_payload {
>>> +   uint16_t         frag_num;              /* current fragment message 
>>> number */
>>> +   uint16_t         frag_total;            /* total number of fragment 
>>> messages */
>>> +} __packed;
>>> +
>>>   #define IKEV2_CRITICAL_PAYLOAD    0x01    /* First bit in the reserved 
>>> field */
>>>     /* IKEv2 payload types */
>>> @@ -99,6 +104,7 @@ struct ikev2_payload {
>>>   #define IKEV2_PAYLOAD_CP  47      /* Configuration Payload */
>>>   #define IKEV2_PAYLOAD_EAP 48      /* Extensible Authentication */
>>>   #define IKEV2_PAYLOAD_GSPM        49      /* RFC6467 Generic Secure 
>>> Password */
>>> +#define IKEV2_PAYLOAD_SKF  53      /* RFC7383 Encrypted Fragment Payload */
>>>     extern struct iked_constmap ikev2_payload_map[];
>>>   @@ -243,6 +249,11 @@ extern struct iked_constmap ikev2_xforma
>>>   #define IKEV2_XFORMDH_X_CURVE25519        1034    /* 
>>> draft-ietf-ipsecme-safecurves-00 */
>>>     extern struct iked_constmap ikev2_xformdh_map[];
>>> +
>>> +#define IKEV2_IPV4_OVERHEAD                (20 + 8 + 28) /* IPv4 + UDP + 
>>> IKE_HDR*/
>>> +#define IKEV2_MAXLEN_IPV4_FRAG             (576 - IKEV2_IPV4_OVERHEAD)
>>> +#define IKEV2_IPV6_OVERHEAD                (40 + 8 + 28) /* IPv6 + UDP + 
>>> IKE_HDR*/
>>> +#define IKEV2_MAXLEN_IPV6_FRAG             (1280 - IKEV2_IPV6_OVERHEAD)
>>>     #define IKEV2_XFORMESN_NONE             0       /* No ESN */
>>>   #define IKEV2_XFORMESN_ESN                1       /* ESN */
>>> Index: ikev2_msg.c
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/ikev2_msg.c,v
>>> retrieving revision 1.53
>>> diff -u -p -r1.53 ikev2_msg.c
>>> --- ikev2_msg.c     27 Nov 2017 18:39:35 -0000      1.53
>>> +++ ikev2_msg.c     30 Mar 2019 17:41:33 -0000
>>> @@ -46,6 +46,9 @@
>>>   void       ikev1_recv(struct iked *, struct iked_message *);
>>>   void       ikev2_msg_response_timeout(struct iked *, void *);
>>>   void       ikev2_msg_retransmit_timeout(struct iked *, void *);
>>> +int         ikev2_check_frag_oversize(struct iked_sa *sa, struct ibuf 
>>> *buf);
>>> +int         ikev2_send_encrypted_fragments(struct iked *env, struct 
>>> iked_sa *sa,
>>> +       struct ibuf *in,uint8_t exchange, uint8_t firstpayload, int 
>>> response);
>>>     void
>>>   ikev2_msg_cb(int fd, short event, void *arg)
>>> @@ -616,7 +619,8 @@ ikev2_msg_decrypt(struct iked *env, stru
>>>         __func__, outlen, encrlen, pad);
>>>     print_hex(ibuf_data(out), 0, ibuf_size(out));
>>>   - if (ibuf_setsize(out, outlen) != 0)
>>> +   /* Strip padding and padding length */
>>> +   if (ibuf_setsize(out, outlen - pad - 1) != 0)
>>>             goto done;
>>>             ibuf_release(src);
>>> @@ -629,6 +633,25 @@ ikev2_msg_decrypt(struct iked *env, stru
>>>   }
>>>     int
>>> +ikev2_check_frag_oversize(struct iked_sa *sa, struct ibuf *buf) {
>>> +   size_t          len = ibuf_length(buf);
>>> +   sa_family_t     sa_fam;
>>> +   size_t          max;
>>> +   size_t          ivlen, integrlen, blocklen;
>>> +
>>> +   sa_fam = ((struct sockaddr *)&sa->sa_local.addr)->sa_family;
>>> +
>>> +   max = sa_fam == AF_INET ? IKEV2_MAXLEN_IPV4_FRAG
>>> +                           : IKEV2_MAXLEN_IPV6_FRAG;
>>> +
>>> +   blocklen = cipher_length(sa->sa_encr);
>>> +   ivlen = cipher_ivlength(sa->sa_encr);
>>> +   integrlen = hash_length(sa->sa_integr);
>>> +
>>> +   return ((len + ivlen + blocklen + integrlen) >= max) && sa->sa_frag;
>>> +}
>>> +
>>> +int
>>>   ikev2_msg_send_encrypt(struct iked *env, struct iked_sa *sa, struct ibuf 
>>> **ep,
>>>       uint8_t exchange, uint8_t firstpayload, int response)
>>>   {
>>> @@ -638,6 +661,12 @@ ikev2_msg_send_encrypt(struct iked *env,
>>>     struct ibuf                     *buf, *e = *ep;
>>>     int                              ret = -1;
>>>   + /* Check if msg needs to be fragmented */
>>> +   if (ikev2_check_frag_oversize(sa, e)) {
>>> +           return ikev2_send_encrypted_fragments(env, sa, e, exchange,
>>> +               firstpayload, response);
>>> +   }
>>> +
>>>     if ((buf = ikev2_msg_init(env, &resp, &sa->sa_peer.addr,
>>>         sa->sa_peer.addr.ss_len, &sa->sa_local.addr,
>>>         sa->sa_local.addr.ss_len, response)) == NULL)
>>> @@ -689,6 +718,123 @@ ikev2_msg_send_encrypt(struct iked *env,
>>>     return (ret);
>>>   }
>>>   +int
>>> +ikev2_send_encrypted_fragments(struct iked *env, struct iked_sa *sa,
>>> +    struct ibuf *in, uint8_t exchange, uint8_t firstpayload, int response) 
>>> {
>>> +   struct iked_message              resp;
>>> +   struct ibuf                     *buf, *e;
>>> +   struct ike_header               *hdr;
>>> +   struct ikev2_payload            *pld;
>>> +   struct ikev2_frag_payload       *frag;
>>> +   sa_family_t                      sa_fam;
>>> +   size_t                           ivlen, integrlen, blocklen;
>>> +   size_t                           max_len, left,  offset=0;;
>>> +   size_t                           frag_num = 1, frag_total;
>>> +   uint8_t                         *data;
>>> +   uint32_t                         msgid;
>>> +   int                              ret = -1;
>>> +
>>> +   sa_fam = ((struct sockaddr *)&sa->sa_local.addr)->sa_family;
>>> +
>>> +   left = ibuf_length(in);
>>> +
>>> +   /* Calculate max allowed size of a fragments payload */
>>> +   blocklen = cipher_length(sa->sa_encr);
>>> +   ivlen = cipher_ivlength(sa->sa_encr);
>>> +   integrlen = hash_length(sa->sa_integr);
>>> +   max_len = (sa_fam == AF_INET ? IKEV2_MAXLEN_IPV4_FRAG
>>> +                                : IKEV2_MAXLEN_IPV6_FRAG)
>>> +                  - ivlen - blocklen - integrlen;
>>> +
>>> +   /* Total number of fragments to send */
>>> +   frag_total = (left / max_len) + 1;
>>> +
>>> +   msgid = response ? sa->sa_msgid : ikev2_msg_id(env, sa);
>>> +
>>> +   while (frag_num <= frag_total) {
>>> +           if ((buf = ikev2_msg_init(env, &resp, &sa->sa_peer.addr,
>>> +               sa->sa_peer.addr.ss_len, &sa->sa_local.addr,
>>> +               sa->sa_local.addr.ss_len, response)) == NULL)
>>> +                   goto done;
>>> +
>>> +           resp.msg_msgid = msgid;
>>> +
>>> +           /* IKE header */
>>> +           if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid,
>>> +               IKEV2_PAYLOAD_SKF, exchange, response ? IKEV2_FLAG_RESPONSE
>>> +                                                     : 0)) == NULL)
>>> +                   goto done;
>>> +
>>> +           /* Payload header */
>>> +           if ((pld = ikev2_add_payload(buf)) == NULL)
>>> +                   goto done;
>>> +
>>> +           /* Fragment header */
>>> +           if ((frag = ibuf_advance(buf, sizeof(*frag))) == NULL) {
>>> +                   log_debug("%s: failed to add SKF fragment header",
>>> +                       __func__);
>>> +                   goto done;
>>> +           }
>>> +           frag->frag_num = htobe16(frag_num);
>>> +           frag->frag_total = htobe16(frag_total);
>>> +
>>> +           /* Encrypt message and add as an E payload */
>>> +           data = ibuf_seek(in, offset, 0);
>>> +           if((e=ibuf_new(data, MIN(left, max_len))) == NULL) {
>>> +                   goto done;
>>> +           }
>>> +           if ((e = ikev2_msg_encrypt(env, sa, e)) == NULL) {
>>> +                   log_debug("%s: encryption failed", __func__);
>>> +                   goto done;
>>> +           }
>>> +           if (ibuf_cat(buf, e) != 0)
>>> +                   goto done;
>>> +
>>> +           if (ikev2_next_payload(pld, ibuf_size(e) + sizeof(*frag),
>>> +               firstpayload) == -1)
>>> +                   goto done;
>>> +
>>> +           if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1)
>>> +                   goto done;
>>> +
>>> +           /* Add integrity checksum (HMAC) */
>>> +           if (ikev2_msg_integr(env, sa, buf) != 0) {
>>> +                   log_debug("%s: integrity checksum failed", __func__);
>>> +                   goto done;
>>> +           }
>>> +
>>> +           log_debug("%s: Fragment %zu of %zu has size of %zu bytes.",
>>> +               __func__, frag_num, frag_total,
>>> +               ibuf_size(buf) - sizeof(*hdr));
>>> +           print_hex(ibuf_data(buf), 0,  ibuf_size(buf));
>>> +
>>> +           resp.msg_data = buf;
>>> +           resp.msg_sa = sa;
>>> +           resp.msg_fd = sa->sa_fd;
>>> +           TAILQ_INIT(&resp.msg_proposals);
>>> +
>>> +           if (ikev2_msg_send(env, &resp) == -1)
>>> +                   goto done;
>>> +
>>> +           offset += MIN(left, max_len);
>>> +           left -= MIN(left, max_len);
>>> +           frag_num++;
>>> +
>>> +           /* MUST be zero after first fragment */
>>> +           firstpayload = 0;
>>> +
>>> +           ikev2_msg_cleanup(env, &resp);
>>> +           ibuf_release(e);
>>> +           e = NULL;
>>> +   }
>>> +
>>> +   return 0;
>>> +done:
>>> +   ikev2_msg_cleanup(env, &resp);
>>> +   ibuf_release(e);
>>> +   return ret;
>>> +}
>>> +
>>>   struct ibuf *
>>>   ikev2_msg_auth(struct iked *env, struct iked_sa *sa, int response)
>>>   {
>>> @@ -990,6 +1136,42 @@ ikev2_msg_lookup(struct iked *env, struc
>>>     }
>>>             return (m);
>>> +}
>>> +
>>> +void
>>> +ikev2_msg_lookup_dispose_all(struct iked *env, struct iked_msgqueue *queue,
>>> +    struct iked_message *msg, struct ike_header *hdr)
>>> +{
>>> +   struct iked_message     *m = NULL, *tmp = NULL;
>>> +
>>> +   TAILQ_FOREACH_SAFE(m, queue, msg_entry, tmp) {
>>> +           if (m->msg_msgid == msg->msg_msgid &&
>>> +               m->msg_exchange == hdr->ike_exchange) {
>>> +                   TAILQ_REMOVE(queue, m, msg_entry);
>>> +                   timer_del(env, &m->msg_timer);
>>> +                   ikev2_msg_cleanup(env, m);
>>> +                   free(m);
>>> +           }
>>> +   }
>>> +}
>>> +
>>> +int
>>> +ikev2_msg_lookup_retransmit_all(struct iked *env, struct iked_msgqueue 
>>> *queue,
>>> +    struct iked_message *msg, struct ike_header *hdr, struct iked_sa *sa)
>>> +{
>>> +   struct iked_message     *m = NULL, *tmp = NULL;
>>> +   int count = 0;
>>> +
>>> +   TAILQ_FOREACH_SAFE(m, queue, msg_entry, tmp) {
>>> +           if (m->msg_msgid == msg->msg_msgid &&
>>> +               m->msg_exchange == hdr->ike_exchange) {
>>> +                   if (ikev2_msg_retransmit_response(env, sa, msg)) {
>>> +                           return -1;
>>> +                   }
>>> +                   count++;
>>> +           }
>>> +   }
>>> +   return count;
>>>   }
>>>     int
>>> Index: ikev2_pld.c
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/ikev2_pld.c,v
>>> retrieving revision 1.70
>>> diff -u -p -r1.70 ikev2_pld.c
>>> --- ikev2_pld.c     22 Mar 2018 21:11:49 -0000      1.70
>>> +++ ikev2_pld.c     30 Mar 2019 17:41:33 -0000
>>> @@ -95,6 +95,10 @@ int       ikev2_pld_auth(struct iked *, struc
>>>         struct iked_message *, size_t, size_t);
>>>   int        ikev2_pld_e(struct iked *, struct ikev2_payload *,
>>>         struct iked_message *, size_t, size_t);
>>> +int         ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
>>> +       struct iked_message *msg, size_t offset, size_t left);
>>> +int         ikev2_frags_reassemble(struct iked *env,
>>> +       struct ikev2_payload *pld, struct iked_message *msg);
>>>   int        ikev2_validate_cp(struct iked_message *, size_t, size_t,
>>>         struct ikev2_cp *);
>>>   int        ikev2_pld_cp(struct iked *, struct ikev2_payload *,
>>> @@ -249,6 +253,9 @@ ikev2_pld_payloads(struct iked *env, str
>>>             case IKEV2_PAYLOAD_SK:
>>>                     ret = ikev2_pld_e(env, &pld, msg, offset, left);
>>>                     break;
>>> +           case IKEV2_PAYLOAD_SKF:
>>> +                   ret = ikev2_pld_ef(env, &pld, msg, offset, left);
>>> +                   break;
>>>             case IKEV2_PAYLOAD_CP | IKED_E:
>>>                     ret = ikev2_pld_cp(env, &pld, msg, offset, left);
>>>                     break;
>>> @@ -266,8 +273,8 @@ ikev2_pld_payloads(struct iked *env, str
>>>                     return (-1);
>>>             }
>>>   -         /* Encrypted payload must appear last */
>>> -           if (payload == IKEV2_PAYLOAD_SK)
>>> +           /* Encrypted payloads must appear last */
>>> +           if ((payload == IKEV2_PAYLOAD_SK) || (payload == 
>>> IKEV2_PAYLOAD_SKF))
>>>                     return (0);
>>>                     payload = pld.pld_nextpayload;
>>> @@ -1251,6 +1258,23 @@ ikev2_pld_notify(struct iked *env, struc
>>>             }
>>>             msg->msg_parent->msg_cookie = msg->msg_cookie;
>>>             break;
>>> +   case IKEV2_N_FRAGMENTATION_SUPPORTED:
>>> +           if (msg->msg_e) {
>>> +                   log_debug("%s: N_FRAGMENTATION_SUPPORTED encrypted",
>>> +                       __func__);
>>> +                   return (-1);
>>> +           }
>>> +           if (len != 0) {
>>> +                   log_debug("%s: ignoring malformed fragmentation"
>>> +                       " notification: %zu", __func__, len);
>>> +                   return (0);
>>> +           }
>>> +           if (!env->sc_frag) {
>>> +                   log_debug("%s: fragmentation disabled", __func__);
>>> +                   return (0);
>>> +           }
>>> +           msg->msg_sa->sa_frag = 1;
>>> +           break;
>>>     case IKEV2_N_SIGNATURE_HASH_ALGORITHMS:
>>>             if (msg->msg_e) {
>>>                     log_debug("%s: SIGNATURE_HASH_ALGORITHMS: encrypted",
>>> @@ -1585,6 +1609,164 @@ ikev2_pld_ts(struct iked *env, struct ik
>>>   }
>>>     int
>>> +ikev2_pld_ef(struct iked *env, struct ikev2_payload *pld,
>>> +    struct iked_message *msg, size_t offset, size_t left)
>>> +{
>>> +   struct iked_sa                  *sa = msg->msg_sa;
>>> +   struct iked_frag                *sa_frag = &sa->sa_fragments;
>>> +   struct iked_frag_entry          *el = NULL;
>>> +   struct ikev2_frag_payload        frag;
>>> +   uint8_t                         *msgbuf = ibuf_data(msg->msg_data);
>>> +   uint8_t                         *buf;
>>> +   struct ibuf                     *e = NULL;
>>> +   size_t                           frag_num, frag_total;
>>> +   size_t                           len;
>>> +   int                              ret = -1;
>>> +   ssize_t                          elen;
>>> +
>>> +   buf = msgbuf + offset;
>>> +   memcpy(&frag, buf, sizeof(frag));
>>> +   frag_num = betoh16(frag.frag_num);
>>> +   frag_total = betoh16(frag.frag_total);
>>> +
>>> +   offset += sizeof(frag);
>>> +   buf = msgbuf + offset;
>>> +   len = left - sizeof(frag);
>>> +
>>> +   /* Limit number of total fragments to avoid DOS */
>>> +   if (frag_total > IKED_FRAG_TOTAL_MAX ) {
>>> +           log_debug("%s: Total Fragments too big  %zu",
>>> +               __func__, frag_total);
>>> +           goto dropall;
>>> +   }
>>> +
>>> +   /* Check sanity of fragment header */
>>> +   if (frag_num == 0 || frag_total == 0) {
>>> +           log_debug("%s: Malformed fragment received: %zu of %zu",
>>> +               __func__, frag_num, frag_total);
>>> +           goto done;
>>> +   }
>>> +   log_debug("%s: Received fragment: %zu of %zu",
>>> +        __func__, frag_num, frag_total);
>>> +
>>> +   /* Check new fragmented message */
>>> +   if (sa_frag->frag_arr == NULL) {
>>> +           sa_frag->frag_arr = reallocarray(NULL, frag_total, 
>>> sizeof(uint8_t*));
>>> +           bzero(sa_frag->frag_arr, frag_total * sizeof(uint8_t*));
>>> +           sa_frag->frag_total = frag_total;
>>> +           sa_frag->frag_nextpayload = pld->pld_nextpayload;
>>> +   }
>>> +
>>> +   /* Drop all fragments if frag_num or frag_total don't match */
>>> +   if (frag_num > sa_frag->frag_total || frag_total > sa_frag->frag_total)
>>> +           goto dropall;
>>> +
>>> +   /* Silent drop if fragment already stored */
>>> +   if (sa_frag->frag_arr[frag_num-1] != NULL)
>>> +           goto done;
>>> +
>>> +        /* Decrypt fragment */
>>> +   if ((e = ibuf_new(buf, len)) == NULL)
>>> +           goto done;
>>> +
>>> +   if ((e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e))
>>> +       == NULL ) {
>>> +           log_debug("%s: Failed to decrypt fragment: %zu of %zu",
>>> +               __func__, frag_num, frag_total);
>>> +           goto done;
>>> +   }
>>> +   elen = ibuf_length(e);
>>> +
>>> +   /* Insert new list element */
>>> +   el = malloc(sizeof(struct iked_frag_entry));
>>> +   if (el == NULL) {
>>> +           log_debug("%s: Failed allocating new fragment: %zu of %zu",
>>> +               __func__, frag_num, frag_total);
>>> +           goto done;
>>> +   }
>>> +   bzero(el, sizeof(*el));
>>> +
>>> +   sa_frag->frag_arr[frag_num-1] = el;
>>> +   el->frag_size = elen;
>>> +   el->frag_data = malloc(elen);
>>> +   if (el->frag_data == NULL) {
>>> +           log_debug("%s: Failed allocating new fragment data: %zu of %zu",
>>> +               __func__, frag_num, frag_total);
>>> +           goto done;
>>> +   }
>>> +   bzero(el->frag_data, sizeof(elen));
>>> +
>>> +   /* Copy plaintext to fragment */
>>> +   memcpy(el->frag_data, ibuf_seek(e, 0, 0), elen);
>>> +   sa_frag->frag_total_size += elen;
>>> +   sa_frag->frag_count++;
>>> +
>>> +   /* If all frags are received start reassembly */
>>> +   if (sa_frag->frag_count == sa_frag->frag_total) {
>>> +           log_debug("%s: All fragments received: %zu of %zu",
>>> +               __func__, frag_num, frag_total);
>>> +           ret = ikev2_frags_reassemble(env, pld, msg);
>>> +   } else {
>>> +           ret = 0;
>>> +   }
>>> +done:
>>> +   ibuf_release(e);
>>> +   return (ret);
>>> +dropall:
>>> +   config_free_fragments(sa_frag);
>>> +   ibuf_release(e);
>>> +   return -1;
>>> +}
>>> +
>>> +int
>>> +ikev2_frags_reassemble(struct iked *env, struct ikev2_payload *pld,
>>> +    struct iked_message *msg)
>>> +{
>>> +   struct iked_frag                *sa_frag = &msg->msg_sa->sa_fragments;
>>> +   struct ibuf                     *e = NULL;
>>> +   struct iked_frag_entry          *el;
>>> +   size_t                           offset = 0;
>>> +   size_t                           i;
>>> +   struct iked_message              emsg;
>>> +   int                              ret = -1;
>>> +
>>> +   /* Reassemble fragments to single buffer */
>>> +   if ((e = ibuf_new(NULL, sa_frag->frag_total_size)) == NULL) {
>>> +           log_debug("%s: Failed allocating SK buffer.", __func__);
>>> +           goto done;
>>> +   }
>>> +
>>> +   /* Empty queue to new buffer */
>>> +   for (i = 0; i < sa_frag->frag_total; i++) {
>>> +           el = sa_frag->frag_arr[i];
>>> +           memcpy(ibuf_seek(e, offset, 0), el->frag_data, el->frag_size);
>>> +           offset += el->frag_size;
>>> +   }
>>> +
>>> +   log_debug("%s: Defragmented length %zd", __func__,
>>> +       sa_frag->frag_total_size);
>>> +   print_hex(ibuf_data(e), 0,  sa_frag->frag_total_size);
>>> +
>>> +   /*
>>> +    * Parse decrypted payload
>>> +    */
>>> +   bzero(&emsg, sizeof(emsg));
>>> +   memcpy(&emsg, msg, sizeof(*msg));
>>> +   emsg.msg_data = e;
>>> +   emsg.msg_e = 1;
>>> +   emsg.msg_parent = msg;
>>> +   TAILQ_INIT(&emsg.msg_proposals);
>>> +
>>> +   ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
>>> +       sa_frag->frag_nextpayload);
>>> +done:
>>> +   config_free_fragments(sa_frag);
>>> +   ibuf_release(e);
>>> +
>>> +   return (ret);
>>> +}
>>> +
>>> +int
>>>   ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
>>>       struct iked_message *msg, size_t offset, size_t left)
>>>   {
>>> @@ -1595,6 +1777,13 @@ ikev2_pld_e(struct iked *env, struct ike
>>>     uint8_t                 *buf;
>>>     size_t                   len;
>>>     int                      ret = -1;
>>> +
>>> +   if (sa->sa_fragments.frag_arr != NULL) {
>>> +           log_warn("%s: Received SK payload when SKFs are in queue.",
>>> +               __func__);
>>> +           config_free_fragments(&sa->sa_fragments);
>>> +           return (ret);
>>> +   }
>>>             buf = msgbuf + offset;
>>>     len = left;
>>> Index: parse.y
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/parse.y,v
>>> retrieving revision 1.78
>>> diff -u -p -r1.78 parse.y
>>> --- parse.y 13 Feb 2019 22:57:07 -0000      1.78
>>> +++ parse.y 30 Mar 2019 17:41:33 -0000
>>> @@ -105,6 +105,7 @@ static int               rules = 0;
>>>   static int                 passive = 0;
>>>   static int                 decouple = 0;
>>>   static int                 mobike = 1;
>>> +static int          fragmentation = 0;
>>>   static char               *ocsp_url = NULL;
>>>     struct ipsec_xf {
>>> @@ -395,6 +396,7 @@ typedef struct {
>>>   %token    IKEV1 FLOW SA TCPMD5 TUNNEL TRANSPORT COUPLE DECOUPLE SET
>>>   %token    INCLUDE LIFETIME BYTES INET INET6 QUICK SKIP DEFAULT
>>>   %token    IPCOMP OCSP IKELIFETIME MOBIKE NOMOBIKE
>>> +%token     FRAGMENTATION NOFRAGMENTATION
>>>   %token    <v.string>              STRING
>>>   %token    <v.number>              NUMBER
>>>   %type     <v.string>              string
>>> @@ -455,6 +457,8 @@ set             : SET ACTIVE    { passive = 0; }
>>>             | SET PASSIVE   { passive = 1; }
>>>             | SET COUPLE    { decouple = 0; }
>>>             | SET DECOUPLE  { decouple = 1; }
>>> +           | SET FRAGMENTATION     { fragmentation = 1; }
>>> +           | SET NOFRAGMENTATION   { fragmentation = 0; }
>>>             | SET MOBIKE    { mobike = 1; }
>>>             | SET NOMOBIKE  { mobike = 0; }
>>>             | SET OCSP STRING               {
>>> @@ -1167,6 +1171,7 @@ lookup(char *s)
>>>             { "esp",                ESP },
>>>             { "file",               FILENAME },
>>>             { "flow",               FLOW },
>>> +           { "fragmentation",      FRAGMENTATION },
>>>             { "from",               FROM },
>>>             { "group",              GROUP },
>>>             { "ike",                IKEV1 },
>>> @@ -1181,6 +1186,7 @@ lookup(char *s)
>>>             { "local",              LOCAL },
>>>             { "mobike",             MOBIKE },
>>>             { "name",               NAME },
>>> +           { "nofragmentation",    NOFRAGMENTATION },
>>>             { "nomobike",           NOMOBIKE },
>>>             { "ocsp",               OCSP },
>>>             { "passive",            PASSIVE },
>>> @@ -1579,6 +1585,7 @@ parse_config(const char *filename, struc
>>>     free(ocsp_url);
>>>             mobike = 1;
>>> +   fragmentation = 0;
>>>     decouple = passive = 0;
>>>     ocsp_url = NULL;
>>>   @@ -1592,6 +1599,7 @@ parse_config(const char *filename, struc
>>>     env->sc_passive = passive ? 1 : 0;
>>>     env->sc_decoupled = decouple ? 1 : 0;
>>>     env->sc_mobike = mobike;
>>> +   env->sc_frag = fragmentation;
>>>     env->sc_ocsp_url = ocsp_url;
>>>             if (!rules)
>>> Index: types.h
>>> ===================================================================
>>> RCS file: /cvs/src/sbin/iked/types.h,v
>>> retrieving revision 1.29
>>> diff -u -p -r1.29 types.h
>>> --- types.h 27 Nov 2017 18:39:35 -0000      1.29
>>> +++ types.h 30 Mar 2019 17:41:33 -0000
>>> @@ -103,6 +103,7 @@ enum imsg_type {
>>>     IMSG_CTL_ACTIVE,
>>>     IMSG_CTL_PASSIVE,
>>>     IMSG_CTL_MOBIKE,
>>> +   IMSG_CTL_FRAGMENTATION,
>>>     IMSG_COMPILE,
>>>     IMSG_UDP_SOCKET,
>>>     IMSG_PFKEY_SOCKET,
>>>
>>

Reply via email to