Hello, I need help with my code. It's divided on two parts, first one is client that sends data to second part which is server. I have managed how to send IPv4 but i have problem with IPv6. Could you help me?
Part 1
Part 2
Part 1
Code:
#include "zadania_client.h"
//#if ZADANIE == 1
//UWAGA: program wymaga uprawnien administratora
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h> //socket(), sendto()
#include <arpa/inet.h> //IPPROTO_RAW
#include <unistd.h> //sleep
#include <netinet/ip.h> //nagl. ip
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <net/if.h>
#include <sys/ioctl.h> //ioctl
#include <ifaddrs.h> //getifaddrs()
#include <netdb.h>
#define MAX_ROZMIAR_DATAGRAMU 200
#define MAX_ROZMIAR_DANYCH 40 //Bajtow
int zadanie;
unsigned short csum();
enum TYPY_DANYCH {
TYP_DANYCH_1 = 1, TYP_DANYCH_2, TYP_DANYCH_3,
};
//Typ 1: Przenoszony jest tylko adres MAC
// Typ 2: Przenoszony jest tylko adres IP
//Typ 3: przenoszone są tylko liczby
enum KODY_OPERACJI {
KOD_OPERACJI_1 = 1,
KOD_OPERACJI_2,
KOD_OPERACJI_3,
KOD_OPERACJI_4,
KOD_OPERACJI_5,
KOD_OPERACJI_7 = 7
};
enum KOD_OPCJI {
KOD_OPCJI_ADDR_IPv4 = 1, KOD_OPCJI_ADDR_MAC, KOD_OPCJI_ADDR_LICZBY
};
//mac IP liczba
struct naglowek_PDU {
unsigned char wersja;
unsigned char kod_operacji;
unsigned char typ_danych;
unsigned char dlugosc_naglowka;
unsigned char rozmiar_pola_danych;
};
struct opcja {
unsigned char kod_opcji;
unsigned char dlugosc_opcji;
unsigned char dane_opcji[10];
};
unsigned char pmac[10];
unsigned char addrmac[6];
unsigned char addrip[4];
#define NAGL_OPCJA_MAC 1
#define NAGL_OPCJA_IP 2
#define NAGL_OPCJA_Liczby 3
#define NAGL_MAC 4
#define NAGL_IP 5
#define NAGL_Liczby 6
#define NAGL_OPCJA_IPv6 7
#define NAGL_OIPv6 8
int main(void) {
puts("Prosty nadajnik RAW");
int gniazdo_raw;
unsigned char datagram[MAX_ROZMIAR_DATAGRAMU];
struct sockaddr_in adres_gniazda_celu;
int rozmiar_danych;
int one = 1;
const int *val = &one;
unsigned char dane[MAX_ROZMIAR_DANYCH];
struct naglowek_PDU nagl_PDU;
struct opcja opcja_MAC;
struct opcja opcja_IP;
struct opcja opcja_liczby;
struct opcja opcja_IPv6;
addrmac[0] = 0x01;
addrmac[1] = 0x01;
addrmac[2] = 0x01;
addrmac[3] = 0x01;
addrmac[4] = 0x01;
addrmac[5] = 0x01;
addrip[0] = 0x01;
addrip[1] = 0x01;
addrip[2] = 0x01;
addrip[3] = 0x01;
pmac[0] = 2000;
pmac[1] = 10;
pmac[2] = 11;
pmac[3] = 12;
pmac[4] = 13;
pmac[5] = 14;
pmac[6] = 15;
pmac[7] = 1;
pmac[8] = 161;
pmac[9] = 162;
//zerowanie buforow
memset(datagram, 0, MAX_ROZMIAR_DATAGRAMU);
memset(dane, 0, MAX_ROZMIAR_DANYCH);
//deklaracja zmiennej wskaznikowej typu struct iphdr
//adres iphdr wskazuje na adres bufora datagram
//zapisywanie struktury iphdr powoduje, ze uzupelnia sie pierwsze 20B bufora,
//czyli w buforze datagram tworzy sie naglowek IPv4
struct iphdr *iph = (struct iphdr*) datagram;
struct iphdr *ip6h = (struct iphdr*) datagram;
// otwieramy gniazdo, IPPROTO_RAW oznacza, ze trzeba zbudowac naglowek IP samemu dla tego gniazda
gniazdo_raw = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (gniazdo_raw == -1) {
//nie moge utworzyc gniaza
perror("Blad:");
exit(1);
}
// ustawimy interfejs do wysylania
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr)); //wyzerujemy strukture
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo"); // wpiszemy nazwe interfejsu 'lo'- interfejs lokalny
setsockopt(gniazdo_raw, SOL_SOCKET, SO_BINDTODEVICE, (void*) &ifr,
sizeof(ifr)); // ustwimy odpowiednia opcje w gniezdzie
//pobranie adresu MAC interfejsu, z ktorego wysylamy ramki
ioctl(gniazdo_raw, SIOCGIFHWADDR, &ifr);
unsigned char *mac;
mac = (unsigned char*) ifr.ifr_hwaddr.sa_data;
printf("Adres MAC interfejsu %s: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
ifr.ifr_name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
//skompletujemy adres gniazda docelowego, jesli naglowek budowany adresu nie trzeba ustawiac
adres_gniazda_celu.sin_family = AF_INET;
adres_gniazda_celu.sin_addr.s_addr = inet_addr("127.0.0.2"); //adres docelowy
//opcja IP_HDRINCL wymusza potrzebe zbudowania naglowka IP w tym programie
if (setsockopt(gniazdo_raw, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {
perror("Blad ustawienia opcji IP_HDRINCL");
exit(0);
}
//adresy IP interfejsow
struct ifaddrs *myaddrs;
struct ifaddrs *ifa;
getifaddrs(&myaddrs); // uzupelnienie struktury myaddrs o info o wlasnych interfejsach
char host[256];
char port[256];
unsigned char adresIPv4interfejsu[4]; // tablica do adresow IPv4 interfejsow
unsigned int adresIPv4interfejsu_int; // zmienna do adresow IPv4 interfejsow
puts("Adresy IPv4 interfejsow:");
unsigned int domena = AF_INET;
for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) {
int family = ifa->ifa_addr->sa_family;
if (family == domena && ifa->ifa_addr) {
int ret = getnameinfo(ifa->ifa_addr,
(family == AF_INET) ?
sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6), host, sizeof(host),
port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
if (0 == ret) {
printf("Interfejs %s: ", ifa->ifa_name);
memcpy(adresIPv4interfejsu, &ifa->ifa_addr->sa_data[2], 4);
memcpy(&adresIPv4interfejsu_int, adresIPv4interfejsu, 4);
adresIPv4interfejsu_int = ntohl(adresIPv4interfejsu_int);
printf("(HEX: %.8x) ", adresIPv4interfejsu_int);
puts(host);
}
}
}
puts("Adresy interfejsów IPv6:");
unsigned int domena1 = AF_INET6;
for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) {
int family = ifa->ifa_addr->sa_family;
if (family == domena1 && ifa->ifa_addr) {
int ret = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),
host, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
if (ret == 0) {
printf("Interfejs %s: ", ifa->ifa_name);
char adresIPv6interfejsu[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr, adresIPv6interfejsu, INET6_ADDRSTRLEN);
printf("%s\n", adresIPv6interfejsu);
}
}
}
//uzupelnienie naglowka ipv4
iph->version = 4;
iph->ihl = 5;
iph->tos = 0xe0;
iph->tot_len = sizeof(struct iphdr) + sizeof(dane);
iph->id = htonl(54321); //jakis identyfikator
iph->frag_off = 0;
iph->ttl = 255;
//iph->protocol = IPPROTO_ICMP;
iph->protocol = 153; // UWAGA: wasny typ protokolu
iph->check = 0; //tymczasowo
iph->saddr = inet_addr("127.0.0.1");
iph->daddr = adres_gniazda_celu.sin_addr.s_addr;
/*
ip6h->version = 6;
ip6h->priority = 0;
ip6h->flow_lbl[0] = 0x12;
ip6h->flow_lbl[1] = 0x34;
ip6h->flow_lbl[2] = 0x56;
ip6h->payload_len = sizeof(dane);
ip6h->nexthdr = IPPROTO_TCP;
ip6h->hop_limit = 64;
inet_pton(AF_INET6, "2001:db8:85a3::8a2e:370:7334", &(ip6h->saddr));
inet_pton(AF_INET6, "2001:db8:85a3::8a2e:370:7335", &(ip6h->daddr));
*/
//suma kontrolna wlasna funkcja
iph->check = csum((unsigned short*) datagram, iph->tot_len); // powinien system tez obliczyc
//////////////////////////////////////
//tutaj jest miejsce na kod studenta (start)
nagl_PDU.wersja = 0x02;
nagl_PDU.kod_operacji = KOD_OPERACJI_1;
nagl_PDU.typ_danych = TYP_DANYCH_1;
nagl_PDU.dlugosc_naglowka = 13;
nagl_PDU.rozmiar_pola_danych = 0;
memset(dane, 1, MAX_ROZMIAR_DANYCH);
memcpy(dane, &nagl_PDU, sizeof(nagl_PDU));
opcja_MAC.kod_opcji = KOD_OPCJI_ADDR_IPv4;
opcja_MAC.dlugosc_opcji = 8;
memcpy(opcja_MAC.dane_opcji, pmac, 6);
memcpy(dane + 5, &opcja_MAC.dane_opcji, 8);
//ustawimy przykladowe dane
#if 0
memset(dane, 1, MAX_ROZMIAR_DANYCH);
memset(dane, 0xff, 2); // ustawimy 2 bajty
memset(dane + 2, 0xff, 2); // ustawimy kolejne
dane[4] = 0x0;
dane[5] = 0xa;
dane[6] = 0xb;
#endif
//tutaj jest miejsce na kod studenta (koniec)
//////////////////////////////////////
if (zadanie == NAGL_OPCJA_IP) {
nagl_PDU.wersja = 1;
nagl_PDU.kod_operacji = KOD_OPERACJI_1;
nagl_PDU.typ_danych = TYP_DANYCH_2;
nagl_PDU.dlugosc_naglowka = 11; //Bajtow
nagl_PDU.rozmiar_pola_danych = 0; //Bajtow
opcja_IP.kod_opcji = KOD_OPCJI_ADDR_IPv4;
opcja_IP.dlugosc_opcji = 6; //Bajtow
memset(opcja_IP.dane_opcji, 0, 10);
opcja_IP.dane_opcji[0] = addrip[0];
opcja_IP.dane_opcji[1] = addrip[1];
opcja_IP.dane_opcji[2] = addrip[2];
opcja_IP.dane_opcji[3] = addrip[3];
memcpy(dane, &nagl_PDU, sizeof(nagl_PDU));
memcpy(dane + sizeof(nagl_PDU), &opcja_IP, 6);
} else if (zadanie == NAGL_OPCJA_MAC) {
nagl_PDU.wersja = 1;
nagl_PDU.kod_operacji = KOD_OPERACJI_1;
nagl_PDU.typ_danych = TYP_DANYCH_1;
nagl_PDU.dlugosc_naglowka = 13; //Bajtow
nagl_PDU.rozmiar_pola_danych = 0; //Bajtow
opcja_MAC.kod_opcji = KOD_OPCJI_ADDR_MAC;
opcja_MAC.dlugosc_opcji = 8; //Bajtow
memset(opcja_MAC.dane_opcji, 0, 10);
opcja_MAC.dane_opcji[0] = addrmac[0];
opcja_MAC.dane_opcji[1] = addrmac[1];
opcja_MAC.dane_opcji[2] = addrmac[2];
opcja_MAC.dane_opcji[3] = addrmac[3];
opcja_MAC.dane_opcji[4] = addrmac[4];
opcja_MAC.dane_opcji[5] = addrmac[5];
memcpy(dane, &nagl_PDU, sizeof(nagl_PDU));
memcpy(dane + sizeof(nagl_PDU), &opcja_MAC, 8);
}
else if (zadanie == NAGL_OPCJA_Liczby) {
nagl_PDU.wersja = 1;
nagl_PDU.kod_operacji = KOD_OPERACJI_2;
nagl_PDU.typ_danych = TYP_DANYCH_3;
nagl_PDU.dlugosc_naglowka = 17; //Bajtow
nagl_PDU.rozmiar_pola_danych = 0; //Bajtow
opcja_liczby.kod_opcji = KOD_OPCJI_ADDR_LICZBY;
opcja_liczby.dlugosc_opcji = 12; //Bajtow
memset(opcja_MAC.dane_opcji, 0, 10);
opcja_liczby.dane_opcji[0] = pmac[0];
opcja_liczby.dane_opcji[1] = pmac[1];
opcja_liczby.dane_opcji[2] = pmac[2];
opcja_liczby.dane_opcji[3] = pmac[3];
opcja_liczby.dane_opcji[4] = pmac[4];
opcja_liczby.dane_opcji[5] = pmac[5];
opcja_liczby.dane_opcji[6] = pmac[6];
opcja_liczby.dane_opcji[7] = pmac[7];
opcja_liczby.dane_opcji[8] = pmac[8];
opcja_liczby.dane_opcji[9] = pmac[9];
memcpy(dane, &nagl_PDU, sizeof(nagl_PDU));
memcpy(dane + sizeof(nagl_PDU), &opcja_liczby, 12);
} else if (zadanie == NAGL_IP) {
nagl_PDU.wersja = 1;
nagl_PDU.kod_operacji = KOD_OPERACJI_1;
nagl_PDU.typ_danych = TYP_DANYCH_2;
nagl_PDU.dlugosc_naglowka = 5; //Bajtow
nagl_PDU.rozmiar_pola_danych = 4; //Bajtow
memcpy(dane, &nagl_PDU, sizeof(nagl_PDU));
memcpy(dane + 5, &addrip, 4);
} else if (zadanie == NAGL_MAC) {
nagl_PDU.wersja = 1;
nagl_PDU.kod_operacji = KOD_OPERACJI_1;
nagl_PDU.typ_danych = TYP_DANYCH_1;
nagl_PDU.dlugosc_naglowka = 5; //Bajtow
nagl_PDU.rozmiar_pola_danych = 6; //Bajtow
memcpy(dane, &nagl_PDU, sizeof(nagl_PDU));
memcpy(dane + 5, &addrmac, 6);
} else if (zadanie == NAGL_Liczby) {
nagl_PDU.wersja = 1;
nagl_PDU.kod_operacji = KOD_OPERACJI_2;
nagl_PDU.typ_danych = TYP_DANYCH_3;
nagl_PDU.dlugosc_naglowka = 5; //Bajtow
nagl_PDU.rozmiar_pola_danych = 10; //Bajtow
memcpy(dane, &nagl_PDU, sizeof(nagl_PDU));
memcpy(dane + 5, &pmac, 10);
} else {
printf("nie wiem co wykonac \n");
}
//kopiujemy dane do bufora za naglowkiem IP
memcpy(datagram + sizeof(struct iphdr), dane, sizeof(dane));
rozmiar_danych = sendto(gniazdo_raw, datagram,
sizeof(struct iphdr) + MAX_ROZMIAR_DANYCH, 0,
(struct sockaddr*) &adres_gniazda_celu, sizeof(adres_gniazda_celu));
if (rozmiar_danych < 0) {
perror("Blad transmisji");
} else {
printf("Wyslano : %d \n", rozmiar_danych);
}
//wylistowanie wyslanego datagramu
int i;
int j = 0;
for (i = 0; i < rozmiar_danych; i++) {
printf("%.2x ", datagram);
j++;
if (0 == j % 20) { // wypisywanie po 20 oktetow
printf("\n");
}
}
printf("\n");
return EXIT_SUCCESS;
}
unsigned short csum(unsigned short *ptr, int nbytes) {
register long sum;
unsigned short oddbyte;
register short answer;
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0;
*((u_char*) &oddbyte) = *(u_char*) ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum = sum + (sum >> 16);
answer = (short) ~sum;
return (answer);
}
Part 2
Code:
#include "zadania_serwer.h"
#if ZADANIE == 1
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/if_ether.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <unistd.h>
enum TYPY_DANYCH {
TYP_DANYCH_1 = 1,
TYP_DANYCH_2,
TYP_DANYCH_3,
};//Typ 1: Przenoszony jest tylko adres MAC
// Typ 2: Przenoszony jest tylko adres IP
//Typ 3: przenoszone są tylko liczby
enum KODY_OPERACJI {
KOD_OPERACJI_1 = 1,
KOD_OPERACJI_2,
KOD_OPERACJI_3,
KOD_OPERACJI_4,
KOD_OPERACJI_5,
KOD_OPERACJI_7=7
};
enum KOD_OPCJI {
KOD_OPCJI1 = 1, KOD_OPCJI2, KOD_OPCJI3};
//mac IP liczba
struct naglowek_PDU {
unsigned char wersja;
unsigned char kod_operacji;
unsigned char typ_danych;
unsigned char dlugosc_naglowka;
unsigned char rozmiar_pola_danych;
};
struct opcja {
unsigned char kod_opcji;
unsigned char dlugosc_opcji;
unsigned char dane_opcji[10];
};
unsigned char pmac[10];
int main(void) {
printf("Uruchamiam odbieranie ramek Ethernet.\n"); /* prints */
//Utworzenie bufora dla odbieranych ramek Ethernet
unsigned char *buffer = (void*) malloc(ETH_FRAME_LEN);
//Otwarcie gniazda pozwalajacego na odbior wszystkich ramek Ethernet
int iEthSockHandl = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
//Kontrola czy gniazdo zostalo otwarte poprawnie, w przypadku bledu wyswietlenie komunikatu.
if (iEthSockHandl < 0)
printf("Problem z otwarciem gniazda : %s!\n", strerror(errno));
// Wymuszenie uzycia wskazanego interfejsu
const char *nazwa_interfejsu;
nazwa_interfejsu = "lo";
//pozyskanie indeksu wskazanego interfejsu
struct ifreq iface;
memset(&iface, 0, sizeof(struct ifreq));
strncpy(iface.ifr_name, nazwa_interfejsu, strlen(nazwa_interfejsu) + 1);
if (ioctl(iEthSockHandl, SIOCGIFINDEX, &iface) < 0) {
perror("SIOCGIFINDEX");
close(iEthSockHandl);
return errno;
}
int index = iface.ifr_ifindex;
//ustawienie gniazda do odbioru na wskazanym interfejsie
struct sockaddr_ll adresGniazda;
memset(&adresGniazda, 0, sizeof(adresGniazda)); //wyzerowanie struktury gniazda
adresGniazda.sll_family = AF_PACKET;
adresGniazda.sll_protocol = htons(ETH_P_ALL);
adresGniazda.sll_ifindex = index; //ustwaienie indeksu interfejsu
//zbindowanie gniazda do interfejsu
if (bind(iEthSockHandl, (struct sockaddr*) &adresGniazda,
sizeof(adresGniazda)) < 0) {
perror("bind");
close(iEthSockHandl);
return errno;
}
//Zmienna do przechowywania rozmiaru odebranych danych
int iDataLen = 0;
int i;
unsigned short typ_ramki;
//Petla nieskonczona do odbierania ramek Ethernet
while (1) {
//Odebranie ramki z utworzonego wczesniej gniazda i zapisanie jej do bufora
iDataLen = recvfrom(iEthSockHandl, buffer, ETH_FRAME_LEN, 0, NULL,
NULL);
//Kontrola czy nie bylo bledu podczas odbierania ramki
if (iDataLen == -1)
printf("Nie moge odebrac ramki: %s! \n", strerror(errno));
else { //jesli ramka odebrana poprawnie wyswietlenie jej zawartosci
printf("\nOdebrano ramke Ethernet o rozmiarze: %d \n", iDataLen);
for (i = 0; i < iDataLen; i++) {
printf("%.2x, ", buffer);
}
printf("\n");
memcpy(&typ_ramki, buffer + 12, 2);
typ_ramki = ntohs(typ_ramki);
printf("Typ ramki: %.4x \n", typ_ramki);
//miejsce na kod studenta (start)
if (buffer[23]==153)
{
printf("=====\n");
printf("datagram\n");
printf("=====\n");
unsigned int obecna_komorka=34;
struct naglowek_PDU nagl_PDU;
memcpy (&nagl_PDU, &buffer[34],5);
printf("naglowek.wersja: 0x%.2x \n",nagl_PDU.wersja);
printf("naglowek.typ: 0x%.2x \n",nagl_PDU.typ_danych);
printf("naglowek.kod: 0x%.2x \n",nagl_PDU.kod_operacji);
printf("naglowek.rozm: 0x%.2x \n",nagl_PDU.rozmiar_pola_danych);
printf("naglowek.dl: 0x%.2x \n",nagl_PDU.dlugosc_naglowka);
unsigned int srcip;
memcpy(&srcip,&buffer[26],4);
printf("srcip %.8x \n", srcip);
unsigned int dip;
memcpy(&dip,&buffer[30],4);
printf("dstip %.8x \n", dip);
unsigned char pmac;
printf("adres ipv6");
memcpy(&pmac,&buffer[39],7);
printf("%d", buffer[39]);
for (i = 40; i < 46; i++) {
printf("%.2x, ", buffer);
}
}
//miejse na kod studenta (koniec)
}
}
return EXIT_SUCCESS;
}