Tue Mar 13 02:12:05 2018 UTC ()
Fix IPv6 ipsecif(4) ATF regression, sorry.

There must *not* be padding between the src sockaddr and the dst sockaddr
after struct sadb_x_policy.


(knakahara)
diff -r1.6 -r1.7 src/sys/net/if_ipsec.c

cvs diff -r1.6 -r1.7 src/sys/net/if_ipsec.c (expand / switch to unified diff)

--- src/sys/net/if_ipsec.c 2018/03/09 11:03:26 1.6
+++ src/sys/net/if_ipsec.c 2018/03/13 02:12:05 1.7
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_ipsec.c,v 1.6 2018/03/09 11:03:26 knakahara Exp $ */ 1/* $NetBSD: if_ipsec.c,v 1.7 2018/03/13 02:12:05 knakahara Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2017 Internet Initiative Japan Inc. 4 * Copyright (c) 2017 Internet Initiative Japan Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.6 2018/03/09 11:03:26 knakahara Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.7 2018/03/13 02:12:05 knakahara Exp $");
31 31
32#ifdef _KERNEL_OPT 32#ifdef _KERNEL_OPT
33#include "opt_inet.h" 33#include "opt_inet.h"
34#endif 34#endif
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/systm.h> 37#include <sys/systm.h>
38#include <sys/kernel.h> 38#include <sys/kernel.h>
39#include <sys/mbuf.h> 39#include <sys/mbuf.h>
40#include <sys/socket.h> 40#include <sys/socket.h>
41#include <sys/sockio.h> 41#include <sys/sockio.h>
42#include <sys/errno.h> 42#include <sys/errno.h>
43#include <sys/ioctl.h> 43#include <sys/ioctl.h>
@@ -1300,47 +1300,57 @@ if_ipsec_unshare_sp(struct ipsec_variant @@ -1300,47 +1300,57 @@ if_ipsec_unshare_sp(struct ipsec_variant
1300 mutex_exit(&ipsec_softcs.lock); 1300 mutex_exit(&ipsec_softcs.lock);
1301 if (sc2 == NULL) 1301 if (sc2 == NULL)
1302 return 0; /* not shared */ 1302 return 0; /* not shared */
1303 1303
1304 IV_SP_IN(var) = NULL; 1304 IV_SP_IN(var) = NULL;
1305 IV_SP_IN6(var) = NULL; 1305 IV_SP_IN6(var) = NULL;
1306 IV_SP_OUT(var) = NULL; 1306 IV_SP_OUT(var) = NULL;
1307 IV_SP_OUT6(var) = NULL; 1307 IV_SP_OUT6(var) = NULL;
1308 if_ipsec_putref_variant(var2, &psref); 1308 if_ipsec_putref_variant(var2, &psref);
1309 return 1; /* shared */ 1309 return 1; /* shared */
1310} 1310}
1311 1311
1312static inline void 1312static inline void
1313if_ipsec_add_mbuf(struct mbuf *m0, void *data, size_t len) 1313if_ipsec_add_mbuf_optalign(struct mbuf *m0, void *data, size_t len, bool align)
1314{ 1314{
1315 struct mbuf *m; 1315 struct mbuf *m;
1316 1316
1317 MGET(m, M_WAITOK | M_ZERO, MT_DATA); 1317 MGET(m, M_WAITOK | M_ZERO, MT_DATA);
1318 m->m_len = PFKEY_ALIGN8(len); 1318 if (align)
 1319 m->m_len = PFKEY_ALIGN8(len);
 1320 else
 1321 m->m_len = len;
1319 m_copyback(m, 0, len, data); 1322 m_copyback(m, 0, len, data);
1320 m_cat(m0, m); 1323 m_cat(m0, m);
1321} 1324}
1322 1325
1323static inline void 1326static inline void
1324if_ipsec_add_mbuf_addr_port(struct mbuf *m0, struct sockaddr *addr, in_port_t port) 1327if_ipsec_add_mbuf(struct mbuf *m0, void *data, size_t len)
 1328{
 1329
 1330 if_ipsec_add_mbuf_optalign(m0, data, len, true);
 1331}
 1332
 1333static inline void
 1334if_ipsec_add_mbuf_addr_port(struct mbuf *m0, struct sockaddr *addr, in_port_t port, bool align)
1325{ 1335{
1326 1336
1327 if (port == 0) { 1337 if (port == 0) {
1328 if_ipsec_add_mbuf(m0, addr, addr->sa_len); 1338 if_ipsec_add_mbuf_optalign(m0, addr, addr->sa_len, align);
1329 } else { 1339 } else {
1330 struct sockaddr addrport; 1340 struct sockaddr addrport;
1331 1341
1332 if_ipsec_set_addr_port(&addrport, addr, port); 1342 if_ipsec_set_addr_port(&addrport, addr, port);
1333 if_ipsec_add_mbuf(m0, &addrport, addrport.sa_len); 1343 if_ipsec_add_mbuf_optalign(m0, &addrport, addrport.sa_len, align);
1334 } 1344 }
1335} 1345}
1336 1346
1337static inline void 1347static inline void
1338if_ipsec_add_pad(struct mbuf *m0, size_t len) 1348if_ipsec_add_pad(struct mbuf *m0, size_t len)
1339{ 1349{
1340 struct mbuf *m; 1350 struct mbuf *m;
1341 1351
1342 if (len == 0) 1352 if (len == 0)
1343 return; 1353 return;
1344 1354
1345 MGET(m, M_WAITOK | M_ZERO, MT_DATA); 1355 MGET(m, M_WAITOK | M_ZERO, MT_DATA);
1346 m->m_len = len; 1356 m->m_len = len;
@@ -1402,45 +1412,42 @@ if_ipsec_set_sadb_dst(struct sadb_addres @@ -1402,45 +1412,42 @@ if_ipsec_set_sadb_dst(struct sadb_addres
1402 1412
1403static inline size_t 1413static inline size_t
1404if_ipsec_set_sadb_x_policy(struct sadb_x_policy *xpl, 1414if_ipsec_set_sadb_x_policy(struct sadb_x_policy *xpl,
1405 struct sadb_x_ipsecrequest *xisr, uint16_t policy, uint8_t dir, uint32_t id, 1415 struct sadb_x_ipsecrequest *xisr, uint16_t policy, uint8_t dir, uint32_t id,
1406 uint8_t level, struct sockaddr *src, struct sockaddr *dst) 1416 uint8_t level, struct sockaddr *src, struct sockaddr *dst)
1407{ 1417{
1408 size_t size; 1418 size_t size;
1409 1419
1410 KASSERT(policy != IPSEC_POLICY_IPSEC || xisr != NULL); 1420 KASSERT(policy != IPSEC_POLICY_IPSEC || xisr != NULL);
1411 1421
1412 size = sizeof(*xpl); 1422 size = sizeof(*xpl);
1413 if (policy == IPSEC_POLICY_IPSEC) { 1423 if (policy == IPSEC_POLICY_IPSEC) {
1414 size += PFKEY_ALIGN8(sizeof(*xisr)); 1424 size += PFKEY_ALIGN8(sizeof(*xisr));
1415 if (src != NULL) 1425 if (src != NULL && dst != NULL)
1416 size += PFKEY_ALIGN8(src->sa_len); 1426 size += PFKEY_ALIGN8(src->sa_len + dst->sa_len);
1417 if (dst != NULL) 
1418 size += PFKEY_ALIGN8(dst->sa_len); 
1419 } 1427 }
1420 xpl->sadb_x_policy_len = PFKEY_UNIT64(size); 1428 xpl->sadb_x_policy_len = PFKEY_UNIT64(size);
1421 xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY; 1429 xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
1422 xpl->sadb_x_policy_type = policy; 1430 xpl->sadb_x_policy_type = policy;
1423 xpl->sadb_x_policy_dir = dir; 1431 xpl->sadb_x_policy_dir = dir;
1424 xpl->sadb_x_policy_reserved = 0; 1432 xpl->sadb_x_policy_reserved = 0;
1425 xpl->sadb_x_policy_id = id; 1433 xpl->sadb_x_policy_id = id;
1426 xpl->sadb_x_policy_reserved2 = 0; 1434 xpl->sadb_x_policy_reserved2 = 0;
1427 1435
1428 if (policy == IPSEC_POLICY_IPSEC) { 1436 if (policy == IPSEC_POLICY_IPSEC) {
1429 xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(sizeof(*xisr)); 1437 xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(sizeof(*xisr));
1430 if (src != NULL) 1438 if (src != NULL && dst != NULL)
1431 xisr->sadb_x_ipsecrequest_len += PFKEY_ALIGN8(src->sa_len); 1439 xisr->sadb_x_ipsecrequest_len +=
1432 if (dst != NULL) 1440 PFKEY_ALIGN8(src->sa_len + dst->sa_len);
1433 xisr->sadb_x_ipsecrequest_len += PFKEY_ALIGN8(dst->sa_len); 
1434 xisr->sadb_x_ipsecrequest_proto = IPPROTO_ESP; 1441 xisr->sadb_x_ipsecrequest_proto = IPPROTO_ESP;
1435 xisr->sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT; 1442 xisr->sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
1436 xisr->sadb_x_ipsecrequest_level = level; 1443 xisr->sadb_x_ipsecrequest_level = level;
1437 xisr->sadb_x_ipsecrequest_reqid = key_newreqid(); 1444 xisr->sadb_x_ipsecrequest_reqid = key_newreqid();
1438 } 1445 }
1439 1446
1440 return size; 1447 return size;
1441} 1448}
1442 1449
1443static inline void 1450static inline void
1444if_ipsec_set_sadb_msg(struct sadb_msg *msg, uint16_t extlen, uint8_t msgtype) 1451if_ipsec_set_sadb_msg(struct sadb_msg *msg, uint16_t extlen, uint8_t msgtype)
1445{ 1452{
1446 1453
@@ -1529,48 +1536,46 @@ if_ipsec_add_sp0(struct sockaddr *src, i @@ -1529,48 +1536,46 @@ if_ipsec_add_sp0(struct sockaddr *src, i
1529 ext_msg_len += PFKEY_UNIT64(size); 1536 ext_msg_len += PFKEY_UNIT64(size);
1530 size = if_ipsec_set_sadb_dst(&xdst, dst, proto); 1537 size = if_ipsec_set_sadb_dst(&xdst, dst, proto);
1531 ext_msg_len += PFKEY_UNIT64(size); 1538 ext_msg_len += PFKEY_UNIT64(size);
1532 size = if_ipsec_set_sadb_x_policy(&xpl, &xisr, policy, dir, 0, level, src, dst); 1539 size = if_ipsec_set_sadb_x_policy(&xpl, &xisr, policy, dir, 0, level, src, dst);
1533 ext_msg_len += PFKEY_UNIT64(size); 1540 ext_msg_len += PFKEY_UNIT64(size);
1534 if_ipsec_set_sadb_msg_add(&msg, ext_msg_len); 1541 if_ipsec_set_sadb_msg_add(&msg, ext_msg_len);
1535 1542
1536 /* build PF_KEY message */ 1543 /* build PF_KEY message */
1537 1544
1538 m->m_len = sizeof(msg); 1545 m->m_len = sizeof(msg);
1539 m_copyback(m, 0, sizeof(msg), &msg); 1546 m_copyback(m, 0, sizeof(msg), &msg);
1540 1547
1541 if_ipsec_add_mbuf(m, &xsrc, sizeof(xsrc)); 1548 if_ipsec_add_mbuf(m, &xsrc, sizeof(xsrc));
1542 if_ipsec_add_mbuf_addr_port(m, src, sport); 1549 if_ipsec_add_mbuf_addr_port(m, src, sport, true);
1543 padlen = PFKEY_UNUNIT64(xsrc.sadb_address_len) 1550 padlen = PFKEY_UNUNIT64(xsrc.sadb_address_len)
1544 - (sizeof(xsrc) + PFKEY_ALIGN8(src->sa_len)); 1551 - (sizeof(xsrc) + PFKEY_ALIGN8(src->sa_len));
1545 if_ipsec_add_pad(m, padlen); 1552 if_ipsec_add_pad(m, padlen);
1546 1553
1547 if_ipsec_add_mbuf(m, &xdst, sizeof(xdst)); 1554 if_ipsec_add_mbuf(m, &xdst, sizeof(xdst));
1548 if_ipsec_add_mbuf_addr_port(m, dst, dport); 1555 if_ipsec_add_mbuf_addr_port(m, dst, dport, true);
1549 padlen = PFKEY_UNUNIT64(xdst.sadb_address_len) 1556 padlen = PFKEY_UNUNIT64(xdst.sadb_address_len)
1550 - (sizeof(xdst) + PFKEY_ALIGN8(dst->sa_len)); 1557 - (sizeof(xdst) + PFKEY_ALIGN8(dst->sa_len));
1551 if_ipsec_add_pad(m, padlen); 1558 if_ipsec_add_pad(m, padlen);
1552 1559
1553 if_ipsec_add_mbuf(m, &xpl, sizeof(xpl)); 1560 if_ipsec_add_mbuf(m, &xpl, sizeof(xpl));
1554 if (policy == IPSEC_POLICY_IPSEC) { 1561 if (policy == IPSEC_POLICY_IPSEC) {
1555 if_ipsec_add_mbuf(m, &xisr, sizeof(xisr)); 1562 if_ipsec_add_mbuf(m, &xisr, sizeof(xisr));
1556 if_ipsec_add_mbuf_addr_port(m, src, sport); 1563 if_ipsec_add_mbuf_addr_port(m, src, sport, false);
1557 if_ipsec_add_mbuf_addr_port(m, dst, dport); 1564 if_ipsec_add_mbuf_addr_port(m, dst, dport, false);
1558 } 1565 }
1559 padlen = PFKEY_UNUNIT64(xpl.sadb_x_policy_len) - sizeof(xpl); 1566 padlen = PFKEY_UNUNIT64(xpl.sadb_x_policy_len) - sizeof(xpl);
1560 if (src != NULL) 1567 if (src != NULL && dst != NULL)
1561 padlen -= PFKEY_ALIGN8(src->sa_len); 1568 padlen -= PFKEY_ALIGN8(src->sa_len + dst->sa_len);
1562 if (dst != NULL) 
1563 padlen -= PFKEY_ALIGN8(dst->sa_len); 
1564 if_ipsec_add_pad(m, padlen); 1569 if_ipsec_add_pad(m, padlen);
1565 1570
1566 /* key_kpi_spdadd() has already done KEY_SP_REF(). */ 1571 /* key_kpi_spdadd() has already done KEY_SP_REF(). */
1567 return key_kpi_spdadd(m); 1572 return key_kpi_spdadd(m);
1568} 1573}
1569 1574
1570static int 1575static int
1571if_ipsec_add_sp(struct ipsec_variant *var, 1576if_ipsec_add_sp(struct ipsec_variant *var,
1572 struct sockaddr *src, in_port_t sport, 1577 struct sockaddr *src, in_port_t sport,
1573 struct sockaddr *dst, in_port_t dport) 1578 struct sockaddr *dst, in_port_t dport)
1574{ 1579{
1575 struct ipsec_softc *sc = var->iv_softc; 1580 struct ipsec_softc *sc = var->iv_softc;
1576 int level; 1581 int level;