xref: /kvmtool/net/uip/dhcp.c (revision 32a44aaf031f433fb1b12e08156a84414f426aa9)
10c4bfcacSAsias He #include "kvm/uip.h"
20c4bfcacSAsias He 
3bdcc9e40SAsias He #include <arpa/inet.h>
4bdcc9e40SAsias He 
58f5f2f95SAsias He static inline bool uip_dhcp_is_discovery(struct uip_dhcp *dhcp)
68f5f2f95SAsias He {
78f5f2f95SAsias He 	return (dhcp->option[2] == UIP_DHCP_DISCOVER &&
88f5f2f95SAsias He 		dhcp->option[1] == UIP_DHCP_TAG_MSG_TYPE_LEN &&
98f5f2f95SAsias He 		dhcp->option[0] == UIP_DHCP_TAG_MSG_TYPE);
108f5f2f95SAsias He }
118f5f2f95SAsias He 
128f5f2f95SAsias He static inline bool uip_dhcp_is_request(struct uip_dhcp *dhcp)
138f5f2f95SAsias He {
148f5f2f95SAsias He 	return (dhcp->option[2] == UIP_DHCP_REQUEST &&
158f5f2f95SAsias He 		dhcp->option[1] == UIP_DHCP_TAG_MSG_TYPE_LEN &&
168f5f2f95SAsias He 		dhcp->option[0] == UIP_DHCP_TAG_MSG_TYPE);
178f5f2f95SAsias He }
188f5f2f95SAsias He 
190c4bfcacSAsias He bool uip_udp_is_dhcp(struct uip_udp *udp)
200c4bfcacSAsias He {
210c4bfcacSAsias He 	struct uip_dhcp *dhcp;
220c4bfcacSAsias He 
230c4bfcacSAsias He 	if (ntohs(udp->sport) != UIP_DHCP_PORT_CLIENT ||
240c4bfcacSAsias He 	    ntohs(udp->dport) != UIP_DHCP_PORT_SERVER)
250c4bfcacSAsias He 		return false;
260c4bfcacSAsias He 
270c4bfcacSAsias He 	dhcp = (struct uip_dhcp *)udp;
280c4bfcacSAsias He 
290c4bfcacSAsias He 	if (ntohl(dhcp->magic_cookie) != UIP_DHCP_MAGIC_COOKIE)
300c4bfcacSAsias He 		return false;
310c4bfcacSAsias He 
320c4bfcacSAsias He 	return true;
330c4bfcacSAsias He }
34bdcc9e40SAsias He 
35bdcc9e40SAsias He int uip_dhcp_get_dns(struct uip_info *info)
36bdcc9e40SAsias He {
37bdcc9e40SAsias He 	char key[256], val[256];
38bdcc9e40SAsias He 	struct in_addr addr;
39bdcc9e40SAsias He 	int ret = -1;
40bdcc9e40SAsias He 	int n = 0;
41bdcc9e40SAsias He 	FILE *fp;
42bdcc9e40SAsias He 	u32 ip;
43bdcc9e40SAsias He 
44bdcc9e40SAsias He 	fp = fopen("/etc/resolv.conf", "r");
45bdcc9e40SAsias He 	if (!fp)
46bdcc9e40SAsias He 		goto out;
47bdcc9e40SAsias He 
48bdcc9e40SAsias He 	while (!feof(fp)) {
49bdcc9e40SAsias He 		if (fscanf(fp, "%s %s\n", key, val) != 2)
50bdcc9e40SAsias He 			continue;
51bdcc9e40SAsias He 		if (strncmp("domain", key, 6) == 0)
52bdcc9e40SAsias He 			info->domain_name = strndup(val, UIP_DHCP_MAX_DOMAIN_NAME_LEN);
53bdcc9e40SAsias He 		else if (strncmp("nameserver", key, 10) == 0) {
54bdcc9e40SAsias He 			if (!inet_aton(val, &addr))
55bdcc9e40SAsias He 				continue;
56bdcc9e40SAsias He 			ip = ntohl(addr.s_addr);
57bdcc9e40SAsias He 			if (n < UIP_DHCP_MAX_DNS_SERVER_NR)
58bdcc9e40SAsias He 				info->dns_ip[n++] = ip;
59bdcc9e40SAsias He 			ret = 0;
60bdcc9e40SAsias He 		}
61bdcc9e40SAsias He 	}
62bdcc9e40SAsias He 
63bdcc9e40SAsias He out:
64bdcc9e40SAsias He 	fclose(fp);
65bdcc9e40SAsias He 	return ret;
66bdcc9e40SAsias He }
67*32a44aafSAsias He 
68*32a44aafSAsias He static int uip_dhcp_fill_option_name_and_server(struct uip_info *info, u8 *opt, int i)
69*32a44aafSAsias He {
70*32a44aafSAsias He 	u8 domain_name_len;
71*32a44aafSAsias He 	u32 *addr;
72*32a44aafSAsias He 	int n;
73*32a44aafSAsias He 
74*32a44aafSAsias He 	if (info->domain_name) {
75*32a44aafSAsias He 		domain_name_len	= strlen(info->domain_name);
76*32a44aafSAsias He 		opt[i++]	= UIP_DHCP_TAG_DOMAIN_NAME;
77*32a44aafSAsias He 		opt[i++]	= domain_name_len;
78*32a44aafSAsias He 		memcpy(&opt[i], info->domain_name, domain_name_len);
79*32a44aafSAsias He 		i		+= domain_name_len;
80*32a44aafSAsias He 	}
81*32a44aafSAsias He 
82*32a44aafSAsias He 	for (n = 0; n < UIP_DHCP_MAX_DNS_SERVER_NR; n++) {
83*32a44aafSAsias He 		if (info->dns_ip[n] == 0)
84*32a44aafSAsias He 			continue;
85*32a44aafSAsias He 		opt[i++]	= UIP_DHCP_TAG_DNS_SERVER;
86*32a44aafSAsias He 		opt[i++]	= UIP_DHCP_TAG_DNS_SERVER_LEN;
87*32a44aafSAsias He 		addr		= (u32 *)&opt[i];
88*32a44aafSAsias He 		*addr		= htonl(info->dns_ip[n]);
89*32a44aafSAsias He 		i		+= UIP_DHCP_TAG_DNS_SERVER_LEN;
90*32a44aafSAsias He 	}
91*32a44aafSAsias He 
92*32a44aafSAsias He 	return i;
93*32a44aafSAsias He }
94