Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Ну и естественно, никакой уважающий себя сетевой стек не собирается принимать пакеты с совершенно незнакомого адреса, даже если порты стоят правильные.
oxpa@oxpa-desktop:~$ netstat -unp
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
udp 0 0 192.168.0.2:38940 8.8.8.8:53 ESTABLISHED 19597/operapluginwr
udp 0 0 127.0.0.1:123 0.0.0.0:*
— data->sock = socket ( PF_INET, SOCK_DGRAM, 0 );
if ( data->sock == -1 ) {
data->logger->log ( LOGGER_ERROR, "Can't allocate socket.\n" );
return -1;
}
if ( bind ( data->sock, ( struct sockaddr* ) &data->si, sizeof ( data->si ) ) < 0 ) {
close ( data->sock );
data->sock = -1;
data->logger->log ( LOGGER_ERROR, "Can't bind socket.\n" );
return -1;
}rxed = recvfrom ( d->sock, rx_buff, sizeof ( rx_buff ), 0, ( struct sockaddr* ) &si_other, &slen );
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
The connect() system call connects the socket referred to by the file descriptor sockfd to the address specified by addr. The addrlen argument specifies the size of addr. The format of the address in addr is determined by the address space of the socket sockfd; see socket(2) for further details.
If the socket sockfd is of type SOCK_DGRAM then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received.
Ну и естественно, никакой уважающий себя сетевой стек не собирается принимать пакеты с совершенно незнакомого адреса, даже если порты стоят правильные.
Но на самом деле, это обычный дефект для протокола без установки сессии, такого как UDP.
Ещё раз: ядро не хранит никакой информации об отправителе или получателе, так как мы работаем без соединений.
/* Check that client and server are using same socket */
if (echoserver.sin_addr.s_addr != echoclient.sin_addr.s_addr) {
Die("Received a packet from an unexpected server");
}
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define BUFFSIZE 255
void Die(char *mess) {
perror(mess);
exit(1);
}
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in echoserver;
struct sockaddr_in echoclient;
char buffer[BUFFSIZE];
unsigned int echolen, clientlen;
int received = 0;
if (argc != 4) {
fprintf(stderr, "USAGE: %s <server_ip> <word> <port>\n", argv[0]);
exit(1);
}
/* Create the UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
Die("Failed to create socket");
}
/* Construct the server sockaddr_in structure */
memset(&echoserver, 0, sizeof(echoserver)); /* Clear struct */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = inet_addr(argv[1]); /* IP address */
echoserver.sin_port = htons(atoi(argv[3])); /* server port */
/* Send the word to the server */
echolen = strlen(argv[2]);
if (sendto(sock, argv[2], echolen, 0,
(struct sockaddr *) &echoserver,
sizeof(echoserver)) != echolen) {
Die("Mismatch in number of sent bytes");
}
/* Receive the word back from the server */
fprintf(stdout, "Received: ");
clientlen = sizeof(echoclient);
if ((received = recvfrom(sock, buffer, BUFFSIZE, 0,
(struct sockaddr *) &echoclient,
&clientlen)) != echolen) {
Die("Mismatch in number of received bytes");
}
/* Check that client and server are using same socket */
if (echoserver.sin_addr.s_addr != echoclient.sin_addr.s_addr) {
Die("Received a packet from an unexpected server");
}
buffer[received] = '\0'; /* Assure null terminated string */
fprintf(stdout, buffer);
fprintf(stdout, "\n");
close(sock);
exit(0);
}
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define BUFFSIZE 255
void Die(char *mess) {
perror(mess);
exit(1);
}
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in echoserver;
struct sockaddr_in echoclient;
char buffer[BUFFSIZE];
unsigned int echolen, clientlen, serverlen;
int received = 0;
if (argc != 2) {
fprintf(stderr, "USAGE: %s <port>\n", argv[0]);
exit(1);
}
/* Create the UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
Die("Failed to create socket");
}
/* Construct the server sockaddr_in structure */
memset(&echoserver, 0, sizeof(echoserver)); /* Clear struct */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = htonl(INADDR_ANY); /* Any IP address */
echoserver.sin_port = htons(atoi(argv[1])); /* server port */
/* Bind the socket */
serverlen = sizeof(echoserver);
if (bind(sock, (struct sockaddr *) &echoserver, serverlen) < 0) {
Die("Failed to bind server socket");
}
/* Run until cancelled */
while (1) {
/* Receive a message from the client */
clientlen = sizeof(echoclient);
if ((received = recvfrom(sock, buffer, BUFFSIZE, 0,
(struct sockaddr *) &echoclient,
&clientlen)) < 0) {
Die("Failed to receive message");
}
fprintf(stderr,
"Client connected: %s\n", inet_ntoa(echoclient.sin_addr));
/* Send the message back to client */
if (sendto(sock, buffer, received, 0,
(struct sockaddr *) &echoclient,
sizeof(echoclient)) != received) {
Die("Mismatch in number of echo'd bytes");
}
}
}
udp 0 0 0.0.0.0:45721 0.0.0.0:* 21444/./client.udp
-- запускаем netcat слушать 1$ nc -u -l 0.0.0.0 10000 -- смотрим что он открыл 2$ netstat -anpu | grep 10000 udp 0 0 0.0.0.0:10000 0.0.0.0:* 26242/nc 2$ lsof -p 26242 | grep UDP nc 26242 jcmvbkbc 3u IPv4 388760 0t0 UDP *:ndmp -- посылаем ему пакет 3$ echo Hello | nc 127.0.0.1 10000 ^C -- смотрим что с ним стало 2$ netstat -anpu | grep 10000 udp 0 0 127.0.0.1:10000 127.0.0.1:51359 ESTABLISHED 26242/nc 2$ lsof -p 26242 | grep UDP nc 26242 jcmvbkbc 3u IPv4 388760 0t0 UDP localhost:ndmp->localhost:51359 -- смотрим что он напечатал 1$ nc -u -l 0.0.0.0 10000 Hello -- шлём ему что-нибудь ещё, с другого порта... не шлётся 3$ echo Hello | nc 127.0.0.1 10000 nc: Write error: Connection refused ^C
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
int main(int argc,char *argv[])
{
int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
int port = 10000;
sockaddr_in sa = {};
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
bind(s, (sockaddr*)&sa, sizeof(sa));
for (;;) {
char buf[100000];
ssize_t sz;
sz = read(s, buf, sizeof(buf));
write(STDOUT_FILENO, buf, sz);
}
return 0;
}
int netcat_socket_new_connect(int domain, int type, const struct in_addr *addr,
in_port_t port, const struct in_addr *local_addr,
in_port_t local_port)
/* now launch the real connection. Since we are in non-blocking mode, this
call will return -1 in MOST cases (on some systems, a connect() to a local
address may immediately return successfully) */
ret = connect(sock, (struct sockaddr *)&rem_addr, sizeof(rem_addr));
if ((ret < 0) && (errno != EINPROGRESS)) {
ret = -5;
goto err;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
int main(int argc,char *argv[])
{
int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
int port = 10000;
struct sockaddr_in sa = {};
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
bind(s, (struct sockaddr*)&sa, sizeof(sa));
for (;;) {
char buf[100000];
struct sockaddr client_sa;
socklen_t client_sa_sz = sizeof(client_sa);
ssize_t sz;
sz = recvfrom(s, buf, sizeof(buf), 0, &client_sa, &client_sa_sz);
write(STDOUT_FILENO, buf, sz);
sendto(s, buf, sz, 0, &client_sa, client_sa_sz);
}
return 0;
}
UDP и проблема доставки ответа