Использование собственного протокола с необработанными сокетами - PullRequest
0 голосов
/ 08 апреля 2019

Мой вопрос связан с использованием флага IP_HDRINCL в setsockopt. Я пытаюсь проверить использование пользовательского протокола с необработанными сокетами. Я не уверен, правильно ли то, что я делаю. Я просто пытаюсь передать строку в код сервера вместе с заголовком ip, прикрепленным клиентским кодом. Первый код, который я написал, был:

Server.c

#include "../cn.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>

int main(int argc, char const *argv[])
{
    int rsfd = socket(AF_INET,SOCK_RAW,253);
    if(rsfd<0)
    {
        perror("Could not create socket");exit(0);
    }
    int val = 1;
    setsockopt(rsfd,IPPROTO_IP,SO_BROADCAST|IP_HDRINCL,&val,sizeof(val));
    char buffer[100];
    struct iphdr *ip;
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("127.0.0.2");
    if(bind(rsfd,(struct sockaddr*)&addr,sizeof(addr))<0)
    {
        perror("Could not bind");exit(0);
    }
    else
        printf("Bound..\n");
    if(recvfrom(rsfd,buffer,100,0,NULL,NULL)<0)
    {
        perror("Could not receive");exit(0);
    }
    else
    {
        printf("Success..\n");
        ip = (struct iphdr*)(buffer);
        char ad[INET_ADDRSTRLEN];
        printf("Protocol No: %d\nTTL: %d\nVersion No: %d\nPacket ID: %d\nSource Address: %s\nChecksum: %d\nLength: %d\n",(int)ip->protocol,(int)ip->ttl,(int)ip->version,(int)ip->id,inet_ntop(AF_INET,&(ip->saddr),ad,INET_ADDRSTRLEN),(int)ip->check,(int)ip->ihl);

    }
    return 0;
}

Client.c

#include "../cn.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>

int main(int argc, char const *argv[])
{
    int rsfd = socket(AF_INET,SOCK_RAW,253);
    if(rsfd<0)
    {
        perror("Could not create socket");exit(0);
    }
    int val = 1;
    setsockopt(rsfd,IPPROTO_IP,SO_BROADCAST|IP_HDRINCL,&val,sizeof(val));
    char buffer[100];
    struct iphdr* ip;
    ip = (struct iphdr*)buffer;
    ip->protocol = 253;
    ip->version = 4;
    ip->id = 0;
    ip->saddr = 0;
    ip->daddr = inet_addr("127.0.0.2");
    printf("Enter a string..\n");
    scanf("%s",buffer+60); //trying to insert a string at buffer+60 position
    printf("Entered: %s\n",buffer+60);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("127.0.0.2");
    if(sendto(rsfd,buffer,100,0,(struct sockaddr*)&addr,sizeof(addr))<0)
        perror("Could not send");
    else
        printf("Sent successfully..\n");
    return 0;
}

Программа работает без ошибок, но когда я попытался напечатать сообщение со смещением 60, оно набрало какое-то мусорное значение. Затем я попытался напечатать все значения в этом символьном буфере, и, к моему изумлению, фактическое сообщение было со смещением 80, что означает ровно 20 байтов от места, где я его вставил. Проведя еще несколько экспериментов, я понял, что этот заголовок ip, полученный на стороне сервера, вообще не является определяемым пользователем заголовком. Это связано с самим сетевым уровнем! Но разве опция IP_HDRINCL не должна удерживать сетевой уровень от присоединения заголовка ip? Я говорю это на основании того, что я истолковал из этого . Где я делаю ошибку? Кроме того, кто-нибудь может предоставить несколько хороших руководств по необработанным сокетам (особенно по реализации пользовательских протоколов)?

...