vmm: Make all task functions return void *
[akaros.git] / user / vmm / nat.c
1 /* Copyright (c) 2016 Google Inc
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Network address translation for VM guests.
6  *
7  * There are two styles of addressing: qemu and real-addr.  qemu-style is what
8  * you expect from Qemu's user-mode networking.  real-addr mode uses the same
9  * addresses for the guest as the host uses.
10  *
11  * For qemu-style networking:
12  *              guest = 10.0.2.15, mask = 255.255.255.0, router = 10.0.2.2.
13  * For real-addr networking:
14  *              guest = host_v4, mask = host_mask, router = host's_route
15  *
16  * Real-addr mode is useful for guests that statically config their address from
17  * the nodes hard drive.  It might also help for apps that want to advertise
18  * their IP address to external users (though that would require straight-thru
19  * port-fowardarding set up by the VMM).
20  *
21  * As far as the guest is concerned, the host is the guest_v4_router.  If we
22  * ever get a remote IP addr of 'router', that'll be redirected to the host's
23  * loopback IP.  That means the guest can't reach the "real" router (in
24  * real-addr mode).  The host can reach the guest via 127.0.0.1.  In either
25  * case, use the host's side of a mapping.
26  *
27  * TODO:
28  * - We're working with the IOVs that the guest gave us through virtio.  If we
29  *   care, that whole thing is susceptible to time-of-check attacks.  The guest
30  *   could be modifying the IOV that we're working on, so we need to not care
31  *   too much about that.
32  *
33  * - Consider having the kernel proto bypass outbound path overwrite the src
34  *   address and the proto port.  We don't care about the proto payload.  We
35  *   might care about IP and proto headers.  o/w, the user could fake traffic
36  *   for other ports - basically they can craft whatever packet they want (which
37  *   is what they had previously with unrestricted access to devether).
38  *
39  * - Consider injecting packets to the guest from #srv/snoop-PID.
40  *
41  * - IPv6 support
42  *
43  * FAQ:
44  * - Why are we using FD taps, instead of threads, to watch all the host FD?
45  *   Couldn't we block a uthread on each FD?  I went back and forth on this.
46  *   The final reason for this is to avoid copies and weird joins.  The
47  *   concurrency with the guest is based on the number of IOVs they give us -
48  *   not the number of host conversations open.  We could listen on 1000 convs,
49  *   each with their own read buffer, but we'd then have to copy the entire
50  *   packet into the IOVs the guest gave us.  We'd also need to synchronize on
51  *   access to virtio and do some structural work (draw out how the packets
52  *   would move around).  It'd be different if each uthread could just push
53  *   packets into virtio-net (push vs the current pull model).
54  *
55  * - What's the deal with sending packets to broadcast domain targets?  Short
56  *   answer: the host responds to every ARP request, regardless of the IP.  If
57  *   the networking is done QEMU style, there's only one other host: the router,
58  *   so that's not interesting.  If we are in real-addr mode and the guest is
59  *   trying to reach someone in our broadcast, they'll be told that we
60  *   (host_eth_addr) is the MAC for that addr.  Then the guest sends us an IP
61  *   packet for that target.  Akaros will see an IP packet and will route it to
62  *   its own broadcast (on the real network).  The guest's ARP only matters when
63  *   it comes to getting the packet to us, not the actual network's broadcast
64  *   domain.
65  *
66  * - Why is the RX path single threaded?  So it's possible to rewrite
67  *   __poll_inbound() such that readv() is not called while holding the rx_mtx.
68  *   To do so, we pop the first item off the inbound_todo list (so we have the
69  *   ref), do the read, then put it back on the list if it hasn't been drained
70  *   to empty.  The main issue, apart from being more complicated, is that since
71  *   we're unlocking and relocking, any invariant that we had before calling
72  *   __poll_inbound needs to be rechecked.  Specifically, we would need to check
73  *   __poll_injection *after* returning from __poll_inbound.  Otherwise we could
74  *   sleep with a packet waiting to be injected.  Whoops!  That could have been
75  *   dealt with, but it's subtle.  There also might be races with FD taps
76  *   firing, the fdtap_watcher not putting items on the list, and the thread
77  *   then not putting it on the list.  Specifically:
78  *      fdtap_watcher:                                                  __poll_inbound:
79  *      -------------------------------------------------------
80  *                                                                                      yanks map off list
81  *                                                                                      map tracked as "on inbound"
82  *                                                                                      unlock mtx
83  *                                                                                      readv, get -1 EAGAIN
84  *                                                                                      decide to drop the item
85  *      packet arrives
86  *      FD tap fires
87  *      send event
88  *      lock mtx
89  *      see map is "on inbound"
90  *      ignore event
91  *      unlock mtx
92  *                                                                                      lock mtx
93  *                                                                                      clear "on inbound"
94  *                                                                                      unlock + sleep on CV
95  *   The FD has data, but we lost the event, and we'll never read it.
96  *
97  * - Why is the fdtap_watcher its own thread?  You can't kick a CV from vcore
98  *   context, since you almost always want to hold the MTX while kicking the CV
99  *   (see the lengthy comments in the CV code).  It's easier to blockon an event
100  *   queue as a uthread.  But since the RX thread wants to sleep on two sources,
101  *   it's simpler this way.  It also decouples the inbound_todo list from the
102  *   evq.
103  *
104  * - Could we model the packet injection with an event queue?  Maybe with a UCQ
105  *   or BCQ.  We'd need some support from the kernel (minor) and maybe
106  *   user-level event posting (major) to do it right.  If we did that, we
107  *   probably could get rid of the fdtap_watcher.  The RX checks inbound_todo,
108  *   then blocks on two evqs (inbound and inject).  This way is simpler, for
109  *   now.
110  *
111  * - Why do we rewrite IP addresses for the router to loopback, instead of
112  *   host_v4_addr?  First off, you have to pick one: loopback or host_v4_addr,
113  *   not both.  If we accept both (say, when the host connects to a static map),
114  *   then on the other end (i.e. TX, response to an RX) will need to know which
115  *   option we chose for its rewriting rule.  We have to be consistent with how
116  *   we handle ROUTER_IP and do the same thing in both directions.  Given that
117  *   we have to pick one of them, I opted for 127.0.0.1.  That way, any host
118  *   users know how to connect to the guest without worrying about their actual
119  *   IP address.  This also allows us to announce services on the host that are
120  *   only available to loopback (i.e. not the main network) and let the guest
121  *   reach those.
122  *
123  * - How can a guest reach the real host IP in qemu mode, but not in real-addr
124  *   mode?  This comes up when someone uses a static map but connects with the
125  *   host_v4_addr as the source (which you do by contacting host_v4_addr as the
126  *   *destination* from akaros).  We don't rewrite those on the RX path.  When
127  *   the guest responds, it responds to whatever the src was on the inbound
128  *   path.  To the guest, our host_v4_addr is just another IP, which the host
129  *   knows how to route to.  It'd be similar to the guest trying to reach an
130  *   address that is in the broadcast domain of the host.  This doesn't work for
131  *   real-addr mode, since the guest has the same IP as the host.  Most guests
132  *   won't emit a packet that is sent to their own IP address.  If they did, the
133  *   NAT code would remap it, but the guest just won't send it out.  Hence the
134  *   warning.
135  */
136
137 #include <vmm/net.h>
138 #include <parlib/iovec.h>
139 #include <iplib/iplib.h>
140 #include <parlib/ros_debug.h>
141 #include <parlib/uthread.h>
142 #include <ndblib/ndb.h>
143 #include <iplib/iplib.h>
144 #include <parlib/printf-ext.h>
145 #include <parlib/event.h>
146 #include <parlib/spinlock.h>
147 #include <parlib/kref.h>
148
149 #include <stdlib.h>
150 #include <stdio.h>
151 #include <string.h>
152 #include <unistd.h>
153 #include <assert.h>
154 #include <sys/types.h>
155 #include <sys/stat.h>
156 #include <fcntl.h>
157 #include <sys/queue.h>
158
159 /* Global control variables.  The main VMM sets these manually. */
160 bool vnet_snoop = FALSE;
161 bool vnet_real_ip_addrs = FALSE;
162 bool vnet_map_diagnostics = FALSE;
163 unsigned long vnet_nat_timeout = 200;
164
165 uint8_t host_v4_addr[IPV4_ADDR_LEN];
166 uint8_t host_v4_mask[IPV4_ADDR_LEN];
167 uint8_t host_v4_router[IPV4_ADDR_LEN];
168 uint8_t host_v4_dns[IPV4_ADDR_LEN];
169
170 uint8_t loopback_v4_addr[IPV4_ADDR_LEN];
171 uint8_t bcast_v4_addr[IPV4_ADDR_LEN];
172
173 uint8_t guest_v4_addr[IPV4_ADDR_LEN];
174 uint8_t guest_v4_mask[IPV4_ADDR_LEN];
175 uint8_t guest_v4_router[IPV4_ADDR_LEN];
176 uint8_t guest_v4_dns[IPV4_ADDR_LEN];
177
178 /* We'll use this in all our eth headers with the guest. */
179 uint8_t host_eth_addr[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x0a};
180 uint8_t guest_eth_addr[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x0b};
181 const char dhcp_hostname[] = "host";
182 const char dhcp_guestname[] = "guest";
183
184 int snoop_fd;
185
186 /* We map between host port and guest port for a given protocol.  We don't care
187  * about confirming IP addresses or anything - we just swap ports. */
188 struct ip_nat_map {
189         TAILQ_ENTRY(ip_nat_map)         lookup_tuple;
190         TAILQ_ENTRY(ip_nat_map)         lookup_fd;
191         struct kref                                     kref;
192         uint8_t                                         protocol;
193         uint16_t                                        guest_port;
194         uint16_t                                        host_port;
195         int                                                     host_data_fd;
196         bool                                            is_static;
197         bool                                            is_stale;
198         /* These fields are protected by the rx mutex */
199         TAILQ_ENTRY(ip_nat_map)         inbound;
200         bool                                            is_on_inbound;
201 };
202
203 #define NR_VNET_HASH 128
204 TAILQ_HEAD(ip_nat_map_tailq, ip_nat_map);
205 struct spin_pdr_lock maps_lock = SPINPDR_INITIALIZER;
206 /* Two hash tables: one for tuples (tx) and one for FD (rx).  There's one kref
207  * for being in both tables; they are treated as a unit. */
208 struct ip_nat_map_tailq map_hash_tuple[NR_VNET_HASH];
209 struct ip_nat_map_tailq map_hash_fd[NR_VNET_HASH];
210
211 /* The todo list, used to track FDs that had activity but haven't told us EAGAIN
212  * yet.  The list is protected by the rx_mtx */
213 struct ip_nat_map_tailq inbound_todo = TAILQ_HEAD_INITIALIZER(inbound_todo);
214
215 /* buf_pkt: tracks a packet, used for injecting packets (usually synthetic
216  * responses) into the guest via receive_packet. */
217 struct buf_pkt {
218         STAILQ_ENTRY(buf_pkt)           next;
219         uint8_t                                         *buf;
220         size_t                                          sz;
221 };
222 STAILQ_HEAD(buf_pkt_stailq, buf_pkt);
223
224 struct buf_pkt_stailq inject_pkts = STAILQ_HEAD_INITIALIZER(inject_pkts);
225 uth_mutex_t *rx_mtx;
226 uth_cond_var_t *rx_cv;
227 struct event_queue *inbound_evq;
228
229 static void tap_inbound_conv(int fd);
230
231 #define GOLDEN_RATIO_64 0x61C8864680B583EBull
232
233 static struct ip_nat_map_tailq *list_hash_tuple(uint8_t protocol,
234                                                 uint16_t guest_port)
235 {
236         size_t idx;
237
238         idx = ((protocol << 16 | guest_port) * GOLDEN_RATIO_64) % NR_VNET_HASH;
239         return &map_hash_tuple[idx];
240 }
241
242 static struct ip_nat_map_tailq *list_hash_fd(int host_data_fd)
243 {
244         size_t idx;
245
246         idx = (host_data_fd * GOLDEN_RATIO_64) % NR_VNET_HASH;
247         return &map_hash_fd[idx];
248 }
249
250 /* Returnes a refcnted map. */
251 static struct ip_nat_map *lookup_map_by_tuple(uint8_t protocol,
252                                               uint16_t guest_port)
253 {
254         struct ip_nat_map *i;
255
256         spin_pdr_lock(&maps_lock);
257         TAILQ_FOREACH(i, list_hash_tuple(protocol, guest_port), lookup_tuple) {
258                 if ((i->protocol == protocol) && (i->guest_port == guest_port)) {
259                         kref_get(&i->kref, 1);
260                         break;
261                 }
262         }
263         spin_pdr_unlock(&maps_lock);
264         return i;
265 }
266
267 static struct ip_nat_map *lookup_map_by_hostfd(int host_data_fd)
268 {
269         struct ip_nat_map *i;
270
271         spin_pdr_lock(&maps_lock);
272         TAILQ_FOREACH(i, list_hash_fd(host_data_fd), lookup_fd) {
273                 if (i->host_data_fd == host_data_fd) {
274                         kref_get(&i->kref, 1);
275                         break;
276                 }
277         }
278         spin_pdr_unlock(&maps_lock);
279         return i;
280 }
281
282 /* Stores the ref to the map in the global lookup 'table.' */
283 static void add_map(struct ip_nat_map *map)
284 {
285         spin_pdr_lock(&maps_lock);
286         TAILQ_INSERT_HEAD(list_hash_tuple(map->protocol, map->guest_port),
287                           map, lookup_tuple);
288         TAILQ_INSERT_HEAD(list_hash_fd(map->host_data_fd), map, lookup_fd);
289         spin_pdr_unlock(&maps_lock);
290 }
291
292 static void map_release(struct kref *kref)
293 {
294         struct ip_nat_map *map = container_of(kref, struct ip_nat_map, kref);
295
296         close(map->host_data_fd);
297         free(map);
298 }
299
300 /* Creates a reference counted ip_nat_map for protocol between guest_port and
301  * host_port.  Static mappings are ones that never expire, such as a port
302  * forwarding.  Caller should add it to the lookup structure.
303  *
304  * For the host port, pass "*" for any port, like in a dialstring. */
305 static struct ip_nat_map *create_map(uint8_t protocol, uint16_t guest_port,
306                                      char *host_port, bool is_static)
307 {
308         struct ip_nat_map *map;
309         char dialstring[128];
310         char conv_dir[NETPATHLEN];
311         char *proto_str;
312         int bypass_fd;
313         bool port_check;
314
315         map = malloc(sizeof(struct ip_nat_map));
316         assert(map);
317         kref_init(&map->kref, map_release, 1);
318         map->protocol = protocol;
319         map->guest_port = guest_port;
320         map->is_static = is_static;
321         map->is_stale = FALSE;
322         map->is_on_inbound = FALSE;
323
324         switch (protocol) {
325         case IP_UDPPROTO:
326                 proto_str = "udp";
327                 break;
328         case IP_TCPPROTO:
329                 proto_str = "tcp";
330                 break;
331         default:
332                 panic("get_map for unsupported protocol %d!", protocol);
333         }
334         snprintf(dialstring, sizeof(dialstring), "%s!*!%s", proto_str, host_port);
335
336         bypass_fd = bypass9(dialstring, conv_dir, 0);
337         if (bypass_fd < 0) {
338                 fprintf(stderr, "Failed to clone a conv for %s:%d (%r), won't bypass!\n",
339                         proto_str, guest_port);
340                 free(map);
341                 return NULL;
342         }
343
344         port_check = get_port9(conv_dir, "local", &map->host_port);
345         parlib_assert_perror(port_check);
346
347         map->host_data_fd = open_data_fd9(conv_dir, O_NONBLOCK);
348         parlib_assert_perror(map->host_data_fd >= 0);
349
350         tap_inbound_conv(map->host_data_fd);
351
352         close(bypass_fd);
353         return map;
354 }
355
356 /* Looks up or creates an ip_nat_map for the given proto/port tuple. */
357 static struct ip_nat_map *get_map_by_tuple(uint8_t protocol,
358                                            uint16_t guest_port)
359 {
360         struct ip_nat_map *map;
361
362         map = lookup_map_by_tuple(protocol, guest_port);
363         if (map)
364                 return map;
365         map = create_map(protocol, guest_port, "*", FALSE);
366         if (!map)
367                 return NULL;
368         kref_get(&map->kref, 1);
369         add_map(map);
370         return map;
371 }
372
373 static void *map_reaper(void *arg)
374 {
375         struct ip_nat_map *i, *temp;
376         struct ip_nat_map_tailq to_release;
377
378         while (1) {
379                 uthread_sleep(vnet_nat_timeout);
380                 TAILQ_INIT(&to_release);
381                 spin_pdr_lock(&maps_lock);
382                 /* Only need to scan one map_hash, might as well be the tuple */
383                 for (int j = 0; j < NR_VNET_HASH; j++) {
384                         TAILQ_FOREACH_SAFE(i, &map_hash_tuple[j], lookup_tuple, temp) {
385                                 if (i->is_static)
386                                         continue;
387                                 if (!i->is_stale) {
388                                         i->is_stale = TRUE;
389                                         continue;
390                                 }
391                                 /* Remove from both lists, hashing for the FD list */
392                                 TAILQ_REMOVE(&map_hash_tuple[j], i, lookup_tuple);
393                                 TAILQ_REMOVE(list_hash_fd(i->host_data_fd), i, lookup_fd);
394                                 /* Use the lookup_tuple for the temp list */
395                                 TAILQ_INSERT_HEAD(&to_release, i, lookup_tuple);
396                         }
397                 }
398                 spin_pdr_unlock(&maps_lock);
399                 TAILQ_FOREACH_SAFE(i, &to_release, lookup_tuple, temp)
400                         kref_put(&i->kref);
401         }
402         return 0;
403 }
404
405 static void map_dumper(void)
406 {
407         struct ip_nat_map *i;
408
409         fprintf(stderr, "\n\nVNET NAT maps:\n---------------\n");
410         spin_pdr_lock(&maps_lock);
411         for (int j = 0; j < NR_VNET_HASH; j++) {
412                 TAILQ_FOREACH(i, &map_hash_tuple[j], lookup_tuple) {
413                         fprintf(stderr, "\tproto %2d, host %5d, guest %5d, FD %4d, stale %d, static %d, ref %d\n",
414                                 i->protocol, i->host_port, i->guest_port, i->host_data_fd,
415                                 i->is_stale, i->is_static, i->kref.refcnt);
416                 }
417         }
418         spin_pdr_unlock(&maps_lock);
419 }
420
421 static void init_map_lookup(struct virtual_machine *vm)
422 {
423         for (int i = 0; i < NR_VNET_HASH; i++)
424                 TAILQ_INIT(&map_hash_tuple[i]);
425         for (int i = 0; i < NR_VNET_HASH; i++)
426                 TAILQ_INIT(&map_hash_fd[i]);
427         vmm_run_task(vm, map_reaper, NULL);
428 }
429
430 static struct buf_pkt *zalloc_bpkt(size_t size)
431 {
432         struct buf_pkt *bpkt;
433
434         bpkt = malloc(sizeof(struct buf_pkt));
435         assert(bpkt);
436         bpkt->sz = size;
437         bpkt->buf = malloc(bpkt->sz);
438         assert(bpkt->buf);
439         memset(bpkt->buf, 0, bpkt->sz);
440         return bpkt;
441 }
442
443 static void free_bpkt(struct buf_pkt *bpkt)
444 {
445         free(bpkt->buf);
446         free(bpkt);
447 }
448
449 /* Queues a buf_pkt, which the rx thread will inject when it wakes. */
450 static void inject_buf_pkt(struct buf_pkt *bpkt)
451 {
452         uth_mutex_lock(rx_mtx);
453         STAILQ_INSERT_TAIL(&inject_pkts, bpkt, next);
454         uth_mutex_unlock(rx_mtx);
455         uth_cond_var_broadcast(rx_cv);
456 }
457
458 /* Helper for xsum_update, mostly for paranoia with integer promotion and
459  * cleanly keeping variables as u16. */
460 static uint16_t ones_comp(uint16_t x)
461 {
462         return ~x;
463 }
464
465 /* IP checksum updater.  If you change amt bytes in a packet from old to new,
466  * this updates the xsum at xsum_off in the iov.
467  *
468  * Assumes a few things:
469  * - there's a 16 byte xsum at xsum_off
470  * - amt is a multiple of two
471  * - the data at *old and *new is network (big) endian
472  *
473  * There's no assumption about the alignment of old and new, thanks to Plan 9's
474  * sensible nhgets() (just byte accesses, not assuming u16 alignment).
475  *
476  * See RFC 1624 for the math.  I opted for Eqn 3, instead of 4, since I didn't
477  * want to deal with subtraction underflow / carry / etc.  Also note that we
478  * need to do the intermediate carry before doing the one's comp.  That wasn't
479  * clear from the RFC either.  RFC 1141 didn't need to do that, since they
480  * didn't complement the intermediate HC (xsum). */
481 static void xsum_update(struct iovec *iov, int iovcnt, size_t xsum_off,
482                         uint8_t *old, uint8_t *new, size_t amt)
483 {
484         uint32_t xsum;
485
486         assert(amt % 2 == 0);
487         xsum = iov_get_be16(iov, iovcnt, xsum_off);
488         /* for each short: HC' = ~(~HC + ~m + m') (' == new, ~ == ones-comp) */
489         for (int i = 0; i < amt / 2; i++, old += 2, new += 2) {
490                 xsum = ones_comp(xsum) + ones_comp(nhgets(old)) + nhgets(new);
491                 /* Need to deal with the carry for any additions, before the outer ~()
492                  * operation.  (Not mentioned in the RFC, determined manually...) */
493                 while (xsum >> 16)
494                         xsum = (xsum & 0xffff) + (xsum >> 16);
495                 /* Yes, next time around the loop we ones comp right back.  Not worth
496                  * optimizing. */
497                 xsum = ones_comp(xsum);
498         }
499         iov_put_be16(iov, iovcnt, xsum_off, xsum);
500 }
501
502 static void snoop_on_virtio(void)
503 {
504         int ret;
505         int srv_fd, pipe_dir_fd, pipe_ctl_fd, pipe_srv_fd, pipe_snoop_fd;
506         const char cmd[] = "oneblock";
507         char buf[MAX_PATH_LEN];
508
509         pipe_dir_fd = open("#pipe", O_PATH);
510         parlib_assert_perror(pipe_dir_fd >= 0);
511
512         pipe_ctl_fd = openat(pipe_dir_fd, "ctl", O_RDWR);
513         parlib_assert_perror(pipe_ctl_fd >= 0);
514         ret = write(pipe_ctl_fd, cmd, sizeof(cmd));
515         parlib_assert_perror(ret == sizeof(cmd));
516         close(pipe_ctl_fd);
517
518         pipe_snoop_fd = openat(pipe_dir_fd, "data", O_RDWR);
519         parlib_assert_perror(pipe_snoop_fd >= 0);
520         ret = fcntl(pipe_snoop_fd, F_SETFL, O_NONBLOCK);
521         parlib_assert_perror(!ret);
522         snoop_fd = pipe_snoop_fd;
523
524         pipe_srv_fd = openat(pipe_dir_fd, "data1", O_RDWR);
525         parlib_assert_perror(pipe_srv_fd >= 0);
526         ret = snprintf(buf, sizeof(buf), "#srv/%s-%d", "snoop", getpid());
527         /* We don't close srv_fd here.  When we exit, it'll close and remove. */
528         srv_fd = open(buf, O_RDWR | O_EXCL | O_CREAT | O_REMCLO, 0444);
529         parlib_assert_perror(srv_fd >= 0);
530         ret = snprintf(buf, sizeof(buf), "%d", pipe_srv_fd);
531         ret = write(srv_fd, buf, ret);
532         parlib_assert_perror(ret > 0);
533         close(pipe_srv_fd);
534 }
535
536 /* Gets the host's IPv4 information from iplib and ndb. */
537 static void get_host_ip_addrs(void)
538 {
539         struct ndb *ndb;
540         struct ndbtuple *nt;
541         char *dns = "dns";
542         char my_ip_str[40];
543         char buf[128];
544         struct ipifc *to_free;
545         struct iplifc *lifc;
546         int ret;
547         uint8_t router_ip[IPaddrlen];
548
549         register_printf_specifier('i', printf_ipaddr, printf_ipaddr_info);
550         register_printf_specifier('M', printf_ipmask, printf_ipmask_info);
551
552         lifc = get_first_noloop_iplifc(NULL, &to_free);
553         if (!lifc) {
554                 fprintf(stderr, "IP addr lookup failed (%r), no VM networking\n");
555                 return;
556         }
557         snprintf(my_ip_str, sizeof(my_ip_str), "%i", lifc->ip);
558         snprintf(buf, sizeof(buf), "%i%M", lifc->ip, lifc->mask);
559         v4parsecidr(host_v4_addr, host_v4_mask, buf);
560         free_ipifc(to_free);
561
562         ret = my_router_addr(router_ip, NULL);
563         if (ret) {
564                 fprintf(stderr, "Router lookup failed (%r), no VM networking\n");
565                 return;
566         }
567         v6tov4(host_v4_router, router_ip);
568
569         ndb = ndbopen("/net/ndb");
570         if (!ndb) {
571                 fprintf(stderr, "NDB open failed (%r), no VM networking\n");
572                 return;
573         }
574         nt = ndbipinfo(ndb, "ip", my_ip_str, &dns, 1);
575         if (!nt) {
576                 fprintf(stderr, "DNS server lookup failed (%r), no VM networking\n");
577                 return;
578         }
579         v4parseip(host_v4_dns, nt->val);
580         ndbfree(nt);
581         ndbclose(ndb);
582 }
583
584 static void set_ip_addrs(void)
585 {
586         get_host_ip_addrs();
587
588         loopback_v4_addr[0] = 127;
589         loopback_v4_addr[1] = 0;
590         loopback_v4_addr[2] = 0;
591         loopback_v4_addr[3] = 1;
592
593         bcast_v4_addr[0] = 255;
594         bcast_v4_addr[1] = 255;
595         bcast_v4_addr[2] = 255;
596         bcast_v4_addr[3] = 255;
597
598         /* even in qemu mode, the guest gets the real DNS IP */
599         memcpy(guest_v4_dns, host_v4_dns, IPV4_ADDR_LEN);
600
601         if (vnet_real_ip_addrs) {
602                 memcpy(guest_v4_addr, host_v4_addr, IPV4_ADDR_LEN);
603                 memcpy(guest_v4_mask, host_v4_mask, IPV4_ADDR_LEN);
604                 memcpy(guest_v4_router, host_v4_router, IPV4_ADDR_LEN);
605         } else {
606                 guest_v4_addr[0] = 10;
607                 guest_v4_addr[1] = 0;
608                 guest_v4_addr[2] = 2;
609                 guest_v4_addr[3] = 15;
610
611                 guest_v4_mask[0] = 255;
612                 guest_v4_mask[1] = 255;
613                 guest_v4_mask[2] = 255;
614                 guest_v4_mask[3] = 0;
615
616                 guest_v4_router[0] = 10;
617                 guest_v4_router[1] = 0;
618                 guest_v4_router[2] = 2;
619                 guest_v4_router[3] = 2;
620         }
621 }
622
623 static void tap_inbound_conv(int fd)
624 {
625         struct fd_tap_req tap_req = {0};
626         int ret;
627
628         tap_req.fd = fd;
629         tap_req.cmd = FDTAP_CMD_ADD;
630         tap_req.filter = FDTAP_FILT_READABLE;
631         tap_req.ev_q = inbound_evq;
632         tap_req.ev_id = fd;
633         tap_req.data = NULL;
634         ret = sys_tap_fds(&tap_req, 1);
635         parlib_assert_perror(ret == 1);
636 }
637
638 /* For every FD tap that fires, make sure the map is on the inbound_todo list
639  * and kick the receiver.
640  *
641  * A map who's FD fires might already be on the list - it's possible for an FD
642  * to drain to 0 and get another packet (thus triggering a tap) before
643  * __poll_inbound() notices and removes it from the list. */
644 static void *fdtap_watcher(void *arg)
645 {
646         struct event_msg msg[1];
647         struct ip_nat_map *map;
648
649         while (1) {
650                 uth_blockon_evqs(msg, NULL, 1, inbound_evq);
651                 map = lookup_map_by_hostfd(msg->ev_type);
652                 /* Could get an event for an FD/map that has since been reaped. */
653                 if (!map)
654                         continue;
655                 uth_mutex_lock(rx_mtx);
656                 if (!map->is_on_inbound) {
657                         map->is_on_inbound = TRUE;
658                         TAILQ_INSERT_TAIL(&inbound_todo, map, inbound);
659                         uth_cond_var_broadcast(rx_cv);
660                 } else {
661                         kref_put(&map->kref);
662                 }
663                 uth_mutex_unlock(rx_mtx);
664         }
665         return 0;
666 }
667
668 static struct event_queue *get_inbound_evq(void)
669 {
670         struct event_queue *ceq;
671
672         ceq = get_eventq_raw();
673         ceq->ev_mbox->type = EV_MBOX_CEQ;
674         ceq_init(&ceq->ev_mbox->ceq, CEQ_OR, NR_FILE_DESC_MAX, 128);
675         /* As far as flags go, we might not want IPI in the future.  Depends on some
676          * longer range VMM/2LS changes.  Regarding INDIR, if you want to find out
677          * about the event (i.e. not poll) for non-VCPD mboxes (like this evq's
678          * mbox), then you need INDIR.  We need that for the wakeup/blockon. */
679         ceq->ev_flags = EVENT_INDIR | EVENT_SPAM_INDIR | EVENT_WAKEUP | EVENT_IPI;
680         evq_attach_wakeup_ctlr(ceq);
681         return ceq;
682 }
683
684 void vnet_port_forward(char *protocol, char *host_port, char *guest_port)
685 {
686         struct ip_nat_map *map;
687         uint8_t proto_nr;
688
689         if (!strcmp("udp", protocol)) {
690                 proto_nr = IP_UDPPROTO;
691         } else if (!strcmp("tcp", protocol)) {
692                 proto_nr = IP_TCPPROTO;
693         } else {
694                 fprintf(stderr, "Can't port forward protocol %s\n", protocol);
695                 return;
696         }
697         map = create_map(proto_nr, atoi(guest_port), host_port, TRUE);
698         if (!map) {
699                 fprintf(stderr, "Failed to set up port forward!");
700                 exit(-1);
701         }
702         add_map(map);
703 }
704
705 static void ev_handle_diag(struct event_msg *ev_msg, unsigned int ev_type,
706                            void *data)
707 {
708         map_dumper();
709 }
710
711 void vnet_init(struct virtual_machine *vm, struct virtio_vq_dev *vqdev)
712 {
713         set_ip_addrs();
714         virtio_net_set_mac(vqdev, guest_eth_addr);
715         rx_mtx = uth_mutex_alloc();
716         rx_cv = uth_cond_var_alloc();
717         if (vnet_snoop)
718                 snoop_on_virtio();
719         init_map_lookup(vm);
720         inbound_evq = get_inbound_evq();
721         vmm_run_task(vm, fdtap_watcher, NULL);
722         if (vnet_map_diagnostics)
723                 register_ev_handler(EV_FREE_APPLE_PIE, ev_handle_diag, NULL);
724 }
725
726 /* Good DHCP reference:
727  * http://www.tcpipguide.com/free/t_TCPIPDynamicHostConfigurationProtocolDHCP.htm
728  */
729 #define DHCP_MAX_OPT_LEN 200
730 #define DHCP_MAIN_BODY_LEN 236
731 #define DHCP_RSP_LEN (DHCP_MAIN_BODY_LEN + DHCP_MAX_OPT_LEN)
732 #define DHCP_LEASE_TIME 3600
733
734 #define DHCP_OP_REQ                             1
735 #define DHCP_OP_RSP                             2
736
737 #define DHCP_MSG_DISCOVER               1
738 #define DHCP_MSG_OFFER                  2
739 #define DHCP_MSG_REQUEST                3
740 #define DHCP_MSG_DECLINE                4
741 #define DHCP_MSG_ACK                    5
742 #define DHCP_MSG_NAK                    6
743 #define DHCP_MSG_RELEASE                7
744 #define DHCP_MSG_INFORM                 8
745
746 #define DHCP_MAGIC_COOKIE_1             0x63
747 #define DHCP_MAGIC_COOKIE_2             0x82
748 #define DHCP_MAGIC_COOKIE_3             0x53
749 #define DHCP_MAGIC_COOKIE_4             0x63
750
751 #define DHCP_OPT_PAD                    0
752 #define DHCP_OPT_SUBNET                 1
753 #define DHCP_OPT_ROUTER                 3
754 #define DHCP_OPT_DNS                    6
755 #define DHCP_OPT_HOSTNAME               12
756 #define DHCP_OPT_LEASE                  51
757 #define DHCP_OPT_MSG_TYPE               53
758 #define DHCP_OPT_SERVER_ID              54
759 #define DHCP_OPT_END_OF_OPT             255
760
761 static int get_dhcp_req_type(struct iovec *iov, int iovcnt)
762 {
763         size_t idx = ETH_HDR_LEN + IPV4_HDR_LEN + UDP_HDR_LEN + DHCP_MAIN_BODY_LEN;
764
765         if (!iov_has_bytes(iov, iovcnt, idx + 4)) {
766                 fprintf(stderr, "DHCP request too short!\n");
767                 return -1;
768         }
769         /* Sanity checks */
770         if ((iov_get_byte(iov, iovcnt, idx + 0) != DHCP_MAGIC_COOKIE_1) ||
771             (iov_get_byte(iov, iovcnt, idx + 1) != DHCP_MAGIC_COOKIE_2) ||
772             (iov_get_byte(iov, iovcnt, idx + 2) != DHCP_MAGIC_COOKIE_3) ||
773             (iov_get_byte(iov, iovcnt, idx + 3) != DHCP_MAGIC_COOKIE_4)) {
774                 fprintf(stderr, "DHCP request didn't have magic cookie!\n");
775                 return -1;
776         }
777         /* Some clients might ask us to look in sname or other locations, which is
778          * communicated by an option.  So far, the clients I've seen just use the
779          * main options to communicate the message type. */
780         idx += 4;
781         while (1) {
782                 if (!iov_has_bytes(iov, iovcnt, idx + 1)) {
783                         fprintf(stderr, "DHCP request too short!\n");
784                         return -1;
785                 }
786                 switch (iov_get_byte(iov, iovcnt, idx)) {
787                 case DHCP_OPT_MSG_TYPE:
788                         if (!iov_has_bytes(iov, iovcnt, idx + 3)) {
789                                 fprintf(stderr, "DHCP request too short!\n");
790                                 return -1;
791                         }
792                         return iov_get_byte(iov, iovcnt, idx + 2);
793                 case DHCP_OPT_PAD:
794                         idx += 1;
795                         break;
796                 case DHCP_OPT_END_OF_OPT:
797                         fprintf(stderr, "DHCP request without a type!\n");
798                         return -1;
799                 default:
800                         if (!iov_has_bytes(iov, iovcnt, idx + 2)) {
801                                 fprintf(stderr, "DHCP request too short!\n");
802                                 return -1;
803                         }
804                         /* idx + 1 is size of the payload.  Skip the opt, size, payload. */
805                         idx += 2 + iov_get_byte(iov, iovcnt, idx + 1);
806                         break;
807                 }
808         }
809 }
810
811 static size_t build_dhcp_response(struct iovec *iov, int iovcnt, uint8_t *buf)
812 {
813         uint8_t *p = buf;
814         int req_type;
815
816         *p++ = DHCP_OP_RSP;
817         *p++ = ETH_HTYPE_ETH;
818         *p++ = ETH_ADDR_LEN;
819         *p++ = 0x00;    /* hops */
820         /* TODO: copies XID; assumes the inbound packet had standard headers */
821         iov_memcpy_from(iov, iovcnt, ETH_HDR_LEN + IPV4_HDR_LEN + UDP_HDR_LEN + 4,
822                         p, 4);
823         p += 4;
824         p += 8;                 /* secs, flags, CIADDR */
825         memcpy(p, guest_v4_addr, IPV4_ADDR_LEN);
826         p += IPV4_ADDR_LEN;
827         memcpy(p, guest_v4_router, IPV4_ADDR_LEN);
828         p += IPV4_ADDR_LEN;
829         memcpy(p, guest_v4_router, IPV4_ADDR_LEN);
830         p += IPV4_ADDR_LEN;
831         iov_memcpy_from(iov, iovcnt, ETH_ADDR_LEN, p, ETH_ADDR_LEN);
832         p += 16;        /* CHaddr has 16 bytes, we only use 6 */
833         memcpy(p, dhcp_hostname, strlen(dhcp_hostname));
834         p += 64;
835         p += 128;
836
837         req_type = get_dhcp_req_type(iov, iovcnt);
838
839         /* DHCP options: Technically, we should be responding with whatever fields
840          * they asked for in their incoming message.  For the most part, there are a
841          * bunch of standard things we can just respond with. */
842
843         *p++ = DHCP_MAGIC_COOKIE_1;
844         *p++ = DHCP_MAGIC_COOKIE_2;
845         *p++ = DHCP_MAGIC_COOKIE_3;
846         *p++ = DHCP_MAGIC_COOKIE_4;
847
848         *p++ = DHCP_OPT_MSG_TYPE;
849         *p++ = 1;
850         switch (req_type) {
851         case DHCP_MSG_DISCOVER:
852                 *p++ = DHCP_MSG_OFFER;
853                 break;
854         case DHCP_MSG_REQUEST:
855                 *p++ = DHCP_MSG_ACK;
856                 break;
857         default:
858                 panic("Unexpected DHCP message type %d", req_type);
859         }
860
861         *p++ = DHCP_OPT_SUBNET;
862         *p++ = 4;
863         memcpy(p, guest_v4_mask, IPV4_ADDR_LEN);
864         p += IPV4_ADDR_LEN;
865
866         *p++ = DHCP_OPT_ROUTER;
867         *p++ = 4;
868         memcpy(p, guest_v4_router, IPV4_ADDR_LEN);
869         p += IPV4_ADDR_LEN;
870
871         *p++ = DHCP_OPT_DNS;
872         *p++ = 4;
873         memcpy(p, guest_v4_dns, IPV4_ADDR_LEN);
874         p += IPV4_ADDR_LEN;
875
876         *p++ = DHCP_OPT_HOSTNAME;
877         *p++ = strlen(dhcp_guestname);  /* not null-terminated */
878         memcpy(p, dhcp_guestname, strlen(dhcp_guestname));
879         p += strlen(dhcp_guestname);
880
881         if (req_type == DHCP_MSG_REQUEST) {
882                 *p++ = DHCP_OPT_LEASE;
883                 *p++ = 4;
884                 hnputl(p, DHCP_LEASE_TIME);
885                 p += 4;
886
887                 *p++ = DHCP_OPT_SERVER_ID;
888                 *p++ = 4;
889                 memcpy(p, guest_v4_dns, IPV4_ADDR_LEN);
890                 p += IPV4_ADDR_LEN;
891
892         }
893
894         *p++ = DHCP_OPT_END_OF_OPT;
895
896         return p - buf;
897 }
898
899 /* Builds a UDP packet responding to IOV with buf of payload_sz.  Sent from
900  * src_port to dst_port.  Returns the new size, including UDP headers. */
901 static size_t build_udp_response(struct iovec *iov, int iovcnt, uint8_t *buf,
902                                  size_t payload_sz,
903                                  uint16_t src_port, uint16_t dst_port)
904 {
905         uint8_t *p = buf;
906
907         hnputs(p, src_port);
908         p += 2;
909         hnputs(p, dst_port);
910         p += 2;
911         hnputs(p, payload_sz + UDP_HDR_LEN);
912         p += 2;
913         /* For v4, we don't need to do the xsum.  It's a minor pain too, since they
914          * xsum parts of the IP header too. */
915         hnputs(p, 0);
916         p += 2;
917
918         return p - buf + payload_sz;
919 }
920
921 /* Builds an IP packet responding to iov with buf of payload_sz.  Sent from->to
922  * with protocol.  Returns the new size, including IP headers.
923  *
924  * We take parameters for the IP, since some usages won't use the iov's IP (e.g.
925  * DHCP). */
926 static size_t build_ip_response(struct iovec *iov, int iovcnt, uint8_t *buf,
927                                 size_t payload_sz, uint8_t *from, uint8_t *to,
928                                 uint8_t protocol)
929 {
930         uint8_t *p = buf;
931         uint8_t *xsum_addr;
932
933         *p = 0x45;              /* version, etc */
934         p += 2;
935         hnputs(p, payload_sz + IPV4_HDR_LEN);
936         p += 2;
937         p += 4;
938         *p = 255;               /* TTL */
939         p += 1;
940         *p = protocol;
941         p += 1;
942         xsum_addr = p;
943         p += 2;
944         memcpy(p, from, IPV4_ADDR_LEN);
945         p += IPV4_ADDR_LEN;
946         memcpy(p, to, IPV4_ADDR_LEN);
947         p += IPV4_ADDR_LEN;
948         hnputs(xsum_addr, ip_calc_xsum(buf, IPV4_HDR_LEN));
949
950         return p - buf + payload_sz;
951 }
952
953 /* Builds an ethernet response to iov from buf of payload_sz.  Returns the new
954  * size, including ethernet headers. */
955 static size_t build_eth_response(struct iovec *iov, int iovcnt, uint8_t *buf,
956                                  size_t payload_sz, uint16_t ether_type)
957 {
958         uint8_t *p = buf;
959
960         iov_memcpy_from(iov, iovcnt, ETH_OFF_SRC, p, ETH_ADDR_LEN);
961         p += ETH_ADDR_LEN;
962         memcpy(p, host_eth_addr, ETH_ADDR_LEN);
963         p += ETH_ADDR_LEN;
964         hnputs(p, ether_type);
965         p += 2;
966
967         return p - buf + payload_sz;
968 }
969
970 static void fake_dhcp_response(struct iovec *iov, int iovcnt)
971 {
972         struct buf_pkt *bpkt;
973         size_t payload_sz;
974
975         switch (get_dhcp_req_type(iov, iovcnt)) {
976         case DHCP_MSG_OFFER:
977         case DHCP_MSG_DECLINE:
978         case DHCP_MSG_ACK:
979         case DHCP_MSG_NAK:
980         case DHCP_MSG_RELEASE:
981         case DHCP_MSG_INFORM:
982                 return;
983         }
984         bpkt = zalloc_bpkt(ETH_HDR_LEN + IPV4_HDR_LEN + UDP_HDR_LEN + DHCP_RSP_LEN);
985
986         payload_sz = build_dhcp_response(iov, iovcnt, bpkt->buf + ETH_HDR_LEN
987                                                       + IPV4_HDR_LEN + UDP_HDR_LEN);
988         payload_sz = build_udp_response(iov, iovcnt,
989                                         bpkt->buf + ETH_HDR_LEN + IPV4_HDR_LEN,
990                                         payload_sz, 67, 68);
991         /* For offers and initial requests, we definitely need to send it to
992          * 255.255.255.255 (bcast).  For renewals, it seems like that that also
993          * suffices, which seems reasonable. */
994         payload_sz = build_ip_response(iov, iovcnt, bpkt->buf + ETH_HDR_LEN,
995                                        payload_sz, guest_v4_router, bcast_v4_addr,
996                                        IP_UDPPROTO);
997         payload_sz = build_eth_response(iov, iovcnt, bpkt->buf, payload_sz,
998                                         ETH_TYPE_IPV4);
999
1000         assert(payload_sz <= bpkt->sz);
1001         bpkt->sz = payload_sz;
1002         inject_buf_pkt(bpkt);
1003 }
1004
1005 static size_t build_arp_response(struct iovec *iov, int iovcnt, uint8_t *buf)
1006 {
1007         uint8_t *p = buf;
1008
1009         hnputs(p, ETH_HTYPE_ETH);
1010         p += 2;
1011         hnputs(p, ETH_TYPE_IPV4);
1012         p += 2;
1013         *p++ = ETH_ADDR_LEN;
1014         *p++ = IPV4_ADDR_LEN;
1015         hnputs(p, ARP_OP_RSP);
1016         p += 2;
1017         /* SHA: addr they are looking for, which is always host's eth addr */
1018         memcpy(p, host_eth_addr, ETH_ADDR_LEN);
1019         p += ETH_ADDR_LEN;
1020         /* SPA: addr they are looking for, which was the request TPA */
1021         iov_memcpy_from(iov, iovcnt, ETH_HDR_LEN + ARP_OFF_TPA, p, IPV4_ADDR_LEN);
1022         p += IPV4_ADDR_LEN;
1023         /* THA was the SHA of the request */
1024         iov_memcpy_from(iov, iovcnt, ETH_HDR_LEN + ARP_OFF_SHA, p, ETH_ADDR_LEN);
1025         p += ETH_ADDR_LEN;
1026         /* TPA was the SPA of the request */
1027         iov_memcpy_from(iov, iovcnt, ETH_HDR_LEN + ARP_OFF_SPA, p, IPV4_ADDR_LEN);
1028         p += IPV4_ADDR_LEN;
1029
1030         return p - buf;
1031 }
1032
1033 static bool should_ignore_arp(struct iovec *iov, int iovcnt)
1034 {
1035         size_t arp_off = ETH_HDR_LEN;
1036
1037         if (iov_get_be16(iov, iovcnt, arp_off + ARP_OFF_OP) != ARP_OP_REQ)
1038                 return TRUE;
1039         /* ARP probes set the SPA to 0.  Ignore these. */
1040         if (iov_get_be32(iov, iovcnt, arp_off + ARP_OFF_SPA) == 0)
1041                 return TRUE;
1042         return FALSE;
1043 }
1044
1045 static void handle_arp_tx(struct iovec *iov, int iovcnt)
1046 {
1047         struct buf_pkt *bpkt;
1048         size_t payload_sz;
1049
1050         if (should_ignore_arp(iov, iovcnt))
1051                 return;
1052         bpkt = zalloc_bpkt(ETH_HDR_LEN + ARP_PKT_LEN);
1053         payload_sz = build_arp_response(iov, iovcnt, bpkt->buf + ETH_HDR_LEN);
1054         payload_sz = build_eth_response(iov, iovcnt, bpkt->buf, payload_sz,
1055                                         ETH_TYPE_ARP);
1056         assert(payload_sz <= bpkt->sz);
1057         bpkt->sz = payload_sz;
1058         inject_buf_pkt(bpkt);
1059 }
1060
1061 /* Helper for protocols: updates an xsum, given a port number change */
1062 static void xsum_changed_port(struct iovec *iov, int iovcnt, size_t xsum_off,
1063                               uint16_t old_port, uint16_t new_port)
1064 {
1065         uint16_t old_port_be, new_port_be;
1066
1067         /* xsum update expects to work on big endian */
1068         hnputs(&old_port_be, old_port);
1069         hnputs(&new_port_be, new_port);
1070         xsum_update(iov, iovcnt, xsum_off, (uint8_t*)&old_port_be,
1071                     (uint8_t*)&new_port_be, 2);
1072 }
1073
1074 static struct ip_nat_map *handle_udp_tx(struct iovec *iov, int iovcnt,
1075                                         size_t udp_off)
1076 {
1077         uint16_t src_port, dst_port;
1078         struct ip_nat_map *map;
1079
1080         if (!iov_has_bytes(iov, iovcnt, udp_off + UDP_HDR_LEN)) {
1081                 fprintf(stderr, "Short UDP header, dropping!\n");
1082                 return NULL;
1083         }
1084         src_port = iov_get_be16(iov, iovcnt, udp_off + UDP_OFF_SRC_PORT);
1085         dst_port = iov_get_be16(iov, iovcnt, udp_off + UDP_OFF_DST_PORT);
1086         if (dst_port == 67) {
1087                 fake_dhcp_response(iov, iovcnt);
1088                 return NULL;
1089         }
1090         map = get_map_by_tuple(IP_UDPPROTO, src_port);
1091         if (!map)
1092                 return NULL;
1093         xsum_changed_port(iov, iovcnt, udp_off + UDP_OFF_XSUM, src_port,
1094                           map->host_port);
1095         iov_put_be16(iov, iovcnt, udp_off + UDP_OFF_SRC_PORT, map->host_port);
1096         return map;
1097 }
1098
1099 static struct ip_nat_map *handle_tcp_tx(struct iovec *iov, int iovcnt,
1100                                         size_t tcp_off)
1101 {
1102         uint16_t src_port, dst_port;
1103         struct ip_nat_map *map;
1104
1105         if (!iov_has_bytes(iov, iovcnt, tcp_off + TCP_HDR_LEN)) {
1106                 fprintf(stderr, "Short TCP header, dropping!\n");
1107                 return NULL;
1108         }
1109         src_port = iov_get_be16(iov, iovcnt, tcp_off + TCP_OFF_SRC_PORT);
1110         dst_port = iov_get_be16(iov, iovcnt, tcp_off + TCP_OFF_DST_PORT);
1111         map = get_map_by_tuple(IP_TCPPROTO, src_port);
1112         if (!map)
1113                 return NULL;
1114         xsum_changed_port(iov, iovcnt, tcp_off + TCP_OFF_XSUM, src_port,
1115                           map->host_port);
1116         iov_put_be16(iov, iovcnt, tcp_off + TCP_OFF_SRC_PORT, map->host_port);
1117         return map;
1118 }
1119
1120 static struct ip_nat_map *handle_icmp_tx(struct iovec *iov, int iovcnt,
1121                                          size_t icmp_off)
1122 {
1123         /* TODO: we could respond to pings sent to us (router_ip).  For anything
1124          * else, we'll need to work with the bypass (if possible, maybe ID it with
1125          * the Identifier field and map that to the bypassed conv)). */
1126         return NULL;
1127 }
1128
1129 /* Some protocols (like TCP and UDP) need to adjust their xsums whenever an IPv4
1130  * address changes. */
1131 static void ipv4_proto_changed_addr(struct iovec *iov, int iovcnt,
1132                                     uint8_t protocol, size_t proto_hdr_off,
1133                                     uint8_t *old_addr, uint8_t *new_addr)
1134 {
1135         switch (protocol) {
1136         case IP_UDPPROTO:
1137                 xsum_update(iov, iovcnt, proto_hdr_off + UDP_OFF_XSUM, old_addr,
1138                             new_addr, IPV4_ADDR_LEN);
1139                 break;
1140         case IP_TCPPROTO:
1141                 xsum_update(iov, iovcnt, proto_hdr_off + TCP_OFF_XSUM, old_addr,
1142                             new_addr, IPV4_ADDR_LEN);
1143                 break;
1144         }
1145 }
1146
1147 /* Helper, changes a packet's IP address, updating xsums.  'which' controls
1148  * whether we're changing the src or dst address. */
1149 static void ipv4_change_addr(struct iovec *iov, int iovcnt, size_t ip_off,
1150                              uint8_t protocol, uint8_t proto_hdr_off,
1151                              uint8_t *old_addr, uint8_t *new_addr, size_t which)
1152 {
1153         xsum_update(iov, iovcnt, ip_off + IPV4_OFF_XSUM, old_addr, new_addr,
1154                     IPV4_ADDR_LEN);
1155         ipv4_proto_changed_addr(iov, iovcnt, protocol, proto_hdr_off, old_addr,
1156                                 new_addr);
1157         iov_memcpy_to(iov, iovcnt, ip_off + which, new_addr, IPV4_ADDR_LEN);
1158 }
1159
1160 static size_t ipv4_get_header_len(struct iovec *iov, int iovcnt, size_t ip_off)
1161 {
1162         /* First byte, lower nibble, times 4. */
1163         return (iov_get_byte(iov, iovcnt, ip_off + 0) & 0x0f) * 4;
1164 }
1165
1166 static size_t ipv4_get_proto_off(struct iovec *iov, int iovcnt, size_t ip_off)
1167 {
1168         return ipv4_get_header_len(iov, iovcnt, ip_off) + ip_off;
1169 }
1170
1171 static uint8_t ipv4_get_version(struct iovec *iov, int iovcnt, size_t ip_off)
1172 {
1173         /* First byte, upper nibble, but keep in the upper nibble location */
1174         return iov_get_byte(iov, iovcnt, ip_off + 0) & 0xf0;
1175 }
1176
1177 static void handle_ipv4_tx(struct iovec *iov, int iovcnt)
1178 {
1179         size_t ip_off = ETH_HDR_LEN;
1180         uint8_t protocol;
1181         size_t proto_hdr_off;
1182         struct ip_nat_map *map;
1183         uint8_t src_addr[IPV4_ADDR_LEN];
1184         uint8_t dst_addr[IPV4_ADDR_LEN];
1185
1186         if (!iov_has_bytes(iov, iovcnt, ip_off + IPV4_HDR_LEN)) {
1187                 fprintf(stderr, "Short IPv4 header, dropping!\n");
1188                 return;
1189         }
1190         /* It's up to each protocol to give us the ip_nat_map matching the packet
1191          * and to change the packet's src port. */
1192         protocol = iov_get_byte(iov, iovcnt, ip_off + IPV4_OFF_PROTO);
1193         proto_hdr_off = ipv4_get_proto_off(iov, iovcnt, ip_off);
1194         switch (protocol) {
1195         case IP_UDPPROTO:
1196                 map = handle_udp_tx(iov, iovcnt, proto_hdr_off);
1197                 break;
1198         case IP_TCPPROTO:
1199                 map = handle_tcp_tx(iov, iovcnt, proto_hdr_off);
1200                 break;
1201         case IP_ICMPPROTO:
1202                 map = handle_icmp_tx(iov, iovcnt, proto_hdr_off);
1203                 break;
1204         }
1205         /* If the protocol handler already dealt with it (e.g. via emulation), we
1206          * bail out.  o/w, they gave us the remapping we should use to rewrite and
1207          * send the packet. */
1208         if (!map)
1209                 return;
1210         /* At this point, we have a refcnted map, which will keep the map alive and
1211          * its FD open. */
1212         iov_memcpy_from(iov, iovcnt, ip_off + IPV4_OFF_SRC, src_addr,
1213                         IPV4_ADDR_LEN);
1214         iov_memcpy_from(iov, iovcnt, ip_off + IPV4_OFF_DST, dst_addr,
1215                         IPV4_ADDR_LEN);
1216         /* If the destination is the ROUTER_IP, then it's really meant to go to the
1217          * host (loopback).  In that case, we also need the src to be loopback, so
1218          * that the *host's* IP stack recognizes the connection (necessary for
1219          * host-initiated connections via static maps). */
1220         if (!memcmp(dst_addr, guest_v4_router, IPV4_ADDR_LEN)) {
1221                 ipv4_change_addr(iov, iovcnt, ip_off, protocol, proto_hdr_off,
1222                                  dst_addr, loopback_v4_addr, IPV4_OFF_DST);
1223                 ipv4_change_addr(iov, iovcnt, ip_off, protocol, proto_hdr_off,
1224                                  src_addr, loopback_v4_addr, IPV4_OFF_SRC);
1225         } else {
1226                 ipv4_change_addr(iov, iovcnt, ip_off, protocol, proto_hdr_off,
1227                                  src_addr, host_v4_addr, IPV4_OFF_SRC);
1228         }
1229         /* We didn't change the size of the packet, just a few fields.  So we
1230          * shouldn't need to worry about iov[] being too big.  This is different
1231          * than the receive case, where the guest should give us an MTU-sized iov.
1232          * Here, they just gave us whatever they wanted to send.
1233          *
1234          * However, we still need to drop the ethernet header from the front of the
1235          * packet, and just send the IP header + payload. */
1236         iov_strip_bytes(iov, iovcnt, ETH_HDR_LEN);
1237         /* As far as blocking goes, this is like blasting out a raw IP packet.  It
1238          * shouldn't block, preferring to drop, though there might be some cases
1239          * where a qlock is grabbed or the medium/NIC blocks. */
1240         writev(map->host_data_fd, iov, iovcnt);
1241         map->is_stale = FALSE;
1242         kref_put(&map->kref);
1243 }
1244
1245 static void handle_ipv6_tx(struct iovec *iov, int iovcnt)
1246 {
1247 }
1248
1249 /* virtio-net calls this when the guest transmits a packet */
1250 int vnet_transmit_packet(struct iovec *iov, int iovcnt)
1251 {
1252         uint16_t ether_type;
1253
1254         if (vnet_snoop)
1255                 writev(snoop_fd, iov, iovcnt);
1256         if (!iov_has_bytes(iov, iovcnt, ETH_HDR_LEN)) {
1257                 fprintf(stderr, "Short ethernet frame from the guest, dropping!\n");
1258                 return -1;
1259         }
1260         ether_type = iov_get_be16(iov, iovcnt, ETH_OFF_ETYPE);
1261         switch (ether_type) {
1262         case ETH_TYPE_ARP:
1263                 handle_arp_tx(iov, iovcnt);
1264                 break;
1265         case ETH_TYPE_IPV4:
1266                 handle_ipv4_tx(iov, iovcnt);
1267                 break;
1268         case ETH_TYPE_IPV6:
1269                 handle_ipv6_tx(iov, iovcnt);
1270                 break;
1271         default:
1272                 fprintf(stderr, "Unknown ethertype 0x%x, dropping!\n", ether_type);
1273                 return -1;
1274         };
1275         return 0;
1276 }
1277
1278 /* Polls for injected packets, filling the iov[iovcnt] on success and returning
1279  * the amount.  0 means 'nothing there.' */
1280 static size_t __poll_injection(struct iovec *iov, int iovcnt)
1281 {
1282         size_t ret;
1283         struct buf_pkt *bpkt;
1284
1285         if (STAILQ_EMPTY(&inject_pkts))
1286                 return 0;
1287         bpkt = STAILQ_FIRST(&inject_pkts);
1288         STAILQ_REMOVE_HEAD(&inject_pkts, next);
1289         iov_memcpy_to(iov, iovcnt, 0, bpkt->buf, bpkt->sz);
1290         ret = bpkt->sz;
1291         free_bpkt(bpkt);
1292         return ret;
1293 }
1294
1295 static void handle_udp_rx(struct iovec *iov, int iovcnt, size_t len,
1296                           struct ip_nat_map *map, size_t udp_off)
1297 {
1298         assert(len >= udp_off + UDP_HDR_LEN);
1299         xsum_changed_port(iov, iovcnt, udp_off + UDP_OFF_XSUM,
1300                           iov_get_be16(iov, iovcnt, udp_off + UDP_OFF_DST_PORT),
1301                           map->guest_port);
1302         iov_put_be16(iov, iovcnt, udp_off + UDP_OFF_DST_PORT, map->guest_port);
1303 }
1304
1305 static void handle_tcp_rx(struct iovec *iov, int iovcnt, size_t len,
1306                           struct ip_nat_map *map, size_t tcp_off)
1307 {
1308         assert(len >= tcp_off + TCP_HDR_LEN);
1309         xsum_changed_port(iov, iovcnt, tcp_off + TCP_OFF_XSUM,
1310                           iov_get_be16(iov, iovcnt, tcp_off + TCP_OFF_DST_PORT),
1311                           map->guest_port);
1312         iov_put_be16(iov, iovcnt, tcp_off + TCP_OFF_DST_PORT, map->guest_port);
1313 }
1314
1315 /* Computes and stores the xsum for the ipv4 header in the iov. */
1316 static void xsum_ipv4_header(struct iovec *iov, int iovcnt, size_t ip_off)
1317 {
1318         size_t hdr_len = ipv4_get_header_len(iov, iovcnt, ip_off);
1319         uint8_t buf[hdr_len];
1320
1321         iov_memcpy_from(iov, iovcnt, ip_off, buf, hdr_len);
1322         *(uint16_t*)&buf[IPV4_OFF_XSUM] = 0;
1323         iov_put_be16(iov, iovcnt, ip_off + IPV4_OFF_XSUM,
1324                      ip_calc_xsum(buf, IPV4_HDR_LEN));
1325 }
1326
1327 static void handle_ipv4_rx(struct iovec *iov, int iovcnt, size_t len,
1328                            struct ip_nat_map *map)
1329 {
1330         size_t ip_off = ETH_HDR_LEN;
1331         uint8_t protocol;
1332         size_t proto_hdr_off;
1333         uint8_t src_addr[IPV4_ADDR_LEN];
1334         uint8_t dst_addr[IPV4_ADDR_LEN];
1335
1336         protocol = iov_get_byte(iov, iovcnt, ip_off + IPV4_OFF_PROTO);
1337         proto_hdr_off = ipv4_get_proto_off(iov, iovcnt, ip_off);
1338         switch (map->protocol) {
1339         case IP_UDPPROTO:
1340                 handle_udp_rx(iov, iovcnt, len, map, proto_hdr_off);
1341                 break;
1342         case IP_TCPPROTO:
1343                 handle_tcp_rx(iov, iovcnt, len, map, proto_hdr_off);
1344                 break;
1345         default:
1346                 panic("Bad proto %d on map for conv FD %d\n", map->protocol,
1347                       map->host_data_fd);
1348         }
1349         iov_memcpy_from(iov, iovcnt, ip_off + IPV4_OFF_SRC, src_addr,
1350                         IPV4_ADDR_LEN);
1351         iov_memcpy_from(iov, iovcnt, ip_off + IPV4_OFF_DST, dst_addr,
1352                         IPV4_ADDR_LEN);
1353         /* If the src was the host (loopback), the guest thinks the remote is
1354          * ROUTER_IP. */
1355         if (!memcmp(src_addr, loopback_v4_addr, IPV4_ADDR_LEN)) {
1356                 ipv4_change_addr(iov, iovcnt, ip_off, map->protocol, proto_hdr_off,
1357                                  src_addr, guest_v4_router, IPV4_OFF_SRC);
1358         }
1359         /* Interesting case.  If we rewrite it to guest_v4_router, when the guest
1360          * responds, *that* packet will get rewritten to loopback.  If we ignore it,
1361          * and it's qemu mode, it'll actually work.  If it's real addr mode, the
1362          * guest won't send an IP packet out that it thinks is for itself.  */
1363         if (vnet_real_ip_addrs && !memcmp(src_addr, host_v4_addr, IPV4_ADDR_LEN)) {
1364                 fprintf(stderr, "VNET received packet from host_v4_addr.  Not translating, the guest cannot respond!\n");
1365         }
1366         /* Regardless, the dst changes from HOST_IP/loopback to GUEST_IP */
1367         ipv4_change_addr(iov, iovcnt, ip_off, map->protocol, proto_hdr_off,
1368                          dst_addr, guest_v4_addr, IPV4_OFF_DST);
1369         /* Note we did the incremental xsum for the IP header, but also do a final
1370          * xsum.  We need the final xsum in case the kernel's networking stack
1371          * messed up the header. */
1372         xsum_ipv4_header(iov, iovcnt, ip_off);
1373 }
1374
1375 /* NAT / translate an inbound packet iov[len], using map.  If a packet comes in
1376  * on a certain FD, then it's going to the guest at the appropriate port, no
1377  * questions asked.
1378  *
1379  * The iov has ETH_HDR_LEN bytes at the front.  The data actually read from the
1380  * conv starts at that offset.  len includes this frontal padding - it's the
1381  * full length of the real data in the iov + the ethernet header.  len may
1382  * include data beyond the IP packet length; we often get padding from the
1383  * kernel networking stack.  Returns the final size of the packet. */
1384 static size_t handle_rx(struct iovec *iov, int iovcnt, size_t len,
1385                         struct ip_nat_map *map)
1386 {
1387         size_t ip_off = ETH_HDR_LEN;
1388         uint8_t version;
1389         uint16_t ether_type;
1390
1391         /* The conv is reading from a Qmsg queue.  We should always receive at least
1392          * an IPv4 header from the kernel. */
1393         assert(len >= IPV4_HDR_LEN + ETH_HDR_LEN);
1394         version = ipv4_get_version(iov, iovcnt, ip_off);
1395         switch (version) {
1396         case IP_VER4:
1397                 ether_type = ETH_TYPE_IPV4;
1398                 handle_ipv4_rx(iov, iovcnt, len, map);
1399                 break;
1400         case IP_VER6:
1401                 ether_type = ETH_TYPE_IPV6;
1402                 /* Technically, this could be a bad actor outside our node */
1403                 panic("Got an IPv6 packet on FD %d!\n", map->host_data_fd);
1404         default:
1405                 panic("Unexpected IP version 0x%x, probably a bug", version);
1406         }
1407         iov_memcpy_to(iov, iovcnt, ETH_OFF_DST, guest_eth_addr, ETH_ADDR_LEN);
1408         iov_memcpy_to(iov, iovcnt, ETH_OFF_SRC, host_eth_addr, ETH_ADDR_LEN);
1409         iov_put_be16(iov, iovcnt, ETH_OFF_ETYPE, ether_type);
1410         return len;
1411 }
1412
1413 /* Polls for inbound packets on the host's FD, filling the iov[iovcnt] on
1414  * success and returning the amount.  0 means 'nothing there.'
1415  *
1416  * Notes on concurrency:
1417  * - The inbound_todo list is protected by the rx_mtx.  Since we're readv()ing
1418  *   while holding the mtx (because we're in a FOREACH), we're single threaded
1419  *   in the RX path.
1420  * - The inbound_todo list is filled by another thread that puts maps on the
1421  *   list whenever their FD tap fires.
1422  * - The maps on the inbound_todo list are refcounted.  It's possible for them
1423  *   to be reaped and removed from the mapping lookup, but the mapping would
1424  *   stay around until we drained all of the packets from the inbound conv. */
1425 static size_t __poll_inbound(struct iovec *iov, int iovcnt)
1426 {
1427         struct ip_nat_map *i, *temp;
1428         ssize_t pkt_sz = 0;
1429         struct iovec iov_copy[iovcnt];
1430
1431         /* We're going to readv ETH_HDR_LEN bytes into the iov.  To do so, we'll use
1432          * a separate iov to track this offset.  The iov and iov_copy both point to
1433          * the same memory (minus the stripping). */
1434         memcpy(iov_copy, iov, sizeof(struct iovec) * iovcnt);
1435         iov_strip_bytes(iov_copy, iovcnt, ETH_HDR_LEN);
1436         TAILQ_FOREACH_SAFE(i, &inbound_todo, inbound, temp) {
1437                 pkt_sz = readv(i->host_data_fd, iov_copy, iovcnt);
1438                 if (pkt_sz > 0) {
1439                         i->is_stale = FALSE;
1440                         return handle_rx(iov, iovcnt, pkt_sz + ETH_HDR_LEN, i);
1441                 }
1442                 parlib_assert_perror(errno == EAGAIN);
1443                 TAILQ_REMOVE(&inbound_todo, i, inbound);
1444                 i->is_on_inbound = FALSE;
1445                 kref_put(&i->kref);
1446         }
1447         return 0;
1448 }
1449
1450 /* virtio-net calls this when it wants us to fill iov with a packet. */
1451 int vnet_receive_packet(struct iovec *iov, int iovcnt)
1452 {
1453         size_t rx_amt;
1454
1455         uth_mutex_lock(rx_mtx);
1456         while (1) {
1457                 rx_amt = __poll_injection(iov, iovcnt);
1458                 if (rx_amt)
1459                         break;
1460                 rx_amt = __poll_inbound(iov, iovcnt);
1461                 if (rx_amt)
1462                         break;
1463                 uth_cond_var_wait(rx_cv, rx_mtx);
1464         }
1465         uth_mutex_unlock(rx_mtx);
1466         iov_trim_len_to(iov, iovcnt, rx_amt);
1467         if (vnet_snoop)
1468                 writev(snoop_fd, iov, iovcnt);
1469         return rx_amt;
1470 }