Patrick Williams | b48b7b4 | 2016-08-17 15:04:38 -0500 | [diff] [blame^] | 1 | racoon: Resend UPDATE message when received EINTR message |
| 2 | |
| 3 | Upstream-Status: Pending |
| 4 | |
| 5 | While kernel is processing the UPDATE message which is sent from racoon, |
| 6 | it maybe interrupted by system signal and if this case happens, |
| 7 | kernel responds with an EINTR message to racoon and kernel fails to |
| 8 | establish the corresponding SA. |
| 9 | Fix this problem by resend the UPDATE message when EINTR(Interrupted |
| 10 | system call) error happens. |
| 11 | |
| 12 | Signed-off-by: Xufeng Zhang <xufeng.zhang@windriver.com> |
| 13 | --- |
| 14 | --- a/src/libipsec/libpfkey.h |
| 15 | +++ b/src/libipsec/libpfkey.h |
| 16 | @@ -92,6 +92,12 @@ |
| 17 | u_int16_t ctxstrlen; /* length of security context string */ |
| 18 | }; |
| 19 | |
| 20 | +struct update_msg_info { |
| 21 | + struct sadb_msg *update_msg; |
| 22 | + int so; |
| 23 | + int len; |
| 24 | +}; |
| 25 | + |
| 26 | /* The options built into libipsec */ |
| 27 | extern int libipsec_opt; |
| 28 | #define LIBIPSEC_OPT_NATT 0x01 |
| 29 | --- a/src/libipsec/pfkey.c |
| 30 | +++ b/src/libipsec/pfkey.c |
| 31 | @@ -1219,7 +1219,8 @@ |
| 32 | } |
| 33 | #endif |
| 34 | |
| 35 | - |
| 36 | +struct update_msg_info update_msg_send = {NULL, 0, 0}; |
| 37 | + |
| 38 | /* sending SADB_ADD or SADB_UPDATE message to the kernel */ |
| 39 | static int |
| 40 | pfkey_send_x1(struct pfkey_send_sa_args *sa_parms) |
| 41 | @@ -1483,10 +1484,24 @@ |
| 42 | |
| 43 | /* send message */ |
| 44 | len = pfkey_send(sa_parms->so, newmsg, len); |
| 45 | - free(newmsg); |
| 46 | |
| 47 | - if (len < 0) |
| 48 | - return -1; |
| 49 | + if (newmsg->sadb_msg_type == SADB_UPDATE) { |
| 50 | + if (update_msg_send.update_msg) |
| 51 | + free(update_msg_send.update_msg); |
| 52 | + update_msg_send.update_msg = newmsg; |
| 53 | + update_msg_send.so = sa_parms->so; |
| 54 | + update_msg_send.len = len; |
| 55 | + |
| 56 | + if (len < 0) { |
| 57 | + free(update_msg_send.update_msg); |
| 58 | + update_msg_send.update_msg = NULL; |
| 59 | + return -1; |
| 60 | + } |
| 61 | + } else { |
| 62 | + free(newmsg); |
| 63 | + if (len < 0) |
| 64 | + return -1; |
| 65 | + } |
| 66 | |
| 67 | __ipsec_errcode = EIPSEC_NO_ERROR; |
| 68 | return len; |
| 69 | --- a/src/racoon/session.c |
| 70 | +++ b/src/racoon/session.c |
| 71 | @@ -100,6 +100,8 @@ |
| 72 | |
| 73 | #include "sainfo.h" |
| 74 | |
| 75 | +extern struct update_msg_info update_msg_send; |
| 76 | + |
| 77 | struct fd_monitor { |
| 78 | int (*callback)(void *ctx, int fd); |
| 79 | void *ctx; |
| 80 | @@ -348,6 +350,11 @@ |
| 81 | close_sockets(); |
| 82 | backupsa_clean(); |
| 83 | |
| 84 | + if (update_msg_send.update_msg) { |
| 85 | + free(update_msg_send.update_msg); |
| 86 | + update_msg_send.update_msg = NULL; |
| 87 | + } |
| 88 | + |
| 89 | plog(LLV_INFO, LOCATION, NULL, "racoon process %d shutdown\n", getpid()); |
| 90 | |
| 91 | exit(0); |
| 92 | --- a/src/racoon/pfkey.c |
| 93 | +++ b/src/racoon/pfkey.c |
| 94 | @@ -103,10 +103,12 @@ |
| 95 | #include "crypto_openssl.h" |
| 96 | #include "grabmyaddr.h" |
| 97 | +#include "../libipsec/libpfkey.h" |
| 98 | |
| 99 | #if defined(SADB_X_EALG_RIJNDAELCBC) && !defined(SADB_X_EALG_AESCBC) |
| 100 | #define SADB_X_EALG_AESCBC SADB_X_EALG_RIJNDAELCBC |
| 101 | #endif |
| 102 | |
| 103 | +extern struct update_msg_info update_msg_send; |
| 104 | /* prototype */ |
| 105 | static u_int ipsecdoi2pfkey_aalg __P((u_int)); |
| 106 | static u_int ipsecdoi2pfkey_ealg __P((u_int)); |
| 107 | @@ -253,6 +255,13 @@ |
| 108 | s_pfkey_type(msg->sadb_msg_type), |
| 109 | strerror(msg->sadb_msg_errno)); |
| 110 | |
| 111 | + if (msg->sadb_msg_errno == EINTR && |
| 112 | + update_msg_send.update_msg) { |
| 113 | + plog(LLV_DEBUG, LOCATION, NULL, |
| 114 | + "pfkey update resend\n"); |
| 115 | + send(update_msg_send.so, (void *)update_msg_send.update_msg, (socklen_t)update_msg_send.len, 0); |
| 116 | + } |
| 117 | + |
| 118 | goto end; |
| 119 | } |
| 120 | |
| 121 | @@ -498,6 +507,11 @@ |
| 122 | { |
| 123 | flushsp(); |
| 124 | |
| 125 | + if (update_msg_send.update_msg) { |
| 126 | + free(update_msg_send.update_msg); |
| 127 | + update_msg_send.update_msg = NULL; |
| 128 | + } |
| 129 | + |
| 130 | if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) { |
| 131 | plog(LLV_ERROR, LOCATION, NULL, |
| 132 | "libipsec sending spddump failed: %s\n", |
| 133 | @@ -1295,6 +1309,8 @@ |
| 134 | return 0; |
| 135 | } |
| 136 | |
| 137 | +int update_received = 0; |
| 138 | + |
| 139 | static int |
| 140 | pk_recvupdate(mhp) |
| 141 | caddr_t *mhp; |
| 142 | @@ -1307,6 +1323,13 @@ |
| 143 | int incomplete = 0; |
| 144 | struct saproto *pr; |
| 145 | |
| 146 | + update_received = 1; |
| 147 | + |
| 148 | + if (update_msg_send.update_msg) { |
| 149 | + free(update_msg_send.update_msg); |
| 150 | + update_msg_send.update_msg = NULL; |
| 151 | + } |
| 152 | + |
| 153 | /* ignore this message because of local test mode. */ |
| 154 | if (f_local) |
| 155 | return 0; |
| 156 | @@ -4163,3 +4186,8 @@ |
| 157 | |
| 158 | return buf; |
| 159 | } |
| 160 | + |
| 161 | +int receive_from_isakmp() |
| 162 | +{ |
| 163 | + return pfkey_handler(NULL, lcconf->sock_pfkey); |
| 164 | +} |
| 165 | --- a/src/racoon/pfkey.h |
| 166 | +++ b/src/racoon/pfkey.h |
| 167 | @@ -71,5 +71,6 @@ |
| 168 | extern u_int32_t pk_getseq __P((void)); |
| 169 | extern const char *sadbsecas2str |
| 170 | __P((struct sockaddr *, struct sockaddr *, int, u_int32_t, int)); |
| 171 | +extern int receive_from_isakmp __P((void)); |
| 172 | |
| 173 | #endif /* _PFKEY_H */ |
| 174 | --- a/src/racoon/isakmp_quick.c |
| 175 | +++ b/src/racoon/isakmp_quick.c |
| 176 | @@ -774,6 +774,8 @@ |
| 177 | return error; |
| 178 | } |
| 179 | |
| 180 | +extern int update_received; |
| 181 | + |
| 182 | /* |
| 183 | * send to responder |
| 184 | * HDR*, HASH(3) |
| 185 | @@ -892,6 +894,11 @@ |
| 186 | } |
| 187 | plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n"); |
| 188 | |
| 189 | + while (!update_received) |
| 190 | + receive_from_isakmp(); |
| 191 | + |
| 192 | + update_received = 0; |
| 193 | + |
| 194 | /* Do ADD for responder */ |
| 195 | if (pk_sendadd(iph2) < 0) { |
| 196 | plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n"); |
| 197 | @@ -1035,6 +1042,11 @@ |
| 198 | } |
| 199 | plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n"); |
| 200 | |
| 201 | + while (!update_received) |
| 202 | + receive_from_isakmp(); |
| 203 | + |
| 204 | + update_received = 0; |
| 205 | + |
| 206 | /* Do ADD for responder */ |
| 207 | if (pk_sendadd(iph2) < 0) { |
| 208 | plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n"); |
| 209 | @@ -1989,6 +2001,11 @@ |
| 210 | } |
| 211 | plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n"); |
| 212 | |
| 213 | + while (!update_received) |
| 214 | + receive_from_isakmp(); |
| 215 | + |
| 216 | + update_received = 0; |
| 217 | + |
| 218 | /* Do ADD for responder */ |
| 219 | if (pk_sendadd(iph2) < 0) { |
| 220 | plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n"); |