使用SOCK_RAW构建全网广播包

来源:互联网 发布:暴雪降至 知乎 编辑:程序博客网 时间:2024/05/14 07:30

使用SOCK_DGRAM在Linux上发送全网广播包:

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netdb.h>


#define PORT 7773
#define MAXDATASIZE 256


int main(int argc,char *argv[])
{
    int ret,socket_fd;
    struct sockaddr_in my_addr;
    char buf[MAXDATASIZE];
    int so_broadcast=1;
    socklen_t size;
    char my_ip[12];


    my_addr.sin_family=AF_INET;
    my_addr.sin_port=htons(PORT);
    my_addr.sin_addr.s_addr=inet_addr("255.255.255.255");
    bzero(&(my_addr.sin_zero),8);
    
    if((socket_fd=(socket(AF_INET,SOCK_DGRAM,0)))==-1) {
        perror("socket");
        exit(1);
    }
    setsockopt(socket_fd,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast));


    strcpy(buf,"Hello,I'm on line!");


    while(1) {
ret=sendto(socket_fd,buf,strlen(buf),0,(struct sockaddr *)&my_addr,sizeof(my_addr));
sleep(1);
printf("next:%d\n",ret);
    }
    return 0;
}

还必须运行此命令,不然即使sendto不报错,实质上也发不出去,对方抓包都抓不到。有些系统会提示:No Route to host.

route add -host 255.255.255.255 dev eth0


由于系统差异,有些系统的UDP协议不支持发送全网广播包,只能发送子网广播包,因此只能使用SOCK_RAW构建UDP包,这样就能实现全网广播包:

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netdb.h>


#define UDP_HEADER_SIZE        8
#define IP_HEADER_SIZE         20
typedef struct udp_hdr{
    unsigned short s_port;
    unsigned short d_port;
    unsigned short length;
    unsigned short cksum;
    char data[0];
}udp_hdr;


int
send_bcast(char *send_data,char *src_ip, uint16_t src_port, uint16_t dest_port)
{
   int                sd;
   udp_hdr  *udp;
   int                count = -1; /* # of expected bcasts,
                                         * default infinite */
   int                send_cnt = 0; /* # of bcasts sent */
   int                recv_cnt = 0; /* # of bcasts received on
                                         * current send */


   int             udplen; /* Total length of packets sent */
   struct sockaddr_in laddr; /* Local address */
   socklen_t          laddr_len; /* Local address */
   struct sockaddr_in faddr; /* Foreign address */
   int                datalen = strlen(send_data); /* data length. */
   /* Parameters (command line options) */
   char              *host;
   unsigned int                ipaddr;
   char *data;
   unsigned char ttl = 64; /* IP_MULTICAST_TTL default 1, must change to 64 */
   
   /* Set 'ipaddr' from first non-option argument. */
   host = "255.255.255.255";
   ipaddr = inet_addr("255.255.255.255");


   if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
   {
      perror("socket");
      goto fail;
   }


    if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL,(char *)&ttl, sizeof(unsigned char)) == -1)
   {
      perror("setsockopt(IP_MULTICAST_TTL)");
   }
    int on=1;
  setsockopt(sd,SOL_SOCKET,SO_REUSEADDR | SO_BROADCAST,&on,sizeof(on));
   
   /* Our local address */
   memset(&laddr, 0, sizeof(laddr));
   laddr.sin_family = AF_INET;
   laddr.sin_addr.s_addr = inet_addr(src_ip);




   /* Foreign adddress (for connect/sendto) */
   memset(&faddr, 0, sizeof(faddr));
   faddr.sin_family      = AF_INET;
   faddr.sin_addr.s_addr = ipaddr;


      /*
       * Initialize the send buffer with an request.
       */


      udplen = datalen + UDP_HEADER_SIZE;
      
      udp = malloc(udplen);
      
      data = udp->data;
      memcpy(data,send_data,datalen);
      
    udp->s_port = htons(src_port);
    udp->d_port = htons(dest_port);
    udp->length = udplen;
    udp->cksum = 0;
    //udp->cksum = chksum((U16 *)udp, udplen);


      laddr_len = sizeof(laddr);
      getsockname(sd, (struct sockaddr *)&laddr, &laddr_len);


      printf("bcast %s (%s) ", host, inet_ntoa(*((struct in_addr *)&ipaddr)));
      if (laddr.sin_addr.s_addr != 0)
      {
printf("from %s: ", inet_ntoa(laddr.sin_addr));
      }
      printf("%d(%d) bytes of data.\n", datalen, udplen+IP_HEADER_SIZE);




     /*
      * Send one echo request
      */
     int retval = sendto(sd, udp, udplen, 0,
    (struct sockaddr *)&faddr, sizeof(faddr));


     if (retval == -1)
     {
    perror("sendto");
     }




fail:
   /* Cleanup and exit. */
   if (udp) free(udp);
   if (sd != -1) close(sd);


  usage:


   return 0;
}


int main(int argc, char *argv[])
{
    int c;
    int enable_double=0;
    int cycles=0;
    char *data;
      
    while ((c = getopt(argc, argv, "r:d:")) != -1)
    {
         switch (c)
         {
            case 'r':
                    cycles = (uint32_t)strtol(optarg,NULL,10);
                    break;
           case 'd':
                    data = optarg;
                    break;
         }
     }
     if(cycles)
     {
        if(data==NULL)
        {
            data="hello";
        }
        while(cycles--)
        {
            send_bcast(data,"10.69.2.214",13334,8080);
        }
     }


     return 0;
}


0 0