Les sockets raw se comportent particulièrement bien avec bind() et connect(), mais je ne peux pas confirmer que votre problème réside avec eux. Je vous suggère de suivre une approche plus directe:
Auteur
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define DEST "127.0.0.1"
int main(int argc, char **argv)
{
int s;
struct sockaddr_in dst_addr;
char packet[50];
struct iphdr *ip = (struct iphdr *)packet;
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("error:");
exit(EXIT_FAILURE);
}
dst_addr.sin_family = AF_INET;
dst_addr.sin_port = 0; /* not needed in SOCK_RAW */
inet_pton(AF_INET, DEST, (struct in_addr *)&dst_addr.sin_addr.s_addr);
memset(dst_addr.sin_zero, 0, sizeof(dst_addr.sin_zero));
memset(packet, 'A', sizeof(packet)); /* payload will be all As */
ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
ip->tot_len = htons(40);
ip->frag_off = 0; /* NF */
ip->ttl = 64;
ip->protocol = IPPROTO_RAW; /* this has to be IPPROTO_RAW */
ip->check = 0;
ip->saddr = dst_addr.sin_addr.s_addr;
ip->daddr = dst_addr.sin_addr.s_addr;
while(42) {
sleep(5);
if (sendto(s, packet, sizeof(packet), 0,
(struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr)) < 0)
perror("uh oh:");
}
return(0);
}
Récepteur
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int s;
struct sockaddr_in src_addr;
char packet[50];
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("error:");
exit(EXIT_FAILURE);
}
memset(packet, 0, sizeof(packet));
socklen_t *len = (socklen_t *)sizeof(src_addr);
int fromlen = sizeof(src_addr);
while(42) {
if (recvfrom(s, &packet, sizeof(packet), 0,
(struct sockaddr *)&src_addr, &fromlen) < 0)
perror("uh oh:");
int i = sizeof(struct iphdr); /* print the payload */
for(; i < sizeof(packet); i++) {
printf("%c", packet[i]);
}
printf("\n");
}
return(0);
}
J'espère que ces se comportent exactement comme vous voulez qu'ils. Lire man 7 raw
pour les détails sanglants de pourquoi cela fonctionne et plus important encoreman 7 packet
si vous voulez l'étendre. Notez également que IPPROTO_RAW implique l'option de socket IP_HDRINCL, c'est pourquoi nous construisons l'en-tête ip nous-mêmes - bien que la somme de contrôle IP et la longueur totale soient calculées et remplies par le noyau, encore.
modifier: En outre, si vous vouliez une socket raw avec laquelle envoyer des données valides à une application comme lighttpd, vous auriez à correspondre l'argument à socket()
ainsi que de fournir des valeurs valides pour les champs d'en-tête IP. Un en-tête Ethernet correct n'est pas obligatoire - le seul champ important sera rempli pour vous par la pile du noyau.
S'il vous plaît après: a) exactement quel type de socket que vous utilisez, est-il un AF_PACKET? b) Comment liez-vous, utilisez-vous bind ou SO_BINDTODEVICE? c) Qu'est-ce que le serveur et qu'est-ce qu'il essaie de faire? Pouvez-vous parler avec une socket IP (en supposant IP ici)? Pouvez-vous envoyer la sortie de netstat --raw? – MarkR
@MarkR: Étant donné qu'il utilise des sockets raw, je devine SOCK_RAW. SOCK_PACKET est obsolète, de toute façon. –
Je trouve la page "man 7 packet" assez utile, veuillez la lire et voir si ce qu'elle décrit correspond à ce que vous faites. – MarkR