C编程 - > wpa_supplicant connected - > udp broadcast sendto“Network Unreachable”

时间:2013-12-02 09:17:30

标签: c sockets networking

我发送广播包以检测dhcp服务器(255.255.255.255到端口67)已经卡住了几个星期。

如果有人可以花点时间在思考过程中发现我的缺陷,我会很感激。

步骤1:准备我的系统自己构建dhcp客户端

我制作了一个shellcript来杀死dhcpd并断开我的Wifi并再次使用wpa_supplicant连接

echo "Killing DHCP daemon to open up port 68"
sudo killall -TERM dhcpcd dhclient

echo "Stopping Network Service"
sudo /etc/init.d/network stop

echo "Ifdown on network interfaces"
sudo /sbin/ifconfig eth0 down
sudo /sbin/ifconfig wlan0 down

echo "Connecting to Wifi using WPA_Supplicant"
sudo /usr/sbin/wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf &

步骤2:检查无线连接是否正常

user@suse:sudo /usr/sbin/wpa_cli status
root's password:
Selected interface 'wlan0'
bssid=5c:35:3b:64:79:59
ssid=Joehoe
id=0
mode=station
pairwise_cipher=TKIP
group_cipher=TKIP
key_mgmt=WPA2-PSK
wpa_state=COMPLETED
address=00:26:c7:1e:a2:42

第3步:碰到我的问题

旁注:如果此时运行/ usr / sbin / dhclient工作正常,那么我得出的结论是无线真的很好

我运行以下代码:

/** Compile : gcc -m32 dhcpclient.c -o dhcpclient */
#define DHCPSERVERPORT 67
#define DHCPCLIENTPORT 68

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/******************************************************************/
/************ DHCP Message Structure  ********************/

typedef struct {
   unsigned char op;                       // Message opcode/type   // unsigned char can be replaced by uint8_t, see C manual for info
  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[16];               // Client hardware address
  char sname[64];                         // Server name
  char file[128];                         // Boot filename
  char magiccookie[4];                    // DHCP option cookie
  char options[59];                       // Optional parameters (actual length dependent on MTU).
} dhcp_msg;


/************ DHCP DISCOVER  ********************/
dhcp_msg dhcpdiscover(){ 

    //struct dhcp_msg dhcpdiscover;
    dhcp_msg dhcpdiscover;
    dhcpdiscover.op = 1;
    dhcpdiscover.htype = 1;
    dhcpdiscover.hlen = 6;
    dhcpdiscover.hops = 0;
    dhcpdiscover.xid = 0;
    dhcpdiscover.secs = 0;
    dhcpdiscover.flags = 0;
    dhcpdiscover.ciaddr.s_addr = htonl(INADDR_ANY);
    dhcpdiscover.yiaddr.s_addr = htonl(INADDR_ANY);
    dhcpdiscover.siaddr.s_addr = htonl(INADDR_ANY);
    dhcpdiscover.giaddr.s_addr = htonl(INADDR_ANY);
        dhcpdiscover.chaddr[0] = 0x00;
        dhcpdiscover.chaddr[1] = 0x26;
        dhcpdiscover.chaddr[2] = 0xC7;
        dhcpdiscover.chaddr[3] = 0x1E;
        dhcpdiscover.chaddr[4] = 0xA2;
        dhcpdiscover.chaddr[5] = 0x42;
    dhcpdiscover.chaddr[6] = 0x00;
    dhcpdiscover.chaddr[7] = 0x00;
    dhcpdiscover.chaddr[8] = 0x00;
    dhcpdiscover.chaddr[9] = 0x00;
    dhcpdiscover.chaddr[10] = 0x00;
    dhcpdiscover.chaddr[11] = 0x00;
    dhcpdiscover.chaddr[12] = 0x00;
    dhcpdiscover.chaddr[13] = 0x00;
    dhcpdiscover.chaddr[14] = 0x00;
    dhcpdiscover.chaddr[15] = 0x00;
    memset(dhcpdiscover.sname,0,sizeof(dhcpdiscover.sname));
    memset(dhcpdiscover.file,0,sizeof(dhcpdiscover.file));
/************   setting magiccookie and options to 0 -> recognized as BootP protocol ***/
    dhcpdiscover.magiccookie[0] = 99;
    dhcpdiscover.magiccookie[1] = 130;
    dhcpdiscover.magiccookie[2] = 83;
    dhcpdiscover.magiccookie[3] = 99;
    dhcpdiscover.options[0] = 53;
    dhcpdiscover.options[1] = 1;
    dhcpdiscover.options[2] = 1;
    dhcpdiscover.options[3] = 255;
/** always set 0xff as DHCP End option to close option listing, rest is padding **/


    return dhcpdiscover;
}

void printDHCPStructure(dhcp_msg dhcpstructure){
   dhcp_msg dhcpstruct = dhcpstructure;
   printf("\n\tDHCP Field\tBytes\tValue\n");
   printf("\t----------------------------------\n");
printf("\top : \t\t1\t%x\n", dhcpstruct.op);
printf("\thtype : \t1\t%x\n", dhcpstruct.htype);
  printf("\thlen : \t\t1\t%x\n", dhcpstruct.hlen);
printf("\thops : \t\t1\t%x\n", dhcpstruct.hops);
 printf("\txid : \t\t1\t%x\n", dhcpstruct.xid);
printf("\tsecs : \t\t1\t%x\n", dhcpstruct.secs);
printf("\tflags : \t1\t%x\n", dhcpstruct.flags);
printf("\tciaddr : \t1\t%s\n", dhcpstruct.ciaddr);




printf("\tyiaddr : \t1\t%s\n", dhcpstruct.yiaddr);
printf("\tsiaddr : \t1\t%s\n", dhcpstruct.siaddr);
printf("\tgiaddr : \t1\t%s\n", dhcpstruct.giaddr);
printf("\tchadddr[MAC] : \t16\t%x:%x:%x:%x:%x:%x\n", dhcpstruct.chaddr[0],dhcpstruct.chaddr[1],dhcpstruct.chaddr[2],dhcpstruct.chaddr[3],dhcpstruct.chaddr[4],dhcpstruct.chaddr[5]);
printf("\tsname : \t64\t%s\n", dhcpstruct.sname);
printf("\tfile : \t\t128\t%s\n", dhcpstruct.file);
printf("\tmgckie_0 : \t1\t%d\n", (unsigned char)dhcpstruct.magiccookie[0]);
printf("\tmgckie_1 : \t1\t%d\n", (unsigned char)dhcpstruct.magiccookie[1]);
printf("\tmgckie_2 : \t1\t%d\n", (unsigned char)dhcpstruct.magiccookie[2]);
printf("\tmgckie_3 : \t1\t%d\n", (unsigned char)dhcpstruct.magiccookie[3]);
printf("\toptions : \t59\t\n");
printf("\n");
}


int bindBroadcastUdpv4(int socket,short int socketport)
 {
int clientsock = socket;
struct sockaddr_in udpaddr;
memset((char *)&udpaddr, 0, sizeof(udpaddr));
udpaddr.sin_family = AF_INET;
udpaddr.sin_addr.s_addr = htonl(INADDR_ANY);
udpaddr.sin_port = htons(socketport);

if (bind(clientsock, (struct sockaddr *)&udpaddr, sizeof(udpaddr)) < 0)
{
    printf("Binding the UDP Socket failed\n");
    printf("Tip 1 : Run 'sudo netstat -l -u -n -p | grep %d'\n", socketport);
    printf("Tip 2 : Run program with root privileges\n");
    perror("Error");
    exit(1);
}
else
{
    return 1;
}
}

/******************************************************************/
/******************************************************************/

int main(int argc, char *argv[])
{

/** Creating UDP client socket **/
int clientsock = socket(AF_INET, SOCK_DGRAM, 0);
int broadcastpermissions = 1;
short int clientport = DHCPCLIENTPORT;
short int destinationport = DHCPSERVERPORT;

if (clientsock < 0)
{
    perror("Error @ Step 1 : Cannot create client socket");
}
else
{
    printf("Step 1 : Client socket created succesfully\n");
}


/** Give client socket broadcast permissions **/
if (broadcastpermissions)
{
    int ret = setsockopt(clientsock,SOL_SOCKET,SO_REUSEADDR,&broadcastpermissions,sizeof(broadcastpermissions));
    if (ret != 0)
    {
        printf("Error @ step 1BisA : Giving Client Socket reuse options FAILED: %d\n", ret);
        exit(0);
    }

    ret = setsockopt(clientsock,SOL_SOCKET,SO_BROADCAST,&broadcastpermissions,sizeof(broadcastpermissions));
    if (ret != 0)
    {
        printf("Error @ step 1BisB : Giving Client Socket broadcast permissions FAILED: %d\n", ret);
        exit(0);
    }
    else
    {
        printf("\tSetting broadcast permissions on client socket succeeded\n");
    }
}

/** Binding the client socket **/
if (bindBroadcastUdpv4(clientsock, clientport))
{
    printf("Step 2 : Socket is binded succesfully\n");
}

/** Create DHCP Discovery data structure **/
dhcp_msg dhcpdiscovery = dhcpdiscover();
printf("Step 3 : DHCP Discovery Data Structure created\n");
printDHCPStructure(dhcpdiscovery);

/** Trying to broadcast to 255.255.255.255 on port 67 to detect DHCP Servers */
struct sockaddr_in destinationaddr;
memset((char *)&destinationaddr, 0, sizeof(destinationaddr));
destinationaddr.sin_family = AF_INET;
//destinationaddr.sin_addr.s_addr = INADDR_BROADCAST;
destinationaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
destinationaddr.sin_port = htons(destinationport);
//destinationaddr.sin_port = destinationport;


/** translate Hexadecimal notation of IP Address to decimal **/
int IP1 = (ntohl(destinationaddr.sin_addr.s_addr) >> 24) & 0xFF;
int IP2 = (ntohl(destinationaddr.sin_addr.s_addr) >> 16) & 0xFF;
int IP3 = (ntohl(destinationaddr.sin_addr.s_addr) >> 8) & 0xFF;
int IP4 = (ntohl(destinationaddr.sin_addr.s_addr)) & 0xFF;

//while(1){};

printf("DEBUG : Clientsock = %d\n", clientsock);
printf("DEBUG : .sin_addr = %p\n", destinationaddr.sin_addr.s_addr);
printf("DEBUG : .sin_port = %d\n", destinationaddr.sin_port);
printf("DEBUG : .sin_port = %d\n", destinationport);



/******************************************************************************************************************************************************************/


int a = sendto(clientsock,&dhcpdiscovery,sizeof(dhcpdiscovery),0,(struct sockaddr *)&destinationaddr, sizeof(destinationaddr));

if (a < 0)
{
    printf("A is :\%d\n", a);
    printf("UDP Message to %d.%d.%d.%d on port %d failed\n",IP1,IP2,IP3,IP4,destinationport);
    perror("Sending failed : ");
    return 667;
}
else
{
        printf("UDP Messsage to %d.%d.%d.%d on port %d SUCCESS !\n",IP1,IP2,IP3,IP4,destinationport);
}

close(clientsock);

}

/******************************************************************/
/******************************************************************/

额外信息: A)如前所述,当运行dhclient时,我得到ip地址分配,wiresharks显示我dhcp对话

B)当已经分配了ipaddress时运行我自己的代码时,发送成功

C)sendTo返回的错误是“网络无法访问”

所以我的问题是:我连接到我的无线AP,我需要执行额外的步骤,以便我可以让我的套接字发送广播数据包? 这样做的原因是要了解网络并学习编程,所以我的编程技巧并不令人敬畏,这就是为什么你可能会看到荒谬的代码。我很感激任何评论,但更愿意坚持我的主要问题。

最诚挚的问候地球人!

1 个答案:

答案 0 :(得分:0)

我认为你想在这里使用原始套接字。虽然它是真的(根据@cklin)这意味着你必须稍微重新发明轮子,dhcp是不寻常的,因为你在正确配置接口之前发送数据包。作为一个简单的指南,我建议你看看busybox以及它的dhclient脚本是如何工作的。另一种选择是libpcap。这可以捕获回复(甚至不是直接发给你的回复),并且具有一些鲜为人知的能够发送原始数据包的功能。我已成功使用它来编写dhcp服务器。