Properly assign ACK and CTS packets to the right TA.
diff --git a/app.py b/app.py
index 309d60c..d727a0b 100644
--- a/app.py
+++ b/app.py
@@ -193,13 +193,13 @@
     for i, (p, frame) in enumerate(wifipacket.Packetize(reader)):
       if not timebase: timebase = p.pcap_secs
       ta = p.get('ta')
+      ra = p.get('ra')
       if ta not in show_hosts and aliases.get(ta) not in show_hosts:
-        ta = '~other'  # '~' causes it to sort last in the list
+        ta = ra = '~other'  # '~' causes it to sort last in the list
       elif ta in aliases:
         ta = aliases[ta]
-      ra = p.get('ra')
       if ra not in show_hosts and aliases.get(ra) not in show_hosts:
-        ra = '~other'  # '~' causes it to sort last in the list
+        ta = ra = '~other'  # '~' causes it to sort last in the list
       elif ra in aliases:
         ra = aliases[ra]
       out[(ta,ra)].append(('%.6f' % (p.pcap_secs - timebase),
@@ -211,9 +211,10 @@
     for sesskey in sessions:
       ta, ra = sesskey
       for k in keys:
-        if ta.startswith('~'): ta = ta[1:]
-        if ra.startswith('~'): ra = ra[1:]
-        headers.append('%s to %s (%s)' % (ta, ra, k))
+        if ta == '~other' and ra == '~other':
+          headers.append('other (%s)' % (k,))
+        else:
+          headers.append('%s to %s (%s)' % (ta, ra, k))
       for secs, values in out[sesskey]:
         data.append([secs] + extra + list(values))
       extra += [None] * len(keys)
diff --git a/wifipacket.py b/wifipacket.py
index 57ffb37..240ea13 100755
--- a/wifipacket.py
+++ b/wifipacket.py
@@ -231,6 +231,8 @@
   if network != LINKTYPE_IEEE802_11_RADIOTAP:
     raise ValueError('unexpected tcpdump network type %r' % network)
 
+  last_ta = None
+  last_ra = None
   while 1:
     opt = Struct({})
 
@@ -314,11 +316,26 @@
         opt.seq = (seq & 0xfff0) >> 4
         opt.frag = (seq & 0x000f)
         ofs += 2
-      else:
+      else:  # ta, ra, xa
         if len(frame) < ofs + 6: break
         opt[fieldname] = MacAddr(frame[ofs:ofs + 6])
         ofs += 6
 
+    # ACK and CTS packets omit TA field for efficiency, so we have to fill
+    # it in from the previous packet's RA field.  We can check that the
+    # new packet's RA == the previous packet's TA, just to make sure we're
+    # not lying about it.
+    if not opt.get('ta'):
+      if (last_ta and last_ra
+          and last_ta == opt.get('ra')
+          and last_ra != opt.get('ra')):
+        opt['ta'] = last_ra
+      last_ta = None
+      last_ra = None
+    else:
+      last_ta = opt.get('ta')
+      last_ra = opt.get('ra')
+
     yield opt, frame