1 #include "kvm/uip.h" 2 3 #include <arpa/inet.h> 4 5 static inline bool uip_dhcp_is_discovery(struct uip_dhcp *dhcp) 6 { 7 return (dhcp->option[2] == UIP_DHCP_DISCOVER && 8 dhcp->option[1] == UIP_DHCP_TAG_MSG_TYPE_LEN && 9 dhcp->option[0] == UIP_DHCP_TAG_MSG_TYPE); 10 } 11 12 static inline bool uip_dhcp_is_request(struct uip_dhcp *dhcp) 13 { 14 return (dhcp->option[2] == UIP_DHCP_REQUEST && 15 dhcp->option[1] == UIP_DHCP_TAG_MSG_TYPE_LEN && 16 dhcp->option[0] == UIP_DHCP_TAG_MSG_TYPE); 17 } 18 19 bool uip_udp_is_dhcp(struct uip_udp *udp) 20 { 21 struct uip_dhcp *dhcp; 22 23 if (ntohs(udp->sport) != UIP_DHCP_PORT_CLIENT || 24 ntohs(udp->dport) != UIP_DHCP_PORT_SERVER) 25 return false; 26 27 dhcp = (struct uip_dhcp *)udp; 28 29 if (ntohl(dhcp->magic_cookie) != UIP_DHCP_MAGIC_COOKIE) 30 return false; 31 32 return true; 33 } 34 35 int uip_dhcp_get_dns(struct uip_info *info) 36 { 37 char key[256], val[256]; 38 struct in_addr addr; 39 int ret = -1; 40 int n = 0; 41 FILE *fp; 42 u32 ip; 43 44 fp = fopen("/etc/resolv.conf", "r"); 45 if (!fp) 46 goto out; 47 48 while (!feof(fp)) { 49 if (fscanf(fp, "%s %s\n", key, val) != 2) 50 continue; 51 if (strncmp("domain", key, 6) == 0) 52 info->domain_name = strndup(val, UIP_DHCP_MAX_DOMAIN_NAME_LEN); 53 else if (strncmp("nameserver", key, 10) == 0) { 54 if (!inet_aton(val, &addr)) 55 continue; 56 ip = ntohl(addr.s_addr); 57 if (n < UIP_DHCP_MAX_DNS_SERVER_NR) 58 info->dns_ip[n++] = ip; 59 ret = 0; 60 } 61 } 62 63 out: 64 fclose(fp); 65 return ret; 66 } 67 68 static int uip_dhcp_fill_option_name_and_server(struct uip_info *info, u8 *opt, int i) 69 { 70 u8 domain_name_len; 71 u32 *addr; 72 int n; 73 74 if (info->domain_name) { 75 domain_name_len = strlen(info->domain_name); 76 opt[i++] = UIP_DHCP_TAG_DOMAIN_NAME; 77 opt[i++] = domain_name_len; 78 memcpy(&opt[i], info->domain_name, domain_name_len); 79 i += domain_name_len; 80 } 81 82 for (n = 0; n < UIP_DHCP_MAX_DNS_SERVER_NR; n++) { 83 if (info->dns_ip[n] == 0) 84 continue; 85 opt[i++] = UIP_DHCP_TAG_DNS_SERVER; 86 opt[i++] = UIP_DHCP_TAG_DNS_SERVER_LEN; 87 addr = (u32 *)&opt[i]; 88 *addr = htonl(info->dns_ip[n]); 89 i += UIP_DHCP_TAG_DNS_SERVER_LEN; 90 } 91 92 return i; 93 } 94 static int uip_dhcp_fill_option(struct uip_info *info, struct uip_dhcp *dhcp, int reply_msg_type) 95 { 96 int i = 0; 97 u32 *addr; 98 u8 *opt; 99 100 opt = dhcp->option; 101 102 opt[i++] = UIP_DHCP_TAG_MSG_TYPE; 103 opt[i++] = UIP_DHCP_TAG_MSG_TYPE_LEN; 104 opt[i++] = reply_msg_type; 105 106 opt[i++] = UIP_DHCP_TAG_SERVER_ID; 107 opt[i++] = UIP_DHCP_TAG_SERVER_ID_LEN; 108 addr = (u32 *)&opt[i]; 109 *addr = htonl(info->host_ip); 110 i += UIP_DHCP_TAG_SERVER_ID_LEN; 111 112 opt[i++] = UIP_DHCP_TAG_LEASE_TIME; 113 opt[i++] = UIP_DHCP_TAG_LEASE_TIME_LEN; 114 addr = (u32 *)&opt[i]; 115 *addr = htonl(UIP_DHCP_LEASE_TIME); 116 i += UIP_DHCP_TAG_LEASE_TIME_LEN; 117 118 opt[i++] = UIP_DHCP_TAG_SUBMASK; 119 opt[i++] = UIP_DHCP_TAG_SUBMASK_LEN; 120 addr = (u32 *)&opt[i]; 121 *addr = htonl(info->guest_netmask); 122 i += UIP_DHCP_TAG_SUBMASK_LEN; 123 124 opt[i++] = UIP_DHCP_TAG_ROUTER; 125 opt[i++] = UIP_DHCP_TAG_ROUTER_LEN; 126 addr = (u32 *)&opt[i]; 127 *addr = htonl(info->host_ip); 128 i += UIP_DHCP_TAG_ROUTER_LEN; 129 130 i = uip_dhcp_fill_option_name_and_server(info, opt, i); 131 132 opt[i++] = UIP_DHCP_TAG_END; 133 134 return 0; 135 } 136 137 static int uip_dhcp_make_pkg(struct uip_info *info, struct uip_udp_socket *sk, struct uip_buf *buf, u8 reply_msg_type) 138 { 139 struct uip_dhcp *dhcp; 140 141 dhcp = (struct uip_dhcp *)buf->eth; 142 143 dhcp->msg_type = 2; 144 dhcp->client_ip = 0; 145 dhcp->your_ip = htonl(info->guest_ip); 146 dhcp->server_ip = htonl(info->host_ip); 147 dhcp->agent_ip = 0; 148 149 uip_dhcp_fill_option(info, dhcp, reply_msg_type); 150 151 sk->sip = htonl(info->guest_ip); 152 sk->dip = htonl(info->host_ip); 153 sk->sport = htons(UIP_DHCP_PORT_CLIENT); 154 sk->dport = htons(UIP_DHCP_PORT_SERVER); 155 156 return 0; 157 } 158