Need help dhcpdiscovery message...using raw sockets..dont want dhcp headers or libraries..do it myself
anyway im getting error on sending my packet..any USEFUL help?
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <string.h>
#define DHCP_UDP_OVERHEAD (14 + /* Ethernet header */ \
20 + /* IP header */ \
8) /* UDP header */
#define DHCP_SNAME_LEN 64
#define DHCP_FILE_LEN 128
#define DHCP_FIXED_NON_UDP 236
#define DHCP_FIXED_LEN (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD)
/* Everything but options. */
#define DHCP_MTU_MAX 1500
#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN)
#define BOOTP_MIN_LEN 300
#define DHCP_MIN_LEN 548
#define DHCP_CLIENT_PORT 68
#define DHCP_SERVER_PORT 67
#define DHCP_CHADDR_LEN 16
#define DHCP_SNAME_LEN 64
#define DHCP_FILE_LEN 128
#define DHCP_OPTIONS_LEN 512
#define DHCP_MIN_OPTIONS_LEN 68
struct dhcp {
unsigned char op; // Message opcode/type
unsigned char htype; // Hardware addr type
unsigned char hlen; // Hardware addr length
unsigned char hops; // Number of relay agent hops from client
unsigned long xid; // Transaction ID
unsigned short secs; // Seconds since client started looking
unsigned short flags; // Flag bits
struct in_addr ciaddr; // Client IP address (if already in use)
struct in_addr yiaddr; // Client IP address
struct in_addr siaddr; // IP address of next server to talk to
struct in_addr giaddr; // DHCP relay agent IP address
unsigned char chaddr[DHCP_CHADDR_LEN]; // Client hardware address
char sname[DHCP_SNAME_LEN]; // Server name
char file[DHCP_FILE_LEN]; // Boot filename
unsigned long cookie; // DHCP option cookie
unsigned char options[0]; // Optional parameters (actual length dependent on MTU).
};
unsigned short in_cksum(unsigned short *addr, int len);
int main(void){
int sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_UDP);
if(sockfd < 0){ printf("socket error\n"); return 1; }
int on = 1;
int ret = setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(int));
if(ret < 0) { printf("socket eror\n"); return 1; }
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr("255.255.255.255");
server.sin_port = htons(67);
server.sin_family = AF_INET;
unsigned int packetsize = sizeof(struct iphdr) + sizeof(struct dhcp);
unsigned char packet[packetsize];
struct iphdr *ip = malloc(sizeof(struct ipdhr *));
if(ip == NULL) return 1;
ip->ihl = 5;
ip->version = 4;
ip->tot_len = sizeof(struct iphdr) + sizeof(struct dhcp);
ip->protocol = IPPROTO_UDP;
ip->saddr = inet_addr("0.0.0.0");
ip->daddr = inet_addr("255.255.255.255");
ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr));
struct dhcp *p = malloc(sizeof(struct dhcp *));
if(p == NULL) return 1;
struct in_addr remote, client;
remote.s_addr = inet_addr("255.255.255.255");
client.s_addr = inet_addr("0.0.0.0");
p->op = 1;
p->htype = 1;
p->hlen = 6;
p->hops = 0;
p->xid = htonl(1000);
p->secs = htons(0);
p->flags = htons(0x8000);
p->ciaddr = client;
p->yiaddr = client;
p->siaddr = server.sin_addr;
p->giaddr = server.sin_addr;
p->chaddr[0] = 'c';
p->chaddr[1] = '7';
p->chaddr[2] = '3';
p->chaddr[3] = '0';
p->chaddr[4] = '0';
p->chaddr[5] = '0';
p->chaddr[6] = 'b';
p->chaddr[7] = 'd';
p->chaddr[8] = '4';
p->chaddr[9] = 'a';
p->chaddr[10] = '4';
p->chaddr[11] = 'g';
memcpy(packet,ip,sizeof(ip));
memcpy(packet + sizeof(ip),p,sizeof(p));
ret = sendto(sockfd,packet,packetsize,0,(struct sockaddr *)&server,sizeof(server));
if(ret < 0){ printf("Error\n") ; return 1; }
//if(ip != NULL){ free(ip); }
//if(p != NULL){ free(p); }
return 0;
}//mai
unsigned short in_cksum(unsigned short *addr, int len){
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1)
{
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return answer;
}