Mercurial > dropbear
comparison dbutil.c @ 297:79bf1023cf11 agent-client
propagate from branch 'au.asn.ucc.matt.dropbear' (head 0501e6f661b5415eb76f3b312d183c3adfbfb712)
to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 01038174ec27245b51bd43a66c01ad930880f67b)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 21 Mar 2006 16:20:59 +0000 |
parents | ca7e76d981d9 044bc108b9b3 |
children | c1e9c81d1d27 |
comparison
equal
deleted
inserted
replaced
225:ca7e76d981d9 | 297:79bf1023cf11 |
---|---|
108 _dropbear_log(LOG_INFO, fmtbuf, param); | 108 _dropbear_log(LOG_INFO, fmtbuf, param); |
109 | 109 |
110 exit(exitcode); | 110 exit(exitcode); |
111 } | 111 } |
112 | 112 |
113 void fail_assert(const char* expr, const char* file, int line) { | |
114 dropbear_exit("failed assertion (%s:%d): `%s'", file, line, expr); | |
115 } | |
116 | |
113 static void generic_dropbear_log(int UNUSED(priority), const char* format, | 117 static void generic_dropbear_log(int UNUSED(priority), const char* format, |
114 va_list param) { | 118 va_list param) { |
115 | 119 |
116 char printbuf[1024]; | 120 char printbuf[1024]; |
117 | 121 |
147 fprintf(stderr, "\n"); | 151 fprintf(stderr, "\n"); |
148 va_end(param); | 152 va_end(param); |
149 } | 153 } |
150 #endif /* DEBUG_TRACE */ | 154 #endif /* DEBUG_TRACE */ |
151 | 155 |
152 /* Listen on address:port. Unless address is NULL, in which case listen on | 156 static void set_sock_priority(int sock) { |
153 * everything. If called with address == "", we'll listen on localhost/loopback. | 157 |
158 int val; | |
159 | |
160 /* disable nagle */ | |
161 val = 1; | |
162 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val)); | |
163 | |
164 /* set the TOS bit. note that this will fail for ipv6, I can't find any | |
165 * equivalent. */ | |
166 #ifdef IPTOS_LOWDELAY | |
167 val = IPTOS_LOWDELAY; | |
168 setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&val, sizeof(val)); | |
169 #endif | |
170 | |
171 #ifdef SO_PRIORITY | |
172 /* linux specific, sets QoS class. | |
173 * 6 looks to be optimal for interactive traffic (see tc-prio(8) ). */ | |
174 val = 6; | |
175 setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) &val, sizeof(val)); | |
176 #endif | |
177 | |
178 } | |
179 | |
180 /* Listen on address:port. | |
181 * Special cases are address of "" listening on everything, | |
182 * and address of NULL listening on localhost only. | |
154 * Returns the number of sockets bound on success, or -1 on failure. On | 183 * Returns the number of sockets bound on success, or -1 on failure. On |
155 * failure, if errstring wasn't NULL, it'll be a newly malloced error | 184 * failure, if errstring wasn't NULL, it'll be a newly malloced error |
156 * string.*/ | 185 * string.*/ |
157 int dropbear_listen(const char* address, const char* port, | 186 int dropbear_listen(const char* address, const char* port, |
158 int *socks, unsigned int sockcount, char **errstring, int *maxfd) { | 187 int *socks, unsigned int sockcount, char **errstring, int *maxfd) { |
168 | 197 |
169 memset(&hints, 0, sizeof(hints)); | 198 memset(&hints, 0, sizeof(hints)); |
170 hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */ | 199 hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */ |
171 hints.ai_socktype = SOCK_STREAM; | 200 hints.ai_socktype = SOCK_STREAM; |
172 | 201 |
173 if (address && address[0] == '\0') { | 202 // for calling getaddrinfo: |
203 // address == NULL and !AI_PASSIVE: local loopback | |
204 // address == NULL and AI_PASSIVE: all interfaces | |
205 // address != NULL: whatever the address says | |
206 if (!address) { | |
174 TRACE(("dropbear_listen: local loopback")) | 207 TRACE(("dropbear_listen: local loopback")) |
175 address = NULL; | |
176 } else { | 208 } else { |
177 TRACE(("dropbear_listen: not local loopback")) | 209 if (address[0] == '\0') { |
210 TRACE(("dropbear_listen: all interfaces")) | |
211 address = NULL; | |
212 } | |
178 hints.ai_flags = AI_PASSIVE; | 213 hints.ai_flags = AI_PASSIVE; |
179 } | 214 } |
180 err = getaddrinfo(address, port, &hints, &res0); | 215 err = getaddrinfo(address, port, &hints, &res0); |
181 | 216 |
182 if (err) { | 217 if (err) { |
183 if (errstring != NULL && *errstring == NULL) { | 218 if (errstring != NULL && *errstring == NULL) { |
184 int len; | 219 int len; |
185 len = 20 + strlen(gai_strerror(err)); | 220 len = 20 + strlen(gai_strerror(err)); |
186 *errstring = (char*)m_malloc(len); | 221 *errstring = (char*)m_malloc(len); |
187 snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err)); | 222 snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err)); |
223 } | |
224 if (res0) { | |
225 freeaddrinfo(res0); | |
226 res0 = NULL; | |
188 } | 227 } |
189 TRACE(("leave dropbear_listen: failed resolving")) | 228 TRACE(("leave dropbear_listen: failed resolving")) |
190 return -1; | 229 return -1; |
191 } | 230 } |
192 | 231 |
213 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val)); | 252 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val)); |
214 linger.l_onoff = 1; | 253 linger.l_onoff = 1; |
215 linger.l_linger = 5; | 254 linger.l_linger = 5; |
216 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger)); | 255 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger)); |
217 | 256 |
218 /* disable nagle */ | 257 set_sock_priority(sock); |
219 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val)); | |
220 | 258 |
221 if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { | 259 if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { |
222 err = errno; | 260 err = errno; |
223 close(sock); | 261 close(sock); |
224 TRACE(("bind(%s) failed", port)) | 262 TRACE(("bind(%s) failed", port)) |
233 } | 271 } |
234 | 272 |
235 *maxfd = MAX(*maxfd, sock); | 273 *maxfd = MAX(*maxfd, sock); |
236 | 274 |
237 nsock++; | 275 nsock++; |
276 } | |
277 | |
278 if (res0) { | |
279 freeaddrinfo(res0); | |
280 res0 = NULL; | |
238 } | 281 } |
239 | 282 |
240 if (nsock == 0) { | 283 if (nsock == 0) { |
241 if (errstring != NULL && *errstring == NULL) { | 284 if (errstring != NULL && *errstring == NULL) { |
242 int len; | 285 int len; |
341 snprintf(*errstring, len, "Error connecting: %s", strerror(err)); | 384 snprintf(*errstring, len, "Error connecting: %s", strerror(err)); |
342 } | 385 } |
343 TRACE(("Error connecting: %s", strerror(err))) | 386 TRACE(("Error connecting: %s", strerror(err))) |
344 } else { | 387 } else { |
345 /* Success */ | 388 /* Success */ |
346 /* (err is used as a dummy var here) */ | 389 set_sock_priority(sock); |
347 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&err, sizeof(err)); | |
348 } | 390 } |
349 | 391 |
350 freeaddrinfo(res0); | 392 freeaddrinfo(res0); |
351 if (sock > 0 && errstring != NULL && *errstring != NULL) { | 393 if (sock > 0 && errstring != NULL && *errstring != NULL) { |
352 m_free(*errstring); | 394 m_free(*errstring); |
553 } | 595 } |
554 | 596 |
555 } | 597 } |
556 #endif | 598 #endif |
557 | 599 |
558 /* loop until the socket is closed (in case of EINTR) or | 600 /* make sure that the socket closes */ |
559 * we get and error. | 601 void m_close(int fd) { |
560 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ | |
561 int m_close(int fd) { | |
562 | 602 |
563 int val; | 603 int val; |
564 do { | 604 do { |
565 val = close(fd); | 605 val = close(fd); |
566 } while (val < 0 && errno == EINTR); | 606 } while (val < 0 && errno == EINTR); |
567 | 607 |
568 if (val == 0 || errno == EBADF) { | 608 if (val < 0 && errno != EBADF) { |
569 return DROPBEAR_SUCCESS; | 609 /* Linux says EIO can happen */ |
570 } else { | 610 dropbear_exit("Error closing fd %d, %s", fd, strerror(errno)); |
571 return DROPBEAR_FAILURE; | |
572 } | 611 } |
573 } | 612 } |
574 | 613 |
575 void * m_malloc(size_t size) { | 614 void * m_malloc(size_t size) { |
576 | 615 |