|
@@ -52,6 +52,8 @@ static int packet_buflen;
|
52
|
52
|
static uint8_t packet_buf[256];
|
53
|
53
|
static enum msg_type packet_type = ECM_MSG;
|
54
|
54
|
|
|
55
|
+extern int ai_family;
|
|
56
|
+
|
55
|
57
|
static void do_log(FILE *f, time_t now, const char *msg) {
|
56
|
58
|
char date[64];
|
57
|
59
|
struct tm tm;
|
|
@@ -76,9 +78,9 @@ static void LOG_func(const char *msg) {
|
76
|
78
|
LOG(msg);
|
77
|
79
|
}
|
78
|
80
|
|
79
|
|
-static const char short_options[] = "i:d:N:Sl:L:F:I:RzM:T:W:O:o:t:rk:g:upwxyc:C:Y:Q:A:s:U:P:B:eZ:Ef:X:H:G:KJ:D:jbhVn:m:";
|
|
81
|
+static const char short_options[] = "i:d:N:Sl:L:F:I:RzM:T:W:O:o:t:rk:g:upwxyc:C:Y:Q:A:s:U:P:B:46eZ:Ef:X:H:G:KJ:D:jbhVn:m:";
|
80
|
82
|
|
81
|
|
-// Unused short options: aqv0123456789
|
|
83
|
+// Unused short options: aqv01235789
|
82
|
84
|
static const struct option long_options[] = {
|
83
|
85
|
{ "ident", required_argument, NULL, 'i' },
|
84
|
86
|
{ "daemon", required_argument, NULL, 'd' },
|
|
@@ -117,6 +119,8 @@ static const struct option long_options[] = {
|
117
|
119
|
{ "camd-user", required_argument, NULL, 'U' },
|
118
|
120
|
{ "camd-pass", required_argument, NULL, 'P' },
|
119
|
121
|
{ "camd-des-key", required_argument, NULL, 'B' },
|
|
122
|
+ { "ipv4", no_argument, NULL, '4' },
|
|
123
|
+ { "ipv6", no_argument, NULL, '6' },
|
120
|
124
|
|
121
|
125
|
{ "emm", no_argument, NULL, 'e' },
|
122
|
126
|
{ "emm-pid", required_argument, NULL, 'Z' },
|
|
@@ -194,10 +198,18 @@ static void show_help(struct ts *ts) {
|
194
|
198
|
printf(" -A --camd-proto <proto> | Set CAMD network protocol.\n");
|
195
|
199
|
printf(" . Valid protocols are: CS378X (default) and NEWCAMD\n");
|
196
|
200
|
printf(" -s --camd-server <host> | Set CAMD server address. Default port: 2233\n");
|
|
201
|
+ printf(" . Example IPv4 addr and port: 127.0.0.1:2233\n");
|
|
202
|
+ printf(" . Example IPv6 addr and port: [2a00::1014]:2233\n");
|
|
203
|
+ printf(" . Example hostname : example.com\n");
|
|
204
|
+ printf(" . Example hostname and port : example.com:2233\n");
|
|
205
|
+ printf(" . Example IPv4 hostname : ipv4.google.com\n");
|
|
206
|
+ printf(" . Example IPv6 hostname : ipv6.google.com\n");
|
197
|
207
|
printf(" -U --camd-user <user> | Set CAMD server user. Default: %s\n", ts->camd.user);
|
198
|
208
|
printf(" -P --camd-pass <pass> | Set CAMD server password. Default: %s\n", ts->camd.pass);
|
199
|
209
|
printf(" -B --camd-des-key <key> | Set DES key for newcamd protocol.\n");
|
200
|
210
|
printf(" . Default: %s\n", ts->camd.newcamd.hex_des_key);
|
|
211
|
+ printf(" -4 --ipv4 | Use only IPv4 addresses of the camd server.\n");
|
|
212
|
+ printf(" -6 --ipv6 | Use only IPv6 addresses of the camd server.\n");
|
201
|
213
|
printf("\n");
|
202
|
214
|
printf("EMM options:\n");
|
203
|
215
|
printf(" -e --emm | Enable sending EMM's to CAMD. Default: %s\n", ts->emm_send ? "enabled" : "disabled");
|
|
@@ -267,8 +279,6 @@ static int parse_io_param(struct io *io, char *opt, int open_flags, mode_t open_
|
267
|
279
|
}
|
268
|
280
|
|
269
|
281
|
static void parse_options(struct ts *ts, int argc, char **argv) {
|
270
|
|
- int h_err;
|
271
|
|
- struct addrinfo hints, *addrinfo = NULL;
|
272
|
282
|
int j, i, ca_err = 0, server_err = 1, input_addr_err = 0, output_addr_err = 0, output_intf_err = 0, ident_err = 0, port_set = 0;
|
273
|
283
|
while ((j = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
|
274
|
284
|
char *p = NULL;
|
|
@@ -438,33 +448,29 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
|
438
|
448
|
}
|
439
|
449
|
break;
|
440
|
450
|
case 's': // --camd-server
|
441
|
|
- p = strrchr(optarg, ':');
|
442
|
|
- if (p) {
|
443
|
|
- *p = 0x00;
|
444
|
|
- ts->camd.server_port = atoi(p + 1);
|
445
|
|
- port_set = 1;
|
446
|
|
- }
|
447
|
|
- server_err = 1;
|
448
|
|
-
|
449
|
|
- memset(&hints, 0, sizeof hints);
|
450
|
|
- hints.ai_family = AF_INET;
|
451
|
|
- hints.ai_socktype = SOCK_STREAM;
|
452
|
|
- h_err = getaddrinfo(optarg, NULL, &hints, &addrinfo);
|
453
|
|
- if (h_err == 0) {
|
454
|
|
- int num_addrs = 0;
|
455
|
|
- struct addrinfo *addr;
|
456
|
|
- for (addr = addrinfo; addr != NULL; addr = addr->ai_next) {
|
457
|
|
- struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr->ai_addr;
|
458
|
|
- if (!ts->camd.server_addr.s_addr) // Get the first IP address
|
459
|
|
- ts->camd.server_addr = ipv4->sin_addr;
|
460
|
|
- num_addrs++;
|
|
451
|
+ server_err = 0;
|
|
452
|
+ ts->camd.hostname = optarg;
|
|
453
|
+ if (optarg[0] == '[') { // Detect IPv6 static address
|
|
454
|
+ p = strrchr(optarg, ']');
|
|
455
|
+ if (!p) {
|
|
456
|
+ fprintf(stderr, "ERROR: Invalid IPv6 address format: %s\n", optarg);
|
|
457
|
+ exit(EXIT_FAILURE);
|
|
458
|
+ }
|
|
459
|
+ ts->camd.hostname = optarg + 1; // Remove first [
|
|
460
|
+ *p = 0x00; // Remove last ]
|
|
461
|
+ char *p2 = strchr(p + 1, ':');
|
|
462
|
+ if (p2) {
|
|
463
|
+ *p2 = 0x00;
|
|
464
|
+ ts->camd.service = p2 + 1;
|
|
465
|
+ port_set = 1;
|
461
|
466
|
}
|
462
|
|
- freeaddrinfo(addrinfo);
|
463
|
|
- if (num_addrs)
|
464
|
|
- server_err = 0;
|
465
|
467
|
} else {
|
466
|
|
- fprintf(stderr, "ERROR: getaddrinfo(%s) returned: %s\n", optarg, gai_strerror(h_err));
|
467
|
|
- exit(EXIT_FAILURE);
|
|
468
|
+ p = strrchr(optarg, ':');
|
|
469
|
+ if (p) {
|
|
470
|
+ *p = 0x00;
|
|
471
|
+ ts->camd.service = p + 1;
|
|
472
|
+ port_set = 1;
|
|
473
|
+ }
|
468
|
474
|
}
|
469
|
475
|
break;
|
470
|
476
|
case 'U': // --camd-user
|
|
@@ -484,6 +490,12 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
|
484
|
490
|
strncpy(ts->camd.newcamd.hex_des_key, optarg, sizeof(ts->camd.newcamd.hex_des_key) - 1);
|
485
|
491
|
ts->camd.newcamd.hex_des_key[sizeof(ts->camd.newcamd.hex_des_key) - 1] = 0;
|
486
|
492
|
break;
|
|
493
|
+ case '4': // --ipv4
|
|
494
|
+ ai_family = AF_INET;
|
|
495
|
+ break;
|
|
496
|
+ case '6': // --ipv6
|
|
497
|
+ ai_family = AF_INET6;
|
|
498
|
+ break;
|
487
|
499
|
|
488
|
500
|
case 'e': // --emm
|
489
|
501
|
ts->emm_send = !ts->emm_send;
|
|
@@ -621,7 +633,7 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
|
621
|
633
|
exit(EXIT_FAILURE);
|
622
|
634
|
}
|
623
|
635
|
if (ts->camd.ops.proto == CAMD_NEWCAMD && !port_set) {
|
624
|
|
- fprintf(stderr, "ERROR: CAMD server port is not set. Use --camd-server %s:xxxx to set the port.\n", inet_ntoa(ts->camd.server_addr));
|
|
636
|
+ fprintf(stderr, "ERROR: CAMD server port is not set. Use --camd-server %s:xxxx to set the port.\n", ts->camd.hostname);
|
625
|
637
|
exit(EXIT_FAILURE);
|
626
|
638
|
}
|
627
|
639
|
|
|
@@ -728,7 +740,11 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
|
728
|
740
|
}
|
729
|
741
|
if (!ts->camd.constant_codeword) {
|
730
|
742
|
ts_LOGf("CAMD proto : %s\n", ts->camd.ops.ident);
|
731
|
|
- ts_LOGf("CAMD addr : tcp://%s:%u/\n", inet_ntoa(ts->camd.server_addr), ts->camd.server_port);
|
|
743
|
+ ts_LOGf("CAMD addr : %s:%s%s\n", ts->camd.hostname, ts->camd.service,
|
|
744
|
+ ai_family == AF_INET ? " (IPv4 only)" :
|
|
745
|
+ ai_family == AF_INET6 ? " (IPv6 only)" :
|
|
746
|
+ " (IPv4/IPv6)"
|
|
747
|
+ );
|
732
|
748
|
ts_LOGf("CAMD user : %s\n", ts->camd.user);
|
733
|
749
|
ts_LOGf("CAMD pass : %s\n", ts->camd.pass);
|
734
|
750
|
if (ts->camd.ops.proto == CAMD_NEWCAMD)
|