Exemple #1
0
void handle_packet(apacket *p, atransport *t)
{
    asocket *s;

    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
            ((char*) (&(p->msg.command)))[1],
            ((char*) (&(p->msg.command)))[2],
            ((char*) (&(p->msg.command)))[3]);
    print_packet("recv", p);

    switch(p->msg.command){
    case A_SYNC:
        if(p->msg.arg0){
            send_packet(p, t);
            if(HOST) send_connect(t);
        } else {
            t->connection_state = CS_OFFLINE;
            handle_offline(t);
            send_packet(p, t);
        }
        return;

    case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
            /* XXX verify version, etc */
        if(t->connection_state != CS_OFFLINE) {
            t->connection_state = CS_OFFLINE;
            handle_offline(t);
        }
        parse_banner((char*) p->data, t);
        handle_online();
        if(!HOST) send_connect(t);
        break;

    case A_OPEN: /* OPEN(local-id, 0, "destination") */
        if(t->connection_state != CS_OFFLINE) {
            char *name = (char*) p->data;
            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
            s = create_local_service_socket(name);
            if(s == 0) {
                send_close(0, p->msg.arg0, t);
            } else {
                s->peer = create_remote_socket(p->msg.arg0, t);
                s->peer->peer = s;
                send_ready(s->id, s->peer->id, t);
                s->ready(s);
            }
        }
        break;

    case A_OKAY: /* READY(local-id, remote-id, "") */
        if(t->connection_state != CS_OFFLINE) {
            if((s = find_local_socket(p->msg.arg1))) {
                if(s->peer == 0) {
                    s->peer = create_remote_socket(p->msg.arg0, t);
                    s->peer->peer = s;
                }
                s->ready(s);
            }
        }
        break;

    case A_CLSE: /* CLOSE(local-id, remote-id, "") */
        if(t->connection_state != CS_OFFLINE) {
            if((s = find_local_socket(p->msg.arg1))) {
                s->close(s);
            }
        }
        break;

    case A_WRTE:
        if(t->connection_state != CS_OFFLINE) {
            if((s = find_local_socket(p->msg.arg1))) {
                unsigned rid = p->msg.arg0;
                p->len = p->msg.data_length;

                if(s->enqueue(s, p) == 0) {
                    D("Enqueue the socket\n");
                    send_ready(s->id, rid, t);
                }
                return;
            }
        }
        break;

    default:
        printf("handle_packet: what is %08x?!\n", p->msg.command);
    }

    put_apacket(p);
}
Exemple #2
0
void handle_packet(apacket *p, atransport *t)
{
    asocket *s;

    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
            ((char*) (&(p->msg.command)))[1],
            ((char*) (&(p->msg.command)))[2],
            ((char*) (&(p->msg.command)))[3]);
    print_packet("recv", p);

    switch(p->msg.command){
    case A_SYNC:
        if(p->msg.arg0){
            send_packet(p, t);
            if(HOST) send_connect(t);
        } else {
            t->connection_state = CS_OFFLINE;
            handle_offline(t);
            send_packet(p, t);
        }
        return;

    case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
            /* XXX verify version, etc */
        if(t->connection_state != CS_OFFLINE) {
            t->connection_state = CS_OFFLINE;
            handle_offline(t);
        }

        parse_banner((char*) p->data, t);

        if (HOST || !auth_enabled) {
            handle_online(t);
            if(!HOST) send_connect(t);
        } else {
		#ifndef NO_AUTH
            send_auth_request(t);
		#endif
        }
        break;

	#ifndef NO_AUTH
    case A_AUTH:
        if (p->msg.arg0 == ADB_AUTH_TOKEN) {
            t->key = adb_auth_nextkey(t->key);
            if (t->key) {
                send_auth_response(p->data, p->msg.data_length, t);
            } else {
                /* No more private keys to try, send the public key */
                send_auth_publickey(t);
            }
        } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
            if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
                adb_auth_verified(t);
                t->failed_auth_attempts = 0;
            } else {
                if (t->failed_auth_attempts++ > 10)
                    adb_sleep_ms(1000);
                send_auth_request(t);
            }
        } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
            adb_auth_confirm_key(p->data, p->msg.data_length, t);
        }
        break;
	#endif

    case A_OPEN: /* OPEN(local-id, 0, "destination") */
        if (t->online) {
            char *name = (char*) p->data;
            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
            s = create_local_service_socket(name);
            if(s == 0) {
                send_close(0, p->msg.arg0, t);
            } else {
                s->peer = create_remote_socket(p->msg.arg0, t);
                s->peer->peer = s;
                send_ready(s->id, s->peer->id, t);
                s->ready(s);
            }
        }
        break;

    case A_OKAY: /* READY(local-id, remote-id, "") */
        if (t->online) {
            if((s = find_local_socket(p->msg.arg1))) {
                if(s->peer == 0) {
                    s->peer = create_remote_socket(p->msg.arg0, t);
                    s->peer->peer = s;
                }
                s->ready(s);
            }
        }
        break;

    case A_CLSE: /* CLOSE(local-id, remote-id, "") */
        if (t->online) {
            D("CLOSE(%d, %d, \"\")\n", p->msg.arg0, p->msg.arg1);
            if((s = find_local_socket(p->msg.arg1))) {
                s->close(s);
            }
        }
        break;

    case A_WRTE:
        if (t->online) {
            if((s = find_local_socket(p->msg.arg1))) {
                unsigned rid = p->msg.arg0;
                p->len = p->msg.data_length;

                if(s->enqueue(s, p) == 0) {
                    D("Enqueue the socket\n");
                    send_ready(s->id, rid, t);
                }
                return;
            }
        }
        break;

    default:
        printf("handle_packet: what is %08x?!\n", p->msg.command);
    }

    put_apacket(p);
}
void handle_packet(apacket *p, atransport *t)
{
    asocket *s;

    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
            ((char*) (&(p->msg.command)))[1],
            ((char*) (&(p->msg.command)))[2],
            ((char*) (&(p->msg.command)))[3]);
    print_packet("recv", p);

    switch(p->msg.command){
    case A_SYNC:
        if(p->msg.arg0){
            send_packet(p, t);
            if(HOST) send_connect(t);
        } else {
            t->connection_state = CS_OFFLINE;
            handle_offline(t);
            send_packet(p, t);
        }
        return;

    case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
            /* XXX verify version, etc */
        if(t->connection_state != CS_OFFLINE) {
            t->connection_state = CS_OFFLINE;
            handle_offline(t);
        }

        parse_banner(reinterpret_cast<const char*>(p->data), t);

        if (HOST || !auth_required) {
            handle_online(t);
            if (!HOST) send_connect(t);
        } else {
            send_auth_request(t);
        }
        break;

    case A_AUTH:
        if (p->msg.arg0 == ADB_AUTH_TOKEN) {
            t->connection_state = CS_UNAUTHORIZED;
            t->key = adb_auth_nextkey(t->key);
            if (t->key) {
                send_auth_response(p->data, p->msg.data_length, t);
            } else {
                /* No more private keys to try, send the public key */
                send_auth_publickey(t);
            }
        } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
            if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
                adb_auth_verified(t);
                t->failed_auth_attempts = 0;
            } else {
                if (t->failed_auth_attempts++ > 10)
                    adb_sleep_ms(1000);
                send_auth_request(t);
            }
        } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
            adb_auth_confirm_key(p->data, p->msg.data_length, t);
        }
        break;

    case A_OPEN: /* OPEN(local-id, 0, "destination") */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
            char *name = (char*) p->data;
            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
            s = create_local_service_socket(name);
            if(s == 0) {
                send_close(0, p->msg.arg0, t);
            } else {
                s->peer = create_remote_socket(p->msg.arg0, t);
                s->peer->peer = s;
                send_ready(s->id, s->peer->id, t);
                s->ready(s);
            }
        }
        break;

    case A_OKAY: /* READY(local-id, remote-id, "") */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
            if((s = find_local_socket(p->msg.arg1, 0))) {
                if(s->peer == 0) {
                    /* On first READY message, create the connection. */
                    s->peer = create_remote_socket(p->msg.arg0, t);
                    s->peer->peer = s;
                    s->ready(s);
                } else if (s->peer->id == p->msg.arg0) {
                    /* Other READY messages must use the same local-id */
                    s->ready(s);
                } else {
                    D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
                      p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
                }
            }
        }
        break;

    case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */
        if (t->online && p->msg.arg1 != 0) {
            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
                /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
                 * a failed OPEN only. However, due to a bug in previous ADB
                 * versions, CLOSE(0, remote-id, "") was also used for normal
                 * CLOSE() operations.
                 *
                 * This is bad because it means a compromised adbd could
                 * send packets to close connections between the host and
                 * other devices. To avoid this, only allow this if the local
                 * socket has a peer on the same transport.
                 */
                if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
                    D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
                      p->msg.arg1, t->serial, s->peer->transport->serial);
                } else {
                    s->close(s);
                }
            }
        }
        break;

    case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
                unsigned rid = p->msg.arg0;
                p->len = p->msg.data_length;

                if(s->enqueue(s, p) == 0) {
                    D("Enqueue the socket\n");
                    send_ready(s->id, rid, t);
                }
                return;
            }
        }
        break;

    default:
        printf("handle_packet: what is %08x?!\n", p->msg.command);
    }

    put_apacket(p);
}
void handle_packet(apacket *p, atransport *t)
{
    D("handle_packet() %c%c%c%c", ((char*) (&(p->msg.command)))[0],
            ((char*) (&(p->msg.command)))[1],
            ((char*) (&(p->msg.command)))[2],
            ((char*) (&(p->msg.command)))[3]);
    print_packet("recv", p);

    switch(p->msg.command){
    case A_SYNC:
        if (p->msg.arg0){
            send_packet(p, t);
#if ADB_HOST
            send_connect(t);
#endif
        } else {
            t->connection_state = kCsOffline;
            handle_offline(t);
            send_packet(p, t);
        }
        return;

    case A_CNXN:  // CONNECT(version, maxdata, "system-id-string")
        handle_new_connection(t, p);
        break;

    case A_AUTH:
        if (p->msg.arg0 == ADB_AUTH_TOKEN) {
            t->connection_state = kCsUnauthorized;
            send_auth_response(p->data, p->msg.data_length, t);
        } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
            if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) {
                adb_auth_verified(t);
                t->failed_auth_attempts = 0;
            } else {
                if (t->failed_auth_attempts++ > 256) adb_sleep_ms(1000);
                send_auth_request(t);
            }
        } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
            adb_auth_confirm_key(p->data, p->msg.data_length, t);
        }
        break;

    case A_OPEN: /* OPEN(local-id, 0, "destination") */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
            char *name = (char*) p->data;
            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
            asocket* s = create_local_service_socket(name, t);
            if (s == nullptr) {
                send_close(0, p->msg.arg0, t);
            } else {
                s->peer = create_remote_socket(p->msg.arg0, t);
                s->peer->peer = s;
                send_ready(s->id, s->peer->id, t);
                s->ready(s);
            }
        }
        break;

    case A_OKAY: /* READY(local-id, remote-id, "") */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
            asocket* s = find_local_socket(p->msg.arg1, 0);
            if (s) {
                if(s->peer == 0) {
                    /* On first READY message, create the connection. */
                    s->peer = create_remote_socket(p->msg.arg0, t);
                    s->peer->peer = s;
                    s->ready(s);
                } else if (s->peer->id == p->msg.arg0) {
                    /* Other READY messages must use the same local-id */
                    s->ready(s);
                } else {
                    D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s",
                      p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
                }
            } else {
                // When receiving A_OKAY from device for A_OPEN request, the host server may
                // have closed the local socket because of client disconnection. Then we need
                // to send A_CLSE back to device to close the service on device.
                send_close(p->msg.arg1, p->msg.arg0, t);
            }
        }
        break;

    case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */
        if (t->online && p->msg.arg1 != 0) {
            asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0);
            if (s) {
                /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
                 * a failed OPEN only. However, due to a bug in previous ADB
                 * versions, CLOSE(0, remote-id, "") was also used for normal
                 * CLOSE() operations.
                 *
                 * This is bad because it means a compromised adbd could
                 * send packets to close connections between the host and
                 * other devices. To avoid this, only allow this if the local
                 * socket has a peer on the same transport.
                 */
                if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
                    D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s",
                      p->msg.arg1, t->serial, s->peer->transport->serial);
                } else {
                    s->close(s);
                }
            }
        }
        break;

    case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
            asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0);
            if (s) {
                unsigned rid = p->msg.arg0;
                p->len = p->msg.data_length;

                if (s->enqueue(s, p) == 0) {
                    D("Enqueue the socket");
                    send_ready(s->id, rid, t);
                }
                return;
            }
        }
        break;

    default:
        printf("handle_packet: what is %08x?!\n", p->msg.command);
    }

    put_apacket(p);
}
Exemple #5
0
void adb_auth_verified(atransport *t)
{
    handle_online(t);
    send_connect(t);
}
Exemple #6
0
void connect_do(void *pri_work, const ip_report_t *r) {
	char shost_s[32];
	union {
		void *ptr;
		send_pri_workunit_t *w;
		uint8_t *inc;
	} w_u;
	union {
		void *ptr;
		connection_status_t *c;
	} c_u;
	union {
		const uint8_t *packet;
		const ip_report_t *r;
		const uint16_t *len;
	} r_u;
	struct in_addr ia;
	uint64_t state_key=0;
	size_t dlen=0, pk_len=0;
	uint32_t dhost=0, shost=0;
	uint16_t sport=0, dport=0;

	if (r == NULL) {
		PANIC("r ptr NULL");
	}
	if (state_tbl == NULL) {
		PANIC("state table null");
	}
	if (pri_work == NULL) {
		PANIC("pri_work NULL");
	}

	if (r->magic != IP_REPORT_MAGIC) {
		ERR("wrong magic number for IP report");
		return;
	}

	state_key=get_connectionkey(r);

	dhost=r->host_addr;
	dport=r->sport;
	sport=r->dport;
	shost=r->send_addr;

	if (rbfind(state_tbl, state_key, &c_u.ptr) > 0) {
		DBG(M_CON, "connection with flags are %s status is %d", strtcpflgs(r->type), c_u.c->status);

		r_u.r=r;

		if (r_u.r->doff) {
			pk_len=r_u.r->doff;
			r_u.packet += sizeof(ip_report_t);
			if (*r_u.len != pk_len) {
				ERR("report is damaged?, packet seems broken");
				return;
			}
			else {
				r_u.len++;

				dlen=try_and_extract_tcp_data(r_u.packet, pk_len, c_u.c);
				if (dlen > 0) {
					c_u.c->tseq += dlen;
				}
			}
		}

		if (c_u.c->m_tstamp == 0 || c_u.c->t_tstamp == 0) {
			c_u.c->m_tstamp=0;
			c_u.c->t_tstamp=0;
		}
		else {
			c_u.c->m_tstamp++; /* XXX good enough for testing */
		}


		if (dlen < c_u.c->window) c_u.c->window -= dlen;

		if (r->type & TH_RST) {
			c_u.c->status=U_TCP_CLOSE;
			s->stats.stream_remote_abort++;
			a_conns--;
		}

		switch (c_u.c->status) {
			case U_TCP_ESTABLISHED:

				if (r->type & TH_PSH) {
					w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
					w_u.w->magic=PRI_4SEND_MAGIC;
					w_u.w->dhost=dhost;
					w_u.w->dport=dport;
					w_u.w->sport=sport;
					w_u.w->shost=c_u.c->send_ip;
					w_u.w->tseq=c_u.c->tseq;
					w_u.w->mseq=c_u.c->mseq;
					w_u.w->window_size=c_u.c->window;
					w_u.w->flags=TH_ACK|TH_FIN;
					w_u.w->doff=0;
					w_u.w->t_tstamp=c_u.c->t_tstamp;
					w_u.w->m_tstamp=c_u.c->m_tstamp;
					c_u.c->m_tstamp++;

					DBG(M_CON, "setting connection state into FIN_WAIT2 and sending ACK|FIN");

					c_u.c->status=U_TCP_FIN_WAIT2;

					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;
					c_u.c->mseq++;
					w_u.ptr=NULL;
				}
				else if (r->type & TH_FIN) {

					c_u.c->tseq += 1; /* FIN eats a seq ;] */

					w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
					w_u.w->magic=PRI_4SEND_MAGIC;
					w_u.w->dhost=dhost;
					w_u.w->dport=dport;
					w_u.w->sport=sport;
					w_u.w->shost=c_u.c->send_ip;
					w_u.w->tseq=c_u.c->tseq;
					w_u.w->mseq=c_u.c->mseq;
					w_u.w->window_size=c_u.c->window;
					w_u.w->flags=TH_ACK;
					w_u.w->doff=0;
					w_u.w->t_tstamp=c_u.c->t_tstamp;
					w_u.w->m_tstamp=c_u.c->m_tstamp;

					DBG(M_CON, "acking FIN");

					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;

					w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
					w_u.w->magic=PRI_4SEND_MAGIC;
					w_u.w->dhost=dhost;
					w_u.w->dport=dport;
					w_u.w->sport=sport;
					w_u.w->shost=c_u.c->send_ip;
					w_u.w->tseq=c_u.c->tseq;
					w_u.w->mseq=c_u.c->mseq;
					w_u.w->window_size=c_u.c->window;
					w_u.w->flags=TH_ACK|TH_FIN;
					w_u.w->doff=0;
					w_u.w->t_tstamp=c_u.c->t_tstamp;
					w_u.w->m_tstamp=c_u.c->m_tstamp;

					c_u.c->m_tstamp++;

					DBG(M_CON, "setting connection into state closed and sending ACK|FIN");
					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;

					c_u.c->status=U_TCP_CLOSE;

					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;
					w_u.ptr=NULL;
					c_u.c->mseq++;
					a_conns--;
				}
				break; /* U_TCP_ESTABLISHED: */

			case U_TCP_CLOSE:
				if (r->type == TH_ACK) {
					break;
				}

				DBG(M_CON, "reseting a packet type %s (no connection entry)", strtcpflgs(r->type));

				s->stats.stream_closed_alien_pkt++;

				w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
				w_u.w->magic=PRI_4SEND_MAGIC;
				w_u.w->dhost=dhost;
				w_u.w->dport=dport;
				w_u.w->sport=sport;
				w_u.w->shost=c_u.c->send_ip;
				w_u.w->tseq=c_u.c->tseq;
				w_u.w->mseq=c_u.c->mseq;
				w_u.w->window_size=c_u.c->window;
				w_u.w->flags=TH_RST;
				w_u.w->doff=0;
				w_u.w->t_tstamp=c_u.c->t_tstamp;
				w_u.w->m_tstamp=c_u.c->m_tstamp;
				c_u.c->m_tstamp++;

				DBG(M_CON, "reseting packed to closed connection");
				fifo_push(pri_work, w_u.ptr);
				s->stats.stream_segments_sent++;
				w_u.ptr=NULL;
				break; /* U_TCP_CLOSE */

			case U_TCP_FIN_WAIT2:

				if (r->type & TH_FIN) {
					/* ok its closed both ways, lets ack the fin and be done with it */

					c_u.c->tseq += 1;

					w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
					w_u.w->magic=PRI_4SEND_MAGIC;
					w_u.w->dhost=dhost;
					w_u.w->dport=dport;
					w_u.w->sport=sport;
					w_u.w->shost=c_u.c->send_ip;
					w_u.w->tseq=c_u.c->tseq;
					w_u.w->mseq=c_u.c->mseq;
					w_u.w->window_size=c_u.c->window;
					w_u.w->flags=TH_ACK;
					w_u.w->doff=0;
					w_u.w->t_tstamp=c_u.c->t_tstamp;
					w_u.w->m_tstamp=c_u.c->m_tstamp;
					c_u.c->m_tstamp++;

					c_u.c->status=U_TCP_CLOSE;

					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;
					w_u.ptr=NULL;
					DBG(M_CON, "Setting connection to closed and acking final fin");
				}
				break; /* U_TCP_FIN_WAIT2 */
# if 0
				if (r->type & (TH_ACK|TH_SYN)) {
				}
				break;
			case U_TCP_FIN_WAIT1:
			case U_TCP_FIN_WAIT2:
			case U_TCP_CLOSING:
			case U_TCP_TIME_WAIT:
			case U_TCP_CLOSE_WAIT:
			case U_TCP_LAST_ACK:
			case U_TCP_CLOSE:
# endif
			default:
				ERR("I have no code. I have no code");
				break;
		}

	} /* found in state table */
	else if ((r->type & (TH_ACK|TH_SYN)) == (TH_ACK|TH_SYN)) { /* should it be in state table */
		DBG(M_CON, "Connection with flags %s", strtcpflgs(r->type));

		/* yes this is a new connection */
		c_u.ptr=xmalloc(sizeof(connection_status_t));
		memset(c_u.ptr, 0, sizeof(connection_status_t));

		c_u.c->status=U_TCP_ESTABLISHED;

		c_u.c->send_ip=shost; /* Our IP */
		c_u.c->recv_len=0;
		c_u.c->send_len=0;
		c_u.c->send_buf=NULL;
		c_u.c->recv_buf=NULL;
		c_u.c->recv_stseq=0;
		c_u.c->tseq=r->tseq;
		c_u.c->mseq=r->mseq;
		c_u.c->window=r->window_size; /* XXX wscale */
		c_u.c->t_tstamp=r->t_tstamp;
		c_u.c->m_tstamp=r->m_tstamp;
		c_u.c->ack_pending=1;

		if (GET_IMMEDIATE()) {
			ia.s_addr=shost;
			snprintf(shost_s, sizeof(shost_s) -1, "%s", inet_ntoa(ia));
			ia.s_addr=dhost;
			VRB(0, "connected %s:%u -> %s:%u", shost_s, sport, inet_ntoa(ia), dport);
		}

		s->stats.stream_connections_est++;

		rbinsert(state_tbl, state_key, c_u.ptr);
		a_conns++;

		send_connect(state_key, c_u.c, pri_work, r);
	} /* looks like something we want to connect to ;] */
	else {
		s->stats.stream_completely_alien_packet++;
		DBG(M_CON, "ignoring packet with flags %s", strtcpflgs(r->type));
	}

	return;
}
Exemple #7
0
	void i2p_stream::read_line(error_code const& e, boost::shared_ptr<handler_type> h)
	{
		TORRENT_ASSERT(m_magic == 0x1337);
#if defined TORRENT_ASIO_DEBUGGING
		complete_async("i2p_stream::read_line");
#endif
		if (handle_error(e, h)) return;

		int read_pos = m_buffer.size();

		// look for \n which means end of the response
		if (m_buffer[read_pos - 1] != '\n')
		{
#if defined TORRENT_ASIO_DEBUGGING
			add_outstanding_async("i2p_stream::read_line");
#endif
			// read another byte from the socket
			m_buffer.resize(read_pos + 1);
			async_read(m_sock, boost::asio::buffer(&m_buffer[read_pos], 1)
				, boost::bind(&i2p_stream::read_line, this, _1, h));
			return;
		}
		m_buffer[read_pos - 1] = 0;

		if (m_command == cmd_incoming)
		{
			// this is the line containing the destination
			// of the incoming connection in an accept call
			m_dest = &m_buffer[0];
			(*h)(e);
			std::vector<char>().swap(m_buffer);
			return;
		}

		error_code invalid_response(i2p_error::parse_failed
			, get_i2p_category());

		// null-terminate the string and parse it
		m_buffer.push_back(0);
		char* ptr = &m_buffer[0];
		char* next = ptr;

		char const* expect1 = 0;
		char const* expect2 = 0;

		switch (m_state)
		{
			case read_hello_response:
				expect1 = "HELLO";
				expect2 = "REPLY";
				break;
			case read_connect_response:
			case read_accept_response:
				expect1 = "STREAM";
				expect2 = "STATUS";
				break;
			case read_session_create_response:
				expect1 = "SESSION";
				expect2 = "STATUS";
				break;
			case read_name_lookup_response:
				expect1 = "NAMING";
				expect2 = "REPLY";
				break;
		}

//		fprintf(stderr, "<<< %s\n", &m_buffer[0]);
		ptr = string_tokenize(next, ' ', &next);
		if (ptr == 0 || expect1 == 0 || strcmp(expect1, ptr)) { handle_error(invalid_response, h); return; }
		ptr = string_tokenize(next, ' ', &next);
		if (ptr == 0 || expect2 == 0 || strcmp(expect2, ptr)) { handle_error(invalid_response, h); return; }

		int result = 0;
//		char const* message = 0;
//		float version = 3.0f;

		for(;;)
		{
			char* name = string_tokenize(next, '=', &next);
			if (name == 0) break;
//			fprintf(stderr, "name=\"%s\"\n", name);
			char* ptr2 = string_tokenize(next, ' ', &next);
			if (ptr2 == 0) { handle_error(invalid_response, h); return; }
//			fprintf(stderr, "value=\"%s\"\n", ptr2);

			if (strcmp("RESULT", name) == 0)
			{
				if (strcmp("OK", ptr2) == 0)
					result = i2p_error::no_error;
				else if (strcmp("CANT_REACH_PEER", ptr2) == 0)
					result = i2p_error::cant_reach_peer;
				else if (strcmp("I2P_ERROR", ptr2) == 0)
					result = i2p_error::i2p_error;
				else if (strcmp("INVALID_KEY", ptr2) == 0)
					result = i2p_error::invalid_key;
				else if (strcmp("INVALID_ID", ptr2) == 0)
					result = i2p_error::invalid_id;
				else if (strcmp("TIMEOUT", ptr2) == 0)
					result = i2p_error::timeout;
				else if (strcmp("KEY_NOT_FOUND", ptr2) == 0)
					result = i2p_error::key_not_found;
				else if (strcmp("DUPLICATED_ID", ptr2) == 0)
					result = i2p_error::duplicated_id;
				else
					result = i2p_error::num_errors; // unknown error
			}
			else if (strcmp("MESSAGE", name) == 0)
			{
//				message = ptr2;
			}
			else if (strcmp("VERSION", name) == 0)
			{
//				version = float(atof(ptr2));
			}
			else if (strcmp("VALUE", name) == 0)
			{
				m_name_lookup = ptr2;
			}
			else if (strcmp("DESTINATION", name) == 0)
			{
				m_dest = ptr2;
			}
		}

		error_code ec(result, get_i2p_category());
		switch (result)
		{
			case i2p_error::no_error:
			case i2p_error::invalid_key:
				break;
			default:
			{
				handle_error (ec, h);
				return;
			}
		}

		switch (m_state)
		{
		case read_hello_response:
			switch (m_command)
			{
				case cmd_create_session:
					send_session_create(h);
					break;
				case cmd_accept:
					send_accept(h);
					break;
				case cmd_connect:
					send_connect(h);
					break;
				default:
					(*h)(e);
					std::vector<char>().swap(m_buffer);
			}
			break;
		case read_connect_response:
		case read_session_create_response:
		case read_name_lookup_response:
			(*h)(ec);
			std::vector<char>().swap(m_buffer);
			break;
		case read_accept_response:
			// the SAM bridge is waiting for an incoming
			// connection.
			// wait for one more line containing
			// the destination of the remote peer
			m_command = cmd_incoming;
			m_buffer.resize(1);
#if defined TORRENT_ASIO_DEBUGGING
			add_outstanding_async("i2p_stream::read_line");
#endif
			async_read(m_sock, boost::asio::buffer(m_buffer)
				, boost::bind(&i2p_stream::read_line, this, _1, h));
			break;
		}

		return;
	}
Exemple #8
0
void adbd_auth_verified(atransport* t) {
    LOG(INFO) << "adb client authorized";
    handle_online(t);
    send_connect(t);
}
Exemple #9
0
void handle_packet(apacket *p, atransport *t)
{
    asocket *s;

	D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
			((char*) (&(p->msg.command)))[1],
			((char*) (&(p->msg.command)))[2],
			((char*) (&(p->msg.command)))[3]);
	print_packet("recv", p);

	switch(p->msg.command){
	case A_SYNC:
		if(p->msg.arg0){
			send_packet(p, t);
			if(HOST) send_connect(t);
		} else {
			t->connection_state = CS_OFFLINE;
			handle_offline(t);
			send_packet(p, t);
		}
		return;

	case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
		/* XXX verify version, etc */
		if(t->connection_state != CS_OFFLINE) {
			t->connection_state = CS_OFFLINE;
			handle_offline(t);
		}
		parse_banner((char*) p->data, t);

		handle_online(t);
		send_connect(t);

		break;

	case A_OPEN: /* OPEN(local-id, 0, "destination") */
		if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
			char *name = (char*) p->data;
			name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
			s = create_local_service_socket(name);
			if(s == 0) {
				send_close(0, p->msg.arg0, t);
			} else {
				s->peer = create_remote_socket(p->msg.arg0, t);
				s->peer->peer = s;
				send_ready(s->id, s->peer->id, t);
				s->ready(s);
			}
		}
		break;

	case A_OKAY: /* READY(local-id, remote-id, "") */
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
            if((s = find_local_socket(p->msg.arg1, 0))) {
                if(s->peer == 0) {
                    /* On first READY message, create the connection. */
                    s->peer = create_remote_socket(p->msg.arg0, t);
                    s->peer->peer = s;
                    s->ready(s);
                } else if (s->peer->id == p->msg.arg0) {
                    /* Other READY messages must use the same local-id */
                    s->ready(s);
                } else {
                    D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
                      p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
                }
            }
        }
		break;

	case A_CLSE: /* CLOSE(local-id, remote-id, "") */
        if (t->online && p->msg.arg1 != 0) {
            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
                /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
                 * a failed OPEN only. However, due to a bug in previous ADB
                 * versions, CLOSE(0, remote-id, "") was also used for normal
                 * CLOSE() operations.
                 *
                 * This is bad because it means a compromised adbd could
                 * send packets to close connections between the host and
                 * other devices. To avoid this, only allow this if the local
                 * socket has a peer on the same transport.
                 */
                if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
                    D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
                      p->msg.arg1, t->serial, s->peer->transport->serial);
                } else {
                    s->close(s);
                }
            }
        }
		break;

	case A_WRTE:
        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
                unsigned rid = p->msg.arg0;
                p->len = p->msg.data_length;

                if(s->enqueue(s, p) == 0) {
                    D("Enqueue the socket\n");
                    send_ready(s->id, rid, t);
                }
                return;
            }
        }
		break;

	default:
		printf("handle_packet: what is %08x?!\n", p->msg.command);
	}

	put_apacket(p);
}
Exemple #10
0
static void
test_send_connect(void)
{
	/* /connect [(host) | (host:port) | (host port)] */

	/* No args, connected, should issue an error message */
	server_connect__called__ = 0;
	server_connect__host__ = NULL;
	server_connect__port__ = NULL;
	*err = 0;

	mock_s.soc = 1; /* Non-negative socket implies connected */

	char str1[] = "";
	send_connect(err, str1, c);

	assert_equals(server_connect__called__, 0);
	assert_strcmp(err, "Error: Already connected or reconnecting to server");


	/* No args, not connected, should attempt to reconnect on the current server */
	server_connect__called__ = 0;
	server_connect__host__ = NULL;
	server_connect__port__ = NULL;

	mock_s.soc = -1; /* -1 socket implies not connected */

	char str2[] = "";
	send_connect(err, str2, c);

	assert_equals(server_connect__called__, 1);
	assert_strcmp(server_connect__host__, "mock-host");
	assert_strcmp(server_connect__port__, "mock-port");


	/* <server> */
	server_connect__called__ = 0;
	server_connect__host__ = NULL;
	server_connect__port__ = NULL;

	char str3[] = "server.tld";
	send_connect(err, str3, c);

	assert_equals(server_connect__called__, 1);
	assert_strcmp(server_connect__host__, "server.tld");
	assert_strcmp(server_connect__port__, "6667");


	/* <server>:<port> */
	server_connect__called__ = 0;
	server_connect__host__ = NULL;
	server_connect__port__ = NULL;

	char str4[] = "server.tld:123";
	send_connect(err, str4, c);

	assert_equals(server_connect__called__, 1);
	assert_strcmp(server_connect__host__, "server.tld");
	assert_strcmp(server_connect__port__, "123");


	/* <server> <port> */
	server_connect__called__ = 0;
	server_connect__host__ = NULL;
	server_connect__port__ = NULL;

	char str5[] = "server.tld 123";
	send_connect(err, str5, c);

	assert_equals(server_connect__called__, 1);
	assert_strcmp(server_connect__host__, "server.tld");
	assert_strcmp(server_connect__port__, "123");
}