Пример #1
0
static void connect_device(const std::string& address, std::string* response) {
    if (address.empty()) {
        *response = "empty address";
        return;
    }

    std::string serial;
    std::string host;
    int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
    if (!parse_host_and_port(address, &serial, &host, &port, response)) {
        return;
    }

    std::string error;
    int fd = network_connect(host.c_str(), port, SOCK_STREAM, 10, &error);
    if (fd == -1) {
        *response = android::base::StringPrintf("unable to connect to %s: %s",
                                                serial.c_str(), error.c_str());
        return;
    }

    D("client: connected %s remote on fd %d", serial.c_str(), fd);
    close_on_exec(fd);
    disable_tcp_nagle(fd);

    int ret = register_socket_transport(fd, serial.c_str(), port, 0);
    if (ret < 0) {
        adb_close(fd);
        *response = android::base::StringPrintf("already connected to %s", serial.c_str());
    } else {
        *response = android::base::StringPrintf("connected to %s", serial.c_str());
    }
}
Пример #2
0
/*
 * Read the host as supplied by the client connection.
 */
static void parse_host_arg(struct hostinfo *hi, char *extra_args, int buflen)
{
	char *val;
	int vallen;
	char *end = extra_args + buflen;

	if (extra_args < end && *extra_args) {
		hi->saw_extended_args = 1;
		if (strncasecmp("host=", extra_args, 5) == 0) {
			val = extra_args + 5;
			vallen = strlen(val) + 1;
			if (*val) {
				/* Split <host>:<port> at colon. */
				char *host;
				char *port;
				parse_host_and_port(val, &host, &port);
				if (port)
					sanitize_client(&hi->tcp_port, port);
				canonicalize_client(&hi->hostname, host);
				hi->hostname_lookup_done = 0;
			}

			/* On to the next one */
			extra_args = val + vallen;
		}
		if (extra_args < end && *extra_args)
			die("Invalid request");
	}
}
Пример #3
0
static int parse_io_param(struct io *io, char *opt, int open_flags, mode_t open_mode) {
	int port_set = 0, host_set;
	io->type = WTF_IO;
	if (strstr(opt, "file://") == opt) {
		io->fname = opt + 7; // strlen("file://")
		io->type = FILE_IO;
	} else if (strchr(opt, '/')) {
		io->fname = opt;
		io->type = FILE_IO;
	}
	if (io->type == FILE_IO) {
		io->fd = open(io->fname, open_flags, open_mode);
		if (io->fd < 0) {
			fprintf(stderr, "ERROR: Can not open file (%s): %s\n", io->fname, strerror(errno));
			exit(EXIT_FAILURE);
		}
		return 1;
	}
	io->type = NET_IO;
	host_set = parse_host_and_port(opt, &io->hostname, &io->service, &port_set);
	return !(!port_set || !host_set);
}
Пример #4
0
/*
 * Read the host as supplied by the client connection.
 */
static void parse_host_arg(char *extra_args, int buflen)
{
	char *val;
	int vallen;
	char *end = extra_args + buflen;

	if (extra_args < end && *extra_args) {
		saw_extended_args = 1;
		if (strncasecmp("host=", extra_args, 5) == 0) {
			val = extra_args + 5;
			vallen = strlen(val) + 1;
			if (*val) {
				/* Split <host>:<port> at colon. */
				char *host;
				char *port;
				parse_host_and_port(val, &host, &port);
				if (port) {
					free(tcp_port);
					tcp_port = xstrdup(port);
				}
				free(hostname);
				hostname = xstrdup_tolower(host);
			}

			/* On to the next one */
			extra_args = val + vallen;
		}
		if (extra_args < end && *extra_args)
			die("Invalid request");
	}

	/*
	 * Locate canonical hostname and its IP address.
	 */
	if (hostname) {
#ifndef NO_IPV6
		struct addrinfo hints;
		struct addrinfo *ai;
		int gai;
		static char addrbuf[HOST_NAME_MAX + 1];

		memset(&hints, 0, sizeof(hints));
		hints.ai_flags = AI_CANONNAME;

		gai = getaddrinfo(hostname, NULL, &hints, &ai);
		if (!gai) {
			struct sockaddr_in *sin_addr = (void *)ai->ai_addr;

			inet_ntop(AF_INET, &sin_addr->sin_addr,
				  addrbuf, sizeof(addrbuf));
			free(ip_address);
			ip_address = xstrdup(addrbuf);

			free(canon_hostname);
			canon_hostname = xstrdup(ai->ai_canonname ?
						 ai->ai_canonname : ip_address);

			freeaddrinfo(ai);
		}
#else
		struct hostent *hent;
		struct sockaddr_in sa;
		char **ap;
		static char addrbuf[HOST_NAME_MAX + 1];

		hent = gethostbyname(hostname);

		ap = hent->h_addr_list;
		memset(&sa, 0, sizeof sa);
		sa.sin_family = hent->h_addrtype;
		sa.sin_port = htons(0);
		memcpy(&sa.sin_addr, *ap, hent->h_length);

		inet_ntop(hent->h_addrtype, &sa.sin_addr,
			  addrbuf, sizeof(addrbuf));

		free(canon_hostname);
		canon_hostname = xstrdup(hent->h_name);
		free(ip_address);
		ip_address = xstrdup(addrbuf);
#endif
	}
}
Пример #5
0
static void parse_options(struct ts *ts, int argc, char **argv) {
	int j, i, ca_err = 0, server_err = 1, input_addr_err = 0, output_addr_err = 0, ident_err = 0, port_set = 0;
	while ((j = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
		if (j == '?')
			exit(EXIT_FAILURE);
		switch (j) {
			case 'i': // -- ident
				ts->ident = optarg;
				break;
			case 'd': // --daemon
				ts->pidfile = optarg;
				break;
			case 'N': // --notify-program
				ts->notify_program = optarg;
				break;

			case 'S': // --syslog
				ts->syslog_active = 1;
				ts->syslog_remote = 0;
				break;
			case 'l': // --syslog-host
				ts->syslog_host = optarg;
				ts->syslog_active = 1;
				ts->syslog_remote = 1;
				break;
			case 'L': // --syslog-port
				ts->syslog_port = atoi(optarg);
				break;
			case 'F': // --log-file
				log_filename = optarg;
				break;

			case 'I': // --input
				input_addr_err = !parse_io_param(&ts->input, optarg, O_RDONLY, 0);
				break;
			case '1': // --input-source
				if (!inet_aton(optarg, &ts->input.isrc)) {
					fprintf(stderr, "ERROR: Can't parse input-source IP address: %s\n", optarg);
					exit(EXIT_FAILURE);
				}
				break;
			case 'R': // --input-rtp
				ts->rtp_input = !ts->rtp_input;
				break;
			case 'z': // --input-ignore-disc
				ts->ts_discont = !ts->ts_discont;
				break;
			case 'M': // --input-service
				ts->forced_service_id = strtoul(optarg, NULL, 0) & 0xffff;
				break;
			case 'T': // --input-buffer
				ts->input_buffer_time = strtoul(optarg, NULL, 0);
				break;
			case 'W': // --input-dump
				ts->input_dump_filename = optarg;
				break;

			case 'O': // --output
				output_addr_err = !parse_io_param(&ts->output, optarg,
					O_CREAT | O_WRONLY | O_TRUNC,
					S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
				break;
			case 'o': // --output-intf
				if (strchr(optarg, '.'))
					inet_aton(optarg, &ts->output.intf);
				else
					ts->output.v6_if_index = atoi(optarg);
				break;
			case 't': // --output-ttl
				ts->output.ttl = atoi(optarg);
				break;
			case 'r': // --output-rtp
				ts->rtp_output = 1;
				break;
			case 'k': // --output-rtp-ssrc
				ts->rtp_ssrc = strtoul(optarg, NULL, 0);
				break;
			case 'g': // --output-tos
				ts->output.tos = (uint8_t)strtol(optarg, NULL, 0);
				break;
			case 'u': // --no-output-on-error
				ts->no_output_on_error = !ts->no_output_on_error;
				break;
			case 'p': // --no-output-filter
				ts->pid_filter = !ts->pid_filter;
				break;
			case 'y': // --output-nit-pass
				ts->nit_passthrough = !ts->nit_passthrough;
				break;
			case 'w': // --output-eit-pass
				ts->eit_passthrough = !ts->eit_passthrough;
				break;
			case 'x': // --output-tdt-pass
				ts->tdt_passthrough = !ts->tdt_passthrough;
				break;
			case 'c': // --ca-system
				if (strcasecmp("IRDETO", optarg) == 0)
					ts->req_CA_sys = CA_IRDETO;
				else if (strcasecmp("CONNAX", optarg) == 0 || strcasecmp("CONAX", optarg) == 0)
					ts->req_CA_sys = CA_CONAX;
				else if (strcasecmp("CRYPTOWORKS", optarg) == 0)
					ts->req_CA_sys = CA_CRYPTOWORKS;
				else if (strcasecmp("SECA", optarg) == 0 || strcasecmp("MEDIAGUARD", optarg) == 0)
					ts->req_CA_sys = CA_SECA;
				else if (strcasecmp("VIACCESS", optarg) == 0)
					ts->req_CA_sys = CA_VIACCESS;
				else if (strcasecmp("VIDEOGUARD", optarg) == 0 || strcasecmp("NDS", optarg) == 0)
					ts->req_CA_sys = CA_VIDEOGUARD;
				else if (strcasecmp("NAGRA", optarg) == 0)
					ts->req_CA_sys = CA_NAGRA;
				else if (strcasecmp("DRE-CRYPT", optarg) == 0 || strcasecmp("DRECRYPT", optarg) == 0)
					ts->req_CA_sys = CA_DRECRYPT;
				else if (strcasecmp("BULCRYPT", optarg) == 0)
					ts->req_CA_sys = CA_BULCRYPT;
				else if (strcasecmp("GRIFFIN", optarg) == 0)
					ts->req_CA_sys = CA_GRIFFIN;
				else if (strcasecmp("DGCRYPT", optarg) == 0)
					ts->req_CA_sys = CA_DGCRYPT;
				else
					ca_err = 1;
				break;
			case 'C': // --caid
				ts->forced_caid = strtoul(optarg, NULL, 0) & 0xffff;
				break;
			case 'Y': // --const-cw
				ts->camd.constant_codeword = 1;
				if (strlen(optarg) > 2 && optarg[0] == '0' && optarg[1] == 'x')
					optarg += 2;
				if (strlen(optarg) != CODEWORD_LENGTH * 2) {
					fprintf(stderr, "ERROR: Constant code word should be %u characters long.\n", CODEWORD_LENGTH * 2);
					exit(EXIT_FAILURE);
				}
				if (decode_hex_string(optarg, ts->camd.key->cw, strlen(optarg)) < 0) {
					fprintf(stderr, "ERROR: Invalid hex string for constant code word: %s\n", optarg);
					exit(EXIT_FAILURE);
				}
				camd_set_cw(ts, ts->camd.key->cw, 0);
				ts->camd.key->is_valid_cw = 1;
				break;
			case 'Q': // --biss-key
				ts->camd.constant_codeword = 1;
				if (strlen(optarg) > 2 && optarg[0] == '0' && optarg[1] == 'x')
					optarg += 2;
				uint8_t *key = ts->camd.key->cw;
				// Sometimes the BISS keys are entered with their checksums already calculated (16 symbols, 8 bytes)
				// This is the same as constant cw with the same key for even and odd
				if (strlen(optarg) == (BISSKEY_LENGTH + 2) * 2) {
					if (decode_hex_string(optarg, key, strlen(optarg)) < 0) {
						fprintf(stderr, "ERROR: Invalid hex string for BISS key: %s\n", optarg);
						exit(EXIT_FAILURE);
					}
				} else {
					// BISS key without checksum (12 symbols, 6 bytes)
					if (strlen(optarg) != BISSKEY_LENGTH * 2) {
						fprintf(stderr, "ERROR: BISS key should be %u characters long.\n", BISSKEY_LENGTH * 2);
						exit(EXIT_FAILURE);
					}
					if (decode_hex_string(optarg, key, strlen(optarg)) < 0) {
						fprintf(stderr, "ERROR: Invalid hex string for BISS key: %s\n", optarg);
						exit(EXIT_FAILURE);
					}
					// Calculate BISS KEY crc
					memmove(key + 4, key + 3, 3);
					key[3] = (uint8_t)(key[0] + key[1] + key[2]);
					key[7] = (uint8_t)(key[4] + key[5] + key[6]);
				}
				// Even and odd keys are the same
				memcpy(key + 8, key, 8);
				camd_set_cw(ts, ts->camd.key->cw, 0);
				ts->camd.key->is_valid_cw = 1;
				break;

			case 'A': // --camd-proto
				if (strcasecmp(optarg, "cs378x") == 0) {
					camd_proto_cs378x(&ts->camd.ops);
				} else if (strcasecmp(optarg, "newcamd") == 0) {
					camd_proto_newcamd(&ts->camd.ops);
				} else {
					fprintf(stderr, "Unknown CAMD protocol: %s\n", optarg);
					exit(EXIT_FAILURE);
				}
				break;
			case 's': // --camd-server
				server_err = !parse_host_and_port(optarg, &ts->camd.hostname, &ts->camd.service, &port_set);
				break;
			case 'U': // --camd-user
				if (strlen(optarg) < 64)
					ts->camd.user = optarg;
				break;
			case 'P': // --camd-pass
				ts->camd.pass = optarg;
				break;
			case 'B': // --camd-des-key
				if (strlen(optarg) > 2 && optarg[0] == '0' && optarg[1] == 'x')
					optarg += 2;
				if (strlen(optarg) != DESKEY_LENGTH) {
					fprintf(stderr, "ERROR: des key should be %u characters long.\n", DESKEY_LENGTH);
					exit(EXIT_FAILURE);
				}
				strncpy(ts->camd.newcamd.hex_des_key, optarg, sizeof(ts->camd.newcamd.hex_des_key) - 1);
				ts->camd.newcamd.hex_des_key[sizeof(ts->camd.newcamd.hex_des_key) - 1] = 0;
				break;
			case '4': // --ipv4
				ai_family = AF_INET;
				break;
			case '6': // --ipv6
				ai_family = AF_INET6;
				break;

			case 'e': // --emm
				ts->process_emm = !ts->process_emm;
				break;
			case 'Z': // --emm-pid
				ts->forced_emm_pid = strtoul(optarg, NULL, 0) & 0x1fff;
				break;
			case 'E': // --emm-only
				ts->process_emm = 1;
				ts->process_ecm = 0;
				ts->output_stream = 0;
				break;
			case 'f': // --emm-report-time
				ts->emm_report_interval = strtoul(optarg, NULL, 10);
				if (ts->emm_report_interval > 86400)
					ts->emm_report_interval = 86400;
				break;

			case 'a': // --emm-filter
				if (ts->emm_filters_num + 1 > MAX_FILTERS) {
					fprintf(stderr, "ERROR: Maximum allowed filters are %d.\n", MAX_FILTERS);
					exit(EXIT_FAILURE);
				}
				if (filter_parse(optarg, &ts->emm_filters[ts->emm_filters_num])) {
					ts->emm_filters_num++;
				} else {
					fprintf(stderr, "ERROR: Can't parse EMM filter: %s\n", optarg);
					exit(EXIT_FAILURE);
				}
				break;

			case 'X': // --ecm-pid
				ts->forced_ecm_pid = strtoul(optarg, NULL, 0) & 0x1fff;
				break;
			case 'v': // --ecm-only
				ts->process_emm = 0;
				ts->process_ecm = 1;
				ts->output_stream = 0;
				break;
			case 'H': // --ecm-report-time
				ts->ecm_report_interval = strtoul(optarg, NULL, 10);
				if (ts->ecm_report_interval > 86400)
					ts->ecm_report_interval = 86400;
				break;
			case 'G': // --ecm-irdeto-type
				ts->irdeto_ecm_idx = strtoul(optarg, NULL, 0);
				ts->irdeto_ecm_filter_type = IRDETO_FILTER_IDX;
				break;
			case '2': // --ecm-irdeto-chid
				ts->irdeto_ecm_chid = strtoul(optarg, NULL, 0);
				ts->irdeto_ecm_filter_type = IRDETO_FILTER_CHID;
				break;
			case 'K': // --ecm-no-log
				ts->ecm_cw_log = !ts->ecm_cw_log;
				break;
			case 'J': // --cw-warn-time
				ts->cw_warn_sec = strtoul(optarg, NULL, 10);
				if (ts->cw_warn_sec > 86400)
					ts->cw_warn_sec = 86400;
				ts->cw_last_warn= ts->cw_last_warn + ts->cw_warn_sec;
				break;
			case 'q': // --ecm-and-emm-only
				ts->process_emm = 1;
				ts->process_ecm = 1;
				ts->output_stream = 0;
				break;

			case 'D': // --debug
				ts->debug_level = atoi(optarg);
				if (ts->debug_level > 0)
					ts->pid_report = 1;
				break;
			case 'j': // --pid-report
				ts->pid_report = 1;
				break;
			case 'b': // --bench
				csa_benchmark();
				exit(EXIT_SUCCESS);

			case 'n': // --ecm-file
			case 'm': // --emm-file
				packet_from_file = 1;
				packet_buflen = file_hex2buf(optarg, packet_buf, sizeof(packet_buf));
				if (!packet_buflen) {
					fprintf(stderr, "ERROR: Can't init packet from file.\n");
					exit(1);
				}
				packet_type = j == 'n' ? ECM_MSG : EMM_MSG;
				break;

			case 'h': // --help
				show_help(ts);
				exit(EXIT_SUCCESS);

			case 'V': // --version
				printf("%s\n", program_id);
				exit(EXIT_SUCCESS);
		}
	}
	if (!ts->ident) {
		if (ts->syslog_active || ts->notify_program)
			ident_err = 1;
	}

	if (packet_from_file) {
		int err = 0;
		if (!ts->forced_caid) {
			fprintf(stderr, "ERROR: CAID was not set. Use --caid option.\n");
			err++;
		}
		if (!ts->forced_service_id) {
			fprintf(stderr, "ERROR: Service id was not set. Use --input-service option.\n");
			err++;
		}
		if (err)
			exit(EXIT_FAILURE);

		ts->threaded = 0;
		input_addr_err = 0;
		output_addr_err = 0;
		ts->input.type = FILE_IO;
		ts->input.fd = 0;
		ts->output.type = FILE_IO;
		ts->output.fd = 1;
		ts->pid_filter = 0;
		ts->process_ecm = 0;
		ts->process_emm = 0;
		ts->output_stream = 0;
		ts->camd.no_reconnect = 1;
		ts->camd.check_emm_errors = 1;
		ts->emm_filters_num = 0;
	}

	// Constant codeword is special. Disable conflicting options
	if (ts->camd.constant_codeword) {
		server_err = 0; // No server settings are required
		ts->process_ecm = 0;
		ts->process_emm = 0;
		ts->output_stream = 1;
	}

	if (ident_err || ca_err || server_err || input_addr_err || output_addr_err || ts->input.type == WTF_IO || ts->output.type == WTF_IO) {
		show_help(ts);
		if (ident_err)
			fprintf(stderr, "ERROR: Ident is not set, please use --ident option.\n");
		if (ca_err)
			fprintf(stderr, "ERROR: Requested CA system is unsupported.\n");
		if (server_err)
			fprintf(stderr, "ERROR: CAMD server address is not set or it is invalid.\n");
		if (input_addr_err)
			fprintf(stderr, "ERROR: Input address is invalid.\n");
		if (output_addr_err)
			fprintf(stderr, "ERROR: Output address is invalid.\n");
		exit(EXIT_FAILURE);
	}
	if (decode_hex_string(ts->camd.newcamd.hex_des_key, ts->camd.newcamd.bin_des_key, DESKEY_LENGTH) < 0) {
		fprintf(stderr, "ERROR: Invalid hex string for des key: %s\n", ts->camd.newcamd.hex_des_key);
		exit(EXIT_FAILURE);
	}
	if (ts->camd.ops.proto == CAMD_NEWCAMD && !port_set) {
		fprintf(stderr, "ERROR: CAMD server port is not set. Use --camd-server %s:xxxx to set the port.\n", ts->camd.hostname);
		exit(EXIT_FAILURE);
	}

	if (log_filename) {
		log_file = fopen(log_filename, "a");
		if (!log_file) {
			fprintf(stderr, "ERROR: Can't open log file %s: %s\n", log_filename, strerror(errno));
			exit(EXIT_FAILURE);
		}
	}

	if (ts->ident)
		ts_LOGf("Ident      : %s\n", ts->ident);
	if (ts->notify_program)
		ts_LOGf("Notify prg : %s\n", ts->notify_program);
	if (ts->pidfile)
		ts_LOGf("Daemonize  : %s pid file.\n", ts->pidfile);
	if (ts->syslog_active) {
		if (ts->syslog_remote)
			ts_LOGf("Syslog     : %s:%d\n", ts->syslog_host, ts->syslog_port);
		else
			ts_LOGf("Syslog     : enabled\n");
	} else {
		if (!packet_from_file)
			ts_LOGf("Syslog     : disabled\n");
	}

	if (!ts->camd.constant_codeword) {
		if (ts->forced_caid)
			ts->req_CA_sys = ts_get_CA_sys(ts->forced_caid);
		if (!ts->forced_caid)
			ts_LOGf("CA System  : %s\n", ts_get_CA_sys_txt(ts->req_CA_sys));
		else
			ts_LOGf("CA System  : %s | CAID: 0x%04x (%d)\n",
				ts_get_CA_sys_txt(ts->req_CA_sys),
				ts->forced_caid, ts->forced_caid);
	} else {
		char cw_even[64], cw_odd[64];
		ts_hex_dump_buf(cw_even, sizeof(cw_even), ts->key.cw    , 8, 0);
		ts_hex_dump_buf(cw_odd , sizeof(cw_odd ), ts->key.cw + 8, 8, 0);
		ts_LOGf("Constant CW: even = %s\n", cw_even);
		ts_LOGf("Constant CW: odd  = %s\n", cw_odd);
	}

	if (ts->input.type == NET_IO) {
		ts_LOGf("Input addr : %s://%s:%s/\n",
			ts->rtp_input ? "rtp" : "udp",
			ts->input.hostname, ts->input.service);
		ts_LOGf("Input src  : %s\n", inet_ntoa(ts->input.isrc));
		if (ts->input_buffer_time) {
			ts_LOGf("Input buff : %u ms\n", ts->input_buffer_time);
		}
	} else if (ts->input.type == FILE_IO) {
		if (!packet_from_file)
			ts_LOGf("Input file : %s\n", ts->input.fd == 0 ? "STDIN" : ts->input.fname);
	}
	if (ts->input_dump_filename) {
		ts->input_dump_file = fopen(ts->input_dump_filename, "w");
		if (ts->input_dump_file)
			ts_LOGf("Input dump : %s\n", ts->input_dump_filename);
		else
			ts_LOGf("Input dump : %s | ERROR: %s\n", ts->input_dump_filename, strerror(errno));
	}
	if (ts->forced_service_id)
		ts_LOGf("Service id : 0x%04x (%d)\n",
			ts->forced_service_id, ts->forced_service_id);
	if (ts->req_CA_sys == CA_IRDETO) {
		switch (ts->irdeto_ecm_filter_type) {
		case IRDETO_FILTER_IDX : ts_LOGf("Irdeto ECM : Index: 0x%02x (%d)\n", ts->irdeto_ecm_idx, ts->irdeto_ecm_idx); break;
		case IRDETO_FILTER_CHID: ts_LOGf("Irdeto ECM : CHID: 0x%04x (%d)\n", ts->irdeto_ecm_chid, ts->irdeto_ecm_chid); break;
		}
	}

	if (ts->output_stream) {
		if (ts->output.type == NET_IO) {
			ts_LOGf("Output addr: %s://%s:%s/\n",
				ts->rtp_output ? "rtp" : "udp",
				ts->output.hostname, ts->output.service);
			ts_LOGf("Output intf: %s (IPv6 intf index:%d)\n",
				inet_ntoa(ts->output.intf), ts->output.v6_if_index);
			ts_LOGf("Output ttl : %d\n", ts->output.ttl);
			if (ts->output.tos > -1)
				ts_LOGf("Output TOS : %u (0x%02x)\n", ts->output.tos, ts->output.tos);
			if (ts->rtp_output) {
				ts_LOGf("RTP SSRC   : %u (0x%04x)\n",
					ts->rtp_ssrc, ts->rtp_ssrc);
				// It is recommended that RTP seqnum starts with random number
				RAND_bytes((unsigned char *)&(ts->rtp_seqnum), 2);
			}
		} else if (ts->output.type == FILE_IO) {
			ts_LOGf("Output file: %s\n", ts->output.fd == 1 ? "STDOUT" : ts->output.fname);
		}
		ts_LOGf("Out filter : %s (%s)%s\n",
			ts->pid_filter ? "enabled" : "disabled",
			ts->pid_filter ? "output only service related PIDs" : "output everything",
			ts->no_output_on_error ? " (No output on CW error)" : ""
		);
		if (ts->pid_filter) {
			if (ts->nit_passthrough)
				ts_LOGf("Out filter : Pass through NIT.\n");
			if (ts->eit_passthrough)
				ts_LOGf("Out filter : Pass through EIT (EPG).\n");
			if (ts->tdt_passthrough)
				ts_LOGf("Out filter : Pass through TDT/TOT.\n");
		}
		ts_LOGf("TS discont : %s\n", ts->ts_discont ? "report" : "ignore");
		ts->threaded = !(ts->input.type == FILE_IO && ts->input.fd != 0);
		ts_LOGf("Decoding   : %s\n", ts->threaded ? "threaded" : "single thread");
	} else {
		ts_LOGf("Decoding   : disabled\n");
	}

	if (!ts->camd.constant_codeword) {
		ts_LOGf("CAMD proto : %s\n", ts->camd.ops.ident);
		ts_LOGf("CAMD addr  : %s:%s%s\n", ts->camd.hostname, ts->camd.service,
			ai_family == AF_INET  ? " (IPv4 only)" :
			ai_family == AF_INET6 ? " (IPv6 only)" :
			" (IPv4/IPv6)"
		);
		ts_LOGf("CAMD user  : %s\n", ts->camd.user);
		ts_LOGf("CAMD pass  : %s\n", ts->camd.pass);
		if (ts->camd.ops.proto == CAMD_NEWCAMD)
			ts_LOGf("CAMD deskey: %s\n", ts->camd.newcamd.hex_des_key);
	}

	if (!packet_from_file)
		ts_LOGf("EMM process: %s\n", ts->process_emm ? "Yes" : "No");

	if (ts->process_emm) {
		if (ts->forced_emm_pid)
			ts_LOGf("EMM pid    : 0x%04x (%d)\n", ts->forced_emm_pid, ts->forced_emm_pid);

		if (ts->emm_report_interval)
			ts_LOGf("EMM report : %d sec\n", ts->emm_report_interval);
		else
			ts_LOGf("EMM report : disabled\n");

		for (i = 0; i < ts->emm_filters_num; i++) {
			char tmp[512];
			filter_dump(&ts->emm_filters[i], tmp, sizeof(tmp));
			ts_LOGf("EMM filter : [%2d] %s\n", i + 1,  tmp);
		}
	}

	if (!packet_from_file)
		ts_LOGf("ECM process: %s\n", ts->process_ecm ? "Yes" : "No");

	if (ts->process_ecm) {
		if (ts->forced_ecm_pid)
			ts_LOGf("ECM pid    : 0x%04x (%d)\n", ts->forced_ecm_pid, ts->forced_ecm_pid);

		if (ts->ecm_report_interval)
			ts_LOGf("ECM report : %d sec\n", ts->emm_report_interval);
		else
			ts_LOGf("ECM report : disabled\n");

		if (ts->cw_warn_sec)
			ts_LOGf("CW warning : %d sec\n", ts->cw_warn_sec);
		else
			ts_LOGf("CW warning : disabled\n");

		if (!ts->ecm_cw_log)
			ts_LOGf("ECM/CW log : disabled\n");
	}

	if (ts->ident) {
		int len = strlen(ts->ident);
		for (i = 0; i < len; i++) {
			if (ts->ident[i] == '/')
				ts->ident[i] = '-';
		}
	}
}
TEST(adb_utils, parse_host_and_port) {
  std::string canonical_address;
  std::string host;
  int port;
  std::string error;

  // Name, default port.
  port = 123;
  ASSERT_TRUE(parse_host_and_port("www.google.com", &canonical_address, &host, &port, &error));
  ASSERT_EQ("www.google.com:123", canonical_address);
  ASSERT_EQ("www.google.com", host);
  ASSERT_EQ(123, port);

  // Name, explicit port.
  ASSERT_TRUE(parse_host_and_port("www.google.com:666", &canonical_address, &host, &port, &error));
  ASSERT_EQ("www.google.com:666", canonical_address);
  ASSERT_EQ("www.google.com", host);
  ASSERT_EQ(666, port);

  // IPv4, default port.
  port = 123;
  ASSERT_TRUE(parse_host_and_port("1.2.3.4", &canonical_address, &host, &port, &error));
  ASSERT_EQ("1.2.3.4:123", canonical_address);
  ASSERT_EQ("1.2.3.4", host);
  ASSERT_EQ(123, port);

  // IPv4, explicit port.
  ASSERT_TRUE(parse_host_and_port("1.2.3.4:666", &canonical_address, &host, &port, &error));
  ASSERT_EQ("1.2.3.4:666", canonical_address);
  ASSERT_EQ("1.2.3.4", host);
  ASSERT_EQ(666, port);

  // Simple IPv6, default port.
  port = 123;
  ASSERT_TRUE(parse_host_and_port("::1", &canonical_address, &host, &port, &error));
  ASSERT_EQ("[::1]:123", canonical_address);
  ASSERT_EQ("::1", host);
  ASSERT_EQ(123, port);

  // Simple IPv6, explicit port.
  ASSERT_TRUE(parse_host_and_port("[::1]:666", &canonical_address, &host, &port, &error));
  ASSERT_EQ("[::1]:666", canonical_address);
  ASSERT_EQ("::1", host);
  ASSERT_EQ(666, port);

  // Hairy IPv6, default port.
  port = 123;
  ASSERT_TRUE(parse_host_and_port("fe80::200:5aee:feaa:20a2", &canonical_address, &host, &port, &error));
  ASSERT_EQ("[fe80::200:5aee:feaa:20a2]:123", canonical_address);
  ASSERT_EQ("fe80::200:5aee:feaa:20a2", host);
  ASSERT_EQ(123, port);

  // Simple IPv6, explicit port.
  ASSERT_TRUE(parse_host_and_port("[fe80::200:5aee:feaa:20a2]:666", &canonical_address, &host, &port, &error));
  ASSERT_EQ("[fe80::200:5aee:feaa:20a2]:666", canonical_address);
  ASSERT_EQ("fe80::200:5aee:feaa:20a2", host);
  ASSERT_EQ(666, port);

  // Invalid IPv4.
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4::", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:hello", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port(":123", &canonical_address, &host, &port, &error));

  // Invalid IPv6.
  EXPECT_FALSE(parse_host_and_port(":1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("::::::::1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]:", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]::", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]:hello", &canonical_address, &host, &port, &error));

  // Invalid ports.
  EXPECT_FALSE(parse_host_and_port("[::1]:-1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]:0", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("[::1]:65536", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:-1", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:0", &canonical_address, &host, &port, &error));
  EXPECT_FALSE(parse_host_and_port("1.2.3.4:65536", &canonical_address, &host, &port, &error));
}
Пример #7
0
/* Handle command line arguments modifying behavior */
static void parse_cli(int argc, char **argv) {
    const char *prog = argv[0];

    static int tls = 0, ssl = 0;
    int c;
    struct passwd* passwd;

    static struct option long_options[] =
    {
        {"tls", 0, &tls, 1},
        {"ssl", 0, &ssl, 1},
        {"write-ip", 0, &OPTIONS.WRITE_IP_OCTET, 1},
        {"write-proxy", 0, &OPTIONS.WRITE_PROXY_LINE, 1},
        {0, 0, 0, 0}
    };

    while (1) {
        int option_index = 0;
        c = getopt_long(argc, argv, "hf:b:n:c:u:r:B:C:q",
                long_options, &option_index);

        if (c == -1)
            break;

        switch (c) {

        case 0:
            break;

        case 'n':
            errno = 0;
            OPTIONS.NCORES = strtol(optarg, NULL, 10);
            if ((errno == ERANGE &&
                (OPTIONS.NCORES == LONG_MAX || OPTIONS.NCORES == LONG_MIN)) ||
                OPTIONS.NCORES < 1 || OPTIONS.NCORES > 128) {
                usage_fail(prog, "invalid option for -n CORES; please provide an integer between 1 and 128\n");
            }
            break;

        case 'b':
            parse_host_and_port(prog, "-b", optarg, 0, &(OPTIONS.BACK_IP), &(OPTIONS.BACK_PORT));
            break;

        case 'f':
            parse_host_and_port(prog, "-f", optarg, 1, &(OPTIONS.FRONT_IP), &(OPTIONS.FRONT_PORT));
            break;
            
        case 'c':
            OPTIONS.CIPHER_SUITE = optarg;
            break;

        case 'u':
            passwd = getpwnam(optarg);
            if (!passwd) {
                if (errno)
                    fail("getpwnam failed");
                else
                    ERR("user not found: %s\n", optarg);
                exit(1);
            }
            OPTIONS.UID = passwd->pw_uid;
            OPTIONS.GID = passwd->pw_gid;
            break;

        case 'r':
            if (optarg && optarg[0] == '/')
                OPTIONS.CHROOT = optarg;
            else {
                ERR("chroot must be absolute path: \"%s\"\n", optarg);
                exit(1);
            }
            break;

        case 'B':
            OPTIONS.BACKLOG = atoi(optarg);
            if ( OPTIONS.BACKLOG <= 0 ) {
                ERR("listen backlog can not be set to %d\n", OPTIONS.BACKLOG);
                exit(1);
            }
            break;

#ifdef USE_SHARED_CACHE
        case 'C':
            OPTIONS.SHARED_CACHE = atoi(optarg);
            if ( OPTIONS.SHARED_CACHE < 0 ) {
                ERR("shared cache size can not be set to %d\n", OPTIONS.SHARED_CACHE);
                exit(1);
            }
            break;
#endif

        case 'q':
            OPTIONS.QUIET = 1;
            break;

        default:
            usage_fail(prog, NULL);
        }
    }

    /* Post-processing */
    if (tls && ssl)
        usage_fail(prog, "Cannot specify both --tls and --ssl");

    if (ssl)
        OPTIONS.ETYPE = ENC_SSL; // implied.. else, TLS

    if (OPTIONS.WRITE_IP_OCTET && OPTIONS.WRITE_PROXY_LINE)
        usage_fail(prog, "Cannot specify both --write-ip and --write-proxy; pick one!");

    argc -= optind;
    argv += optind;

    if (argc != 1)
        usage_fail(prog, "exactly one argument is required: path to PEM file with cert/key");

    OPTIONS.CERT_FILE = argv[0];
}
Пример #8
0
int handle_host_request(const char* service, TransportType type,
                        const char* serial, int reply_fd, asocket* s) {
    if (strcmp(service, "kill") == 0) {
        fprintf(stderr, "adb server killed by remote request\n");
        fflush(stdout);
        SendOkay(reply_fd);
        exit(0);
    }

#if ADB_HOST
    // "transport:" is used for switching transport with a specified serial number
    // "transport-usb:" is used for switching transport to the only USB transport
    // "transport-local:" is used for switching transport to the only local transport
    // "transport-any:" is used for switching transport to the only transport
    if (!strncmp(service, "transport", strlen("transport"))) {
        TransportType type = kTransportAny;

        if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
            type = kTransportUsb;
        } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
            type = kTransportLocal;
        } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
            type = kTransportAny;
        } else if (!strncmp(service, "transport:", strlen("transport:"))) {
            service += strlen("transport:");
            serial = service;
        }

        std::string error_msg;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &error_msg);
        if (t != nullptr) {
            s->transport = t;
            SendOkay(reply_fd);
        } else {
            SendFail(reply_fd, error_msg);
        }
        return 1;
    }

    // return a list of all connected devices
    if (!strncmp(service, "devices", 7)) {
        bool long_listing = (strcmp(service+7, "-l") == 0);
        if (long_listing || service[7] == 0) {
            D("Getting device list...\n");
            std::string device_list = list_transports(long_listing);
            D("Sending device list...\n");
            return SendOkay(reply_fd, device_list);
        }
        return 1;
    }

    // remove TCP transport
    if (!strncmp(service, "disconnect:", 11)) {
        const std::string address(service + 11);
        if (address.empty()) {
            // disconnect from all TCP devices
            unregister_all_tcp_transports();
            return SendOkay(reply_fd, "disconnected everything");
        }

        std::string serial;
        std::string host;
        int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
        std::string error;
        if (!parse_host_and_port(address, &serial, &host, &port, &error)) {
            return SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s",
                            address.c_str(), error.c_str()));
        }
        atransport* t = find_transport(serial.c_str());
        if (t == nullptr) {
            return SendFail(reply_fd, android::base::StringPrintf("no such device '%s'",
                            serial.c_str()));
        }
        unregister_transport(t);
        return SendOkay(reply_fd, android::base::StringPrintf("disconnected %s", address.c_str()));
    }

    // returns our value for ADB_SERVER_VERSION
    if (!strcmp(service, "version")) {
        return SendOkay(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION));
    }

    // These always report "unknown" rather than the actual error, for scripts.
    if (!strcmp(service, "get-serialno")) {
        std::string ignored;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored);
        return SendOkay(reply_fd, (t && t->serial) ? t->serial : "unknown");
    }
    if (!strcmp(service, "get-devpath")) {
        std::string ignored;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored);
        return SendOkay(reply_fd, (t && t->devpath) ? t->devpath : "unknown");
    }
    if (!strcmp(service, "get-state")) {
        std::string ignored;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored);
        return SendOkay(reply_fd, t ? t->connection_state_name() : "unknown");
    }

    // indicates a new emulator instance has started
    if (!strncmp(service, "emulator:", 9)) {
        int  port = atoi(service+9);
        local_connect(port);
        /* we don't even need to send a reply */
        return 0;
    }
#endif // ADB_HOST

    int ret = handle_forward_request(service, type, serial, reply_fd);
    if (ret >= 0)
        return ret - 1;
    return -1;
}
Пример #9
0
int handle_host_request(const char* service, TransportType type,
                        const char* serial, int reply_fd, asocket* s) {
    if (strcmp(service, "kill") == 0) {
        fprintf(stderr, "adb server killed by remote request\n");
        fflush(stdout);
        SendOkay(reply_fd);

        // At least on Windows, if we exit() without shutdown(SD_SEND) or
        // closesocket(), the client's next recv() will error-out with
        // WSAECONNRESET and they'll never read the OKAY.
        adb_shutdown(reply_fd);

        exit(0);
    }

#if ADB_HOST
    // "transport:" is used for switching transport with a specified serial number
    // "transport-usb:" is used for switching transport to the only USB transport
    // "transport-local:" is used for switching transport to the only local transport
    // "transport-any:" is used for switching transport to the only transport
    if (!strncmp(service, "transport", strlen("transport"))) {
        TransportType type = kTransportAny;

        if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
            type = kTransportUsb;
        } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
            type = kTransportLocal;
        } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
            type = kTransportAny;
        } else if (!strncmp(service, "transport:", strlen("transport:"))) {
            service += strlen("transport:");
            serial = service;
        }

        std::string error_msg;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &error_msg);
        if (t != nullptr) {
            s->transport = t;
            SendOkay(reply_fd);
        } else {
            SendFail(reply_fd, error_msg);
        }
        return 1;
    }

    // return a list of all connected devices
    if (!strncmp(service, "devices", 7)) {
        bool long_listing = (strcmp(service+7, "-l") == 0);
        if (long_listing || service[7] == 0) {
            D("Getting device list...");
            std::string device_list = list_transports(long_listing);
            D("Sending device list...");
            return SendOkay(reply_fd, device_list);
        }
        return 1;
    }

    if (!strcmp(service, "features")) {
        std::string error_msg;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &error_msg);
        if (t != nullptr) {
            SendOkay(reply_fd, android::base::Join(t->features(), '\n'));
        } else {
            SendFail(reply_fd, error_msg);
        }
        return 0;
    }

    if (!strncmp(service, "check-feature:", strlen("check-feature:"))) {
        std::string error_msg;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &error_msg);
        if (t && t->CanUseFeature(service + strlen("check-feature:"))) {
            // We could potentially extend this to reply with the feature
            // version if that becomes necessary.
            SendOkay(reply_fd, "1");
        } else {
            // Empty response means unsupported feature.
            SendOkay(reply_fd, "");
        }
        return 0;
    }

    // remove TCP transport
    if (!strncmp(service, "disconnect:", 11)) {
        const std::string address(service + 11);
        if (address.empty()) {
            kick_all_tcp_devices();
            return SendOkay(reply_fd, "disconnected everything");
        }

        std::string serial;
        std::string host;
        int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
        std::string error;
        if (!parse_host_and_port(address, &serial, &host, &port, &error)) {
            return SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s",
                                                                  address.c_str(), error.c_str()));
        }
        atransport* t = find_transport(serial.c_str());
        if (t == nullptr) {
            return SendFail(reply_fd, android::base::StringPrintf("no such device '%s'",
                                                                  serial.c_str()));
        }
        kick_transport(t);
        return SendOkay(reply_fd, android::base::StringPrintf("disconnected %s", address.c_str()));
    }

    // returns our value for ADB_SERVER_VERSION
    if (!strcmp(service, "version")) {
        return SendOkay(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION));
    }

    // These always report "unknown" rather than the actual error, for scripts.
    if (!strcmp(service, "get-serialno")) {
        std::string ignored;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored);
        return SendOkay(reply_fd, (t && t->serial) ? t->serial : "unknown");
    }
    if (!strcmp(service, "get-devpath")) {
        std::string ignored;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored);
        return SendOkay(reply_fd, (t && t->devpath) ? t->devpath : "unknown");
    }
    if (!strcmp(service, "get-state")) {
        std::string ignored;
        atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored);
        return SendOkay(reply_fd, t ? t->connection_state_name() : "unknown");
    }

    // indicates a new emulator instance has started
    if (!strncmp(service, "emulator:", 9)) {
        int  port = atoi(service+9);
        local_connect(port);
        /* we don't even need to send a reply */
        return 0;
    }
#endif // ADB_HOST

    int ret = handle_forward_request(service, type, serial, reply_fd);
    if (ret >= 0)
      return ret - 1;
    return -1;
}
Пример #10
0
Файл: stud.c Проект: djs55/stud
/* Handle command line arguments modifying behavior */
static void parse_cli(int argc, char **argv) {
    char *prog = argv[0];
    OPTIONS.FRONT_IP = NULL;
    OPTIONS.FRONT_PORT = "8443";

    OPTIONS.BACK_IP = "127.0.0.1";
    OPTIONS.BACK_PORT = "8000";

    OPTIONS.ETYPE = ENC_TLS;

    OPTIONS.NCORES = 1;

    OPTIONS.WRITE_IP_OCTET = 0;

    OPTIONS.CIPHER_SUITE = NULL;
    
    static int tls = 0, ssl = 0, writeip = 0;
    int c;

    static struct option long_options[] =
    {
        {"tls", 0, &tls, 1},
        {"ssl", 0, &ssl, 1},
        {"write-ip", 0, &writeip, 1},
        {0, 0, 0, 0}
    };

    while (1) {
        int option_index = 0;
        c = getopt_long(argc, argv, "hf:b:n:c:",
                long_options, &option_index);

        if (c == -1)
            break;

        switch (c) {

        case 0:
            break;

        case 'n':
            OPTIONS.NCORES = strtol(optarg, NULL, 10);
            if (errno || OPTIONS.NCORES < 1 || OPTIONS.NCORES > 128)
                usage_fail(prog, "invalid option for -n CORES; please provide an integer between 1 and 128\n");
            break;

        case 'b':
            parse_host_and_port(prog, "-b", optarg, 0, &(OPTIONS.BACK_IP), &(OPTIONS.BACK_PORT));
            break;

        case 'f':
            parse_host_and_port(prog, "-f", optarg, 1, &(OPTIONS.FRONT_IP), &(OPTIONS.FRONT_PORT));
            break;
            
        case 'c':
            OPTIONS.CIPHER_SUITE = optarg;
            break;

        default:
            usage_fail(prog, NULL);
        }
    }

    /* Post-processing */
    if (tls && ssl)
        usage_fail(prog, "Cannot specify both --tls and --ssl");

    if (ssl)
        OPTIONS.ETYPE = ENC_SSL; // implied.. else, TLS

    if (writeip)
        OPTIONS.WRITE_IP_OCTET = 1;

    argc -= optind;
    argv += optind;

    if (argc != 1)
        usage_fail(prog, "exactly one argument is required: path to PEM file with cert/key");

    OPTIONS.CERT_FILE = argv[0];
}