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