File: | programs/pluto/send.c |
Warning: | line 142, column 3 Null pointer passed as an argument to a 'nonnull' parameter |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * sending packets, for libreswan | |||
3 | * | |||
4 | * Copyright (C) 1997 Angelos D. Keromytis. | |||
5 | * Copyright (C) 1998-2002, 2013,2016 D. Hugh Redelmeier <hugh@mimosa.com> | |||
6 | * Copyright (C) 2003-2008 Michael C Richardson <mcr@xelerance.com> | |||
7 | * Copyright (C) 2003-2010 Paul Wouters <paul@xelerance.com> | |||
8 | * Copyright (C) 2008-2009 David McCullough <david_mccullough@securecomputing.com> | |||
9 | * Copyright (C) 2009 Avesh Agarwal <avagarwa@redhat.com> | |||
10 | * Copyright (C) 2010 Tuomo Soini <tis@foobar.fi> | |||
11 | * Copyright (C) 2012-2019 Paul Wouters <pwouters@redhat.com> | |||
12 | * Copyright (C) 2013 Wolfgang Nothdurft <wolfgang@linogate.de> | |||
13 | * Copyright (C) 2016-2019 Andrew Cagney <cagney@gnu.org> | |||
14 | * Copyright (C) 2017-2019 D. Hugh Redelmeier <hugh@mimosa.com> | |||
15 | * Copyright (C) 2019 Antony Antony <antony@phenome.org> | |||
16 | * | |||
17 | * This program is free software; you can redistribute it and/or modify it | |||
18 | * under the terms of the GNU General Public License as published by the | |||
19 | * Free Software Foundation; either version 2 of the License, or (at your | |||
20 | * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>. | |||
21 | * | |||
22 | * This program is distributed in the hope that it will be useful, but | |||
23 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |||
24 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
25 | * for more details. | |||
26 | * | |||
27 | */ | |||
28 | ||||
29 | #include <unistd.h> /* for usleep() */ | |||
30 | #include <errno(*__errno_location ()).h> | |||
31 | ||||
32 | #include "defs.h" | |||
33 | ||||
34 | #include "send.h" | |||
35 | ||||
36 | #include "log.h" | |||
37 | #include "state.h" | |||
38 | #include "server.h" | |||
39 | #include "demux.h" | |||
40 | #include "pluto_stats.h" | |||
41 | #include "ip_endpoint.h" | |||
42 | #include "ip_sockaddr.h" | |||
43 | #include "ip_protocol.h" | |||
44 | #include "iface.h" | |||
45 | ||||
46 | /* send_ike_msg logic is broken into layers. | |||
47 | * The rest of the system thinks it is simple. | |||
48 | * We have three entrypoints that control options | |||
49 | * for reporting write failure and actions on resending (fragment?): | |||
50 | * send_ike_msg(), resend_ike_v1_msg(), and send_keepalive(). | |||
51 | * | |||
52 | * The first two call send_or_resend_ike_msg(). | |||
53 | * That handles an IKE message. | |||
54 | * It calls send_v1_frags() if the message needs to be fragmented. | |||
55 | * Otherwise it calls send_packet() to send it in one gulp. | |||
56 | * | |||
57 | * send_v1_frags() breaks an IKE message into fragments and sends | |||
58 | * them by send_packet(). | |||
59 | * | |||
60 | * send_keepalive() calls send_packet() directly: uses a special | |||
61 | * tiny packet; non-ESP marker does not apply; logging on write error | |||
62 | * is suppressed. | |||
63 | * | |||
64 | * send_packet() sends a UDP packet, possibly prefixed by a non-ESP Marker | |||
65 | * for NATT. It accepts two chunks because this avoids double-copying. | |||
66 | */ | |||
67 | ||||
68 | bool_Bool send_chunks(const char *where, bool_Bool just_a_keepalive, | |||
69 | so_serial_t serialno, /* can be SOS_NOBODY */ | |||
70 | const struct iface_port *interface, | |||
71 | ip_address remote_endpoint, | |||
72 | chunk_t a, chunk_t b) | |||
73 | { | |||
74 | /* NOTE: on system with limited stack, buf could be made static */ | |||
75 | uint8_t buf[MAX_OUTPUT_UDP_SIZE65536]; | |||
76 | ||||
77 | /* Each fragment, if we are doing NATT, needs a non-ESP_Marker prefix. | |||
78 | * natt_bonus is the size of the addition (0 if not needed). | |||
79 | */ | |||
80 | size_t natt_bonus; | |||
81 | ||||
82 | if (interface == NULL((void*)0)) { | |||
83 | libreswan_log("Cannot send packet - interface vanished!")loglog(RC_LOG, "Cannot send packet - interface vanished!"); | |||
84 | return FALSE0; | |||
85 | } | |||
86 | ||||
87 | /* bandaid */ | |||
88 | if (a.ptr == NULL((void*)0)) { | |||
89 | libreswan_log("Cannot send packet - a.ptr is NULL")loglog(RC_LOG, "Cannot send packet - a.ptr is NULL"); | |||
90 | return FALSE0; | |||
91 | } | |||
92 | ||||
93 | /* | |||
94 | * XXX: | |||
95 | * | |||
96 | * Isn't it a bit late to be checking for this? demux should | |||
97 | * have rejected a packet with a bogus remote address, and | |||
98 | * connection should have rejected a bogus address in a | |||
99 | * connection configuration? | |||
100 | * | |||
101 | * Code attempting to call this function with | |||
102 | * hsetportof(port,addr) where addr is invalid also get an | |||
103 | * expecation failed message. | |||
104 | */ | |||
105 | if (isanyaddr(&remote_endpoint)) { | |||
106 | /* not asserting, who knows what nonsense a user can generate */ | |||
107 | endpoint_buf b; | |||
108 | libreswan_log("Will not send packet to bogus address %s",loglog(RC_LOG, "Will not send packet to bogus address %s", str_sensitive_endpoint (&remote_endpoint, &b)) | |||
109 | str_sensitive_endpoint(&remote_endpoint, &b))loglog(RC_LOG, "Will not send packet to bogus address %s", str_sensitive_endpoint (&remote_endpoint, &b)); | |||
110 | return FALSE0; | |||
111 | } | |||
112 | ||||
113 | /* | |||
114 | * If we are doing NATT, so that the other end doesn't mistake | |||
115 | * this message for ESP, each message needs a non-ESP_Marker | |||
116 | * prefix. natt_bonus is the size of the addition (0 if not | |||
117 | * needed). | |||
118 | */ | |||
119 | natt_bonus = !just_a_keepalive && | |||
120 | interface->esp_encapsulation_enabled ? | |||
121 | NON_ESP_MARKER_SIZE4 : 0; | |||
122 | ||||
123 | const uint8_t *ptr; | |||
124 | size_t len = natt_bonus + a.len + b.len; | |||
125 | ssize_t wlen; | |||
126 | ||||
127 | if (len > MAX_OUTPUT_UDP_SIZE65536) { | |||
128 | loglog(RC_LOG_SERIOUS, "send_ike_msg(): really too big %zu bytes", len); | |||
129 | return FALSE0; | |||
130 | } | |||
131 | ||||
132 | if (len != a.len) { | |||
133 | /* copying required */ | |||
134 | ||||
135 | /* 1. non-ESP Marker (0x00 octets) */ | |||
136 | memset(buf, 0x00, natt_bonus); | |||
137 | ||||
138 | /* 2. chunk a */ | |||
139 | memcpy(buf + natt_bonus, a.ptr, a.len); | |||
140 | ||||
141 | /* 3. chunk b */ | |||
142 | memcpy(buf + natt_bonus + a.len, b.ptr, b.len); | |||
| ||||
143 | ||||
144 | ptr = buf; | |||
145 | } else { | |||
146 | ptr = a.ptr; | |||
147 | } | |||
148 | ||||
149 | if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) { | |||
150 | endpoint_buf lb; | |||
151 | endpoint_buf rb; | |||
152 | DBG_log("sending %zu bytes for %s through %s from %s to %s using %s (for #%lu)", | |||
153 | len, where, | |||
154 | interface->ip_dev->id_rname, | |||
155 | str_endpoint(&interface->local_endpoint, &lb), | |||
156 | str_endpoint(&remote_endpoint, &rb), | |||
157 | interface->protocol->name, | |||
158 | serialno); | |||
159 | DBG_dump(NULL((void*)0), ptr, len); | |||
160 | } | |||
161 | ||||
162 | wlen = interface->io->write_packet(interface, ptr, len, &remote_endpoint); | |||
163 | ||||
164 | if (wlen != (ssize_t)len) { | |||
165 | if (!just_a_keepalive) { | |||
166 | endpoint_buf lb; | |||
167 | endpoint_buf rb; | |||
168 | LOG_ERRNO(errno, "send on %s from %s to %s using %s failed in %s",{ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "send on %s from %s to %s using %s failed in %s", interface ->ip_dev->id_rname, str_endpoint(&interface->local_endpoint , &lb), str_sensitive_endpoint(&remote_endpoint, & rb), interface->protocol->name, where); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream (buf); } } | |||
169 | interface->ip_dev->id_rname,{ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "send on %s from %s to %s using %s failed in %s", interface ->ip_dev->id_rname, str_endpoint(&interface->local_endpoint , &lb), str_sensitive_endpoint(&remote_endpoint, & rb), interface->protocol->name, where); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream (buf); } } | |||
170 | str_endpoint(&interface->local_endpoint, &lb),{ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "send on %s from %s to %s using %s failed in %s", interface ->ip_dev->id_rname, str_endpoint(&interface->local_endpoint , &lb), str_sensitive_endpoint(&remote_endpoint, & rb), interface->protocol->name, where); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream (buf); } } | |||
171 | str_sensitive_endpoint(&remote_endpoint, &rb),{ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "send on %s from %s to %s using %s failed in %s", interface ->ip_dev->id_rname, str_endpoint(&interface->local_endpoint , &lb), str_sensitive_endpoint(&remote_endpoint, & rb), interface->protocol->name, where); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream (buf); } } | |||
172 | interface->protocol->name,{ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "send on %s from %s to %s using %s failed in %s", interface ->ip_dev->id_rname, str_endpoint(&interface->local_endpoint , &lb), str_sensitive_endpoint(&remote_endpoint, & rb), interface->protocol->name, where); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream (buf); } } | |||
173 | where){ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "send on %s from %s to %s using %s failed in %s", interface ->ip_dev->id_rname, str_endpoint(&interface->local_endpoint , &lb), str_sensitive_endpoint(&remote_endpoint, & rb), interface->protocol->name, where); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream (buf); } }; | |||
174 | } | |||
175 | return FALSE0; | |||
176 | } | |||
177 | ||||
178 | pstats_ike_out_bytes += len; | |||
179 | ||||
180 | /* Send a duplicate packet when this impair is enabled - used for testing */ | |||
181 | if (impair.jacob_two_two) { | |||
182 | /* sleep for half a second, and second another packet */ | |||
183 | usleep(500000); | |||
184 | endpoint_buf b; | |||
185 | endpoint_buf ib; | |||
186 | DBG_log("JACOB 2-2: resending %zu bytes for %s through %s from %s to %s:", | |||
187 | len, | |||
188 | where, | |||
189 | interface->ip_dev->id_rname, | |||
190 | str_endpoint(&interface->local_endpoint, &ib), | |||
191 | str_endpoint(&remote_endpoint, &b)); | |||
192 | ||||
193 | ip_sockaddr remote_sa = sockaddr_from_endpoint(&remote_endpoint); | |||
194 | wlen = sendto(interface->fd, ptr, len, 0, &remote_sa.sa.sa, remote_sa.len); | |||
195 | if (wlen != (ssize_t)len) { | |||
196 | if (!just_a_keepalive) { | |||
197 | LOG_ERRNO(errno,{ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "sendto on %s to %s failed in %s", interface->ip_dev ->id_rname, str_endpoint(&remote_endpoint, &b), where ); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror (e_)); jambuf_to_error_stream(buf); } } | |||
198 | "sendto on %s to %s failed in %s",{ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "sendto on %s to %s failed in %s", interface->ip_dev ->id_rname, str_endpoint(&remote_endpoint, &b), where ); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror (e_)); jambuf_to_error_stream(buf); } } | |||
199 | interface->ip_dev->id_rname,{ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "sendto on %s to %s failed in %s", interface->ip_dev ->id_rname, str_endpoint(&remote_endpoint, &b), where ); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror (e_)); jambuf_to_error_stream(buf); } } | |||
200 | str_endpoint(&remote_endpoint, &b),{ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "sendto on %s to %s failed in %s", interface->ip_dev ->id_rname, str_endpoint(&remote_endpoint, &b), where ); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror (e_)); jambuf_to_error_stream(buf); } } | |||
201 | where){ int e_ = (*__errno_location ()); for (char lswbuf[((size_t) 1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_ = ( (void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf ), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf = ((void*)0)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam (buf, "sendto on %s to %s failed in %s", interface->ip_dev ->id_rname, str_endpoint(&remote_endpoint, &b), where ); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror (e_)); jambuf_to_error_stream(buf); } }; | |||
202 | } | |||
203 | return FALSE0; | |||
204 | } | |||
205 | } | |||
206 | return TRUE1; | |||
207 | } | |||
208 | ||||
209 | bool_Bool send_chunk(const char *where, so_serial_t serialno, /* can be SOS_NOBODY */ | |||
210 | const struct iface_port *interface, | |||
211 | ip_address remote_endpoint, chunk_t packet) | |||
212 | { | |||
213 | return send_chunks(where, FALSE0, serialno, | |||
214 | interface, remote_endpoint, | |||
215 | packet, EMPTY_CHUNK((const chunk_t) { .ptr = ((void*)0), .len = 0 })); | |||
216 | } | |||
217 | ||||
218 | bool_Bool send_chunks_using_state(struct state *st, const char *where, | |||
219 | chunk_t a, chunk_t b) | |||
220 | { | |||
221 | return send_chunks(where, FALSE0, | |||
222 | st->st_serialno, st->st_interface, | |||
223 | st->st_remote_endpoint, a, b); | |||
224 | } | |||
225 | ||||
226 | bool_Bool send_chunk_using_state(struct state *st, const char *where, chunk_t packet) | |||
227 | { | |||
228 | return send_chunks_using_state(st, where, packet, EMPTY_CHUNK((const chunk_t) { .ptr = ((void*)0), .len = 0 })); | |||
229 | } | |||
230 | ||||
231 | bool_Bool send_ike_msg_without_recording(struct state *st, pb_stream *pbs, | |||
232 | const char *where) | |||
233 | { | |||
234 | return send_chunk_using_state(st, where, same_out_pbs_as_chunk(pbs)); | |||
| ||||
235 | } | |||
236 | ||||
237 | /* | |||
238 | * send keepalive is special in two ways: | |||
239 | * We don't want send errors logged (too noisy). | |||
240 | * We don't want the packet prefixed with a non-ESP Marker. | |||
241 | */ | |||
242 | bool_Bool send_keepalive(struct state *st, const char *where) | |||
243 | { | |||
244 | static unsigned char ka_payload = 0xff; | |||
245 | ||||
246 | return send_chunks(where, TRUE1, | |||
247 | st->st_serialno, st->st_interface, | |||
248 | st->st_remote_endpoint, | |||
249 | THING_AS_CHUNK(ka_payload)chunk2(&(ka_payload), sizeof(ka_payload)), | |||
250 | EMPTY_CHUNK((const chunk_t) { .ptr = ((void*)0), .len = 0 })); | |||
251 | } |