| File: | src/usr.sbin/sasyncd/pfkey.c |
| Warning: | line 489, column 14 Result of 'calloc' is converted to a pointer of type 'u_int8_t', which is incompatible with sizeof operand type 'u_int64_t' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: pfkey.c,v 1.29 2018/06/28 02:37:26 gsoares Exp $ */ |
| 2 | |
| 3 | /* |
| 4 | * Copyright (c) 2005 Håkan Olsson. All rights reserved. |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions |
| 8 | * are met: |
| 9 | * |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | /* |
| 29 | * This code was written under funding by Multicom Security AB. |
| 30 | */ |
| 31 | |
| 32 | |
| 33 | #include <sys/types.h> |
| 34 | #include <sys/ioctl.h> |
| 35 | #include <sys/select.h> |
| 36 | #include <sys/socket.h> |
| 37 | #include <sys/queue.h> |
| 38 | #include <sys/sysctl.h> |
| 39 | #include <net/pfkeyv2.h> |
| 40 | #include <netinet/ip_ipsp.h> |
| 41 | |
| 42 | #include <errno(*__errno()).h> |
| 43 | #include <stdio.h> |
| 44 | #include <stdlib.h> |
| 45 | #include <string.h> |
| 46 | #include <unistd.h> |
| 47 | |
| 48 | #include "sasyncd.h" |
| 49 | #include "monitor.h" |
| 50 | #include "net.h" |
| 51 | |
| 52 | struct pfkey_msg |
| 53 | { |
| 54 | SIMPLEQ_ENTRY(pfkey_msg)struct { struct pfkey_msg *sqe_next; } next; |
| 55 | |
| 56 | u_int8_t *buf; |
| 57 | u_int32_t len; |
| 58 | }; |
| 59 | |
| 60 | SIMPLEQ_HEAD(, pfkey_msg)struct { struct pfkey_msg *sqh_first; struct pfkey_msg **sqh_last ; } pfkey_msglist; |
| 61 | |
| 62 | static const char *msgtypes[] = { |
| 63 | "RESERVED", "GETSPI", "UPDATE", "ADD", "DELETE", "GET", "ACQUIRE", |
| 64 | "REGISTER", "EXPIRE", "FLUSH", "DUMP", "X_PROMISC", "X_ADDFLOW", |
| 65 | "X_DELFLOW", "X_GRPSPIS", "X_ASKPOLICY", "X_SPDDUMP" |
| 66 | }; |
| 67 | |
| 68 | #define CHUNKsizeof(u_int64_t) sizeof(u_int64_t) |
| 69 | |
| 70 | static const char *pfkey_print_type(struct sadb_msg *); |
| 71 | |
| 72 | static int |
| 73 | pfkey_write(u_int8_t *buf, ssize_t len) |
| 74 | { |
| 75 | struct sadb_msg *msg = (struct sadb_msg *)buf; |
| 76 | ssize_t n; |
| 77 | |
| 78 | if (cfgstate.pfkey_socket == -1) |
| 79 | return 0; |
| 80 | |
| 81 | do { |
| 82 | n = write(cfgstate.pfkey_socket, buf, len); |
| 83 | } while (n == -1 && (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)); |
| 84 | if (n == -1) { |
| 85 | log_err("pfkey: msg %s write() failed on socket %d", |
| 86 | pfkey_print_type(msg), cfgstate.pfkey_socket); |
| 87 | return -1; |
| 88 | } |
| 89 | |
| 90 | return 0; |
| 91 | } |
| 92 | |
| 93 | int |
| 94 | pfkey_set_promisc(void) |
| 95 | { |
| 96 | struct sadb_msg msg; |
| 97 | static u_int32_t seq = 1; |
| 98 | |
| 99 | memset(&msg, 0, sizeof msg); |
| 100 | msg.sadb_msg_version = PF_KEY_V22; |
| 101 | msg.sadb_msg_seq = seq++; |
| 102 | msg.sadb_msg_satype = 1; /* Special; 1 to enable, 0 to disable */ |
| 103 | msg.sadb_msg_type = SADB_X_PROMISC11; |
| 104 | msg.sadb_msg_pid = getpid(); |
| 105 | msg.sadb_msg_len = sizeof msg / CHUNKsizeof(u_int64_t); |
| 106 | |
| 107 | return pfkey_write((u_int8_t *)&msg, sizeof msg); |
| 108 | } |
| 109 | |
| 110 | /* Send a SADB_FLUSH PFKEY message to peer 'p' */ |
| 111 | static void |
| 112 | pfkey_send_flush(struct syncpeer *p) |
| 113 | { |
| 114 | struct sadb_msg *m = calloc(1, sizeof *m); |
| 115 | static u_int32_t seq = 1; |
| 116 | |
| 117 | if (m) { |
| 118 | m->sadb_msg_version = PF_KEY_V22; |
| 119 | m->sadb_msg_seq = seq++; |
| 120 | m->sadb_msg_type = SADB_FLUSH9; |
| 121 | m->sadb_msg_satype = SADB_SATYPE_UNSPEC0; |
| 122 | m->sadb_msg_pid = getpid(); |
| 123 | m->sadb_msg_len = sizeof *m / CHUNKsizeof(u_int64_t); |
| 124 | |
| 125 | log_msg(2, "pfkey_send_flush: sending FLUSH to peer %s", |
| 126 | p->name); |
| 127 | net_queue(p, MSG_PFKEYDATA1, (u_int8_t *)m, sizeof *m); |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | static const char * |
| 132 | pfkey_print_type(struct sadb_msg *msg) |
| 133 | { |
| 134 | static char uk[20]; |
| 135 | |
| 136 | if (msg->sadb_msg_type < sizeof msgtypes / sizeof msgtypes[0]) |
| 137 | return msgtypes[msg->sadb_msg_type]; |
| 138 | else { |
| 139 | snprintf(uk, sizeof uk, "<unknown(%d)>", msg->sadb_msg_type); |
| 140 | return uk; |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | static struct sadb_ext * |
| 145 | pfkey_find_ext(struct sadb_msg *msg, u_int16_t type) |
| 146 | { |
| 147 | struct sadb_ext *ext; |
| 148 | u_int8_t *e; |
| 149 | |
| 150 | for (e = (u_int8_t *)msg + sizeof *msg; |
| 151 | e < (u_int8_t *)msg + msg->sadb_msg_len * CHUNKsizeof(u_int64_t); |
| 152 | e += ext->sadb_ext_len * CHUNKsizeof(u_int64_t)) { |
| 153 | ext = (struct sadb_ext *)e; |
| 154 | if (ext->sadb_ext_len == 0) |
| 155 | break; |
| 156 | if (ext->sadb_ext_type != type) |
| 157 | continue; |
| 158 | return ext; |
| 159 | } |
| 160 | return NULL((void *)0); |
| 161 | } |
| 162 | |
| 163 | /* Return: 0 means ok to sync msg, 1 means to skip it */ |
| 164 | static int |
| 165 | pfkey_msg_filter(struct sadb_msg *msg) |
| 166 | { |
| 167 | struct sockaddr *src = 0, *dst = 0; |
| 168 | struct syncpeer *p; |
| 169 | struct sadb_ext *ext; |
| 170 | u_int8_t *max; |
| 171 | |
| 172 | switch (msg->sadb_msg_type) { |
| 173 | case SADB_X_PROMISC11: |
| 174 | case SADB_DUMP10: |
| 175 | case SADB_GET5: |
| 176 | case SADB_GETSPI1: |
| 177 | case SADB_ACQUIRE6: |
| 178 | case SADB_X_ASKPOLICY15: |
| 179 | case SADB_REGISTER7: |
| 180 | /* Some messages should not be synced. */ |
| 181 | return 1; |
| 182 | |
| 183 | case SADB_ADD3: |
| 184 | /* No point in syncing LARVAL SAs */ |
| 185 | if (pfkey_find_ext(msg, SADB_EXT_KEY_ENCRYPT9) == 0) |
| 186 | return 1; |
| 187 | case SADB_DELETE4: |
| 188 | case SADB_X_ADDFLOW12: |
| 189 | case SADB_X_DELFLOW13: |
| 190 | case SADB_EXPIRE8: |
| 191 | /* Continue below */ |
| 192 | break; |
| 193 | case SADB_FLUSH9: |
| 194 | if ((cfgstate.flags & FM_MASK0x0003) == FM_NEVER0x0001) |
| 195 | return 1; |
| 196 | break; |
| 197 | default: |
| 198 | return 0; |
| 199 | } |
| 200 | |
| 201 | if ((cfgstate.flags & SKIP_LOCAL_SAS0x0004) == 0) |
| 202 | return 0; |
| 203 | |
| 204 | /* SRC or DST address of this msg must not be one of our peers. */ |
| 205 | ext = pfkey_find_ext(msg, SADB_EXT_ADDRESS_SRC5); |
| 206 | if (ext) |
| 207 | src = (struct sockaddr *)((struct sadb_address *)ext + 1); |
| 208 | ext = pfkey_find_ext(msg, SADB_EXT_ADDRESS_DST6); |
| 209 | if (ext) |
| 210 | dst = (struct sockaddr *)((struct sadb_address *)ext + 1); |
| 211 | if (!src && !dst) |
| 212 | return 0; |
| 213 | |
| 214 | max = (u_int8_t *)msg + msg->sadb_msg_len * CHUNKsizeof(u_int64_t); |
| 215 | if (src && ((u_int8_t *)src + src->sa_len) > max) |
| 216 | return 1; |
| 217 | if (dst && ((u_int8_t *)dst + dst->sa_len) > max) |
| 218 | return 1; |
| 219 | |
| 220 | /* Found SRC or DST, check it against our peers */ |
| 221 | for (p = LIST_FIRST(&cfgstate.peerlist)((&cfgstate.peerlist)->lh_first); p; p = LIST_NEXT(p, link)((p)->link.le_next)) { |
| 222 | if (p->socket < 0 || p->sa->sa_family != |
| 223 | (src ? src->sa_family : dst->sa_family)) |
| 224 | continue; |
| 225 | |
| 226 | switch (p->sa->sa_family) { |
| 227 | case AF_INET2: |
| 228 | if (src && memcmp( |
| 229 | &((struct sockaddr_in *)p->sa)->sin_addr.s_addr, |
| 230 | &((struct sockaddr_in *)src)->sin_addr.s_addr, |
| 231 | sizeof(struct in_addr)) == 0) |
| 232 | return 1; |
| 233 | if (dst && memcmp( |
| 234 | &((struct sockaddr_in *)p->sa)->sin_addr.s_addr, |
| 235 | &((struct sockaddr_in *)dst)->sin_addr.s_addr, |
| 236 | sizeof(struct in_addr)) == 0) |
| 237 | return 1; |
| 238 | break; |
| 239 | case AF_INET624: |
| 240 | if (src && |
| 241 | memcmp(&((struct sockaddr_in6 *)p->sa)->sin6_addr, |
| 242 | &((struct sockaddr_in6 *)src)->sin6_addr, |
| 243 | sizeof(struct in_addr)) == 0) |
| 244 | return 1; |
| 245 | if (dst && |
| 246 | memcmp(&((struct sockaddr_in6 *)p->sa)->sin6_addr, |
| 247 | &((struct sockaddr_in6 *)dst)->sin6_addr, |
| 248 | sizeof(struct in_addr)) == 0) |
| 249 | return 1; |
| 250 | break; |
| 251 | } |
| 252 | } |
| 253 | return 0; |
| 254 | } |
| 255 | |
| 256 | static int |
| 257 | pfkey_handle_message(struct sadb_msg *m) |
| 258 | { |
| 259 | struct sadb_msg *msg = m; |
| 260 | |
| 261 | /* |
| 262 | * Report errors, but ignore for DELETE (both isakmpd and kernel will |
| 263 | * expire the SA, if the kernel is first, DELETE returns failure). |
| 264 | */ |
| 265 | if (msg->sadb_msg_errno && msg->sadb_msg_type != SADB_DELETE4 && |
| 266 | msg->sadb_msg_pid == (u_int32_t)getpid()) { |
| 267 | errno(*__errno()) = msg->sadb_msg_errno; |
| 268 | log_msg(1, "pfkey error (%s)", pfkey_print_type(msg)); |
| 269 | } |
| 270 | |
| 271 | /* We only want promiscuous messages here, skip all others. */ |
| 272 | if (msg->sadb_msg_type != SADB_X_PROMISC11 || |
| 273 | (msg->sadb_msg_len * CHUNKsizeof(u_int64_t)) < 2 * sizeof *msg) { |
| 274 | free(m); |
| 275 | return 0; |
| 276 | } |
| 277 | /* Move next msg to start of the buffer. */ |
| 278 | msg++; |
| 279 | |
| 280 | /* |
| 281 | * We should not listen to PFKEY messages when we are not running |
| 282 | * as MASTER, or the pid is our own. |
| 283 | */ |
| 284 | if (cfgstate.runstate != MASTER || |
| 285 | msg->sadb_msg_pid == (u_int32_t)getpid()) { |
| 286 | free(m); |
| 287 | return 0; |
| 288 | } |
| 289 | |
| 290 | if (pfkey_msg_filter(msg)) { |
| 291 | free(m); |
| 292 | return 0; |
| 293 | } |
| 294 | |
| 295 | switch (msg->sadb_msg_type) { |
| 296 | case SADB_UPDATE2: |
| 297 | /* |
| 298 | * Tweak -- the peers do not have a larval SA to update, so |
| 299 | * instead we ADD it here. |
| 300 | */ |
| 301 | msg->sadb_msg_type = SADB_ADD3; |
| 302 | /* FALLTHROUGH */ |
| 303 | |
| 304 | default: |
| 305 | /* Pass the rest along to our peers. */ |
| 306 | memmove(m, msg, msg->sadb_msg_len * CHUNKsizeof(u_int64_t)); /* for realloc */ |
| 307 | return net_queue(NULL((void *)0), MSG_PFKEYDATA1, (u_int8_t *)m, |
| 308 | m->sadb_msg_len * CHUNKsizeof(u_int64_t)); |
| 309 | } |
| 310 | |
| 311 | return 0; |
| 312 | } |
| 313 | |
| 314 | static int |
| 315 | pfkey_read(void) |
| 316 | { |
| 317 | struct sadb_msg hdr, *msg; |
| 318 | u_int8_t *data; |
| 319 | ssize_t datalen; |
| 320 | int fd = cfgstate.pfkey_socket; |
| 321 | |
| 322 | if (recv(fd, &hdr, sizeof hdr, MSG_PEEK0x2) != sizeof hdr) { |
| 323 | log_err("pfkey_read: recv() failed"); |
| 324 | return -1; |
| 325 | } |
| 326 | datalen = hdr.sadb_msg_len * CHUNKsizeof(u_int64_t); |
| 327 | data = reallocarray(NULL((void *)0), hdr.sadb_msg_len, CHUNKsizeof(u_int64_t)); |
| 328 | if (!data) { |
| 329 | log_err("pfkey_read: malloc(%lu) failed", datalen); |
| 330 | return -1; |
| 331 | } |
| 332 | msg = (struct sadb_msg *)data; |
| 333 | |
| 334 | if (read(fd, data, datalen) != datalen) { |
| 335 | log_err("pfkey_read: read() failed, %lu bytes", datalen); |
| 336 | free(data); |
| 337 | return -1; |
| 338 | } |
| 339 | |
| 340 | return pfkey_handle_message(msg); |
| 341 | } |
| 342 | |
| 343 | int |
| 344 | pfkey_init(int reinit) |
| 345 | { |
| 346 | int fd; |
| 347 | |
| 348 | fd = socket(PF_KEY30, SOCK_RAW3, PF_KEY_V22); |
| 349 | if (fd == -1) { |
| 350 | perror("failed to open PF_KEY socket"); |
| 351 | return -1; |
| 352 | } |
| 353 | cfgstate.pfkey_socket = fd; |
| 354 | |
| 355 | if (cfgstate.runstate == MASTER) |
| 356 | pfkey_set_promisc(); |
| 357 | |
| 358 | if (reinit) |
| 359 | return (fd > -1 ? 0 : -1); |
| 360 | |
| 361 | SIMPLEQ_INIT(&pfkey_msglist)do { (&pfkey_msglist)->sqh_first = ((void *)0); (& pfkey_msglist)->sqh_last = &(&pfkey_msglist)->sqh_first ; } while (0); |
| 362 | return 0; |
| 363 | } |
| 364 | |
| 365 | void |
| 366 | pfkey_set_rfd(fd_set *fds) |
| 367 | { |
| 368 | if (cfgstate.pfkey_socket != -1) |
| 369 | FD_SET(cfgstate.pfkey_socket, fds)__fd_set((cfgstate.pfkey_socket), (fds)); |
| 370 | } |
| 371 | |
| 372 | void |
| 373 | pfkey_set_pending_wfd(fd_set *fds) |
| 374 | { |
| 375 | if (cfgstate.pfkey_socket != -1 && SIMPLEQ_FIRST(&pfkey_msglist)((&pfkey_msglist)->sqh_first)) |
| 376 | FD_SET(cfgstate.pfkey_socket, fds)__fd_set((cfgstate.pfkey_socket), (fds)); |
| 377 | } |
| 378 | |
| 379 | void |
| 380 | pfkey_read_message(fd_set *fds) |
| 381 | { |
| 382 | if (cfgstate.pfkey_socket != -1) |
| 383 | if (FD_ISSET(cfgstate.pfkey_socket, fds)__fd_isset((cfgstate.pfkey_socket), (fds))) |
| 384 | (void)pfkey_read(); |
| 385 | } |
| 386 | |
| 387 | void |
| 388 | pfkey_send_message(fd_set *fds) |
| 389 | { |
| 390 | struct pfkey_msg *pmsg = SIMPLEQ_FIRST(&pfkey_msglist)((&pfkey_msglist)->sqh_first); |
| 391 | |
| 392 | if (!pmsg || !FD_ISSET(cfgstate.pfkey_socket, fds)__fd_isset((cfgstate.pfkey_socket), (fds))) |
| 393 | return; |
| 394 | |
| 395 | if (cfgstate.pfkey_socket == -1) |
| 396 | if (pfkey_init(1)) /* Reinit socket */ |
| 397 | return; |
| 398 | |
| 399 | (void)pfkey_write(pmsg->buf, pmsg->len); |
| 400 | |
| 401 | SIMPLEQ_REMOVE_HEAD(&pfkey_msglist, next)do { if (((&pfkey_msglist)->sqh_first = (&pfkey_msglist )->sqh_first->next.sqe_next) == ((void *)0)) (&pfkey_msglist )->sqh_last = &(&pfkey_msglist)->sqh_first; } while (0); |
| 402 | free(pmsg->buf); |
| 403 | free(pmsg); |
| 404 | |
| 405 | return; |
| 406 | } |
| 407 | |
| 408 | int |
| 409 | pfkey_queue_message(u_int8_t *data, u_int32_t datalen) |
| 410 | { |
| 411 | struct pfkey_msg *pmsg; |
| 412 | struct sadb_msg *sadb = (struct sadb_msg *)data; |
| 413 | static u_int32_t seq = 1; |
| 414 | |
| 415 | pmsg = malloc(sizeof *pmsg); |
| 416 | if (!pmsg) { |
| 417 | log_err("malloc()"); |
| 418 | return -1; |
| 419 | } |
| 420 | memset(pmsg, 0, sizeof *pmsg); |
| 421 | |
| 422 | pmsg->buf = data; |
| 423 | pmsg->len = datalen; |
| 424 | |
| 425 | sadb->sadb_msg_pid = getpid(); |
| 426 | sadb->sadb_msg_seq = seq++; |
| 427 | log_msg(2, "pfkey_queue_message: pfkey %s len %zu seq %u", |
| 428 | pfkey_print_type(sadb), sadb->sadb_msg_len * CHUNKsizeof(u_int64_t), |
| 429 | sadb->sadb_msg_seq); |
| 430 | |
| 431 | SIMPLEQ_INSERT_TAIL(&pfkey_msglist, pmsg, next)do { (pmsg)->next.sqe_next = ((void *)0); *(&pfkey_msglist )->sqh_last = (pmsg); (&pfkey_msglist)->sqh_last = & (pmsg)->next.sqe_next; } while (0); |
| 432 | return 0; |
| 433 | } |
| 434 | |
| 435 | void |
| 436 | pfkey_shutdown(void) |
| 437 | { |
| 438 | struct pfkey_msg *p = SIMPLEQ_FIRST(&pfkey_msglist)((&pfkey_msglist)->sqh_first); |
| 439 | |
| 440 | while ((p = SIMPLEQ_FIRST(&pfkey_msglist)((&pfkey_msglist)->sqh_first))) { |
| 441 | SIMPLEQ_REMOVE_HEAD(&pfkey_msglist, next)do { if (((&pfkey_msglist)->sqh_first = (&pfkey_msglist )->sqh_first->next.sqe_next) == ((void *)0)) (&pfkey_msglist )->sqh_last = &(&pfkey_msglist)->sqh_first; } while (0); |
| 442 | free(p->buf); |
| 443 | free(p); |
| 444 | } |
| 445 | |
| 446 | if (cfgstate.pfkey_socket > -1) |
| 447 | close(cfgstate.pfkey_socket); |
| 448 | } |
| 449 | |
| 450 | /* ------------------------------------------------------------------------- */ |
| 451 | |
| 452 | void |
| 453 | pfkey_snapshot(void *v) |
| 454 | { |
| 455 | struct syncpeer *p = (struct syncpeer *)v; |
| 456 | struct sadb_msg *m; |
| 457 | u_int8_t *sadb, *spd, *max, *next, *sendbuf; |
| 458 | u_int32_t sadbsz, spdsz; |
| 459 | |
| 460 | if (!p) |
| 461 | return; |
| 462 | |
| 463 | if (monitor_get_pfkey_snap(&sadb, &sadbsz, &spd, &spdsz)) { |
| 464 | log_msg(0, "pfkey_snapshot: failed to get pfkey snapshot"); |
| 465 | return; |
| 466 | } |
| 467 | |
| 468 | /* XXX needs moving if snapshot is called more than once per peer */ |
| 469 | if ((cfgstate.flags & FM_MASK0x0003) == FM_STARTUP0x0000) |
| 470 | pfkey_send_flush(p); |
| 471 | |
| 472 | /* Parse SADB data */ |
| 473 | if (sadbsz && sadb) { |
| 474 | dump_buf(2, sadb, sadbsz, "pfkey_snapshot: SADB data"); |
| 475 | max = sadb + sadbsz; |
| 476 | for (next = sadb; next < max; |
| 477 | next += m->sadb_msg_len * CHUNKsizeof(u_int64_t)) { |
| 478 | m = (struct sadb_msg *)next; |
| 479 | if (m->sadb_msg_len == 0) |
| 480 | break; |
| 481 | |
| 482 | /* Tweak and send this SA to the peer. */ |
| 483 | m->sadb_msg_type = SADB_ADD3; |
| 484 | |
| 485 | if (pfkey_msg_filter(m)) |
| 486 | continue; |
| 487 | |
| 488 | /* Allocate msgbuffer, net_queue() will free it. */ |
| 489 | sendbuf = calloc(m->sadb_msg_len, CHUNKsizeof(u_int64_t)); |
Result of 'calloc' is converted to a pointer of type 'u_int8_t', which is incompatible with sizeof operand type 'u_int64_t' | |
| 490 | if (sendbuf) { |
| 491 | memcpy(sendbuf, m, m->sadb_msg_len * CHUNKsizeof(u_int64_t)); |
| 492 | net_queue(p, MSG_PFKEYDATA1, sendbuf, |
| 493 | m->sadb_msg_len * CHUNKsizeof(u_int64_t)); |
| 494 | log_msg(2, "pfkey_snapshot: sync SA %p len %zu " |
| 495 | "to peer %s", m, |
| 496 | m->sadb_msg_len * CHUNKsizeof(u_int64_t), p->name); |
| 497 | } |
| 498 | } |
| 499 | freezero(sadb, sadbsz); |
| 500 | } |
| 501 | |
| 502 | /* Parse SPD data */ |
| 503 | if (spdsz && spd) { |
| 504 | dump_buf(2, spd, spdsz, "pfkey_snapshot: SPD data"); |
| 505 | max = spd + spdsz; |
| 506 | for (next = spd; next < max; next += m->sadb_msg_len * CHUNKsizeof(u_int64_t)) { |
| 507 | m = (struct sadb_msg *)next; |
| 508 | if (m->sadb_msg_len == 0) |
| 509 | break; |
| 510 | |
| 511 | /* Tweak msg type. */ |
| 512 | m->sadb_msg_type = SADB_X_ADDFLOW12; |
| 513 | |
| 514 | if (pfkey_msg_filter(m)) |
| 515 | continue; |
| 516 | |
| 517 | /* Allocate msgbuffer, freed by net_queue(). */ |
| 518 | sendbuf = calloc(m->sadb_msg_len, CHUNKsizeof(u_int64_t)); |
| 519 | if (sendbuf) { |
| 520 | memcpy(sendbuf, m, m->sadb_msg_len * CHUNKsizeof(u_int64_t)); |
| 521 | net_queue(p, MSG_PFKEYDATA1, sendbuf, |
| 522 | m->sadb_msg_len * CHUNKsizeof(u_int64_t)); |
| 523 | log_msg(2, "pfkey_snapshot: sync FLOW %p len " |
| 524 | "%zu to peer %s", m, |
| 525 | m->sadb_msg_len * CHUNKsizeof(u_int64_t), p->name); |
| 526 | } |
| 527 | } |
| 528 | /* Cleanup. */ |
| 529 | freezero(spd, spdsz); |
| 530 | } |
| 531 | |
| 532 | net_ctl_send_endsnap(p); |
| 533 | return; |
| 534 | } |