mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 06:48:05 +01:00
leave the socks handshake on the inbuf until it's complete
this paves the way for supporting socks5 and other handshakes it also removes those pesky AP-only variables from connection_t also hacked a fix for a bug where some streams weren't ending properly -- maybe because marked connections weren't flushing properly? svn:r472
This commit is contained in:
parent
b97945e411
commit
078c5ab617
8 changed files with 149 additions and 150 deletions
|
@ -126,8 +126,8 @@ int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datale
|
|||
*buf_datalen -= write_result;
|
||||
*buf_flushlen -= write_result;
|
||||
memmove(*buf, *buf+write_result, *buf_datalen);
|
||||
// log_fn(LOG_DEBUG,"flushed %d bytes, %d ready to flush, %d remain.",
|
||||
// write_result,*buf_flushlen,*buf_datalen);
|
||||
log_fn(LOG_DEBUG,"%d: flushed %d bytes, %d ready to flush, %d remain.",
|
||||
s,write_result,*buf_flushlen,*buf_datalen);
|
||||
return *buf_flushlen;
|
||||
/* XXX USE_TLS should change to return write_result like any sane function would */
|
||||
}
|
||||
|
@ -257,6 +257,86 @@ int fetch_from_buf_http(char *buf, int *buf_datalen,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* There is a (possibly incomplete) socks handshake on *buf, of the
|
||||
* forms
|
||||
* socks4: "socksheader || username\0".
|
||||
* socks4a: "socksheader || username\0 || destaddr\0".
|
||||
* If it's a complete and valid handshake, and destaddr fits in addr_out,
|
||||
* then pull the handshake off the buf, assign to addr_out and port_out,
|
||||
* and return 1.
|
||||
* If it's invalid or too big, return -1.
|
||||
* Else it's not all there yet, change nothing return 0.
|
||||
*/
|
||||
int fetch_from_buf_socks(char *buf, int *buf_datalen,
|
||||
char *addr_out, int max_addrlen,
|
||||
uint16_t *port_out) {
|
||||
socks4_t *socks4_info;
|
||||
char tmpbuf[512];
|
||||
uint16_t port;
|
||||
enum {socks4, socks4a } socks_prot = socks4a;
|
||||
char *next, *startaddr;
|
||||
|
||||
if(*buf_datalen < sizeof(socks4_t)) /* basic info available? */
|
||||
return 0; /* not yet */
|
||||
|
||||
socks4_info = (socks4_t *)buf;
|
||||
|
||||
if(socks4_info->version != 4) {
|
||||
log_fn(LOG_NOTICE,"Unrecognized version %d.",socks4_info->version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(socks4_info->command != 1) { /* not a connect? we don't support it. */
|
||||
log_fn(LOG_NOTICE,"command %d not '1'.",socks4_info->command);
|
||||
return -1;
|
||||
}
|
||||
|
||||
port = ntohs(*(uint16_t*)&socks4_info->destport);
|
||||
if(!port) {
|
||||
log_fn(LOG_NOTICE,"Port is zero.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(socks4_info->destip[0] || socks4_info->destip[1] ||
|
||||
socks4_info->destip[2] || !socks4_info->destip[3]) { /* not 0.0.0.x */
|
||||
log_fn(LOG_NOTICE,"destip not in form 0.0.0.x.");
|
||||
sprintf(tmpbuf, "%d.%d.%d.%d", socks4_info->destip[0],
|
||||
socks4_info->destip[1], socks4_info->destip[2], socks4_info->destip[3]);
|
||||
if(max_addrlen <= strlen(tmpbuf)) {
|
||||
log_fn(LOG_DEBUG,"socks4-addr too long.");
|
||||
return -1;
|
||||
}
|
||||
log_fn(LOG_DEBUG,"Successfully read destip (%s)", tmpbuf);
|
||||
socks_prot = socks4;
|
||||
}
|
||||
|
||||
next = memchr(buf+sizeof(socks4_t), 0, *buf_datalen);
|
||||
if(!next) {
|
||||
log_fn(LOG_DEBUG,"Username not here yet.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
startaddr = next+1;
|
||||
if(socks_prot == socks4a) {
|
||||
next = memchr(startaddr, 0, buf+*buf_datalen-startaddr);
|
||||
if(!next) {
|
||||
log_fn(LOG_DEBUG,"Destaddr not here yet.");
|
||||
return 0;
|
||||
}
|
||||
if(max_addrlen <= next-startaddr) {
|
||||
log_fn(LOG_DEBUG,"Destaddr not here yet.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
log_fn(LOG_DEBUG,"Everything is here. Success.");
|
||||
*port_out = port;
|
||||
strcpy(addr_out, socks_prot == socks4 ? tmpbuf : startaddr);
|
||||
*buf_datalen -= (next-buf+1); /* next points to the final \0 on inbuf */
|
||||
memmove(buf, next+1, *buf_datalen);
|
||||
// log_fn(LOG_DEBUG,"buf_datalen is now %d:'%s'",*buf_datalen,buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int find_on_inbuf(char *string, int string_len,
|
||||
char *buf, int buf_datalen) {
|
||||
/* find first instance of needle 'string' on haystack 'buf'. return how
|
||||
|
|
|
@ -807,8 +807,9 @@ int circuit_send_next_onion_skin(circuit_t *circ) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* take the 'extend' cell, pull out addr/port plus the onion skin. Connect
|
||||
* to the next hop, and pass it the onion skin in a create cell.
|
||||
/* take the 'extend' cell, pull out addr/port plus the onion skin. Make
|
||||
* sure we're connected to the next hop, and pass it the onion skin in
|
||||
* a create cell.
|
||||
*/
|
||||
int circuit_extend(cell_t *cell, circuit_t *circ) {
|
||||
connection_t *n_conn;
|
||||
|
|
|
@ -98,8 +98,6 @@ void connection_free(connection_t *conn) {
|
|||
buf_free(conn->outbuf);
|
||||
if(conn->address)
|
||||
free(conn->address);
|
||||
if(conn->dest_addr)
|
||||
free(conn->dest_addr);
|
||||
|
||||
if(connection_speaks_cells(conn)) {
|
||||
directory_set_dirty();
|
||||
|
@ -527,13 +525,6 @@ int connection_fetch_from_buf(char *string, int len, connection_t *conn) {
|
|||
return fetch_from_buf(string, len, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen);
|
||||
}
|
||||
|
||||
int connection_fetch_from_buf_http(connection_t *conn,
|
||||
char *headers_out, int max_headerlen,
|
||||
char *body_out, int max_bodylen) {
|
||||
return fetch_from_buf_http(conn->inbuf,&conn->inbuf_datalen,
|
||||
headers_out, max_headerlen, body_out, max_bodylen);
|
||||
}
|
||||
|
||||
int connection_find_on_inbuf(char *string, int len, connection_t *conn) {
|
||||
return find_on_inbuf(string, len, conn->inbuf, conn->inbuf_datalen);
|
||||
}
|
||||
|
@ -782,13 +773,6 @@ void assert_connection_ok(connection_t *conn, time_t now)
|
|||
/* XXX unchecked, package window, deliver window. */
|
||||
}
|
||||
|
||||
if (conn->type != CONN_TYPE_AP) {
|
||||
assert(!conn->socks_version);
|
||||
assert(!conn->read_username);
|
||||
assert(!conn->dest_addr);
|
||||
assert(!conn->dest_port);
|
||||
}
|
||||
|
||||
switch(conn->type)
|
||||
{
|
||||
case CONN_TYPE_OR_LISTENER:
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
extern or_options_t options; /* command-line and config-file options */
|
||||
|
||||
static int connection_ap_handshake_process_socks(connection_t *conn);
|
||||
static int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
|
||||
static int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ,
|
||||
char *destaddr, uint16_t destport);
|
||||
static int connection_ap_handshake_socks_reply(connection_t *conn, char result);
|
||||
|
||||
static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
|
||||
|
@ -17,16 +18,6 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
|
|||
#define SOCKS4_REQUEST_IDENT_FAILED 92
|
||||
#define SOCKS4_REQUEST_IDENT_CONFLICT 93
|
||||
|
||||
/* structure of a socks client operation */
|
||||
typedef struct {
|
||||
unsigned char version; /* socks version number */
|
||||
unsigned char command; /* command code */
|
||||
unsigned char destport[2]; /* destination port, network order */
|
||||
unsigned char destip[4]; /* destination address */
|
||||
/* userid follows, terminated by a NULL */
|
||||
/* dest host follows, terminated by a NULL */
|
||||
} socks4_t;
|
||||
|
||||
int connection_edge_process_inbuf(connection_t *conn) {
|
||||
|
||||
assert(conn);
|
||||
|
@ -441,86 +432,24 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) {
|
|||
}
|
||||
|
||||
static int connection_ap_handshake_process_socks(connection_t *conn) {
|
||||
socks4_t socks4_info;
|
||||
circuit_t *circ;
|
||||
char tmpbuf[512];
|
||||
int amt;
|
||||
char destaddr[200];
|
||||
uint16_t destport;
|
||||
|
||||
assert(conn);
|
||||
|
||||
log_fn(LOG_DEBUG,"entered.");
|
||||
|
||||
if(!conn->socks_version) { /* try to pull it in */
|
||||
|
||||
if(conn->inbuf_datalen < sizeof(socks4_t)) /* basic info available? */
|
||||
return 0; /* not yet */
|
||||
|
||||
connection_fetch_from_buf((char *)&socks4_info,sizeof(socks4_t),conn);
|
||||
|
||||
log_fn(LOG_DEBUG,"Successfully read socks info.");
|
||||
|
||||
if(socks4_info.version != 4) {
|
||||
log_fn(LOG_NOTICE,"Unrecognized version %d.",socks4_info.version);
|
||||
switch(fetch_from_buf_socks(conn->inbuf,&conn->inbuf_datalen,
|
||||
destaddr, sizeof(destaddr), &destport)) {
|
||||
case -1:
|
||||
log_fn(LOG_DEBUG,"Fetching socks handshake failed. Closing.");
|
||||
connection_ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
||||
return -1;
|
||||
}
|
||||
conn->socks_version = socks4_info.version;
|
||||
|
||||
if(socks4_info.command != 1) { /* not a connect? we don't support it. */
|
||||
log_fn(LOG_NOTICE,"command %d not '1'.",socks4_info.command);
|
||||
connection_ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn->dest_port = ntohs(*(uint16_t*)&socks4_info.destport);
|
||||
if(!conn->dest_port) {
|
||||
log_fn(LOG_NOTICE,"Port is zero.");
|
||||
connection_ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
||||
return -1;
|
||||
}
|
||||
log_fn(LOG_NOTICE,"Dest port is %d.",conn->dest_port);
|
||||
|
||||
if(socks4_info.destip[0] ||
|
||||
socks4_info.destip[1] ||
|
||||
socks4_info.destip[2] ||
|
||||
!socks4_info.destip[3]) { /* not 0.0.0.x */
|
||||
log_fn(LOG_NOTICE,"destip not in form 0.0.0.x.");
|
||||
sprintf(tmpbuf, "%d.%d.%d.%d", socks4_info.destip[0],
|
||||
socks4_info.destip[1], socks4_info.destip[2], socks4_info.destip[3]);
|
||||
conn->dest_addr = strdup(tmpbuf);
|
||||
log_fn(LOG_DEBUG,"Successfully read destip (%s)", conn->dest_addr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!conn->read_username) { /* the socks spec says we've got to read stuff until we get a null */
|
||||
amt = connection_find_on_inbuf("\0", 1, conn);
|
||||
if(amt < 0) /* not there yet */
|
||||
case 0:
|
||||
log_fn(LOG_DEBUG,"Fetching socks handshake, not all here yet. Ignoring.");
|
||||
return 0;
|
||||
if(amt > 500) {
|
||||
log_fn(LOG_NOTICE,"username too long.");
|
||||
connection_ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
||||
return -1;
|
||||
}
|
||||
connection_fetch_from_buf(tmpbuf,amt,conn);
|
||||
conn->read_username = 1;
|
||||
log_fn(LOG_DEBUG,"Successfully read username.");
|
||||
}
|
||||
|
||||
if(!conn->dest_addr) { /* no dest_addr found yet */
|
||||
amt = connection_find_on_inbuf("\0", 1, conn);
|
||||
if(amt < 0) /* not there yet */
|
||||
return 0;
|
||||
if(amt > 500) {
|
||||
log_fn(LOG_NOTICE,"dest_addr too long.");
|
||||
connection_ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
||||
return -1;
|
||||
}
|
||||
connection_fetch_from_buf(tmpbuf,amt,conn);
|
||||
|
||||
conn->dest_addr = strdup(tmpbuf);
|
||||
log_fn(LOG_NOTICE,"successfully read dest addr '%s'",
|
||||
conn->dest_addr);
|
||||
/* case 1, fall through */
|
||||
}
|
||||
|
||||
/* find the circuit that we should use, if there is one. */
|
||||
|
@ -542,7 +471,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
|
|||
assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
|
||||
conn->cpath_layer = circ->cpath->prev;
|
||||
|
||||
if(connection_ap_handshake_send_begin(conn, circ) < 0) {
|
||||
if(connection_ap_handshake_send_begin(conn, circ, destaddr, destport) < 0) {
|
||||
circuit_close(circ);
|
||||
return -1;
|
||||
}
|
||||
|
@ -550,11 +479,12 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ) {
|
||||
/* deliver the destaddr:destport in a relay cell */
|
||||
static int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ,
|
||||
char *destaddr, uint16_t destport) {
|
||||
cell_t cell;
|
||||
|
||||
memset(&cell, 0, sizeof(cell_t));
|
||||
/* deliver the dest_addr in a relay cell */
|
||||
|
||||
cell.command = CELL_RELAY;
|
||||
cell.aci = circ->n_aci;
|
||||
SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_BEGIN);
|
||||
|
@ -566,7 +496,7 @@ static int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *
|
|||
memcpy(cell.payload+RELAY_HEADER_SIZE, ap_conn->stream_id, STREAM_ID_SIZE);
|
||||
cell.length =
|
||||
snprintf(cell.payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE, CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE-STREAM_ID_SIZE,
|
||||
"%s:%d", ap_conn->dest_addr, ap_conn->dest_port) +
|
||||
"%s:%d", destaddr, destport) +
|
||||
1 + STREAM_ID_SIZE + RELAY_HEADER_SIZE;
|
||||
log_fn(LOG_DEBUG,"Sending relay cell (id %d) to begin stream %d.", *(int *)(cell.payload+1),*(int *)ap_conn->stream_id);
|
||||
if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, ap_conn->cpath_layer) < 0) {
|
||||
|
|
|
@ -141,7 +141,8 @@ int connection_dir_process_inbuf(connection_t *conn) {
|
|||
switch(conn->state) {
|
||||
case DIR_CONN_STATE_CLIENT_READING_GET:
|
||||
/* kill it, but first process the_directory and learn about new routers. */
|
||||
switch(connection_fetch_from_buf_http(conn, NULL, 0, the_directory, MAX_DIR_SIZE)) {
|
||||
switch(fetch_from_buf_http(conn->inbuf,&conn->inbuf_datalen,
|
||||
NULL, 0, the_directory, MAX_DIR_SIZE)) {
|
||||
case -1: /* overflow */
|
||||
log_fn(LOG_DEBUG,"'get' response too large. Failing.");
|
||||
return -1;
|
||||
|
@ -191,7 +192,8 @@ static int directory_handle_command(connection_t *conn) {
|
|||
|
||||
assert(conn && conn->type == CONN_TYPE_DIR);
|
||||
|
||||
switch(connection_fetch_from_buf_http(conn, headers, sizeof(headers), body, sizeof(body))) {
|
||||
switch(fetch_from_buf_http(conn->inbuf,&conn->inbuf_datalen,
|
||||
headers, sizeof(headers), body, sizeof(body))) {
|
||||
case -1: /* overflow */
|
||||
log_fn(LOG_DEBUG,"input too large. Failing.");
|
||||
return -1;
|
||||
|
|
|
@ -301,9 +301,11 @@ static void check_conn_marked(int i) {
|
|||
assert(conn);
|
||||
if(conn->marked_for_close) {
|
||||
log_fn(LOG_DEBUG,"Cleaning up connection.");
|
||||
if(conn->s >= 0) { /* might be an incomplete exit connection */
|
||||
if(conn->s >= 0) { /* might be an incomplete edge connection */
|
||||
/* FIXME there's got to be a better way to check for this -- and make other checks? */
|
||||
connection_flush_buf(conn); /* flush it first */
|
||||
connection_handle_write(conn); /* flush it first */
|
||||
if(connection_wants_to_flush(conn)) /* not done flushing */
|
||||
log_fn(LOG_WARNING,"Conn (socket %d) still wants to flush. Losing %d bytes!",conn->s, conn->inbuf_datalen);
|
||||
}
|
||||
connection_remove(conn);
|
||||
connection_free(conn);
|
||||
|
|
22
src/or/or.h
22
src/or/or.h
|
@ -215,6 +215,16 @@
|
|||
/* legal characters in a filename */
|
||||
#define CONFIG_LEGAL_FILENAME_CHARACTERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/"
|
||||
|
||||
/* structure of a socks client operation */
|
||||
typedef struct {
|
||||
unsigned char version; /* socks version number */
|
||||
unsigned char command; /* command code */
|
||||
unsigned char destport[2]; /* destination port, network order */
|
||||
unsigned char destip[4]; /* destination address */
|
||||
/* userid follows, terminated by a NULL */
|
||||
/* dest host follows, terminated by a NULL */
|
||||
} socks4_t;
|
||||
|
||||
typedef uint16_t aci_t;
|
||||
|
||||
/* cell definition */
|
||||
|
@ -293,12 +303,6 @@ struct connection_t {
|
|||
|
||||
int done_sending; /* for half-open connections; not used currently */
|
||||
int done_receiving;
|
||||
|
||||
/* Used only by AP connections: */
|
||||
char socks_version; /* what socks version are they speaking at me? */
|
||||
char read_username; /* have i read the username yet? */
|
||||
char *dest_addr; /* what address and port are this stream's destination? */
|
||||
uint16_t dest_port; /* host order */
|
||||
};
|
||||
|
||||
typedef struct connection_t connection_t;
|
||||
|
@ -443,6 +447,9 @@ int fetch_from_buf(char *string, int string_len, char **buf, int *buflen, int *b
|
|||
int fetch_from_buf_http(char *buf, int *buf_datalen,
|
||||
char *headers_out, int max_headerlen,
|
||||
char *body_out, int max_bodylen);
|
||||
int fetch_from_buf_socks(char *buf, int *buf_datalen,
|
||||
char *addr_out, int max_addrlen,
|
||||
uint16_t *port_out);
|
||||
int find_on_inbuf(char *string, int string_len, char *buf, int buf_datalen);
|
||||
|
||||
/********************************* circuit.c ***************************/
|
||||
|
@ -510,9 +517,6 @@ int connection_handle_read(connection_t *conn);
|
|||
int connection_read_to_buf(connection_t *conn);
|
||||
|
||||
int connection_fetch_from_buf(char *string, int len, connection_t *conn);
|
||||
int connection_fetch_from_buf_http(connection_t *conn,
|
||||
char *headers_out, int max_headerlen,
|
||||
char *body_out, int max_bodylen);
|
||||
int connection_find_on_inbuf(char *string, int len, connection_t *conn);
|
||||
|
||||
int connection_wants_to_flush(connection_t *conn);
|
||||
|
|
|
@ -42,39 +42,35 @@ router_resolve_directory(directory_t *dir);
|
|||
int learn_my_address(struct sockaddr_in *me) {
|
||||
/* local host information */
|
||||
char localhostname[512];
|
||||
static struct hostent *localhost;
|
||||
struct hostent *localhost;
|
||||
static struct sockaddr_in answer;
|
||||
static int already_learned=0;
|
||||
|
||||
if(already_learned) {
|
||||
memset(me,0,sizeof(struct sockaddr_in));
|
||||
me->sin_family = AF_INET;
|
||||
memcpy((void *)&me->sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
|
||||
me->sin_port = htons((uint16_t) options.ORPort);
|
||||
return 0;
|
||||
if(!already_learned) {
|
||||
/* obtain local host information */
|
||||
if(gethostname(localhostname,512) < 0) {
|
||||
log_fn(LOG_ERR,"Error obtaining local hostname");
|
||||
return -1;
|
||||
}
|
||||
log_fn(LOG_DEBUG,"localhostname is '%s'.",localhostname);
|
||||
localhost = gethostbyname(localhostname);
|
||||
if (!localhost) {
|
||||
log_fn(LOG_ERR,"Error obtaining local host info.");
|
||||
return -1;
|
||||
}
|
||||
memset(&answer,0,sizeof(struct sockaddr_in));
|
||||
answer.sin_family = AF_INET;
|
||||
memcpy((void *)&answer.sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
|
||||
answer.sin_port = htons((uint16_t) options.ORPort);
|
||||
log_fn(LOG_DEBUG,"chose address as '%s'.",inet_ntoa(answer.sin_addr));
|
||||
if (!strncmp("127.",inet_ntoa(answer.sin_addr), 4) &&
|
||||
strcasecmp(localhostname, "localhost")) {
|
||||
/* We're a loopback IP but we're not called localhost. Uh oh! */
|
||||
log_fn(LOG_WARNING, "Got a loopback address: /etc/hosts may be wrong");
|
||||
}
|
||||
already_learned = 1;
|
||||
}
|
||||
|
||||
/* obtain local host information */
|
||||
if(gethostname(localhostname,512) < 0) {
|
||||
log_fn(LOG_ERR,"Error obtaining local hostname");
|
||||
return -1;
|
||||
}
|
||||
log_fn(LOG_DEBUG,"localhostname is '%s'.",localhostname);
|
||||
localhost = gethostbyname(localhostname);
|
||||
if (!localhost) {
|
||||
log_fn(LOG_ERR,"Error obtaining local host info.");
|
||||
return -1;
|
||||
}
|
||||
memset(me,0,sizeof(struct sockaddr_in));
|
||||
me->sin_family = AF_INET;
|
||||
memcpy((void *)&me->sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
|
||||
me->sin_port = htons((uint16_t) options.ORPort);
|
||||
log_fn(LOG_DEBUG,"chose address as '%s'.",inet_ntoa(me->sin_addr));
|
||||
if (!strncmp("127.",inet_ntoa(me->sin_addr), 4) &&
|
||||
strcasecmp(localhostname, "localhost")) {
|
||||
/* We're a loopback IP but we're not called localhost. Uh oh! */
|
||||
log_fn(LOG_WARNING, "Got a loopback address: /etc/hosts may be wrong");
|
||||
}
|
||||
already_learned=1;
|
||||
memcpy(me,&answer,sizeof(struct sockaddr_in));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue