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?
dest
. Are you sending it to the broadcast address? What is the content of your routing tables? – Fokkerdest
is a pointer tosockaddr_bcast
which is filled out toward the end ofsend_dhcp_discover
. And as far as routing tables, not a clue, I'll look them up. – Misstrace
and check return code from every system call you use for sending your packet – Fokkerstrace
, irritatingly enough. Any alternatives that you know of, or justprintf
? – Mishtonl
forINADDR_BROADCAST
andINADDR_ANY
: #6082392 – Savilstrace
doesn't seem to need special priviledges (it hasn't its S-UID set). Maybe you can compile it from sources – Fokkerhtonl()
withINADDR_BROADCAST
andINADDR_ANY
, and they demonstrate that opinions are divided over whether you should. – TuppenceSO_DONTROUTE
. – Tuppence