sendto function setting “network is unreachable” e

2019-07-29 11:31发布

问题:

I'll apologise for any lack of clarity, and I'll do my best to update with any missed info, but I'm struggling to understand what I need to do to figure out why the network is unreachable.

I'm getting the output "sendto failed Network is unreachable" from the function

int send_dhcp_packet(void * buffer, int buffer_size, int sock, struct sockaddr_in* dest)
{
    int result;

    result = sendto(sock, (char*) buffer, buffer_size, 0, (struct sockaddr*)dest, sizeof(*dest));

    if(result < 0)
    {
        printf("sendto failed %s\n", strerror(errno));
        return -1;
    }

    return 0;
}

Where buffer is a struct of type dhcp_packet

typedef struct dhcp_packet_struct
{
    uint8_t op; //Packet type
    uint8_t htype; //Type of hardware address for this machine
    uint8_t hlen; //Length of hardware address for this machine
    uint8_t hops; //Number of hops to the gateway
    uint32_t xid; //Random transaction ID to match this boot request with responses
    uint16_t secs; //Seconds since booted
    uint16_t flags; //Flags for the packet 

    struct in_addr ciaddr; //IP of this machine if it has one
    struct in_addr yiaddr; //IP of this machine offered by the DHCP server
    struct in_addr siaddr; //IP of the DHCP server
    struct in_addr giaddr; //IP of the DHCP relay

    unsigned char chaddr[MAX_DHCP_CHADDR_LENGTH]; //Hardware address of this machine
    char sname[MAX_DHCP_SNAME_LENGTH]; //Name of DHCP server
    char file[MAX_DHCP_FILE_LENGTH]; //Boot file name (full path qualified, null terminated string. Used by later sessions)
    char options[MAX_DHCP_OPTIONS_LENGTH]; //DHCP options. Variable length octet strings
}dhcp_packet;

And I'm setting it up in the following function

int send_dhcp_discover(int sock)
{
    dhcp_packet discover_packet;
    struct sockaddr_in sockaddr_bcast;

    //We're setting up the discover packet
    bzero(&discover_packet, sizeof(discover_packet));

    discover_packet.op = BOOTREQUEST;

    discover_packet.htype = ETHERNET_HARDWARE_ADDRESS;

    discover_packet.hlen = ETHERNET_HARDWARE_ADDRESS_LENGTH;

    discover_packet.hops = 0;

    srand(time(NULL));
    packet_xid = random();
    discover_packet.xid = htonl(packet_xid);
    ntohl(packet_xid);

    discover_packet.secs = DHCP_PACKET_SECS;

    //Tell the server to broadcast it's response
    discover_packet.flags = htons(DHCP_BROADCAST_FLAG);

    memcpy(discover_packet.chaddr, client_hardware_address, ETHERNET_HARDWARE_ADDRESS_LENGTH); //Our hw address

    //First 4 bytes is a magic cookie
    discover_packet.options[0] = '\x63';
    discover_packet.options[1] = '\x82';
    discover_packet.options[2] = '\x53';
    discover_packet.options[3] = '\x63';

    discover_packet.options[4] = DHCP_OPTION_MESSAGE_TYPE;
    discover_packet.options[5] = '\x01'; //Message option length (bytes)
    discover_packet.options[6] = DHCPDISCOVER;

    if(request_specific_address)
    {
        discover_packet.options[7] = DHCP_OPTION_REQUESTED_ADDRESS;
        discover_packet.options[8] = '\x04'; //Length (bytes)
        memcpy(&discover_packet.options[9], &requested_address, sizeof(requested_address));
    }

    //Send the discover packet to the broadcast address
    //Set up the struct
    sockaddr_bcast.sin_family = AF_INET;
    sockaddr_bcast.sin_port = htons(DHCP_SERVER_PORT);
    sockaddr_bcast.sin_addr.s_addr = INADDR_BROADCAST;
    bzero(&sockaddr_bcast.sin_zero, sizeof(sockaddr_bcast.sin_zero));

    //Send the damn packet already
    send_dhcp_packet(&discover_packet, sizeof(discover_packet), sock, &sockaddr_bcast);

    return 0;
}

How the socket is set up

int create_dhcp_socket()
{
    struct sockaddr_in name;
    struct ifreq interface;
    int sock;
    int flag = 1;

    //Set up the address that we're going to use
    bzero(&name, sizeof(name));
    name.sin_family = AF_INET;
    name.sin_port = htons(DHCP_CLIENT_PORT); //Converts from host byte order to network byte order
    name.sin_addr.s_addr = INADDR_ANY; //Listen on any address

    //Create a socket
    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //Creates endpoint using ipv4, supporting datagrams over UDP
    if(sock < 0)
    {
        printf("Error: couldn't create socket\n");
        return -1;
    }

    flag = 1;

    //Set the reuse option so there aren't errors on restarting
    if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag)) < 0)
    {
        printf("Error: couldn't set reuse option on DHCP socket\n");
        return -1;
    }

    //Set the broadcast option
    if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&flag, sizeof(flag)) < 0)
    {
        printf("Error: couldn't set broadcast option on DHCP socket\n");
        return -1;
    }

    strncpy(interface.ifr_ifrn.ifrn_name, network_interface_name, IFNAMSIZ);

    if(bind(sock, (struct sockaddr*)&name, sizeof(name)) < 0)
    {
        printf("Error: couldn't bind DHCP socket (port %d). Check yo privilage\n", DHCP_CLIENT_PORT);
        return -1;
    }

    return sock;
}

I guess the question is; why is the network unreachable and how do I fix it so that it's reachable?

标签: c sockets dhcp