Here's the update.

What changed:
- fixed cleanup of fragments in SA
- fixed retransmission of fragmented messages
- adjusted copyright headers
- Added some comments

I also included Stuart's manpage parts as well as some line breaks.
We've been testing this version and haven't found anything off so far,
looking forward to your results.

Regards,
Tobias


Index: regress/sbin/iked/parser/common.c
===================================================================
RCS file: /mount/openbsd/cvs/src/regress/sbin/iked/parser/common.c,v
retrieving revision 1.1
diff -u -p -u -r1.1 common.c
--- regress/sbin/iked/parser/common.c   29 May 2017 20:59:28 -0000      1.1
+++ regress/sbin/iked/parser/common.c   1 Apr 2019 12:46:40 -0000
@@ -166,6 +166,11 @@ config_add_proposal(struct iked_proposal
        return (NULL);
 }
 
+void config_free_fragments(struct iked_frag *frag)
+{
+       return;
+}
+
 int
 ikev2_send_informational(struct iked *env, struct iked_message *msg)
 {
Index: regress/sbin/iked/parser/test_parser_fuzz.c
===================================================================
RCS file: /mount/openbsd/cvs/src/regress/sbin/iked/parser/test_parser_fuzz.c,v
retrieving revision 1.2
diff -u -p -u -r1.2 test_parser_fuzz.c
--- regress/sbin/iked/parser/test_parser_fuzz.c 22 Mar 2018 21:11:49 -0000      
1.2
+++ regress/sbin/iked/parser/test_parser_fuzz.c 1 Apr 2019 12:46:40 -0000
@@ -183,6 +183,50 @@ u_int8_t ts_pld[] = {
        0xac, 0x28, 0x7d, 0x00, 0xac, 0x28, 0x7d, 0xff
 };
 
+uint8_t skf_1of1_pld[] = {
+       0x21, 0x00, 0x01, 0x98, 0x00, 0x01, 0x00, 0x01, 0x14, 0x77,
+       0x25, 0x7b, 0x82, 0xc0, 0xdb, 0x0b, 0x24, 0x36, 0x36, 0x13,
+       0x36, 0xe4, 0x99, 0xad, 0xf5, 0xaf, 0x26, 0x6f, 0x47, 0xd2,
+       0x0d, 0x65, 0xe1, 0xa8, 0xcb, 0x35, 0x1e, 0x53, 0xce, 0x6d,
+       0x8e, 0xf9, 0xe4, 0x51, 0xe3, 0x27, 0x10, 0x43, 0x38, 0x84,
+       0x54, 0x1d, 0x7a, 0x1a, 0x89, 0x34, 0x06, 0xb3, 0x62, 0x86,
+       0x98, 0x3b, 0x39, 0x91, 0x6e, 0xe8, 0x65, 0x3e, 0x31, 0xa8,
+       0x08, 0xfe, 0x83, 0x56, 0x30, 0xd3, 0xe0, 0xfd, 0x73, 0x92,
+       0x85, 0x2d, 0xae, 0x1d, 0x7d, 0xdb, 0x47, 0x05, 0x57, 0xe7,
+       0x8e, 0xc5, 0xa5, 0x1b, 0x0e, 0x85, 0x1f, 0x12, 0x6d, 0xe6,
+       0xdb, 0x3a, 0x3e, 0x99, 0xd1, 0x23, 0x41, 0xa4, 0x1c, 0x46,
+       0x38, 0xd1, 0xa8, 0x84, 0x96, 0x13, 0xdb, 0x2a, 0x1d, 0x3b,
+       0xb8, 0xd2, 0x04, 0xb3, 0x0d, 0xb4, 0x71, 0x90, 0xdb, 0xf6,
+       0x2d, 0x60, 0x01, 0xc2, 0xb2, 0x89, 0xbd, 0xe9, 0x95, 0x7b,
+       0x53, 0xa4, 0x94, 0x7e, 0x12, 0xe9, 0x5f, 0xfc, 0x51, 0x17,
+       0x94, 0x3e, 0xba, 0xc2, 0xa5, 0x4d, 0x3a, 0x4d, 0x4b, 0x95,
+       0x6d, 0x91, 0xc2, 0xb0, 0x2d, 0xb7, 0x24, 0xe8, 0x3b, 0xbd,
+       0xe0, 0xcc, 0x09, 0x50, 0x11, 0x83, 0xc0, 0xcd, 0x29, 0x33,
+       0xd5, 0x8f, 0x8a, 0xd1, 0xe3, 0xe8, 0x4f, 0x6a, 0x10, 0x4a,
+       0x64, 0x97, 0x0f, 0x38, 0x58, 0x8d, 0x7f, 0x5d, 0xb4, 0x6b,
+       0xa0, 0x42, 0x5e, 0x95, 0xe6, 0x08, 0x3e, 0x01, 0xf8, 0x82,
+       0x90, 0x81, 0xd4, 0x70, 0xb5, 0xb2, 0x8c, 0x64, 0xa9, 0x56,
+       0xdd, 0xc2, 0xda, 0xe1, 0xd3, 0xad, 0xf8, 0x5b, 0x99, 0x0b,
+       0x19, 0x5e, 0x88, 0x0d, 0x81, 0x04, 0x4d, 0xc1, 0x43, 0x41,
+       0xf1, 0xd3, 0x45, 0x65, 0x62, 0x70, 0x2f, 0xfa, 0x62, 0xbe,
+       0x7d, 0xf4, 0x94, 0x91, 0xe0, 0xbb, 0xb1, 0xbc, 0xe5, 0x27,
+       0xc8, 0x15, 0xd4, 0xcb, 0x82, 0x97, 0x15, 0x46, 0x82, 0xbb,
+       0x48, 0xbb, 0x16, 0x25, 0xbe, 0x82, 0xe4, 0x27, 0x80, 0xf3,
+       0xc2, 0x92, 0x3b, 0xd6, 0xc3, 0x65, 0x20, 0xec, 0x50, 0xdb,
+       0x6a, 0xcb, 0x47, 0x73, 0xf7, 0x98, 0xf1, 0x66, 0x5e, 0xc4,
+       0xe9, 0x87, 0xf8, 0xcb, 0x1e, 0x06, 0xa7, 0x67, 0xf5, 0xec,
+       0x73, 0xe5, 0xc7, 0x4d, 0xc2, 0x90, 0xe4, 0xdf, 0x9d, 0x1f,
+       0x05, 0x67, 0x99, 0xd6, 0xf0, 0xc4, 0x20, 0xbc, 0xf8, 0xf5,
+       0x3e, 0x19, 0xe9, 0x3a, 0x12, 0xe1, 0xcc, 0x9f, 0x81, 0x55,
+       0x1e, 0xad, 0xc8, 0xa3, 0xe5, 0x98, 0xbe, 0xe0, 0x4d, 0xb7,
+       0x6b, 0xd5, 0xbe, 0x6a, 0x3d, 0x76, 0xb6, 0xe2, 0xa5, 0xa7,
+       0x96, 0x68, 0xeb, 0x91, 0xee, 0x02, 0xfc, 0xe4, 0x01, 0xc3,
+       0x24, 0xda, 0x4c, 0xff, 0x10, 0x27, 0x78, 0xb0, 0x0b, 0x55,
+       0x5c, 0xce, 0x62, 0x7d, 0x33, 0x2b, 0x25, 0x99, 0xaa, 0x99,
+       0xea, 0xa3, 0x1d, 0xd8, 0x2b, 0x57, 0xb5, 0xe4, 0x04, 0x21,
+       0x75, 0xd9, 0xc4, 0xd0, 0x3d, 0xa1, 0xa5, 0x8f
+};
+
 u_int8_t sk_pld[] = {
         0x21, 0x00, 0x01, 0x94, 0x14, 0x77, 0x25, 0x7b, 0x82, 0xc0,
         0xdb, 0x0b, 0x24, 0x36, 0x36, 0x13, 0x36, 0xe4, 0x99, 0xad,
@@ -441,6 +485,25 @@ parser_fuzz_tests(void)
        ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL);
        ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0);
        set_length(ibuf_data(data), ibuf_size(data));
+       print_hex(ibuf_data(data), 0, ibuf_size(data));
+       prepare_header(&hdr, data);
+       prepare_message(&msg, data);
+       ASSERT_INT_EQ(ikev2_pld_parse(NULL, &hdr, &msg, 0), 0);
+       fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP |
+           FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
+           FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END |
+           FUZZ_BASE64,
+           ibuf_data(data), ibuf_size(data));
+       ibuf_free(data);
+       perform_test(fuzz);
+       TEST_DONE();
+
+       TEST_START("fuzz skf_1of1 payload");
+       ASSERT_PTR_NE(data = ibuf_new(cookies, sizeof(cookies)), NULL);
+       ASSERT_INT_EQ(ibuf_add(data, genhdr, sizeof(genhdr)), 0);
+       ASSERT_INT_EQ(ibuf_add(data, skf_1of1_pld, sizeof(skf_1of1_pld)), 0);
+       set_length(ibuf_data(data), ibuf_size(data));
+       set_nextpayload(ibuf_data(data), IKEV2_PAYLOAD_SKF);
        print_hex(ibuf_data(data), 0, ibuf_size(data));
        prepare_header(&hdr, data);
        prepare_message(&msg, data);
Index: sbin/iked/config.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/config.c,v
retrieving revision 1.49
diff -u -p -u -r1.49 config.c
--- sbin/iked/config.c  27 Nov 2017 18:39:35 -0000      1.49
+++ sbin/iked/config.c  1 Apr 2019 14:58:00 -0000
@@ -1,6 +1,7 @@
 /*     $OpenBSD: config.c,v 1.49 2017/11/27 18:39:35 patrick Exp $     */
 
 /*
+ * Copyright (c) 2019 Tobias Heider <tobias.hei...@stusta.de>
  * Copyright (c) 2010-2013 Reyk Floeter <r...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -94,12 +95,29 @@ 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_total; i++) {
+                       if (frag->frag_arr[i] != NULL)
+                               free(frag->frag_arr[i]->frag_data);
+                       free(frag->frag_arr[i]);
+               }
+               free(frag->frag_arr);
+               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);
@@ -836,6 +854,30 @@ config_getmobike(struct iked *env, struc
        log_debug("%s: %smobike", __func__, env->sc_mobike ? "" : "no ");
        return (0);
 }
+
+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
 config_setocsp(struct iked *env)
Index: sbin/iked/iked.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/iked.c,v
retrieving revision 1.36
diff -u -p -u -r1.36 iked.c
--- sbin/iked/iked.c    27 Nov 2017 18:39:35 -0000      1.36
+++ sbin/iked/iked.c    1 Apr 2019 14:59:14 -0000
@@ -1,6 +1,7 @@
 /*     $OpenBSD: iked.c,v 1.36 2017/11/27 18:39:35 patrick Exp $       */
 
 /*
+ * Copyright (c) 2019 Tobias Heider <tobias.hei...@stusta.de>
  * Copyright (c) 2010-2013 Reyk Floeter <r...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -251,6 +252,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 +284,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: sbin/iked/iked.conf.5
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/iked.conf.5,v
retrieving revision 1.53
diff -u -p -u -r1.53 iked.conf.5
--- sbin/iked/iked.conf.5       31 Jan 2018 13:25:55 -0000      1.53
+++ sbin/iked/iked.conf.5       1 Apr 2019 15:03:43 -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: sbin/iked/iked.h
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/iked.h,v
retrieving revision 1.119
diff -u -p -u -r1.119 iked.h
--- sbin/iked/iked.h    6 Aug 2018 06:30:06 -0000       1.119
+++ sbin/iked/iked.h    1 Apr 2019 14:56:58 -0000
@@ -1,6 +1,7 @@
 /*     $OpenBSD: iked.h,v 1.119 2018/08/06 06:30:06 mestre Exp $       */
 
 /*
+ * Copyright (c) 2019 Tobias Heider <tobias.hei...@stusta.de>
  * Copyright (c) 2010-2013 Reyk Floeter <r...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -362,6 +363,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 +393,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 +463,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 +621,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 +673,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 +722,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 +882,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: sbin/iked/ikev2.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/ikev2.c,v
retrieving revision 1.168
diff -u -p -u -r1.168 ikev2.c
--- sbin/iked/ikev2.c   27 Feb 2019 06:33:56 -0000      1.168
+++ sbin/iked/ikev2.c   1 Apr 2019 14:53:26 -0000
@@ -1,6 +1,7 @@
 /*     $OpenBSD: ikev2.c,v 1.168 2019/02/27 06:33:56 sthen Exp $       */
 
 /*
+ * Copyright (c) 2019 Tobias Heider <tobias.hei...@stusta.de>
  * Copyright (c) 2010-2013 Reyk Floeter <r...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -144,6 +145,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 +205,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 +404,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 +447,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 +460,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 +488,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 +810,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 +1032,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 */
@@ -1652,6 +1669,30 @@ ikev2_add_mobike(struct iked *env, struc
        return (len);
 }
 
+
+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_sighashnotify(struct ibuf *e, struct ikev2_payload **pld,
     ssize_t len)
@@ -2283,6 +2324,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 +2451,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 +2536,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: sbin/iked/ikev2.h
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/ikev2.h,v
retrieving revision 1.28
diff -u -p -u -r1.28 ikev2.h
--- sbin/iked/ikev2.h   27 Feb 2019 06:33:57 -0000      1.28
+++ sbin/iked/ikev2.h   1 Apr 2019 14:56:14 -0000
@@ -1,6 +1,7 @@
 /*     $OpenBSD: ikev2.h,v 1.28 2019/02/27 06:33:57 sthen Exp $        */
 
 /*
+ * Copyright (c) 2019 Tobias Heider <tobias.hei...@stusta.de>
  * Copyright (c) 2010-2013 Reyk Floeter <r...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -78,6 +79,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 +105,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 +250,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: sbin/iked/ikev2_msg.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/ikev2_msg.c,v
retrieving revision 1.53
diff -u -p -u -r1.53 ikev2_msg.c
--- sbin/iked/ikev2_msg.c       27 Nov 2017 18:39:35 -0000      1.53
+++ sbin/iked/ikev2_msg.c       1 Apr 2019 14:55:35 -0000
@@ -1,6 +1,7 @@
 /*     $OpenBSD: ikev2_msg.c,v 1.53 2017/11/27 18:39:35 patrick Exp $  */
 
 /*
+ * Copyright (c) 2019 Tobias Heider <tobias.hei...@stusta.de>
  * Copyright (c) 2010-2013 Reyk Floeter <r...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -46,6 +47,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 +620,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 +634,26 @@ 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);
+
+       /* Estimated maximum packet size (with 0 < padding < blocklen) */
+       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 +663,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 +720,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 +1138,41 @@ 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, m))
+                               return -1;
+                       count++;
+               }
+       }
+       return count;
 }
 
 int
Index: sbin/iked/ikev2_pld.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/ikev2_pld.c,v
retrieving revision 1.70
diff -u -p -u -r1.70 ikev2_pld.c
--- sbin/iked/ikev2_pld.c       22 Mar 2018 21:11:49 -0000      1.70
+++ sbin/iked/ikev2_pld.c       1 Apr 2019 14:55:07 -0000
@@ -1,6 +1,7 @@
 /*     $OpenBSD: ikev2_pld.c,v 1.70 2018/03/22 21:11:49 patrick Exp $  */
 
 /*
+ * Copyright (c) 2019 Tobias Heider <tobias.hei...@stusta.de>
  * Copyright (c) 2010-2013 Reyk Floeter <r...@openbsd.org>
  * Copyright (c) 2014 Hans-Joerg Hoexer
  *
@@ -95,6 +96,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 +254,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 +274,9 @@ 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 +1260,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 +1611,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;
+       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 = recallocarray(NULL, 0, frag_total,
+                   sizeof(struct iked_frag_entry*));
+               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 = calloc(1, 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;
+       }
+
+       sa_frag->frag_arr[frag_num-1] = el;
+       el->frag_size = elen;
+       el->frag_data = calloc(1, elen);
+       if (el->frag_data == NULL) {
+               log_debug("%s: Failed allocating new fragment data: %zu of %zu",
+                   __func__, frag_num, frag_total);
+               goto done;
+       }
+
+       /* 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;
+       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 */
+       offset = 0;
+       for (i = 0; i < sa_frag->frag_total; i++) {
+               if ((el = sa_frag->frag_arr[i]) == NULL)
+                       fatalx("Tried to reassemble shallow frag_arr");
+               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 +1779,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: sbin/iked/parse.y
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/parse.y,v
retrieving revision 1.78
diff -u -p -u -r1.78 parse.y
--- sbin/iked/parse.y   13 Feb 2019 22:57:07 -0000      1.78
+++ sbin/iked/parse.y   1 Apr 2019 14:52:26 -0000
@@ -1,6 +1,7 @@
 /*     $OpenBSD: parse.y,v 1.78 2019/02/13 22:57:07 deraadt Exp $      */
 
 /*
+ * Copyright (c) 2019 Tobias Heider <tobias.hei...@stusta.de>
  * Copyright (c) 2010-2013 Reyk Floeter <r...@openbsd.org>
  * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoe...@openbsd.org>
  * Copyright (c) 2002, 2003, 2004 Henning Brauer <henn...@openbsd.org>
@@ -105,6 +106,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 +397,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 +458,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 +1172,7 @@ lookup(char *s)
                { "esp",                ESP },
                { "file",               FILENAME },
                { "flow",               FLOW },
+               { "fragmentation",      FRAGMENTATION },
                { "from",               FROM },
                { "group",              GROUP },
                { "ike",                IKEV1 },
@@ -1181,6 +1187,7 @@ lookup(char *s)
                { "local",              LOCAL },
                { "mobike",             MOBIKE },
                { "name",               NAME },
+               { "nofragmentation",    NOFRAGMENTATION },
                { "nomobike",           NOMOBIKE },
                { "ocsp",               OCSP },
                { "passive",            PASSIVE },
@@ -1579,6 +1586,7 @@ parse_config(const char *filename, struc
        free(ocsp_url);
 
        mobike = 1;
+       fragmentation = 0;
        decouple = passive = 0;
        ocsp_url = NULL;
 
@@ -1592,6 +1600,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: sbin/iked/types.h
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/types.h,v
retrieving revision 1.29
diff -u -p -u -r1.29 types.h
--- sbin/iked/types.h   27 Nov 2017 18:39:35 -0000      1.29
+++ sbin/iked/types.h   1 Apr 2019 15:00:45 -0000
@@ -1,6 +1,7 @@
 /*     $OpenBSD: types.h,v 1.29 2017/11/27 18:39:35 patrick Exp $      */
 
 /*
+ * Copyright (c) 2019 Tobias Heider <tobias.hei...@stusta.de>
  * Copyright (c) 2010-2013 Reyk Floeter <r...@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -103,6 +104,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