These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / SLOF / clients / net-snk / app / netlib / dhcp.c
index 5f26f3a..7e2e88c 100644 (file)
@@ -11,7 +11,7 @@
  *****************************************************************************/
 
 
-/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ALGORITHMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+/******************************* ALGORITHMS ******************************/
 
 /** \file dhcp.c <pre>
  * **************** State-transition diagram for DHCP client  *************
  * </pre> */
 
 
-/*>>>>>>>>>>>>>>>>>>>>> DEFINITIONS & DECLARATIONS <<<<<<<<<<<<<<<<<<<<<<*/
+/********************** DEFINITIONS & DECLARATIONS ***********************/
 
 #include <dhcp.h>
 #include <ethernet.h>
 #include <ipv4.h>
 #include <udp.h>
 #include <dns.h>
+#include <netapps/args.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -110,11 +111,11 @@ static uint8_t dhcp_magic[] = {0x63, 0x82, 0x53, 0x63};
  *  If flag[i] == TRUE then field for i-th option retains valid value and
  *  information from this field may retrived (in case of receiving) or will
  *  be transmitted (in case of transmitting).
- *  
+ *
  */
 typedef struct {
        uint8_t    flag[256];         /**< Show if corresponding opt. is valid */
-       uint8_t    request_list[256]; /**< o.55 If i-th member is TRUE, then i-th  
+       uint8_t    request_list[256]; /**< o.55 If i-th member is TRUE, then i-th
                                          option will be requested from server */
        uint32_t   server_ID;         /**< o.54 Identifies DHCP-server         */
        uint32_t   requested_IP;      /**< o.50 Must be filled in DHCP-Request */
@@ -132,65 +133,57 @@ typedef struct {
 static uint8_t dhcp_state;
 
 
-/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> PROTOTYPES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
-
-static int32_t
-dhcp_attempt(int fd);
+/***************************** PROTOTYPES ********************************/
 
-static int32_t
-dhcp_encode_options(uint8_t * opt_field, dhcp_options_t * opt_struct);
+static int32_t dhcp_attempt(int fd);
 
-static int32_t
-dhcp_decode_options(uint8_t opt_field[], uint32_t opt_len,
-                    dhcp_options_t * opt_struct);
+static int32_t dhcp_encode_options(uint8_t * opt_field, dhcp_options_t * opt_struct);
 
-static int8_t
-dhcp_merge_options(uint8_t dst_options[], uint32_t * dst_len,
-                   uint8_t src_options[], uint32_t src_len);
+static int32_t dhcp_decode_options(uint8_t opt_field[], uint32_t opt_len,
+                                  dhcp_options_t * opt_struct);
 
-static int8_t
-dhcp_find_option(uint8_t options[], uint32_t len,
-                 uint8_t op_code, uint32_t * op_offset);
-
-static void
-dhcp_append_option(uint8_t dst_options[], uint32_t * dst_len,
-                   uint8_t * new_option);
+static int8_t dhcp_merge_options(uint8_t dst_options[], uint32_t * dst_len,
+                                uint8_t src_options[], uint32_t src_len);
 
-static void
-dhcp_combine_option(uint8_t dst_options[], uint32_t * dst_len,
-                    uint32_t dst_offset, uint8_t * new_option);
+static int8_t dhcp_find_option(uint8_t options[], uint32_t len,
+                              uint8_t op_code, uint32_t * op_offset);
 
-static void
-dhcp_send_discover(int fd);
+static void dhcp_append_option(uint8_t dst_options[], uint32_t * dst_len,
+                              uint8_t * new_option);
 
-static void
-dhcp_send_request(int fd);
+static void dhcp_combine_option(uint8_t dst_options[], uint32_t * dst_len,
+                               uint32_t dst_offset, uint8_t * new_option);
 
-static uint8_t
-strtoip(int8_t * str, uint32_t * ip);
+static void dhcp_send_discover(int fd);
 
+static void dhcp_send_request(int fd);
 
-/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> LOCAL VARIABLES <<<<<<<<<<<<<<<<<<<<<<<<<<*/
+/***************************** LOCAL VARIABLES ***************************/
 
 static uint8_t  ether_packet[ETH_MTU_SIZE];
 static uint32_t dhcp_own_ip        = 0;
 static uint32_t dhcp_server_ip     = 0;
 static uint32_t dhcp_siaddr_ip     = 0;
-static int8_t   dhcp_filename[256];
-static int8_t   dhcp_tftp_name[256];
+static char   dhcp_filename[256];
+static char   dhcp_tftp_name[256];
+static uint32_t dhcp_xid;
 
 static char   * response_buffer;
 
-/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+/***************************** IMPLEMENTATION ****************************/
 
-int32_t
-dhcpv4(char *ret_buffer, filename_ip_t * fn_ip) {
+void dhcpv4_generate_transaction_id(void)
+{
+       dhcp_xid = (rand() << 16) ^ rand();
+}
 
+int32_t dhcpv4(char *ret_buffer, filename_ip_t *fn_ip)
+{
        uint32_t dhcp_tftp_ip     = 0;
        int fd = fn_ip->fd;
 
-       strcpy((char *) dhcp_filename, "");
-       strcpy((char *) dhcp_tftp_name, "");
+       strcpy(dhcp_filename, "");
+       strcpy(dhcp_tftp_name, "");
 
        response_buffer = ret_buffer;
 
@@ -204,11 +197,11 @@ dhcpv4(char *ret_buffer, filename_ip_t * fn_ip) {
                dhcp_siaddr_ip = fn_ip->server_ip;
        }
        if(fn_ip->filename[0] != 0) {
-               strcpy((char *) dhcp_filename, (char *) fn_ip->filename);
+               strcpy(dhcp_filename, (char *) fn_ip->filename);
        }
 
        // TFTP SERVER
-       if (!strlen((char *) dhcp_tftp_name)) {
+       if (!strlen(dhcp_tftp_name)) {
                if (!dhcp_siaddr_ip) {
                        // ERROR: TFTP name is not presented
                        return -3;
@@ -219,9 +212,9 @@ dhcpv4(char *ret_buffer, filename_ip_t * fn_ip) {
        }
        else {
                // TFTP server defined by its name
-               if (!strtoip(dhcp_tftp_name, &(dhcp_tftp_ip))) {
-                       if (!dns_get_ip(fd, dhcp_tftp_name, (uint8_t *)&(dhcp_tftp_ip), 4)) {
-                               // DNS error - can't obtain TFTP-server name  
+               if (!strtoip(dhcp_tftp_name, (char *)&dhcp_tftp_ip)) {
+                       if (!dns_get_ip(fd, dhcp_tftp_name, (uint8_t *)&dhcp_tftp_ip, 4)) {
+                               // DNS error - can't obtain TFTP-server name
                                // Use TFTP-ip from siaddr field, if presented
                                if (dhcp_siaddr_ip) {
                                        dhcp_tftp_ip = dhcp_siaddr_ip;
@@ -237,7 +230,7 @@ dhcpv4(char *ret_buffer, filename_ip_t * fn_ip) {
        // Store configuration info into filename_ip strucutre
        fn_ip -> own_ip = dhcp_own_ip;
        fn_ip -> server_ip = dhcp_tftp_ip;
-       strcpy((char *) fn_ip -> filename, (char *) dhcp_filename);
+       strcpy((char *) fn_ip -> filename, dhcp_filename);
 
        return 0;
 }
@@ -245,8 +238,8 @@ dhcpv4(char *ret_buffer, filename_ip_t * fn_ip) {
 /**
  * DHCP: Tries o obtain DHCP parameters, refer to state-transition diagram
  */
-static int32_t
-dhcp_attempt(int fd) {
+static int32_t dhcp_attempt(int fd)
+{
        int sec;
 
        // Send DISCOVER message and switch DHCP-client to SELECT state
@@ -270,7 +263,7 @@ dhcp_attempt(int fd) {
                } while (get_timer() > 0);
        }
 
-       // timeout 
+       // timeout
        return 0;
 }
 
@@ -278,7 +271,7 @@ dhcp_attempt(int fd) {
  * DHCP: Supplements DHCP-message with options stored in structure.
  *       For more information about option coding see dhcp_options_t.
  *
- * @param  opt_field     Points to the "vend" field of DHCP-message  
+ * @param  opt_field     Points to the "vend" field of DHCP-message
  *                       (destination)
  * @param  opt_struct    this structure stores info about the options which
  *                       will be added to DHCP-message (source)
@@ -286,8 +279,8 @@ dhcp_attempt(int fd) {
  *                       FALSE - error condition occurs.
  * @see                  dhcp_options_t
  */
-static int32_t
-dhcp_encode_options(uint8_t * opt_field, dhcp_options_t * opt_struct) {
+static int32_t dhcp_encode_options(uint8_t * opt_field, dhcp_options_t * opt_struct)
+{
        uint8_t * options = opt_field;
        uint16_t i, sum; // used to define is any options set
 
@@ -380,7 +373,7 @@ dhcp_encode_options(uint8_t * opt_field, dhcp_options_t * opt_struct) {
  * DHCP: Extracts encoded options from DHCP-message into the structure.
  *       For more information about option coding see dhcp_options_t.
  *
- * @param  opt_field     Points to the "options" field of DHCP-message  
+ * @param  opt_field     Points to the "options" field of DHCP-message
  *                       (source).
  * @param  opt_len       Length of "options" field.
  * @param  opt_struct    this structure stores info about the options which
@@ -389,10 +382,10 @@ dhcp_encode_options(uint8_t * opt_field, dhcp_options_t * opt_struct) {
  *                       FALSE - error condition occurs.
  * @see                  dhcp_options_t
  */
-static int32_t
-dhcp_decode_options(uint8_t opt_field[], uint32_t opt_len,
-                    dhcp_options_t * opt_struct) {
-       int32_t offset = 0;
+static int32_t dhcp_decode_options(uint8_t opt_field[], uint32_t opt_len,
+                                  dhcp_options_t * opt_struct)
+{
+       uint32_t offset = 0;
 
        memset(opt_struct, 0, sizeof(dhcp_options_t));
 
@@ -407,30 +400,30 @@ dhcp_decode_options(uint8_t opt_field[], uint32_t opt_len,
                switch(opt_field[offset]) {
                case DHCP_OVERLOAD :
                        opt_struct -> overload = opt_field[offset + 2];
-                       offset += 2 + opt_field[offset + 1]; 
+                       offset += 2 + opt_field[offset + 1];
                        break;
 
                case DHCP_REQUESTED_IP :
                        opt_struct -> requested_IP = htonl(* (uint32_t *) (opt_field + offset + 2));
-                       offset += 2 + opt_field[offset + 1]; 
+                       offset += 2 + opt_field[offset + 1];
                        break;
 
                case DHCP_MASK :
                        opt_struct -> flag[DHCP_MASK] = 1;
                        opt_struct -> subnet_mask = htonl(* (uint32_t *) (opt_field + offset + 2));
-                       offset += 2 + opt_field[offset + 1]; 
+                       offset += 2 + opt_field[offset + 1];
                        break;
 
                case DHCP_DNS :
                        opt_struct -> flag[DHCP_DNS] = 1;
                        opt_struct -> dns_IP = htonl(* (uint32_t *) (opt_field + offset + 2));
-                       offset += 2 + opt_field[offset + 1]; 
+                       offset += 2 + opt_field[offset + 1];
                        break;
 
                case DHCP_ROUTER :
                        opt_struct -> flag[DHCP_ROUTER] = 1;
                        opt_struct -> router_IP = htonl(* (uint32_t *) (opt_field + offset + 2));
-                       offset += 2 + opt_field[offset + 1]; 
+                       offset += 2 + opt_field[offset + 1];
                        break;
 
                case DHCP_MSG_TYPE :
@@ -492,11 +485,12 @@ dhcp_decode_options(uint8_t opt_field[], uint32_t opt_len,
  *                       FALSE - error condition occurs.
  */
 static int8_t dhcp_merge_options(uint8_t dst_options[], uint32_t * dst_len,
-                                 uint8_t src_options[], uint32_t src_len) {
-       int32_t dst_offset, src_offset = 0;
+                                uint8_t src_options[], uint32_t src_len)
+{
+       uint32_t dst_offset, src_offset = 0;
 
        // remove ENDOPT if presented
-       if (dhcp_find_option(dst_options, * dst_len, DHCP_ENDOPT, (uint32_t *) &dst_offset))
+       if (dhcp_find_option(dst_options, * dst_len, DHCP_ENDOPT, &dst_offset))
                * dst_len = dst_offset;
 
        while (src_offset < src_len) {
@@ -509,7 +503,7 @@ static int8_t dhcp_merge_options(uint8_t dst_options[], uint32_t * dst_len,
                default:
                        if (dhcp_find_option(dst_options, * dst_len,
                                             src_options[src_offset],
-                                            (uint32_t *) &dst_offset)) {
+                                            &dst_offset)) {
                                dhcp_combine_option(dst_options, dst_len,
                                                    dst_offset,
                                                    (uint8_t *) src_options +
@@ -522,7 +516,7 @@ static int8_t dhcp_merge_options(uint8_t dst_options[], uint32_t * dst_len,
                }
        }
 
-       if (src_offset == src_len) 
+       if (src_offset == src_len)
                return 1;
        return 0;
 }
@@ -540,7 +534,8 @@ static int8_t dhcp_merge_options(uint8_t dst_options[], uint32_t * dst_len,
  *                       FALSE - option wasn't find.
  */
 static int8_t dhcp_find_option(uint8_t options[], uint32_t len,
-                               uint8_t op_code, uint32_t * op_offset) {
+                              uint8_t op_code, uint32_t * op_offset)
+{
        uint32_t srch_offset = 0;
        * op_offset = 0;
 
@@ -568,9 +563,9 @@ static int8_t dhcp_find_option(uint8_t options[], uint32_t len,
  * @param  dst_len       length of the "options" field (modified)
  * @param  new_option    points to an option in another list (src)
  */
-static void
-dhcp_append_option(uint8_t dst_options[], uint32_t * dst_len,
-                   uint8_t * new_option) {
+static void dhcp_append_option(uint8_t dst_options[], uint32_t * dst_len,
+                              uint8_t * new_option)
+{
        memcpy(dst_options + ( * dst_len), new_option, 2 + (* (new_option + 1)));
        * dst_len += 2 + *(new_option + 1);
 }
@@ -586,10 +581,9 @@ dhcp_append_option(uint8_t dst_options[], uint32_t * dst_len,
  * @param  dst_offset    offset of the option from beginning of the list
  * @param  new_option    points to an option in another list (src)
  */
-static void
-dhcp_combine_option(uint8_t dst_options[], uint32_t * dst_len,
-                    uint32_t dst_offset, uint8_t * new_option) {
-
+static void dhcp_combine_option(uint8_t dst_options[], uint32_t * dst_len,
+                               uint32_t dst_offset, uint8_t * new_option)
+{
        uint8_t tmp_buffer[1024]; // use to provide safe memcpy
        uint32_t tail_len;
 
@@ -612,8 +606,8 @@ dhcp_combine_option(uint8_t dst_options[], uint32_t * dst_len,
 /**
  * DHCP: Sends DHCP-Discover message. Looks for DHCP servers.
  */
-static void
-dhcp_send_discover(int fd) {
+static void dhcp_send_discover(int fd)
+{
        uint32_t packetsize = sizeof(struct iphdr) +
                              sizeof(struct udphdr) + sizeof(struct btphdr);
        struct btphdr *btph;
@@ -627,6 +621,7 @@ dhcp_send_discover(int fd) {
        btph -> op = 1;
        btph -> htype = 1;
        btph -> hlen = 6;
+       btph -> xid = dhcp_xid;
        memcpy(btph -> chaddr, get_mac_address(), 6);
 
        memset(&opt, 0, sizeof(dhcp_options_t));
@@ -655,8 +650,8 @@ dhcp_send_discover(int fd) {
 /**
  * DHCP: Sends DHCP-Request message. Asks for acknowledgment to occupy IP.
  */
-static void
-dhcp_send_request(int fd) {
+static void dhcp_send_request(int fd)
+{
        uint32_t packetsize = sizeof(struct iphdr) +
                              sizeof(struct udphdr) + sizeof(struct btphdr);
        struct btphdr *btph;
@@ -670,6 +665,7 @@ dhcp_send_request(int fd) {
        btph -> op = 1;
        btph -> htype = 1;
        btph -> hlen = 6;
+       btph -> xid = dhcp_xid;
        memcpy(btph -> chaddr, get_mac_address(), 6);
 
        memset(&opt, 0, sizeof(dhcp_options_t));
@@ -704,7 +700,8 @@ dhcp_send_request(int fd) {
 /**
  * DHCP: Sends DHCP-Release message. Releases occupied IP.
  */
-void dhcp_send_release(int fd) {
+void dhcp_send_release(int fd)
+{
        uint32_t packetsize = sizeof(struct iphdr) +
                              sizeof(struct udphdr) + sizeof(struct btphdr);
        struct btphdr *btph;
@@ -718,6 +715,7 @@ void dhcp_send_release(int fd) {
        btph -> op = 1;
        btph -> htype = 1;
        btph -> hlen = 6;
+       btph -> xid = dhcp_xid;
        strcpy((char *) btph -> file, "");
        memcpy(btph -> chaddr, get_mac_address(), 6);
        btph -> ciaddr = htonl(dhcp_own_ip);
@@ -730,7 +728,7 @@ void dhcp_send_release(int fd) {
 
        dhcp_encode_options(btph -> vend, &opt);
 
-       fill_udphdr(&ether_packet[sizeof(struct iphdr)], 
+       fill_udphdr(&ether_packet[sizeof(struct iphdr)],
                    sizeof(struct btphdr) + sizeof(struct udphdr),
                    UDPPORT_BOOTPC, UDPPORT_BOOTPS);
        fill_iphdr(ether_packet, sizeof(struct btphdr) +
@@ -753,18 +751,21 @@ void dhcp_send_release(int fd) {
  * @see               btphdr
  */
 
-int8_t
-handle_dhcp(int fd, uint8_t * packet, int32_t packetsize) {
+int8_t handle_dhcp(int fd, uint8_t * packet, int32_t packetsize)
+{
        struct btphdr * btph;
        struct iphdr * iph;
        dhcp_options_t opt;
 
-       memset(&opt, 0, sizeof(dhcp_options_t));  
+       memset(&opt, 0, sizeof(dhcp_options_t));
        btph = (struct btphdr *) packet;
        iph = (struct iphdr *) packet - sizeof(struct udphdr) -
              sizeof(struct iphdr);
-       if (btph -> op != 2)
-               return -1; // it is not Boot Reply
+
+       if (btph->op != 2)
+               return -1;              /* It is not a Bootp/DHCP reply */
+       if (btph->xid != dhcp_xid)
+               return -1;              /* The transaction ID does not match */
 
        if (memcmp(btph -> vend, dhcp_magic, 4)) {
                // It is BootP - RFC 951
@@ -788,7 +789,7 @@ handle_dhcp(int fd, uint8_t * packet, int32_t packetsize) {
        }
 
 
-       // decode options  
+       // decode options
        if (!dhcp_decode_options(btph -> vend, packetsize -
                                 sizeof(struct btphdr) + sizeof(btph -> vend),
                                 &opt)) {
@@ -902,7 +903,7 @@ handle_dhcp(int fd, uint8_t * packet, int32_t packetsize) {
                                else {
                                        strcpy((char *) dhcp_filename, "");
                                        if (opt.overload != DHCP_OVERLOAD_FILE &&
-                                               opt.overload != DHCP_OVERLOAD_BOTH && 
+                                               opt.overload != DHCP_OVERLOAD_BOTH &&
                                                strlen((char *) btph -> file)) {
                                                strncpy((char *) dhcp_filename,
                                                        (char *) btph->file,
@@ -952,47 +953,3 @@ handle_dhcp(int fd, uint8_t * packet, int32_t packetsize) {
 
        return 0;
 }
-
-/**
- * DHCP: Converts "255.255.255.255" -> 32-bit long IP
- *
- * @param  str        string to be converted
- * @param  ip         in case of SUCCESS - 32-bit long IP
-                      in case of FAULT - zero
- * @return            TRUE - IP converted successfully;
- *                    FALSE - error condition occurs (e.g. bad format)
- */
-static uint8_t
-strtoip(int8_t * str, uint32_t * ip) {
-       int8_t ** ptr = &str;
-       int16_t i = 0, res, len;
-       char octet[256];
-
-       * ip = 0;
-
-       while (**ptr != 0) {
-               if (i > 3 || !isdigit(**ptr))
-                       return 0;
-               if (strstr((char *) * ptr, ".") != NULL) {
-                       len = (int16_t) ((int8_t *) strstr((char *) * ptr, ".") - 
-                             (int8_t *) (* ptr));
-                       strncpy(octet, (char *) * ptr, len); octet[len] = 0;
-                       * ptr += len;
-               }
-               else {
-                       strcpy(octet, (char *) * ptr);
-                       * ptr += strlen(octet);
-               }
-               res = strtol(octet, NULL, 10);
-               if ((res > 255) || (res < 0))
-                       return 0;
-               * ip = ((* ip) << 8) + res;
-               i++;
-               if (** ptr == '.')
-                       (*ptr)++;
-       }
-
-       if (i != 4)
-               return 0;
-       return 1;
-}