예제 #1
0
libnet_ptag_t
libnet_build_bootpv4(u_char opcode, u_char htype, u_char hlen, u_char hopcount,
            u_long xid, u_short secs, u_short flags, u_long cip, u_long yip,
            u_long sip, u_long gip, u_char *chaddr, u_char *sname, u_char *file,
            u_char *payload, u_long payload_s, libnet_t *l, libnet_ptag_t ptag)
{
    return (libnet_build_dhcpv4(opcode, htype, hlen, hopcount, xid, secs,
        flags, cip, yip, sip, gip, chaddr, sname, file, payload, payload_s, 
        l, ptag));
}
예제 #2
0
libnet_ptag_t
libnet_build_bootpv4(uint8_t opcode, uint8_t htype, uint8_t hlen,
uint8_t hopcount, uint32_t xid, uint16_t secs, uint16_t flags,
uint32_t cip, uint32_t yip, uint32_t sip, uint32_t gip, const uint8_t *chaddr,
const char *sname, const char *file, const uint8_t *payload, uint32_t payload_s,
libnet_t *l, libnet_ptag_t ptag)
{
    return (libnet_build_dhcpv4(opcode, htype, hlen, hopcount, xid, secs,
        flags, cip, yip, sip, gip, chaddr, sname, file, payload, payload_s, 
        l, ptag));
}
예제 #3
0
int main(int argc, char **argv) {
  int ch, dhcp_payload_len;
  unsigned char *dhcp_payload;
  libnet_ptag_t ptag_dhcpv4, ptag_udp, ptag_ipv4, ptag_ethernet;

  char *arg_secs, *arg_cip, *arg_chaddr, *arg_sip, *arg_ifname;
  char *arg_operation, *arg_timeout, *arg_xid, *arg_flags, *arg_yip;
  char *arg_gip, *arg_sname, *arg_fname, *arg_ether_dst, *stmp;
  char *arg_ipv4_src, *arg_ipv4_dst, *arg_ipv4_tos, *arg_ipv4_ttl;
  char *arg_reply_count;

  if (argc < 2) usage("too few arguments");

  srandom(time(NULL));

  arg_secs = arg_cip = arg_chaddr = arg_sip = arg_ifname = NULL;
  arg_operation = arg_timeout = arg_xid = arg_flags = arg_yip = NULL;
  arg_gip = arg_sname = arg_fname = arg_ether_dst = arg_reply_count = NULL;
  arg_ipv4_src = arg_ipv4_dst = arg_ipv4_tos = arg_ipv4_ttl = NULL;
  verbosity = 1;

  while ((ch = getopt(argc, argv, "s:c:h:i:o:t:x:f:y:g:S:A:B:O:X:v:F:T:L:Q:E:w:n:m")) != -1) {
    switch (ch) {
      case 's': arg_secs = optarg; break;
      case 'c': arg_cip = optarg; break;
      case 'h': arg_chaddr = optarg; break;
      case 'S': arg_sip = optarg; break;
      case 'i': arg_ifname = optarg; break;
      case 'o': arg_operation = optarg; break;
      case 't': arg_timeout = optarg; break;
      case 'x': arg_xid = optarg; break;
      case 'f': arg_flags = optarg; break;
      case 'y': arg_yip = optarg; break;
      case 'B': arg_fname = optarg; break;
      case 'A': arg_sname = optarg; break;
      case 'g': arg_gip = optarg; break;
      case 'F': arg_ipv4_src = optarg; break;
      case 'T': arg_ipv4_dst = optarg; break;
      case 'L': arg_ipv4_ttl = optarg; break;
      case 'Q': arg_ipv4_tos = optarg; break;
      case 'n': arg_reply_count = optarg; break;
      case 'E': arg_ether_dst = optarg; break;
      case 'v': verbosity = atoi(optarg); break;
      case 'm': no_double_options = 0; break;
      case 'O': add_option(optarg); break;
      case 'X': add_hexoption(optarg); break;
      case 'w': option_lookup(optarg); break;
      case '?':
      default:
        usage("unknown argument");
    }
  }
  argc -= optind;
  argv += optind;

  /* Set some basic defaults */
  set_defaults();

  /* Make sure network interface was specified with -i option */
  if (arg_ifname == NULL) {
    usage("Error: network interface (-i option) not specified.");
  }
  strncpy(ifname, arg_ifname, 99);

  /* Try to have pcap and libnet use the interface */
  pcp = pcap_open_live(ifname, SNAPLEN, 1, 1, pcap_errbuf);
  if (pcp == NULL) {
    printf("pcap_open_live(%s) failed! Did you give the right interface name " 
           "and are you root?\n", ifname);
    printf("pcap said: %s\n", pcap_errbuf);
    exit(1);
  }
  lnp = libnet_init(LIBNET_LINK, ifname, libnet_errbuf);
  if (lnp == NULL) {
    printf("libnet_init(%s) failed!\n", ifname);
    printf("libnet said: %s\n", libnet_errbuf);
    exit(1);
  }

  /* Set chaddr MAC address */
  if (arg_chaddr != NULL) {
    int len = ETHER_ADDR_LEN;
    /*chaddr = libnet_hex_aton((int8_t *)arg_chaddr, &len);*/
    chaddr = libnet_hex_aton(arg_chaddr, &len);
    if (chaddr == NULL) {
      if (verbosity > 0)
        printf("Invalid chaddr MAC address specified (%s)\n", arg_chaddr);
      exit(1);
    }
  }
  else {
    /* Try to retrieve MAC address using libnet */
    chaddr = (u_int8_t *)libnet_get_hwaddr(lnp);
    if (chaddr == NULL) {
      if (verbosity > 1) {
        printf("Failed to retrieve MAC address for interface %s, using 0:0:0:0:0:0\n"
          "Libnet said: %s\n", ifname, libnet_errbuf);
      }
      memset(chaddr, 0, ETHER_ADDR_LEN);
    }
  }

  /* Set cip address */  
  if (arg_cip != NULL) {
    cip = inet_addr(arg_cip);
    if (cip == INADDR_NONE) {
      if (verbosity > 0) 
        printf("Invalid cip address specified (%s)\n", arg_cip);
      exit(1);
    }
    cip = ntohl(cip);
  }
  else {
    /* Try to retrieve IP address using libnet */
    cip = libnet_get_ipaddr4(lnp);
    if ((int)cip == -1) {
      if (verbosity > 1) {
        printf("Failed to retrieve IPv4 address for interface %s, using cip 0.0.0.0\n"
          "Libnet said: %s\n", ifname, libnet_errbuf);
      }
      cip = inet_addr("0.0.0.0");
    }
    else
      cip = htonl(cip);
  }


  /**************************/
  /* Set various parameters */
  /**************************/

  if (arg_operation != NULL) {
    if (option_added(LIBNET_DHCP_MESSAGETYPE) && no_double_options) {
      if (verbosity > 0) {
        printf("Error: DHCP messagetype specified twice (don't use -o option if\n"
               "       you also intend to use -O to set option 53 (messagetype))\n");
      }
      exit(1);
    }
    if (strcasecmp(arg_operation, "discover") == 0) {
      operation = LIBNET_DHCP_MSGDISCOVER;
      if (arg_timeout == NULL)
        timeout = 5;
    }
    else if (strcasecmp(arg_operation, "request") == 0) {
      operation = LIBNET_DHCP_MSGREQUEST;
      if (arg_timeout == NULL)
        timeout = 5;
    }
    else if (strcasecmp(arg_operation, "inform") == 0) {
      operation = LIBNET_DHCP_MSGINFORM;
      if (timeout == 0)
        timeout = 5;
    }
    else if (strcasecmp(arg_operation, "release") == 0)
      operation = LIBNET_DHCP_MSGRELEASE;
    else if (strcasecmp(arg_operation, "decline") == 0)
      operation = LIBNET_DHCP_MSGDECLINE;
    else {
      if (verbosity > 0)
        usage("Invalid DHCP operation type");
      else
        exit(1);
    }
    /* Add MESSAGETYPE DHCP option */
    num_options++;
    options = (struct dhcp_option *)
      realloc(options, num_options * sizeof(struct dhcp_option));
    options[num_options-1].opnum = LIBNET_DHCP_MESSAGETYPE;
    options[num_options-1].oplen = 1;
    options[num_options-1].opdata[0] = operation;
  }
  else {
    /* no "-o operation" argument given */
    if (option_added(LIBNET_DHCP_MESSAGETYPE) == 0) {
      /* Add MESSAGETYPE DHCP option */
      num_options++;
      options = (struct dhcp_option *)
        realloc(options, num_options * sizeof(struct dhcp_option));
      options[num_options-1].opnum = LIBNET_DHCP_MESSAGETYPE;
      options[num_options-1].oplen = 1;
      options[num_options-1].opdata[0] = operation;
    }
  }

  if (arg_secs != NULL) {
    unsigned long ultmp;
    ultmp = strtoul(arg_secs, &stmp, 0);
    if (*stmp != '\0' || ultmp > 65535) {
      if (verbosity > 0)
        printf("Error: secs must be 0-65535 (was: %s)\n",
          arg_secs);
      exit(1);
    }
    secs = (u_int16_t)ultmp;
  }

  if (arg_timeout != NULL) {
    timeout = strtoul(arg_timeout, &stmp, 0);
    if (*stmp != '\0') {
      if (verbosity > 0)
        printf("Error: timeout value must be 0 or a positive integer (was: %s)\n",
          arg_timeout);
      exit(1);
    }
  }

  if (arg_reply_count != NULL) {
    reply_count = strtoul(arg_reply_count, &stmp, 0);
    if (*stmp != '\0') {
      if (verbosity > 0)
        printf("Error: reply_count value must be 0 or a positive integer (was: %s)\n",
          arg_reply_count);
      exit(1);
    }
  }

  if (arg_xid != NULL) {
    xid = strtoul(arg_xid, &stmp, 0);
    if (*stmp != '\0') {
      if (verbosity > 0) 
        printf("Error: xid value must be 0 or a positive integer (was: %s)\n",
          arg_xid);
      exit(1);
    } 
  }

  if (arg_flags != NULL) {
    unsigned long ultmp;
    ultmp = strtoul(arg_flags, &stmp, 0);
    if (*stmp != '\0' || ultmp > 65535) {
      if (verbosity > 0) 
        printf("Error: flags value must be 0-65535 (was: %s)\n",
          arg_flags);
      exit(1);
    }
    flags = (u_int16_t)ultmp;
  }

  if (arg_sip != NULL) {
    sip = inet_addr(arg_sip);
    if (sip == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified sip value is not a valid IPv4 address (was: %s)\n",
          arg_sip);
      exit(1);
    }
  }

  if (arg_yip != NULL) {
    yip = inet_addr(arg_yip);
    if (yip == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified yip value is not a valid IPv4 address (was: %s)\n",
          arg_yip);
      exit(1);
    }
  }

  if (arg_gip != NULL) {
    gip = inet_addr(arg_gip);
    if (gip == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified gip value is not a valid IPv4 address (was: %s)\n",
          arg_gip);
      exit(1);
    }
  }

  if (arg_fname != NULL) {
    fname = (char *)malloc(strlen(fname)+1);
    strcpy(fname, arg_fname);
  }
  if (arg_sname != NULL) {
    sname = (char *)malloc(strlen(sname)+1);
    strcpy(sname, arg_sname);
  }

  if (arg_ipv4_src != NULL) {
    ipv4_src = inet_addr(arg_ipv4_src);
    if (ipv4_src == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified ipv4_src value is not a valid IPv4 address (was: %s)\n",
          arg_ipv4_src);
      exit(1);
    }
  }

  if (arg_ipv4_dst != NULL) {
    ipv4_dst = inet_addr(arg_ipv4_dst);
    if (ipv4_dst == INADDR_NONE) {
      if (verbosity > 0)
        printf("Error: specified ipv4_dst value is not a valid IPv4 address (was: %s)\n",
          arg_ipv4_dst);
      exit(1);
    }
  }

  if (arg_ipv4_ttl != NULL) {
    unsigned long ultmp;
    ultmp = strtoul(arg_ipv4_ttl, &stmp, 0);
    if (*stmp != '\0' || ultmp > 255) {
      if (verbosity > 0) 
        printf("Error: ipv4_ttl value must be 0-255 (was: %s)\n",
          arg_xid);
      exit(1);
    }
    ipv4_ttl = (u_int8_t)ultmp;
  }

  if (arg_ipv4_tos != NULL) {
    unsigned long ultmp;
    ultmp = strtoul(arg_ipv4_tos, &stmp, 0);
    if (*stmp != '\0' || ultmp > 255) {
      if (verbosity > 0) 
        printf("Error: ipv4_tos value must be 0-255 (was: %s)\n",
          arg_ipv4_tos);
      exit(1);
    }
    ipv4_tos = (u_int8_t)ultmp;
  }

  if (arg_ether_dst != NULL) {
    int l = ETHER_ADDR_LEN;
    /*ether_dst = libnet_hex_aton((int8_t *)arg_ether_dst, &l);*/
    ether_dst = libnet_hex_aton(arg_ether_dst, &l);
    if (ether_dst == NULL) {
      if (verbosity > 0)
        printf("Error: invalid ethernet destination MAC specified (was: %s)\n",
          arg_ether_dst);
      exit(1);
    }
  }


  /******************************
   * Done setting parameters.   *
   * Start building DHCP packet *
   ******************************/

  libnet_clear_packet(lnp);

  /* Build DHCP payload (DHCP options section) */
  dhcp_payload = build_payload(&dhcp_payload_len);

  /* Create DHCP message */
  ptag_dhcpv4 = 
    libnet_build_dhcpv4(LIBNET_DHCP_REQUEST,
                         BOOTP_HTYPE_ETHER,
                         ETHER_ADDR_LEN,
                         BOOTP_HOPCOUNT,
                         xid,
                         secs,
                         flags,
                         cip,
                         yip,
                         sip,
                         gip,
                         chaddr,
                         sname,
                         fname,
                         dhcp_payload,
                         dhcp_payload_len,
                         lnp,
                         0);
  if (ptag_dhcpv4 == -1) {
    printf("Failed to build bootp packet: %s\n", libnet_errbuf);
    exit(1);
  }

/*
libnet_ptag_t
libnet_build_udp(u_int16_t sp, u_int16_t dp, u_int16_t len, u_int16_t sum,
u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
*/

  /* Create UDP datagram */
  ptag_udp =
    libnet_build_udp(UDP_SRCPORT,
                     UDP_DSTPORT,
                     dhcp_payload_len + LIBNET_DHCPV4_H + LIBNET_UDP_H,
                     0,
                     NULL,
                     0,
                     lnp,
                     0);
  if (ptag_udp == -1) {
    printf("Failed to build udp packet: %s\n", libnet_errbuf);
    exit(1);
  }

/*
libnet_ptag_t
libnet_build_ipv4(u_int16_t len, u_int8_t tos, u_int16_t id, u_int16_t frag,
u_int8_t ttl, u_int8_t prot, u_int16_t sum, u_int32_t src, u_int32_t dst,
u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
*/

  /* Create IPv4 datagram */
  ptag_ipv4 =
    libnet_build_ipv4(dhcp_payload_len + LIBNET_DHCPV4_H + LIBNET_UDP_H + LIBNET_IPV4_H,
                      ipv4_tos,
                      ipv4_id++,
                      0,
                      ipv4_ttl,
                      IPPROTO_UDP,
                      0,
                      ipv4_src,
                      ipv4_dst,
                      NULL,
                      0,
                      lnp,
                      0);
  if (ptag_ipv4 == -1) {
    printf("Failed to build ipv4 packet: %s\n", libnet_errbuf);
    exit(1);
  }

  /* Create ethernet packet */
  ptag_ethernet = 
    libnet_autobuild_ethernet(ether_dst,
                              ETHERTYPE_IP,
                              lnp);
  if (ptag_ethernet == -1) {
    printf("Failed to build ethernet packet: %s\n", libnet_errbuf);
    exit(1);
  }

  /* Write packet to network */
  if (libnet_write(lnp) == -1) {
    printf("Failed to write ethernet packet to network: %s\n", libnet_errbuf);
    exit(1);
  }

  /* If we have to wait and listen for server replies, we use
     a timer and a signal handler to quit. We do this as libpcap
     doesn't support non-blocking packet capture on some (many?)
     platforms. We could have launched another thread also, but
     using timers and signals is simpler.
   */
  if (timeout > 0) {
    struct itimerval itv;
    itv.it_interval.tv_sec = itv.it_value.tv_sec = timeout;
    itv.it_interval.tv_usec = itv.it_value.tv_usec = 0;
    setitimer(ITIMER_REAL, &itv, NULL);
    signal(SIGALRM, sighandler);
    pcap_loop(pcp, -1, pcap_callback, NULL);    
  }

  libnet_destroy(lnp);
  pcap_close(pcp);
  exit(0);
}
예제 #4
0
int
main(int argc, char *argv[])
{
    char *intf;
    u_long src_ip, options_len, orig_len;
    int i;
    
    libnet_t *l;
    libnet_ptag_t t;
    libnet_ptag_t ip;
    libnet_ptag_t udp;
    libnet_ptag_t dhcp;
    struct libnet_ether_addr *ethaddr;
    struct libnet_stats ls;
    
    char errbuf[LIBNET_ERRBUF_SIZE];
    
    u_char options_req[] = { LIBNET_DHCP_SUBNETMASK , LIBNET_DHCP_BROADCASTADDR , LIBNET_DHCP_TIMEOFFSET , LIBNET_DHCP_ROUTER , LIBNET_DHCP_DOMAINNAME , LIBNET_DHCP_DNS , LIBNET_DHCP_HOSTNAME };
    u_char *options;
    u_char enet_dst[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    u_char *tmp;
    
    // have to specify interface
    if (argc != 2)
        usage(argv[0]);
    intf = argv[1];
    
    l = libnet_init(
            LIBNET_LINK,                            // injection type
            intf,                                   // network interface
            errbuf);                                // errbuf
    if (!l)
    {
        fprintf(stderr, "libnet_init: %s", errbuf);
        exit(EXIT_FAILURE);
    }
    else {
        src_ip = libnet_get_ipaddr4(l);;
        
        if ((ethaddr = libnet_get_hwaddr(l)) == NULL)
        {
            fprintf(stderr, "libnet_get_hwaddr: %s\n", libnet_geterror(l));
            exit(EXIT_FAILURE);
        }
        
        printf("ip addr     : %s\n", libnet_addr2name4(src_ip, LIBNET_DONT_RESOLVE));
        printf("eth addr    : ");
        for (i = 0; i < 6; i++) {
            printf("%x", ethaddr->ether_addr_octet[i]);
            if (i != 5) {
                printf(":");
            }
        }
        printf("\n");
        
        
        // build options packet
        i = 0;
        options_len = 3;                            // update total payload size
        
        // we are a discover packet
        options = malloc(3);
        options[i++] = LIBNET_DHCP_MESSAGETYPE;     // type
        options[i++] = 1;                           // len
        options[i++] = LIBNET_DHCP_MSGDISCOVER;     // data
        
        orig_len = options_len;
        options_len += sizeof(options_req) + 2;     // update total payload size
        
        // workaround for realloc on old machines
        // options = realloc(options, options_len); // resize options buffer
        tmp = malloc(options_len);
        memcpy(tmp, options, orig_len);
        free(options);
        options = tmp;
        
        // we are going to request some parameters
        options[i++] = LIBNET_DHCP_PARAMREQUEST;    // type
        options[i++] = sizeof(options_req);         // len
        memcpy(options + i, options_req, sizeof(options_req)); // data
        i += sizeof(options_req);
        
        // if we have an ip already, let's request it.
        if (src_ip)
        {
            orig_len = options_len;
            options_len += 2 + sizeof(src_ip);
            
            // workaround for realloc on old machines
            // options = realloc(options, options_len);
            tmp = malloc(options_len);
            memcpy(tmp, options, orig_len);
            free(options);
            options = tmp;
            
            options[i++] = LIBNET_DHCP_DISCOVERADDR;	// type
            options[i++] = sizeof(src_ip);			    // len
            memcpy(options + i, (char *)&src_ip, sizeof(src_ip));// data
            i += sizeof(src_ip);
        }
        
        // end our options packet
        options[i] = LIBNET_DHCP_END;
        
        // make sure we are at least the minimum length, if not fill
        // this could go in libnet, but we will leave it in the app for now
        if (options_len + LIBNET_DHCPV4_H < LIBNET_BOOTP_MIN_LEN)
        {
            orig_len = options_len;
            options_len = LIBNET_BOOTP_MIN_LEN - LIBNET_DHCPV4_H;
            
            // workaround for realloc on old machines
            // options = realloc(options, options_len);
            tmp = malloc(options_len);
            memcpy(tmp, options, orig_len);
            free(options);
            options = tmp;
            
            memset(options + i, 0, options_len - i);
        }
        
        // the goodies are here
        dhcp = libnet_build_dhcpv4(
                LIBNET_DHCP_REQUEST,                            // opcode
                1,                                              // hardware type
                6,                                              // hardware address length
                0,                                              // hop count
                0xdeadbeef,                                     // transaction id
                0,                                              // seconds since bootstrap
                0x8000,                                         // flags
                0,                                              // client ip
                0,                                              // your ip
                0,                                              // server ip
                0,                                              // gateway ip
                ethaddr->ether_addr_octet,                      // client hardware addr
                NULL,                                           // server host name
                NULL,                                           // boot file
                options,                                        // dhcp options stuck in payload since it is dynamic
                options_len,                                    // length of options
                l,                                              // libnet handle 
                0);                                             // libnet id 
        
        // wrap it
        udp = libnet_build_udp(
                68,                                             // source port
                67,                                             // destination port
                LIBNET_UDP_H + LIBNET_DHCPV4_H + options_len,   // packet size
                0,                                              // checksum
                NULL,                                           // payload 
                0,                                              // payload size 
                l,                                              // libnet handle 
                0);                                             // libnet id 
        
        // hook me up with some ipv4
        ip = libnet_build_ipv4(
                LIBNET_IPV4_H + LIBNET_UDP_H + LIBNET_DHCPV4_H
                + options_len,                                  // length
                0x10,                                           // TOS
                0,                                              // IP ID
                0,                                              // IP Frag 
                16,                                             // TTL
                IPPROTO_UDP,                                    // protocol
                0,                                              // checksum
                src_ip,                                         // src ip
                inet_addr("255.255.255.255"),                   // destination ip
                NULL,                                           // payload
                0,                                              // payload size
                l,                                              // libnet handle
                0);                                             // libnet id
        
        // we can just autobuild since we arent doing anything tricky
        t = libnet_autobuild_ethernet(
                enet_dst,                                       // ethernet destination
                ETHERTYPE_IP,                                   // protocol type
                l);                                             // libnet handle
        
        // write to the wire
        if (libnet_write(l) == -1)
        {
            fprintf(stderr, " %s: libnet_write: %s\n", argv[0],
                    strerror(errno));
            exit(EXIT_FAILURE);
        }
        
        // fill and print stats
        libnet_stats(l, &ls);
        fprintf(stderr, "Packets sent:  %ld\n"
                    "Packet errors: %ld\n"
                    "Bytes written: %ld\n",
                    ls.packets_sent, ls.packet_errors, ls.bytes_written);
        libnet_destroy(l);
        
        // free mem
        free(options);
        
        exit(0);
    }
    exit(0);
}
예제 #5
0
void configure_net_dhcp() {
     kprintf("k_network: configure_net_dhcp() - attempting DHCP configuration\n");

     kprintf("k_network: configure_net_dhcp() - building DHCP request\n");
     EFI_SIMPLE_NETWORK_MODE *m = simple_net->Mode;

     int i = 0;
     u_char options_req[] = { LIBNET_DHCP_SUBNETMASK,
                             LIBNET_DHCP_BROADCASTADDR, LIBNET_DHCP_TIMEOFFSET,
                             LIBNET_DHCP_ROUTER, LIBNET_DHCP_DOMAINNAME,
                             LIBNET_DHCP_DNS, LIBNET_DHCP_HOSTNAME };
     u_char *options;
     libnet_t *l;
     char* err_buf;
     l = libnet_init(LIBNET_NONE,NULL,err_buf);
     if(!l) {
        kprintf("libnet_init: %s\n", err_buf);
     }
     kprintf("k_network: configure_net_dhcp() - libnet setup\n");

     u_long options_len = 3;
     libnet_ptag_t dhcp_packet;
     libnet_ptag_t udp_packet;
     libnet_ptag_t ip_packet;
     options = malloc(3);
     options[i++] = LIBNET_DHCP_MESSAGETYPE;
     options[i++] = 1;
     options[i++] = LIBNET_DHCP_MSGDISCOVER;
     u_long orig_len = options_len;
     options_len += sizeof(options_req) + 2;
     u_char *tmp = malloc(options_len);
     memcpy(tmp, options, orig_len);
     free(options);
     options = tmp;

     options[i++] = LIBNET_DHCP_PARAMREQUEST;
     options[i++] = sizeof(options_req);
     memcpy(options + i, options_req, sizeof(options_req));
     i += sizeof(options_req);

     orig_len = options_len;
     options_len += 1;

     
     tmp = malloc(options_len);
     memcpy(tmp, options, orig_len);
     free(options);
     options = tmp;
     options[i++] = LIBNET_DHCP_END;

            if (options_len + LIBNET_DHCPV4_H < LIBNET_BOOTP_MIN_LEN)
        {
            orig_len = options_len;
            options_len = LIBNET_BOOTP_MIN_LEN - LIBNET_DHCPV4_H;
            
            tmp = malloc(options_len);
            memcpy(tmp, options, orig_len);
            free(options);
            options = tmp;
            
            memset(options + i, 0, options_len - i);
        }

     
     dhcp_packet = libnet_build_dhcpv4(
                LIBNET_DHCP_REQUEST,            /* opcode */
                1,                              /* hardware type */
                6,                              /* hardware address length */
                0,                              /* hop count */
                0xdeadbeef,                     /* transaction id */
                0,                              /* seconds since bootstrap */
                0x8000,                         /* flags */
                0,                              /* client ip */
                0,                              /* your ip */
                0,                              /* server ip */
                0,                              /* gateway ip */
                m->CurrentAddress.Addr,      /* client hardware addr */
                NULL,                           /* server host name */
                NULL,                           /* boot file */
                options,                        /* dhcp options in payload */
                options_len,                    /* length of options */
                l,                              /* libnet context */
                0);                             /* libnet ptag */

udp_packet = libnet_build_udp(
                68,                             /* source port */
                67,                             /* destination port */
                LIBNET_UDP_H + LIBNET_DHCPV4_H + options_len,  /* packet size */
                0,                              /* checksum */
                NULL,                           /* payload */
                0,                              /* payload size */
                l,                              /* libnet context */
                0);                             /* libnet ptag */

ip_packet = libnet_build_ipv4(
                LIBNET_IPV4_H + LIBNET_UDP_H + LIBNET_DHCPV4_H
                + options_len,                  /* length */
                0x10,                           /* TOS */
                0,                              /* IP ID */
                0,                              /* IP Frag */
                16,                             /* TTL */
                IPPROTO_UDP,                    /* protocol */
                0,                              /* checksum */
                0,                         /* src ip */
                0,   /* destination ip */
                NULL,                           /* payload */
                0,                              /* payload size */
                l,                              /* libnet context */
                0);                             /* libnet ptag */
     uint32_t pack_size=0;
     uint8_t  *pack;

/*     char _tx_buf[4096];
     void* buf = (void*)_tx_buf;

     memset(buf,0,4096);
//     UINTN pack_size = sizeof(struct dhcp_msg);
     UINTN pack_size=0;
//     EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp_req = (EFI_PXE_BASE_CODE_DHCPV4_PACKET*)malloc(sizeof(EFI_PXE_BASE_CODE_DHCPV4_PACKET));
     struct dhcp_msg *dhcp_req = (struct dhcp_msg*)(buf +(m->MediaHeaderSize)+ (sizeof(struct iphdr) + sizeof(struct udphdr)));

     uint64_t req_id = (uint64_t)rand();

     int i=0;

     memset((void*)dhcp_req,0,pack_size);
     dhcp_req->op    = 1; // request
     dhcp_req->htype    = m->IfType;
     dhcp_req->hlen = m->HwAddressSize;
     dhcp_req->hops  = 0;
     dhcp_req->xid     = req_id;
     dhcp_req->secs   = 0;
     dhcp_req->flags     = 0x8000;
     for(i=0; i< m->HwAddressSize; i++) {
         dhcp_req->chaddr[i] = m->CurrentAddress.Addr[i];
     }
     dhcp_req->cookie = 0x63825363;

     dhcp_req->options[0] = 53;
     dhcp_req->options[1] = 1;
     dhcp_req->options[2] = 1;


     kprintf("k_network: configure_net_dhcp() ID is %#llx\n",req_id);
     struct iphdr *iph = (struct iphdr *)(buf+(m->MediaHeaderSize));
     struct udphdr *udph = (struct udphdr *) (buf + sizeof (struct iphdr)+(m->MediaHeaderSize));
     memset((void*)iph,0,sizeof(struct iphdr));
//     memset((void*)udph,0,sizeof(struct udph));
     iph->ihl = 5;
     iph->version = 4;
     iph->tot_len  = htons(sizeof(struct iphdr));
     iph->protocol = IPPROTO_UDP;
     iph->ttl      = 255;
     iph->saddr    = INADDR_ANY;
     iph->daddr    = INADDR_ANY;
//     iph->check    = csum ((unsigned short *) buf, iph->tot_len);
//     udph->uh_ulen = sizeof(struct udphdr) + pack_size;
//     udph->uh_sum  = csum((unsigned short*)(buf - sizeof(struct udphdr)),pack_size+sizeof(struct udphdr));
//     udph->uh_sport  = 68;
//     udph->uh_dport    = 68;*/

     EFI_MAC_ADDRESS anywhere;
     for(i=0; i< m->HwAddressSize; i++) {
         anywhere.Addr[i] = 255;
     }
     
     kprintf("k_network:configure_net_dhcp() - Transmitting request\n");
     UINT16 ether_type = 0x800;
//     EFI_STATUS send_s = simple_net->Transmit(simple_net,0,tx_size,buf,NULL,&anywhere,&ether_type);
     EFI_STATUS send_s = simple_net->Transmit(simple_net,m->MediaHeaderSize,pack_size,(void*)pack,NULL,&anywhere,&ether_type);

     kprintf("k_network:configure_net_dhcp() - Waiting for transmission\n");
     void* tx_buf=NULL;
     while(tx_buf==NULL && (send_s==0)) {
       tx_buf=NULL;
       send_s = simple_net->GetStatus(simple_net,0,&tx_buf);
       if(send_s != 0) kprintf("!\n");
     }
     kprintf("k_network:configure_net_dhcp() - Transmitted, tx_buf at  %#llx \n",tx_buf);
}
예제 #6
0
static int dhcp_discovery(libnet_t *ln, uint8_t *enet_src, uint32_t dhcp_xid)
{
	uint32_t options_len = 0;
	uint32_t options_ofs = 0;
	libnet_ptag_t eth;
	libnet_ptag_t ip;
	libnet_ptag_t udp;
	libnet_ptag_t dhcp;
	uint8_t enet_dst[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

	uint8_t options_req[] = {
		LIBNET_DHCP_SUBNETMASK, LIBNET_DHCP_BROADCASTADDR,
		LIBNET_DHCP_ROUTER, LIBNET_DHCP_DOMAINNAME, LIBNET_DHCP_DNS,
		LIBNET_DHCP_HOSTNAME, LIBNET_DHCP_TIMEOFFSET
	};

	/* build DHCP Discovery options packet */
	options_len = 3;
	options = realloc(options, options_len);
	options[options_ofs++] = LIBNET_DHCP_MESSAGETYPE;
	options[options_ofs++] = 1;
	options[options_ofs++] = LIBNET_DHCP_MSGDISCOVER;

	/* we are going to request some parameters */
	options_len += sizeof(options_req) + 2;
	options = realloc(options, options_len);
	options[options_ofs++] = LIBNET_DHCP_PARAMREQUEST;
	options[options_ofs++] = sizeof(options_req);
	memcpy(options + options_ofs, options_req, sizeof(options_req));
	options_ofs += sizeof(options_req);

	/* gpxe client support */
	if (gpxe) {
		options_len += 6;
		options = realloc(options, options_len);
		options[options_ofs++] = 0x4d;
		options[options_ofs++] = 0x4;
		options[options_ofs++] = 'g';
		options[options_ofs++] = 'P';
		options[options_ofs++] = 'X';
		options[options_ofs++] = 'E';
	}

	/* end our options packet */
	options_len += 1;
	options = realloc(options, options_len);
	options[options_ofs++] = LIBNET_DHCP_END;

	if (options_len + LIBNET_DHCPV4_H < LIBNET_BOOTP_MIN_LEN) {
		options_len = LIBNET_BOOTP_MIN_LEN - LIBNET_DHCPV4_H;
		options = realloc(options, options_len);
		memset(options + options_ofs, 0, options_len - options_ofs);
	}

	dhcp = libnet_build_dhcpv4(LIBNET_DHCP_REQUEST,
				   1, 6, 0,
				   dhcp_xid,
				   0, 0x8000, 0, 0, 0, 0,
				   enet_src,
				   NULL, NULL,
				   options, options_len,
				   ln, 0);

	udp = libnet_build_udp(68, 67,
			       LIBNET_UDP_H + LIBNET_DHCPV4_H + options_len,
			       0, NULL, 0, ln, 0);

	ip = libnet_build_ipv4(LIBNET_IPV4_H + LIBNET_UDP_H +
			       LIBNET_DHCPV4_H + options_len,
			       0x10, 0, 0, 16, IPPROTO_UDP, 0, 0,
			       inet_addr("255.255.255.255"),
			       NULL, 0, ln, 0);

	eth = libnet_build_ethernet(enet_dst, enet_src, ETHERTYPE_IP,
				    NULL, 0, ln, 0);

	if (libnet_write(ln) == -1) {
		fprintf(stderr, "libnet_write: %s\n", strerror(errno));
		exit(EXIT_FAILURE);
	}

	free(options);

	return 0;
}