AWDL://CRSE MODULE 04 / 07 TOPIC OWL · OPENDROP STATUS REFERENCE_IMPL SIGNAL_LIVE
// MODULE_04 OPEN_SOURCE USERSPACE_AWDL

مشروع OWL و OpenDrop.

OWL (Open Wireless Link) هو التطبيق المرجعي مفتوح المصدر لـ AWDL على Linux، يعمل بالكامل في userspace. OpenDrop يجلس فوقه ليطبّق AirDrop. معاً يثبتان أن التوافقية الكاملة ممكنة على عتاد غير Apple — بشرط بطاقة Wi-Fi مناسبة.

المعمارية العامة لـ OWL

OWL يستغلّ واجهة Wi-Fi بقدرتي active monitor + injection، ويبني فوقها كل منطق AWDL برمجياً:

FIG_4.1aOWL · USERSPACE ARCHITECTURE
USERSPACE · owl process Channel Hop Engine hi-res timer switch ch each AW Sync & Election FSM tracks master / TSF listen → slave/master Frame Parser/Builder TLV codec AWDL headers mDNS responder _airdrop._tcp.local TUN bridge awdl0 ↔ kernel IPv6 AF_PACKET raw capture + inject LINUX KERNEL mac80211 / cfg80211 ath9k driver IPv6 stack TUN driver NIC (AR9280) · active monitor + injection ↺ hardware auto-ACKs incoming frames addressed to OWL's MAC ↺
المعمارية الكاملة. لاحظ السهم الأحمر: AF_PACKET هو القناة الوحيدة بين OWL والعتاد. والـ ACK يحدث في العتاد نفسه دون مرور بالكود.

المكوّنات الستة

  1. Channel Hopping Engine: مؤقّت برمجي يبدّل قناة الواجهة وفق التسلسل المُعلَن، متزامناً مع نوافذ الـ AW.
  2. Synchronization & Election: يستمع لإطارات Sync من Master قائم؛ إن لم يسمع أحداً، يبدأ الانتخاب ببثّ إطارات Sync الخاصة به.
  3. Frame Processing: يلتقط الإطارات عبر packet sockets (AF_PACKET)، يحلّل الـ TLVs و AWDL headers، ويبني الإطارات الصادرة ويحقنها.
  4. ACK handling: لا يبني OWL إطارات ACK برمجياً؛ عتاد AR9280 في active monitor يؤكّد تلقائياً أي إطار موجّه لعنوان MAC الخاص بنسخة OWL.
  5. IPv6 عبر TUN: الحمولة المستخرجة تُمرَّر لمكدّس IPv6 في النظام عبر واجهة TUN، فتعمل بقيّة البروتوكولات (mDNS, TCP) طبيعياً.
  6. mDNS responder: يعلن خدمة AirDrop وتبادل الـ TXT records لبدء طبقة AirDrop.
// THE_REASON_HARDWARE_MATTERS

المكوّن #4 (ACK) هو الذي يفسّر لماذا تحتاج بطاقة Atheros تحديداً. OWL لا يستطيع توليد ACK حتى لو أراد. هذه المهمة موكّلة للسيليكون. كل ما يفعله OWL هو ضبط عنوان MAC للواجهة حتى يعرف العتاد متى يجب أن يؤكّد.

محرك القفز بين القنوات — تفاصيل التنفيذ

channel_hop.c · simplified loop
/* read schedule from latest Master frame */
uint8_t schedule[16];   // 16 slots, one channel each
uint64_t master_tsf;     // reference time from Master

while (running) {
    uint64_t now    = get_local_tsf();
    uint32_t aw_dur = 16 * 1024;          // 16 TU in µs
    uint32_t idx    = ((now - master_tsf) / aw_dur) % 16;
    uint8_t  ch     = schedule[idx];

    iw_set_channel("mon0", ch);

    uint64_t next_boundary = master_tsf
                            + (((now - master_tsf) / aw_dur) + 1) * aw_dur;

    sleep_until(next_boundary - SWITCH_LATENCY_FUDGE);
}

آلة حالة المزامنة والانتخاب — في الكود

تنفيذ مبسّط لمنطق الوحدة 1.6:

election_fsm.c · core loop
enum state { LISTENING, SLAVE, MASTER } s = LISTENING;

while (running) {
    frame_t f = recv_frame();    // blocks with timeout

    if (f.type == PSF || f.type == MIF) {
        peer_t p = parse_election_tlv(&f);

        if (p.metric > my_metric) {
            /* adopt their timing, follow them */
            adjust_tsf(p.tsf);
            adopt_channel_seq(p.channel_seq_tlv);
            s = SLAVE;
            last_heard = now();
        }
    }

    if (now() - last_heard > MASTER_TIMEOUT) {
        /* no master heard recently — claim the throne */
        s = MASTER;
        broadcast_psf();
    }

    if (s == MASTER && psf_due()) {
        broadcast_psf();        // every ~110 ms
    }

    update_sync_tree();
    sleep_until(next_event());
}

تحليل وبناء الإطارات

التحليل (parsing)

  1. فكّ ترويسة 802.11 → التحقق من BSSID == 00:25:00:FF:94:73
  2. فكّ Action frame والـ OUI = 00:17:F2
  3. المرور على الـ TLVs واحداً واحداً (type / length / value)
  4. تخزين القيم في بنية state للجار (peer)

البناء (building)

عكس العملية — تركيب ترويسة MAC + Action + الـ TLVs المطلوبة (Sync/Election/Channel Seq)، أو لإطار بيانات: MAC + AWDL data header + حمولة IPv6.

// BYTE_PRECISION

يجب احترام endianness وحقول الطول بدقّة؛ خطأ بايت واحد = إطار يُرفض بصمت من الـ peer دون أي رسالة خطأ.

tlv_parse.c · linear TLV walk
int parse_tlvs(const uint8_t *buf, size_t len, peer_t *p) {
    size_t off = 0;
    while (off + 3 <= len) {
        uint8_t  type   = buf[off];
        uint16_t tlv_len = le16(&buf[off + 1]);
        const uint8_t *val = &buf[off + 3];

        if (off + 3 + tlv_len > len) return -1; /* malformed */

        switch (type) {
            case 0x04: parse_sync_params(val, tlv_len, p);     break;
            case 0x05: parse_election(val, tlv_len, p);        break;
            case 0x12: parse_channel_sequence(val, tlv_len, p); break;
            case 0x02: parse_service_response(val, tlv_len, p); break;
            /* … other TLVs … */
            default:  /* unknown — skip, forward-compat */           break;
        }
        off += 3 + tlv_len;
    }
    return 0;
}

OpenDrop — AirDrop في userspace

OpenDrop (بايثون) يجلس فوق رابط IPv6 الذي يوفّره OWL، ويطبّق مكدّس الوحدة 2:

FIG_4.5aOWL + OPENDROP · COMBINED RUNTIME
opendrop (python) mDNS · HTTPS · plist · cpio other consumers airplay clones, custom apps ↓ IPv6 link-local over awdl0 ↓ OWL (C) · awdl0 interface channel hop · sync · election · TLV codec · TUN bridge ↓ raw packet sockets · mon0 ↓ ath9k card · active monitor
OWL يوفّر «الكيبل الافتراضي»، و OpenDrop يجلس فوقه. أي تطبيق آخر فوق IPv6 يستطيع استخدام نفس الرابط.

البناء والتشغيل (نظرة عملية)

تسلسل التشغيل النموذجي:

root@workstation: ~ · bringing OWL + OpenDrop up
# 1) متطلبات
$ sudo apt install libpcap-dev libnl-3-dev libnl-genl-3-dev cmake build-essential
$ pip install opendrop      # أو من المصدر

# 2) جهّز واجهة active monitor (مثال ath9k)
$ sudo iw dev wlan0 del
$ sudo iw phy phy0 interface add mon0 type monitor flags active
$ sudo ip link set mon0 up

# 3) شغّل OWL على الواجهة (ينشئ awdl0 افتراضياً)
$ sudo owl -i mon0
  [awdl] starting on channel 44
  [awdl] BSSID = 00:25:00:ff:94:73
  [awdl] no master heard, becoming MASTER
  [awdl] heard peer a4:83:e7:…  metric=510 (higher)
  [awdl] demoting to SLAVE, syncing TSF
  [awdl] awdl0 up — fe80::a8bb:ccff:fe11:2233

# 4) في نافذة أخرى، شغّل OpenDrop فوق واجهة awdl0
$ opendrop find
  Looking for receivers. Press Ctrl+C to stop ...
  Found  index=0  ID=4F2A19BB  name="Khaled's iPhone"

$ opendrop send -r 0 -f file.jpg
  Asking receiver to accept ...
  Receiver accepted
  Uploading file ...
  Uploading has been successful
// NOTE

هذه أوامر توضيحية للمسار العام؛ الأسماء والأعلام تتغيّر بين الإصدارات. اعتمد README الرسمي للمشروع كمصدر نهائي.

نقاط ارتكاز الوحدة 4

  • OWL ينفّذ AWDL كاملاً في userspace فوق بطاقة active-monitor+injection.
  • لا يولّد ACK برمجياً — العتاد يفعل ذلك تلقائياً (السبب الجذري لأهمية اختيار البطاقة).
  • يلتقط/يحقن عبر AF_PACKET، ويجسر للـ IPv6 عبر TUN.
  • OpenDrop يبني AirDrop فوق رابط OWL، ويبدع في وضع Everyone.

تمارين الوحدة 4

  1. لماذا يستخدم OWL واجهة TUN بدل تنفيذ مكدّس IPv6 من الصفر؟ ما الذي يكسبه من النواة؟
  2. حدّد في معمارية OWL: أي مكوّن يكسر إذا انجرفت ساعتك المحلية عن الـ Master؟ ولماذا؟
  3. لماذا يكتفي OpenDrop عملياً بوضع Everyone؟ اربط بـ الوحدة 2.6.