mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-20 17:44:33 +08:00
a61bd7b9fe
This patch adds 12 small test cases: 01-04 test for the sysctl net.sctp.l3mdev_accept. 05-10 test for only binding to a right l3mdev device, the connection can be created. 11-12 test for two socks binding to different l3mdev devices at the same time, each of them can process the packets from the corresponding peer. The tests run for both IPv4 and IPv6 SCTP. Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
138 lines
2.8 KiB
C
138 lines
2.8 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
|
|
static void set_addr(struct sockaddr_storage *ss, char *ip, char *port, int *len)
|
|
{
|
|
if (ss->ss_family == AF_INET) {
|
|
struct sockaddr_in *a = (struct sockaddr_in *)ss;
|
|
|
|
a->sin_addr.s_addr = inet_addr(ip);
|
|
a->sin_port = htons(atoi(port));
|
|
*len = sizeof(*a);
|
|
} else {
|
|
struct sockaddr_in6 *a = (struct sockaddr_in6 *)ss;
|
|
|
|
a->sin6_family = AF_INET6;
|
|
inet_pton(AF_INET6, ip, &a->sin6_addr);
|
|
a->sin6_port = htons(atoi(port));
|
|
*len = sizeof(*a);
|
|
}
|
|
}
|
|
|
|
static int do_client(int argc, char *argv[])
|
|
{
|
|
struct sockaddr_storage ss;
|
|
char buf[] = "hello";
|
|
int csk, ret, len;
|
|
|
|
if (argc < 5) {
|
|
printf("%s client -4|6 IP PORT [IP PORT]\n", argv[0]);
|
|
return -1;
|
|
}
|
|
|
|
bzero((void *)&ss, sizeof(ss));
|
|
ss.ss_family = !strcmp(argv[2], "-4") ? AF_INET : AF_INET6;
|
|
csk = socket(ss.ss_family, SOCK_STREAM, IPPROTO_SCTP);
|
|
if (csk < 0) {
|
|
printf("failed to create socket\n");
|
|
return -1;
|
|
}
|
|
|
|
if (argc >= 7) {
|
|
set_addr(&ss, argv[5], argv[6], &len);
|
|
ret = bind(csk, (struct sockaddr *)&ss, len);
|
|
if (ret < 0) {
|
|
printf("failed to bind to address\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
set_addr(&ss, argv[3], argv[4], &len);
|
|
ret = connect(csk, (struct sockaddr *)&ss, len);
|
|
if (ret < 0) {
|
|
printf("failed to connect to peer\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = send(csk, buf, strlen(buf) + 1, 0);
|
|
if (ret < 0) {
|
|
printf("failed to send msg %d\n", ret);
|
|
return -1;
|
|
}
|
|
close(csk);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct sockaddr_storage ss;
|
|
int lsk, csk, ret, len;
|
|
char buf[20];
|
|
|
|
if (argc < 2 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) {
|
|
printf("%s server|client ...\n", argv[0]);
|
|
return -1;
|
|
}
|
|
|
|
if (!strcmp(argv[1], "client"))
|
|
return do_client(argc, argv);
|
|
|
|
if (argc < 5) {
|
|
printf("%s server -4|6 IP PORT [IFACE]\n", argv[0]);
|
|
return -1;
|
|
}
|
|
|
|
ss.ss_family = !strcmp(argv[2], "-4") ? AF_INET : AF_INET6;
|
|
lsk = socket(ss.ss_family, SOCK_STREAM, IPPROTO_SCTP);
|
|
if (lsk < 0) {
|
|
printf("failed to create lsk\n");
|
|
return -1;
|
|
}
|
|
|
|
if (argc >= 6) {
|
|
ret = setsockopt(lsk, SOL_SOCKET, SO_BINDTODEVICE,
|
|
argv[5], strlen(argv[5]) + 1);
|
|
if (ret < 0) {
|
|
printf("failed to bind to device\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
set_addr(&ss, argv[3], argv[4], &len);
|
|
ret = bind(lsk, (struct sockaddr *)&ss, len);
|
|
if (ret < 0) {
|
|
printf("failed to bind to address\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = listen(lsk, 5);
|
|
if (ret < 0) {
|
|
printf("failed to listen on port\n");
|
|
return -1;
|
|
}
|
|
|
|
csk = accept(lsk, (struct sockaddr *)NULL, (socklen_t *)NULL);
|
|
if (csk < 0) {
|
|
printf("failed to accept new client\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = recv(csk, buf, sizeof(buf), 0);
|
|
if (ret <= 0) {
|
|
printf("failed to recv msg %d\n", ret);
|
|
return -1;
|
|
}
|
|
close(csk);
|
|
close(lsk);
|
|
|
|
return 0;
|
|
}
|