Datenstruktur per Fifo/named Pipe übergeben.
-
Ich empfange in einem Prozess Ethernetpakete (kein TCP/IP). Diese möchte ich an mein Hauptprogramm weitergeben. Kann ich das direkt mit einer Fifo Queue machen, oder muss ich mein Ethernetpaket im Empfangsprogramm in klartext auslesen und dann rübergeben.
Noch mal fürs Verständnis:
Prozess a: Empfängt Ethernetpaket (Zieladresse, Queladresse, Ethertype ...)read(sock,packet,packetsize);
--> übergibt dieses packet an Prozess b: Hier lese ich mein empfangenes Paket aus und zerstückel es, wie benötigt.
So lese ich meine Pakete bisher testweise aus und da klappt es. Diese Daten müsste ich übergeben.
int packetsize = sizeof(struct ether_header) + sizeof(struct MEINPAKETINHALT) char packet[packetsize]; struct ether_header *ethhdr = (struct ether_header *) packet; struct MEINPAKETINHALT *mpi = (struct MEINPAKETINHALT *)(packet + sizeof(struct ether_header)); // Raw Socket oeffnen if( (sock = socket(AF_INET,SOCK_PACKET,htons(MEINETHERTYPE))) == -1) { perror("socket"); exit(1); } // Lese Pakete aus dem Raw Socket while(1) { i++; printf ("Empfangenes Paket Nr.: %d ; Packetsize: %d\n",i,packetsize); read(sock,packet,packetsize);//Original printf("Ziel:%s ", ether_ntoa (ethhdr->ether_dhost)); printf ("Quelle: %s - Ethertype: %X\n ",ether_ntoa (ethhdr->ether_shost), ethhdr->ether_type); ... }
Kann ich das empfangene paket als ein Block übergeben und im Prozess b auslesen?
Ich habe bisher nur Sachen gesehen, die Text oder Zahlen übergeben, aber keine Stuctures.
Vielen Dank für jede Hilfe
-
möglicherweise wäre es sinnvoller, ein unix datagram socket zu verwenden, da ein fifo ein stream ist und du eh schon pakete hast, die anscheinend auch noch eine fixe größe haben. verschicken kannst du über einen filedescriptor sowieso alles. die byteorder musst du bei lokalen sockets nicht beachten.
EDIT:
laut socket(2) is SOCK_PACKET veraltet. schau dir vielleicht packet(7) an.
-
Hm, wenn ich jetzt SOCK_DGRAM anstatt SOCK_PACKET benuzte bringt mir sendto eine Fehlermeldung. Leider weiß ich nicht, was damit gemeint ist. Folgendermaßen versende ich die Pakete (ZielAdresse ist eine Broadcast MAC Adresse):
// Includes #include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #include <net/ethernet.h> #include <unistd.h>//sleep() // Main part int main(void) { int sock; struct sockaddr addr; unsigned int packetsize = sizeof (struct Meintestpaket)+ sizeof(struct ether_header); unsigned char packet[packetsize]; struct ether_header *ethhdr = (struct ether_header *)packet; struct MEINPAKETINHALT *mpi = (struct MEINPAKETINHALT *)(packet + sizeof(struct ether_header)); char smac[18], dmac[18];//source MAC Adresse und ZielMACadresse char *quellmac; char dev1[6]; strncpy(dmac,"01:15:01:00:00:01",18);//ZielMAC strncpy(smac,"00:01:23:45:67:89",18);//QuellMAC strncpy(dev1,"eth0",6); // Packet Buffer initialisieren memset(packet,0,packetsize); // Erstelle einen Socket Deskriptor if( ( sock = socket(PF_PACKET,SOCK_DGRAM,htons(MEINETHERTYPE))) == -1 ) { perror("socketfehler"); exit(1); } // Ethernet Header Optionen memcpy(ethhdr->ether_dhost,(u_char *)ether_aton(dmac),ETHADDRLENGTH); // Destination MAC memcpy(ethhdr->ether_shost,(u_char *)ether_aton(smac),ETHADDRLENGTH); // Source MAC ethhdr->ether_type = htons(MEINETHERTYPE); // Schicke das Paket auf die Reise strncpy(addr.sa_data,dev1,sizeof(addr.sa_data)); int i=0; while(i<16){ printf ("Packetsize: %d\n",packetsize); printf("Sending Packet Nr.:%d\n",i); printf("Ziel:%s ", ether_ntoa (ethhdr->ether_dhost)); printf ("Quelle: %s Ethertype: %X\n",ether_ntoa (ethhdr->ether_shost), ethhdr->ether_type); //usleep (1000000); if( (sendto(sock,packet,packetsize,0,&addr,sizeof(struct sockaddr))) == -1 ) { perror("sendto"); // exit(1); } i++; printf("i ist gleich %d \n ",i); } //printf("Paketlänge:%d\n",packetsize); exit (0); }
So sah der Code für meinen Socketdescriptor vorher aus:
if( ( sock = socket(AF_INET,SOCK_PACKET,htons(MEINETHERTYPE))) == -1 ) { perror("socket"); exit(1); }
Beim Ausführen bekomme ich jetzt die Meldung
sendto: Invalid ArgumentKann mir jemand weiterhelfen und einen Tip geben, wo das Problem liegt? Beim Erstellen des Sockets meckert er nicht und bei sendto habe ich nichts geändert. Weiß jemand welches Argument gemeint ist?
Vielen Dank für jede Hilfe.
-
ein kleines beispielprogramm:
#include <sys/socket.h> #include <netpacket/packet.h> #include <net/ethernet.h> #include <netinet/ether.h> #include <sys/ioctl.h> #include <net/if.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #define PROTO 0x1234 #define PAYLOAD_LENGTH 1024 int main(void) { struct sockaddr_ll addr; struct ether_addr eaddr; int s; char payload[PAYLOAD_LENGTH]; struct ifreq ifreq; memset(payload, 'a', PAYLOAD_LENGTH); ether_aton_r("00:30:18:a4:e0:2e", &eaddr); strncpy(ifreq.ifr_name, "eth0", IFNAMSIZ); addr.sll_family = AF_PACKET; addr.sll_protocol = PROTO; addr.sll_hatype = ARPHRD_ETHER; addr.sll_pkttype = 0; addr.sll_halen = sizeof(struct ether_addr); memcpy(addr.sll_addr, &eaddr, sizeof(struct ether_addr)); if((s = socket(PF_PACKET, SOCK_DGRAM, PROTO)) == -1) { perror("socket"); exit(EXIT_FAILURE); } if(ioctl(s, SIOCGIFINDEX, &ifreq) == -1) { perror("socket"); exit(EXIT_FAILURE); } addr.sll_ifindex = ifreq.ifr_ifindex; if(sendto(s, payload, PAYLOAD_LENGTH, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr_ll)) == -1) { perror("sendto"); exit(EXIT_FAILURE); } close(s); return EXIT_SUCCESS; }
für ein SOCK_DGRAM musst du eine adresse vom typ sockaddr_ll an sendto übergeben. das ioctl wird dazu verwendet, zu einem device namen den interface index herauszufinden. du musst dann den ethernet header nicht als daten mitgeben, sondern nur die payload.
-
Danke für das Beispiel. Ich habe es jetzt hinbekommen. Ich hatte die Funktionsweise der structure sockaddr_ll nicht richtig verstanden und hätte vermutlich noch länger dran rumgedoktert, von dem ioctl ganz zu schweigen. Wieder was gelernt. Prima