2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2017 Joyent, Inc.
16 #include <sys/socket.h>
17 #include <net/pfkeyv2.h>
25 #define COOKIE64 0xc0ffee4afee01deaULL
26 #define COOKIE32 0x90125
27 #define RESERVED 0xc0ffee
30 * Exits app on failure.
33 write_and_read(int s
, sadb_msg_t
*samsg
, uint64_t *readbuf
, int readlen
,
37 uint8_t msgtype
= samsg
->sadb_msg_type
;
38 pid_t pid
= samsg
->sadb_msg_pid
;
39 uint8_t seq
= samsg
->sadb_msg_seq
;
41 rc
= write(s
, samsg
, SADB_64TO8(samsg
->sadb_msg_len
));
43 err(-1, "%s write error", msgtypestr
);
45 /* Yes, parameter re-use, but we're done writing. */
46 samsg
= (sadb_msg_t
*)readbuf
;
48 rc
= read(s
, readbuf
, readlen
);
50 err(-1, "%s read reply error", msgtypestr
);
51 } while (samsg
->sadb_msg_seq
!= seq
|| samsg
->sadb_msg_pid
!= pid
||
52 samsg
->sadb_msg_type
!= msgtype
);
54 if (samsg
->sadb_msg_errno
!= 0) {
55 errno
= samsg
->sadb_msg_errno
;
56 err(-1, "%s reply has error (diag = %d)", msgtypestr
,
57 samsg
->sadb_x_msg_diagnostic
);
62 main(int argc
, char *argv
[])
68 sadb_address_t
*dstext
, *srcext
;
70 struct sockaddr_in
*sin
;
71 uint64_t writebuf
[20]; /* PF_KEY likes 64-bit alignment. */
72 uint64_t readbuf
[128];
73 uint64_t *extptr
, *endptr
;
78 if (argc
!= 2 && argc
!= 3) {
79 (void) fprintf(stderr
, "Usage: %s <spi-value> {64}\n",
83 do_64_test
= (argc
== 3);
85 spi
= strtoul(argv
[1], NULL
, 0);
88 err(-1, "Argument %s is not a parsable number:",
92 err(-1, "Zero SPI not allowed:");
96 s
= socket(PF_KEY
, SOCK_RAW
, PF_KEY_V2
);
98 err(-1, "socket(PF_KEY)");
101 samsg
= (sadb_msg_t
*)writebuf
;
102 samsg
->sadb_msg_version
= PF_KEY_V2
;
103 samsg
->sadb_msg_type
= SADB_UPDATE
;
104 samsg
->sadb_msg_errno
= 0;
105 samsg
->sadb_msg_satype
= SADB_SATYPE_AH
;
106 samsg
->sadb_msg_reserved
= 0;
107 samsg
->sadb_msg_seq
= 1;
108 samsg
->sadb_msg_pid
= pid
;
109 samsg
->sadb_msg_len
= SADB_8TO64(sizeof (*samsg
) + sizeof (*saext
) +
110 2 * (sizeof (*dstext
) + sizeof (*sin
)) + sizeof (*kmcext
));
112 /* SA extension. Only used to set the SPI. */
113 saext
= (sadb_sa_t
*)(samsg
+ 1);
114 memset(saext
, 0, sizeof (*saext
));
115 saext
->sadb_sa_len
= SADB_8TO64(sizeof (*saext
));
116 saext
->sadb_sa_exttype
= SADB_EXT_SA
;
117 saext
->sadb_sa_spi
= htonl(spi
);
118 saext
->sadb_sa_state
= SADB_SASTATE_MATURE
;
120 /* Destination IP, always 127.0.0.1 for this test. */
121 dstext
= (sadb_address_t
*)(saext
+ 1);
122 dstext
->sadb_address_len
= SADB_8TO64(sizeof (*dstext
) + sizeof (*sin
));
123 dstext
->sadb_address_exttype
= SADB_EXT_ADDRESS_DST
;
124 dstext
->sadb_address_proto
= 0;
125 dstext
->sadb_address_prefixlen
= 0;
126 dstext
->sadb_address_reserved
= 0;
127 sin
= (struct sockaddr_in
*)(dstext
+ 1);
128 sin
->sin_family
= AF_INET
;
130 sin
->sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
132 /* PF_KEY requires a source address, even if it's a wildcard. */
133 srcext
= (sadb_address_t
*)(sin
+ 1);
134 srcext
->sadb_address_len
= SADB_8TO64(sizeof (*srcext
) + sizeof (*sin
));
135 srcext
->sadb_address_exttype
= SADB_EXT_ADDRESS_SRC
;
136 srcext
->sadb_address_proto
= 0;
137 srcext
->sadb_address_prefixlen
= 0;
138 srcext
->sadb_address_reserved
= 0;
139 sin
= (struct sockaddr_in
*)(srcext
+ 1);
140 sin
->sin_family
= AF_INET
;
142 sin
->sin_addr
.s_addr
= 0;
145 * KM cookie. Depending, either make it IKEv1, 32-bit, AND store
146 * garbage in the reserved field, or just put a big 64-bit cookie in.
148 kmcext
= (sadb_x_kmc_t
*)(sin
+ 1);
149 kmcext
->sadb_x_kmc_len
= SADB_8TO64(sizeof (*kmcext
));
150 kmcext
->sadb_x_kmc_exttype
= SADB_X_EXT_KM_COOKIE
;
152 /* 64-bit cookie test. KINK is non-zero, and non-IKEv1. */
153 kmcext
->sadb_x_kmc_proto
= SADB_X_KMP_KINK
;
154 kmcext
->sadb_x_kmc_cookie64
= COOKIE64
;
156 /* IKEv1 32-bit cookie test. */
157 kmcext
->sadb_x_kmc_proto
= SADB_X_KMP_IKE
;
158 kmcext
->sadb_x_kmc_cookie
= COOKIE32
;
159 kmcext
->sadb_x_kmc_reserved
= RESERVED
;
162 write_and_read(s
, samsg
, readbuf
, sizeof (readbuf
), "SADB_UPDATE");
165 * Okay, it worked! Now let's find the KMC reported back from the
168 samsg
->sadb_msg_type
= SADB_GET
;
169 samsg
->sadb_msg_len
-= SADB_8TO64(sizeof (*kmcext
));
171 /* Everything else in writebuf is good to go. */
172 write_and_read(s
, samsg
, readbuf
, sizeof (readbuf
), "SADB_GET");
174 /* Actually find the KMC extension. (expand for loop for readability) */
175 samsg
= (sadb_msg_t
*)readbuf
;
176 extptr
= (uint64_t *)(samsg
+ 1);
177 endptr
= extptr
+ samsg
->sadb_msg_len
- SADB_8TO64(sizeof (*samsg
));
178 ext
= (sadb_ext_t
*)extptr
;
180 while ((extptr
< endptr
) &&
181 (ext
->sadb_ext_type
!= SADB_X_EXT_KM_COOKIE
)) {
182 extptr
+= ext
->sadb_ext_len
;
183 ext
= (sadb_ext_t
*)extptr
;
186 if (extptr
== endptr
) {
187 (void) fprintf(stderr
, "Can't find KMC extension in reply.\n");
190 kmcext
= (sadb_x_kmc_t
*)extptr
;
193 if (kmcext
->sadb_x_kmc_proto
!= SADB_X_KMP_KINK
||
194 kmcext
->sadb_x_kmc_cookie64
!= COOKIE64
) {
195 (void) fprintf(stderr
, "Unexpected 64-bit results: "
196 "KMC received was %d, expecting %d,\n",
197 kmcext
->sadb_x_kmc_proto
, SADB_X_KMP_KINK
);
198 (void) fprintf(stderr
, "64-bit cookie recevied was "
199 "0x%"PRIx64
", expecting 0x%"PRIx64
"\n",
200 kmcext
->sadb_x_kmc_cookie64
, COOKIE64
);
204 if (kmcext
->sadb_x_kmc_proto
!= SADB_X_KMP_IKE
||
205 kmcext
->sadb_x_kmc_cookie
!= COOKIE32
||
206 kmcext
->sadb_x_kmc_reserved
!= 0) {
207 (void) fprintf(stderr
, "Unexpected IKE/32-bit results:"
208 " KMC received was %d, expecting %d,\n",
209 kmcext
->sadb_x_kmc_proto
, SADB_X_KMP_IKE
);
210 (void) fprintf(stderr
, "32-bit cookie recevied was "
211 "0x%"PRIx32
", expecting 0x%"PRIx32
"\n",
212 kmcext
->sadb_x_kmc_cookie64
, COOKIE32
);
213 (void) fprintf(stderr
, "32-bit reserved recevied was "
214 "0x%"PRIx32
", expecting 0\n",
215 kmcext
->sadb_x_kmc_cookie64
);