mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
nettest: Add support for TCP_MD5 extensions
Update nettest to implement TCP_MD5SIG_EXT for a prefix and a device. Add a new option, -m, to specify a prefix and length to use with MD5 auth. The device option comes from the existing -d option. If either are set and MD5 auth is requested, TCP_MD5SIG_EXT is used instead of TCP_MD5SIG. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1bfb45d860
commit
eb09cf03b9
1 changed files with 69 additions and 13 deletions
|
@ -74,7 +74,14 @@ struct sock_args {
|
||||||
int use_cmsg;
|
int use_cmsg;
|
||||||
const char *dev;
|
const char *dev;
|
||||||
int ifindex;
|
int ifindex;
|
||||||
|
|
||||||
const char *password;
|
const char *password;
|
||||||
|
/* prefix for MD5 password */
|
||||||
|
union {
|
||||||
|
struct sockaddr_in v4;
|
||||||
|
struct sockaddr_in6 v6;
|
||||||
|
} md5_prefix;
|
||||||
|
unsigned int prefix_len;
|
||||||
|
|
||||||
/* expected addresses and device index for connection */
|
/* expected addresses and device index for connection */
|
||||||
int expected_ifindex;
|
int expected_ifindex;
|
||||||
|
@ -200,20 +207,33 @@ static void log_address(const char *desc, struct sockaddr *sa)
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tcp_md5sig(int sd, void *addr, socklen_t alen, const char *password)
|
static int tcp_md5sig(int sd, void *addr, socklen_t alen, struct sock_args *args)
|
||||||
{
|
{
|
||||||
struct tcp_md5sig md5sig;
|
int keylen = strlen(args->password);
|
||||||
int keylen = password ? strlen(password) : 0;
|
struct tcp_md5sig md5sig = {};
|
||||||
|
int opt = TCP_MD5SIG;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
memset(&md5sig, 0, sizeof(md5sig));
|
|
||||||
memcpy(&md5sig.tcpm_addr, addr, alen);
|
|
||||||
md5sig.tcpm_keylen = keylen;
|
md5sig.tcpm_keylen = keylen;
|
||||||
|
memcpy(md5sig.tcpm_key, args->password, keylen);
|
||||||
|
|
||||||
if (keylen)
|
if (args->prefix_len) {
|
||||||
memcpy(md5sig.tcpm_key, password, keylen);
|
opt = TCP_MD5SIG_EXT;
|
||||||
|
md5sig.tcpm_flags |= TCP_MD5SIG_FLAG_PREFIX;
|
||||||
|
|
||||||
rc = setsockopt(sd, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof(md5sig));
|
md5sig.tcpm_prefixlen = args->prefix_len;
|
||||||
|
addr = &args->md5_prefix;
|
||||||
|
}
|
||||||
|
memcpy(&md5sig.tcpm_addr, addr, alen);
|
||||||
|
|
||||||
|
if (args->ifindex) {
|
||||||
|
opt = TCP_MD5SIG_EXT;
|
||||||
|
md5sig.tcpm_flags |= TCP_MD5SIG_FLAG_IFINDEX;
|
||||||
|
|
||||||
|
md5sig.tcpm_ifindex = args->ifindex;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = setsockopt(sd, IPPROTO_TCP, opt, &md5sig, sizeof(md5sig));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
/* ENOENT is harmless. Returned when a password is cleared */
|
/* ENOENT is harmless. Returned when a password is cleared */
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
|
@ -254,7 +274,7 @@ static int tcp_md5_remote(int sd, struct sock_args *args)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcp_md5sig(sd, addr, alen, args->password))
|
if (tcp_md5sig(sd, addr, alen, args))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1313,7 +1333,7 @@ static int connectsock(void *addr, socklen_t alen, struct sock_args *args)
|
||||||
if (args->type != SOCK_STREAM)
|
if (args->type != SOCK_STREAM)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (args->password && tcp_md5sig(sd, addr, alen, args->password))
|
if (args->password && tcp_md5sig(sd, addr, alen, args))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (args->bind_test_only)
|
if (args->bind_test_only)
|
||||||
|
@ -1405,16 +1425,18 @@ enum addr_type {
|
||||||
ADDR_TYPE_MCAST,
|
ADDR_TYPE_MCAST,
|
||||||
ADDR_TYPE_EXPECTED_LOCAL,
|
ADDR_TYPE_EXPECTED_LOCAL,
|
||||||
ADDR_TYPE_EXPECTED_REMOTE,
|
ADDR_TYPE_EXPECTED_REMOTE,
|
||||||
|
ADDR_TYPE_MD5_PREFIX,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int convert_addr(struct sock_args *args, const char *_str,
|
static int convert_addr(struct sock_args *args, const char *_str,
|
||||||
enum addr_type atype)
|
enum addr_type atype)
|
||||||
{
|
{
|
||||||
|
int pfx_len_max = args->version == AF_INET6 ? 128 : 32;
|
||||||
int family = args->version;
|
int family = args->version;
|
||||||
|
char *str, *dev, *sep;
|
||||||
struct in6_addr *in6;
|
struct in6_addr *in6;
|
||||||
struct in_addr *in;
|
struct in_addr *in;
|
||||||
const char *desc;
|
const char *desc;
|
||||||
char *str, *dev;
|
|
||||||
void *addr;
|
void *addr;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
@ -1443,6 +1465,30 @@ static int convert_addr(struct sock_args *args, const char *_str,
|
||||||
desc = "expected remote";
|
desc = "expected remote";
|
||||||
addr = &args->expected_raddr;
|
addr = &args->expected_raddr;
|
||||||
break;
|
break;
|
||||||
|
case ADDR_TYPE_MD5_PREFIX:
|
||||||
|
desc = "md5 prefix";
|
||||||
|
if (family == AF_INET) {
|
||||||
|
args->md5_prefix.v4.sin_family = AF_INET;
|
||||||
|
addr = &args->md5_prefix.v4.sin_addr;
|
||||||
|
} else if (family == AF_INET6) {
|
||||||
|
args->md5_prefix.v6.sin6_family = AF_INET6;
|
||||||
|
addr = &args->md5_prefix.v6.sin6_addr;
|
||||||
|
} else
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sep = strchr(str, '/');
|
||||||
|
if (sep) {
|
||||||
|
*sep = '\0';
|
||||||
|
sep++;
|
||||||
|
if (str_to_uint(sep, 1, pfx_len_max,
|
||||||
|
&args->prefix_len) != 0) {
|
||||||
|
fprintf(stderr, "Invalid port\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args->prefix_len = pfx_len_max;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log_error("unknown address type");
|
log_error("unknown address type");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -1522,7 +1568,7 @@ static char *random_msg(int len)
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GETOPT_STR "sr:l:p:t:g:P:DRn:M:d:SCi6L:0:1:2:Fbq"
|
#define GETOPT_STR "sr:l:p:t:g:P:DRn:M:m:d:SCi6L:0:1:2:Fbq"
|
||||||
|
|
||||||
static void print_usage(char *prog)
|
static void print_usage(char *prog)
|
||||||
{
|
{
|
||||||
|
@ -1551,6 +1597,7 @@ static void print_usage(char *prog)
|
||||||
" -n num number of times to send message\n"
|
" -n num number of times to send message\n"
|
||||||
"\n"
|
"\n"
|
||||||
" -M password use MD5 sum protection\n"
|
" -M password use MD5 sum protection\n"
|
||||||
|
" -m prefix/len prefix and length to use for MD5 key\n"
|
||||||
" -g grp multicast group (e.g., 239.1.1.1)\n"
|
" -g grp multicast group (e.g., 239.1.1.1)\n"
|
||||||
" -i interactive mode (default is echo and terminate)\n"
|
" -i interactive mode (default is echo and terminate)\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -1642,6 +1689,10 @@ int main(int argc, char *argv[])
|
||||||
case 'M':
|
case 'M':
|
||||||
args.password = optarg;
|
args.password = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'm':
|
||||||
|
if (convert_addr(&args, optarg, ADDR_TYPE_MD5_PREFIX) < 0)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
args.use_setsockopt = 1;
|
args.use_setsockopt = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -1706,11 +1757,16 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.password &&
|
if (args.password &&
|
||||||
(!args.has_remote_ip || args.type != SOCK_STREAM)) {
|
((!args.has_remote_ip && !args.prefix_len) || args.type != SOCK_STREAM)) {
|
||||||
log_error("MD5 passwords apply to TCP only and require a remote ip for the password\n");
|
log_error("MD5 passwords apply to TCP only and require a remote ip for the password\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.prefix_len && !args.password) {
|
||||||
|
log_error("Prefix range for MD5 protection specified without a password\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((args.use_setsockopt || args.use_cmsg) && !args.ifindex) {
|
if ((args.use_setsockopt || args.use_cmsg) && !args.ifindex) {
|
||||||
fprintf(stderr, "Device binding not specified\n");
|
fprintf(stderr, "Device binding not specified\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue