Mercurial > dropbear
comparison dbutil.c @ 579:8c737cd7c1af
merge of '48fdaa8706d1acda35e9d564adc9a1fbc96c18c8'
and '658fd03abd21e0da7c4c89b9fff9dc693c72daae'
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sat, 27 Feb 2010 11:53:18 +0000 |
parents | 005530560594 |
children | a98a2138364a |
comparison
equal
deleted
inserted
replaced
577:69e98c45db7c | 579:8c737cd7c1af |
---|---|
293 | 293 |
294 TRACE(("leave dropbear_listen: success, %d socks bound", nsock)) | 294 TRACE(("leave dropbear_listen: success, %d socks bound", nsock)) |
295 return nsock; | 295 return nsock; |
296 } | 296 } |
297 | 297 |
298 /* Connect to a given unix socket. The socket is blocking */ | |
299 #ifdef ENABLE_CONNECT_UNIX | |
300 int connect_unix(const char* path) { | |
301 struct sockaddr_un addr; | |
302 int fd = -1; | |
303 | |
304 memset((void*)&addr, 0x0, sizeof(addr)); | |
305 addr.sun_family = AF_UNIX; | |
306 strlcpy(addr.sun_path, path, sizeof(addr.sun_path)); | |
307 fd = socket(PF_UNIX, SOCK_STREAM, 0); | |
308 if (fd < 0) { | |
309 TRACE(("Failed to open unix socket")) | |
310 return -1; | |
311 } | |
312 if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { | |
313 TRACE(("Failed to connect to '%s' socket", path)) | |
314 return -1; | |
315 } | |
316 return fd; | |
317 } | |
318 #endif | |
319 | |
298 /* Connect via TCP to a host. Connection will try ipv4 or ipv6, will | 320 /* Connect via TCP to a host. Connection will try ipv4 or ipv6, will |
299 * return immediately if nonblocking is set. On failure, if errstring | 321 * return immediately if nonblocking is set. On failure, if errstring |
300 * wasn't null, it will be a newly malloced error message */ | 322 * wasn't null, it will be a newly malloced error message */ |
301 | 323 |
302 /* TODO: maxfd */ | 324 /* TODO: maxfd */ |
339 err = errno; | 361 err = errno; |
340 continue; | 362 continue; |
341 } | 363 } |
342 | 364 |
343 if (nonblocking) { | 365 if (nonblocking) { |
344 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { | 366 setnonblocking(sock); |
345 close(sock); | |
346 sock = -1; | |
347 if (errstring != NULL && *errstring == NULL) { | |
348 *errstring = m_strdup("Failed non-blocking"); | |
349 } | |
350 TRACE(("Failed non-blocking: %s", strerror(errno))) | |
351 continue; | |
352 } | |
353 } | 367 } |
354 | 368 |
355 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { | 369 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { |
356 if (errno == EINPROGRESS && nonblocking) { | 370 if (errno == EINPROGRESS && nonblocking) { |
357 TRACE(("Connect in progress")) | 371 TRACE(("Connect in progress")) |
523 } | 537 } |
524 | 538 |
525 execv(usershell, argv); | 539 execv(usershell, argv); |
526 } | 540 } |
527 | 541 |
542 void get_socket_address(int fd, char **local_host, char **local_port, | |
543 char **remote_host, char **remote_port, int host_lookup) | |
544 { | |
545 struct sockaddr_storage addr; | |
546 socklen_t addrlen; | |
547 | |
548 if (local_host || local_port) { | |
549 addrlen = sizeof(addr); | |
550 if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) < 0) { | |
551 dropbear_exit("Failed socket address: %s", strerror(errno)); | |
552 } | |
553 getaddrstring(&addr, local_host, local_port, host_lookup); | |
554 } | |
555 if (remote_host || remote_port) { | |
556 addrlen = sizeof(addr); | |
557 if (getpeername(fd, (struct sockaddr*)&addr, &addrlen) < 0) { | |
558 dropbear_exit("Failed socket address: %s", strerror(errno)); | |
559 } | |
560 getaddrstring(&addr, remote_host, remote_port, host_lookup); | |
561 } | |
562 } | |
563 | |
528 /* Return a string representation of the socket address passed. The return | 564 /* Return a string representation of the socket address passed. The return |
529 * value is allocated with malloc() */ | 565 * value is allocated with malloc() */ |
530 unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) { | 566 void getaddrstring(struct sockaddr_storage* addr, |
531 | 567 char **ret_host, char **ret_port, |
532 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; | 568 int host_lookup) { |
533 char *retstring = NULL; | 569 |
570 char host[NI_MAXHOST+1], serv[NI_MAXSERV+1]; | |
571 unsigned int len; | |
534 int ret; | 572 int ret; |
535 unsigned int len; | 573 |
574 int flags = NI_NUMERICSERV | NI_NUMERICHOST; | |
575 | |
576 #ifndef DO_HOST_LOOKUP | |
577 host_lookup = 0; | |
578 #endif | |
579 | |
580 if (host_lookup) { | |
581 flags = NI_NUMERICSERV; | |
582 } | |
536 | 583 |
537 len = sizeof(struct sockaddr_storage); | 584 len = sizeof(struct sockaddr_storage); |
538 /* Some platforms such as Solaris 8 require that len is the length | 585 /* Some platforms such as Solaris 8 require that len is the length |
539 * of the specific structure. Some older linux systems (glibc 2.1.3 | 586 * of the specific structure. Some older linux systems (glibc 2.1.3 |
540 * such as debian potato) have sockaddr_storage.__ss_family instead | 587 * such as debian potato) have sockaddr_storage.__ss_family instead |
548 len = sizeof(struct sockaddr_in6); | 595 len = sizeof(struct sockaddr_in6); |
549 } | 596 } |
550 #endif | 597 #endif |
551 #endif | 598 #endif |
552 | 599 |
553 ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf), | 600 ret = getnameinfo((struct sockaddr*)addr, len, host, sizeof(host)-1, |
554 sbuf, sizeof(sbuf), NI_NUMERICSERV | NI_NUMERICHOST); | 601 serv, sizeof(serv)-1, flags); |
555 | 602 |
556 if (ret != 0) { | 603 if (ret != 0) { |
557 /* This is a fairly bad failure - it'll fallback to IP if it | 604 if (host_lookup) { |
558 * just can't resolve */ | 605 /* On some systems (Darwin does it) we get EINTR from getnameinfo |
559 dropbear_exit("failed lookup (%d, %d)", ret, errno); | 606 * somehow. Eew. So we'll just return the IP, since that doesn't seem |
560 } | 607 * to exhibit that behaviour. */ |
561 | 608 getaddrstring(addr, ret_host, ret_port, 0); |
562 if (withport) { | 609 return; |
563 len = strlen(hbuf) + 2 + strlen(sbuf); | 610 } else { |
564 retstring = (char*)m_malloc(len); | 611 /* if we can't do a numeric lookup, something's gone terribly wrong */ |
565 snprintf(retstring, len, "%s:%s", hbuf, sbuf); | 612 dropbear_exit("Failed lookup: %s", gai_strerror(ret)); |
566 } else { | 613 } |
567 retstring = m_strdup(hbuf); | 614 } |
568 } | 615 |
569 | 616 if (ret_host) { |
570 return retstring; | 617 *ret_host = m_strdup(host); |
571 | 618 } |
572 } | 619 if (ret_port) { |
573 | 620 *ret_port = m_strdup(serv); |
574 /* Get the hostname corresponding to the address addr. On failure, the IP | 621 } |
575 * address is returned. The return value is allocated with strdup() */ | |
576 char* getaddrhostname(struct sockaddr_storage * addr) { | |
577 | |
578 char hbuf[NI_MAXHOST]; | |
579 char sbuf[NI_MAXSERV]; | |
580 int ret; | |
581 unsigned int len; | |
582 #ifdef DO_HOST_LOOKUP | |
583 const int flags = NI_NUMERICSERV; | |
584 #else | |
585 const int flags = NI_NUMERICHOST | NI_NUMERICSERV; | |
586 #endif | |
587 | |
588 len = sizeof(struct sockaddr_storage); | |
589 /* Some platforms such as Solaris 8 require that len is the length | |
590 * of the specific structure. */ | |
591 #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY | |
592 if (addr->ss_family == AF_INET) { | |
593 len = sizeof(struct sockaddr_in); | |
594 } | |
595 #ifdef AF_INET6 | |
596 if (addr->ss_family == AF_INET6) { | |
597 len = sizeof(struct sockaddr_in6); | |
598 } | |
599 #endif | |
600 #endif | |
601 | |
602 | |
603 ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf), | |
604 sbuf, sizeof(sbuf), flags); | |
605 | |
606 if (ret != 0) { | |
607 /* On some systems (Darwin does it) we get EINTR from getnameinfo | |
608 * somehow. Eew. So we'll just return the IP, since that doesn't seem | |
609 * to exhibit that behaviour. */ | |
610 return getaddrstring(addr, 0); | |
611 } | |
612 | |
613 return m_strdup(hbuf); | |
614 } | 622 } |
615 | 623 |
616 #ifdef DEBUG_TRACE | 624 #ifdef DEBUG_TRACE |
617 void printhex(const char * label, const unsigned char * buf, int len) { | 625 void printhex(const char * label, const unsigned char * buf, int len) { |
618 | 626 |