1 #include <assert.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #include <uv.h> 7 8 uv_loop_t *loop; 9 uv_udp_t send_socket; 10 uv_udp_t recv_socket; 11 12 void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { 13 buf->base = malloc(suggested_size); 14 buf->len = suggested_size; 15 } 16 17 void on_read(uv_udp_t *req, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags) { 18 if (nread < 0) { 19 fprintf(stderr, "Read error %s\n", uv_err_name(nread)); 20 uv_close((uv_handle_t*) req, NULL); 21 free(buf->base); 22 return; 23 } 24 25 char sender[17] = { 0 }; 26 uv_ip4_name((const struct sockaddr_in*) addr, sender, 16); 27 fprintf(stderr, "Recv from %s\n", sender); 28 29 // ... DHCP specific code 30 unsigned int *as_integer = (unsigned int*)buf->base; 31 unsigned int ipbin = ntohl(as_integer[4]); 32 unsigned char ip[4] = {0}; 33 int i; 34 for (i = 0; i < 4; i++) 35 ip[i] = (ipbin >> i*8) & 0xff; 36 fprintf(stderr, "Offered IP %d.%d.%d.%d\n", ip[3], ip[2], ip[1], ip[0]); 37 38 free(buf->base); 39 uv_udp_recv_stop(req); 40 } 41 42 uv_buf_t make_discover_msg() { 43 uv_buf_t buffer; 44 alloc_buffer(NULL, 256, &buffer); 45 memset(buffer.base, 0, buffer.len); 46 47 // BOOTREQUEST 48 buffer.base[0] = 0x1; 49 // HTYPE ethernet 50 buffer.base[1] = 0x1; 51 // HLEN 52 buffer.base[2] = 0x6; 53 // HOPS 54 buffer.base[3] = 0x0; 55 // XID 4 bytes 56 buffer.base[4] = (unsigned int) random(); 57 // SECS 58 buffer.base[8] = 0x0; 59 // FLAGS 60 buffer.base[10] = 0x80; 61 // CIADDR 12-15 is all zeros 62 // YIADDR 16-19 is all zeros 63 // SIADDR 20-23 is all zeros 64 // GIADDR 24-27 is all zeros 65 // CHADDR 28-43 is the MAC address, use your own 66 buffer.base[28] = 0xe4; 67 buffer.base[29] = 0xce; 68 buffer.base[30] = 0x8f; 69 buffer.base[31] = 0x13; 70 buffer.base[32] = 0xf6; 71 buffer.base[33] = 0xd4; 72 // SNAME 64 bytes zero 73 // FILE 128 bytes zero 74 // OPTIONS 75 // - magic cookie 76 buffer.base[236] = 99; 77 buffer.base[237] = 130; 78 buffer.base[238] = 83; 79 buffer.base[239] = 99; 80 81 // DHCP Message type 82 buffer.base[240] = 53; 83 buffer.base[241] = 1; 84 buffer.base[242] = 1; // DHCPDISCOVER 85 86 // DHCP Parameter request list 87 buffer.base[243] = 55; 88 buffer.base[244] = 4; 89 buffer.base[245] = 1; 90 buffer.base[246] = 3; 91 buffer.base[247] = 15; 92 buffer.base[248] = 6; 93 94 return buffer; 95 } 96 97 void on_send(uv_udp_send_t *req, int status) { 98 if (status) { 99 fprintf(stderr, "Send error %s\n", uv_strerror(status)); 100 return; 101 } 102 } 103 104 int main() { 105 loop = uv_default_loop(); 106 107 uv_udp_init(loop, &recv_socket); 108 struct sockaddr_in recv_addr; 109 uv_ip4_addr("0.0.0.0", 68, &recv_addr); 110 uv_udp_bind(&recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR); 111 uv_udp_recv_start(&recv_socket, alloc_buffer, on_read); 112 113 uv_udp_init(loop, &send_socket); 114 struct sockaddr_in broadcast_addr; 115 uv_ip4_addr("0.0.0.0", 0, &broadcast_addr); 116 uv_udp_bind(&send_socket, (const struct sockaddr *)&broadcast_addr, 0); 117 uv_udp_set_broadcast(&send_socket, 1); 118 119 uv_udp_send_t send_req; 120 uv_buf_t discover_msg = make_discover_msg(); 121 122 struct sockaddr_in send_addr; 123 uv_ip4_addr("255.255.255.255", 67, &send_addr); 124 uv_udp_send(&send_req, &send_socket, &discover_msg, 1, (const struct sockaddr *)&send_addr, on_send); 125 126 return uv_run(loop, UV_RUN_DEFAULT); 127 } 128