kvm tools: Add ivshmem device
[linux-2.6/next.git] / tools / kvm / net / uip / dhcp.c
blobbd3c53ba1416e08b1de9cd9254028db1b3e81a15
1 #include "kvm/uip.h"
3 #include <arpa/inet.h>
5 static inline bool uip_dhcp_is_discovery(struct uip_dhcp *dhcp)
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);
12 static inline bool uip_dhcp_is_request(struct uip_dhcp *dhcp)
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);
19 bool uip_udp_is_dhcp(struct uip_udp *udp)
21 struct uip_dhcp *dhcp;
23 if (ntohs(udp->sport) != UIP_DHCP_PORT_CLIENT ||
24 ntohs(udp->dport) != UIP_DHCP_PORT_SERVER)
25 return false;
27 dhcp = (struct uip_dhcp *)udp;
29 if (ntohl(dhcp->magic_cookie) != UIP_DHCP_MAGIC_COOKIE)
30 return false;
32 return true;
35 int uip_dhcp_get_dns(struct uip_info *info)
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;
44 fp = fopen("/etc/resolv.conf", "r");
45 if (!fp)
46 goto out;
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;
63 out:
64 fclose(fp);
65 return ret;
68 static int uip_dhcp_fill_option_name_and_server(struct uip_info *info, u8 *opt, int i)
70 u8 domain_name_len;
71 u32 *addr;
72 int n;
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;
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;
92 return i;
94 static int uip_dhcp_fill_option(struct uip_info *info, struct uip_dhcp *dhcp, int reply_msg_type)
96 int i = 0;
97 u32 *addr;
98 u8 *opt;
100 opt = dhcp->option;
102 opt[i++] = UIP_DHCP_TAG_MSG_TYPE;
103 opt[i++] = UIP_DHCP_TAG_MSG_TYPE_LEN;
104 opt[i++] = reply_msg_type;
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;
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;
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;
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;
130 i = uip_dhcp_fill_option_name_and_server(info, opt, i);
132 opt[i++] = UIP_DHCP_TAG_END;
134 return 0;
137 static int uip_dhcp_make_pkg(struct uip_info *info, struct uip_udp_socket *sk, struct uip_buf *buf, u8 reply_msg_type)
139 struct uip_dhcp *dhcp;
141 dhcp = (struct uip_dhcp *)buf->eth;
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;
149 uip_dhcp_fill_option(info, dhcp, reply_msg_type);
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);
156 return 0;
159 int uip_tx_do_ipv4_udp_dhcp(struct uip_tx_arg *arg)
161 struct uip_udp_socket sk;
162 struct uip_dhcp *dhcp;
163 struct uip_info *info;
164 struct uip_buf *buf;
165 u8 reply_msg_type;
167 dhcp = (struct uip_dhcp *)arg->eth;
169 if (uip_dhcp_is_discovery(dhcp))
170 reply_msg_type = UIP_DHCP_OFFER;
171 else if (uip_dhcp_is_request(dhcp))
172 reply_msg_type = UIP_DHCP_ACK;
173 else
174 return -1;
176 buf = uip_buf_clone(arg);
177 info = arg->info;
180 * Cook DHCP pkg
182 uip_dhcp_make_pkg(info, &sk, buf, reply_msg_type);
185 * Cook UDP pkg
187 uip_udp_make_pkg(info, &sk, buf, NULL, UIP_DHCP_MAX_PAYLOAD_LEN);
190 * Send data received from socket to guest
192 uip_buf_set_used(info, buf);
194 return 0;