-const
[oweals/gnunet.git] / src / transport / plugin_transport_wlan.c
1 /*
2   This file is part of GNUnet
3   (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors)
4
5   GNUnet is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published
7   by the Free Software Foundation; either version 3, or (at your
8   option) any later version.
9
10   GNUnet is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with GNUnet; see the file COPYING.  If not, write to the
17   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18   Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file transport/plugin_transport_wlan.c
23  * @brief transport plugin for wlan
24  * @author David Brodski
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_statistics_service.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_transport_plugin.h"
34 #include "plugin_transport_wlan.h"
35 #include "gnunet_common.h"
36 #include "gnunet_crypto_lib.h"
37 #include "gnunet_fragmentation_lib.h"
38 #include "gnunet_constants.h"
39
40 #define LOG(kind,...) GNUNET_log_from (kind, "transport-wlan",__VA_ARGS__)
41
42 #define PLUGIN_NAME "wlan"
43
44 /**
45  * Max size of packet (that we give to the WLAN driver for transmission)
46  */
47 #define WLAN_MTU 1430
48
49 /**
50  * time out of a mac endpoint
51  */
52 #define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2)
53
54 /**
55  * We reduce the frequence of HELLO beacons in relation to
56  * the number of MAC addresses currently visible to us.
57  * This is the multiplication factor.
58  */
59 #define HELLO_BEACON_SCALING_FACTOR GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
60
61 /**
62  * Maximum number of messages in defragmentation queue per MAC
63  */
64 #define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 2
65
66 /**
67  * Link layer control fields for better compatibility
68  * (i.e. GNUnet over WLAN is not IP-over-WLAN).
69  */
70 #define WLAN_LLC_DSAP_FIELD 0x1f
71 #define WLAN_LLC_SSAP_FIELD 0x1f
72
73
74 GNUNET_NETWORK_STRUCT_BEGIN
75 /**
76  * Header for messages which need fragmentation.  This is the format of
77  * a message we obtain AFTER defragmentation.  We then need to check
78  * the CRC and then tokenize the payload and pass it to the
79  * 'receive' callback.
80  */
81 struct WlanHeader
82 {
83
84   /**
85    * Message type is #GNUNET_MESSAGE_TYPE_WLAN_DATA.
86    */
87   struct GNUNET_MessageHeader header;
88
89   /**
90    * CRC32 checksum (only over the payload), in NBO.
91    */
92   uint32_t crc GNUNET_PACKED;
93
94   /**
95    * Sender of the message.
96    */
97   struct GNUNET_PeerIdentity sender;
98
99   /**
100    * Target of the message.
101    */
102   struct GNUNET_PeerIdentity target;
103
104   /* followed by payload, possibly including
105      multiple messages! */
106
107 };
108
109
110 struct WlanAddress
111 {
112   uint32_t options GNUNET_PACKED;
113
114   struct GNUNET_TRANSPORT_WLAN_MacAddress mac;
115 };
116
117
118 GNUNET_NETWORK_STRUCT_END
119
120
121 /**
122  * Information kept for each message that is yet to be fragmented and
123  * transmitted.
124  */
125 struct PendingMessage
126 {
127   /**
128    * next entry in the DLL
129    */
130   struct PendingMessage *next;
131
132   /**
133    * previous entry in the DLL
134    */
135   struct PendingMessage *prev;
136
137   /**
138    * The pending message
139    */
140   struct WlanHeader *msg;
141
142   /**
143    * Continuation function to call once the message
144    * has been sent.  Can be NULL if there is no
145    * continuation to call.
146    */
147   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
148
149   /**
150    * Cls for transmit_cont
151    */
152   void *transmit_cont_cls;
153
154   /**
155    * Timeout task (for this message).
156    */
157   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
158
159 };
160
161
162 /**
163  * Session handle for connections with other peers.
164  */
165 struct Session
166 {
167   /**
168    * To whom are we talking to (set to our identity
169    * if we are still waiting for the welcome message)
170    */
171   struct GNUNET_PeerIdentity target;
172
173   /**
174    * We keep all sessions in a DLL at their respective
175    * `struct MACEndpoint *`.
176    */
177   struct Session *next;
178
179   /**
180    * We keep all sessions in a DLL at their respective
181    * 'struct MACEndpoint'.
182    */
183   struct Session *prev;
184
185   /**
186    * MAC endpoint with the address of this peer.
187    */
188   struct MacEndpoint *mac;
189
190   /**
191    * Address associated with this session and MAC endpoint
192    */
193   struct GNUNET_HELLO_Address *address;
194
195   /**
196    * Head of messages currently pending for transmission to this peer.
197    */
198   struct PendingMessage *pending_message_head;
199
200   /**
201    * Tail of messages currently pending for transmission to this peer.
202    */
203   struct PendingMessage *pending_message_tail;
204
205   /**
206    * When should this session time out?
207    */
208   struct GNUNET_TIME_Absolute timeout;
209
210   /**
211    * Timeout task (for the session).
212    */
213   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
214 };
215
216
217 /**
218  * Struct for messages that are being fragmented in a MAC's transmission queue.
219  */
220 struct FragmentMessage
221 {
222
223   /**
224    * This is a doubly-linked list.
225    */
226   struct FragmentMessage *next;
227
228   /**
229    * This is a doubly-linked list.
230    */
231   struct FragmentMessage *prev;
232
233   /**
234    * MAC endpoint this message belongs to
235    */
236   struct MacEndpoint *macendpoint;
237
238   /**
239    * Fragmentation context
240    */
241   struct GNUNET_FRAGMENT_Context *fragcontext;
242
243   /**
244    * Transmission handle to helper (to cancel if the frag context
245    * is destroyed early for some reason).
246    */
247   struct GNUNET_HELPER_SendHandle *sh;
248
249   /**
250    * Intended recipient.
251    */
252   struct GNUNET_PeerIdentity target;
253
254   /**
255    * Timeout value for the message.
256    */
257   struct GNUNET_TIME_Absolute timeout;
258
259   /**
260    * Timeout task.
261    */
262   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
263
264   /**
265    * Continuation to call when we're done with this message.
266    */
267   GNUNET_TRANSPORT_TransmitContinuation cont;
268
269   /**
270    * Closure for @e cont
271    */
272   void *cont_cls;
273
274   /**
275    * Size of original message
276    */
277   size_t size_payload;
278
279   /**
280    * Number of bytes used to transmit message
281    */
282   size_t size_on_wire;
283
284 };
285
286
287 /**
288  * Struct to represent one network card connection
289  */
290 struct MacEndpoint
291 {
292
293   /**
294    * We keep all MACs in a DLL in the plugin.
295    */
296   struct MacEndpoint *next;
297
298   /**
299    * We keep all MACs in a DLL in the plugin.
300    */
301   struct MacEndpoint *prev;
302
303   /**
304    * Pointer to the global plugin struct.
305    */
306   struct Plugin *plugin;
307
308   /**
309    * Head of sessions that use this MAC.
310    */
311   struct Session *sessions_head;
312
313   /**
314    * Tail of sessions that use this MAC.
315    */
316   struct Session *sessions_tail;
317
318   /**
319    * Head of messages we are currently sending to this MAC.
320    */
321   struct FragmentMessage *sending_messages_head;
322
323   /**
324    * Tail of messages we are currently sending to this MAC.
325    */
326   struct FragmentMessage *sending_messages_tail;
327
328   /**
329    * Defrag context for this MAC
330    */
331   struct GNUNET_DEFRAGMENT_Context *defrag;
332
333   /**
334    * When should this endpoint time out?
335    */
336   struct GNUNET_TIME_Absolute timeout;
337
338   /**
339    * Timeout task.
340    */
341   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
342
343   /**
344    * count of messages in the fragment out queue for this mac endpoint
345    */
346   unsigned int fragment_messages_out_count;
347
348   /**
349    * peer MAC address
350    */
351   struct WlanAddress wlan_addr;
352
353   /**
354    * Message delay for fragmentation context
355    */
356   struct GNUNET_TIME_Relative msg_delay;
357
358   /**
359    * ACK delay for fragmentation context
360    */
361   struct GNUNET_TIME_Relative ack_delay;
362
363   /**
364    * Desired transmission power for this MAC
365    */
366   uint16_t tx_power;
367
368   /**
369    * Desired transmission rate for this MAC
370    */
371   uint8_t rate;
372
373   /**
374    * Antenna we should use for this MAC
375    */
376   uint8_t antenna;
377
378 };
379
380
381 /**
382  * Encapsulation of all of the state of the plugin.
383  */
384 struct Plugin
385 {
386   /**
387    * Our environment.
388    */
389   struct GNUNET_TRANSPORT_PluginEnvironment *env;
390
391   /**
392    * Handle to helper process for priviledged operations.
393    */
394   struct GNUNET_HELPER_Handle *suid_helper;
395
396   /**
397    * ARGV-vector for the helper (all helpers take only the binary
398    * name, one actual argument, plus the NULL terminator for 'argv').
399    */
400   char * helper_argv[3];
401
402   /**
403    * The interface of the wlan card given to us by the user.
404    */
405   char *interface;
406
407   /**
408    * Tokenizer for demultiplexing of data packets resulting from defragmentation.
409    */
410   struct GNUNET_SERVER_MessageStreamTokenizer *fragment_data_tokenizer;
411
412   /**
413    * Tokenizer for demultiplexing of data packets received from the suid helper
414    */
415   struct GNUNET_SERVER_MessageStreamTokenizer *helper_payload_tokenizer;
416
417   /**
418    * Tokenizer for demultiplexing of data packets that follow the WLAN Header
419    */
420   struct GNUNET_SERVER_MessageStreamTokenizer *wlan_header_payload_tokenizer;
421
422   /**
423    * Head of list of open connections.
424    */
425   struct MacEndpoint *mac_head;
426
427   /**
428    * Tail of list of open connections.
429    */
430   struct MacEndpoint *mac_tail;
431
432   /**
433    * Number of connections
434    */
435   unsigned int mac_count;
436
437   /**
438    * Task that periodically sends a HELLO beacon via the helper.
439    */
440   GNUNET_SCHEDULER_TaskIdentifier beacon_task;
441
442   /**
443    * Tracker for bandwidth limit
444    */
445   struct GNUNET_BANDWIDTH_Tracker tracker;
446
447   /**
448    * The mac_address of the wlan card given to us by the helper.
449    */
450   struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address;
451
452   /**
453    * Have we received a control message with our MAC address yet?
454    */
455   int have_mac;
456
457   /**
458    * Options for addresses
459    */
460   uint32_t options;
461
462 };
463
464
465 /**
466  * Information associated with a message.  Can contain
467  * the session or the MAC endpoint associated with the
468  * message (or both).
469  */
470 struct MacAndSession
471 {
472   /**
473    * NULL if the identity of the other peer is not known.
474    */
475   struct Session *session;
476
477   /**
478    * MAC address of the other peer, NULL if not known.
479    */
480   struct MacEndpoint *endpoint;
481 };
482
483 /**
484  * Function called for a quick conversion of the binary address to
485  * a numeric address.  Note that the caller must not free the
486  * address and that the next call to this function is allowed
487  * to override the address again.
488  *
489  * @param cls closure
490  * @param addr binary address
491  * @param addrlen length of the address
492  * @return string representing the same address
493  */
494 static const char *
495 wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen);
496
497 /**
498  * Print MAC addresses nicely.
499  *
500  * @param mac the mac address
501  * @return string to a static buffer with the human-readable mac, will be overwritten during the next call to this function
502  */
503 static const char *
504 mac_to_string (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac)
505 {
506   static char macstr[20];
507
508   GNUNET_snprintf (macstr, sizeof (macstr), "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
509                                                                  mac->mac[0], mac->mac[1],
510                    mac->mac[2], mac->mac[3], mac->mac[4], mac->mac[5]);
511   return macstr;
512 }
513
514
515 /**
516  * Fill the radiotap header
517  *
518  * @param endpoint pointer to the endpoint, can be NULL
519  * @param header pointer to the radiotap header
520  * @param size total message size
521  */
522 static void
523 get_radiotap_header (struct MacEndpoint *endpoint,
524                      struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header,
525                      uint16_t size)
526 {
527   header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER);
528   header->header.size = ntohs (size);
529   if (NULL != endpoint)
530   {
531     header->rate = endpoint->rate;
532     header->tx_power = endpoint->tx_power;
533     header->antenna = endpoint->antenna;
534   }
535   else
536   {
537     header->rate = 255;
538     header->tx_power = 0;
539     header->antenna = 0;
540   }
541 }
542
543
544 /**
545  * Generate the WLAN hardware header for one packet
546  *
547  * @param plugin the plugin handle
548  * @param header address to write the header to
549  * @param to_mac_addr address of the recipient
550  * @param size size of the whole packet, needed to calculate the time to send the packet
551  */
552 static void
553 get_wlan_header (struct Plugin *plugin,
554                  struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *header,
555                  const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr,
556                  unsigned int size)
557 {
558   const int rate = 11000000;
559
560   header->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
561   header->addr1 = *to_mac_addr;
562   header->addr2 = plugin->mac_address;
563   header->addr3 = mac_bssid_gnunet;
564   header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290);
565   header->sequence_control = 0; // FIXME?
566   header->llc[0] = WLAN_LLC_DSAP_FIELD;
567   header->llc[1] = WLAN_LLC_SSAP_FIELD;
568   header->llc[2] = 0;  // FIXME?
569   header->llc[3] = 0;  // FIXME?
570 }
571
572
573 /**
574  * Send an ACK for a fragment we received.
575  *
576  * @param cls the 'struct MacEndpoint' the ACK must be sent to
577  * @param msg_id id of the message
578  * @param hdr pointer to the hdr where the ack is stored
579  */
580 static void
581 send_ack (void *cls, uint32_t msg_id,
582           const struct GNUNET_MessageHeader *hdr)
583 {
584   struct MacEndpoint *endpoint = cls;
585   struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage* radio_header;
586   uint16_t msize = ntohs (hdr->size);
587   size_t size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize;
588   char buf[size];
589
590   if (NULL == endpoint)
591   {
592     GNUNET_break (0);
593     return;
594   }
595
596   if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
597   {
598     GNUNET_break (0);
599     return;
600   }
601   LOG (GNUNET_ERROR_TYPE_DEBUG,
602        "Sending ACK to helper\n");
603   radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf;
604   get_radiotap_header (endpoint, radio_header, size);
605   get_wlan_header (endpoint->plugin,
606                    &radio_header->frame,
607                    &endpoint->wlan_addr.mac,
608                    sizeof (endpoint->wlan_addr.mac));
609   memcpy (&radio_header[1], hdr, msize);
610   if (NULL !=
611       GNUNET_HELPER_send (endpoint->plugin->suid_helper,
612                           &radio_header->header,
613                           GNUNET_NO /* dropping ACKs is bad */,
614                           NULL, NULL))
615     GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN ACKs sent"),
616                               1, GNUNET_NO);
617 }
618
619
620 /**
621  * Handles the data after all fragments are put together
622  *
623  * @param cls macendpoint this messages belongs to
624  * @param hdr pointer to the data
625  */
626 static void
627 wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
628 {
629   struct MacEndpoint *endpoint = cls;
630   struct Plugin *plugin = endpoint->plugin;
631   struct MacAndSession mas;
632
633   GNUNET_STATISTICS_update (plugin->env->stats,
634                             _("# WLAN messages defragmented"), 1,
635                             GNUNET_NO);
636   mas.session = NULL;
637   mas.endpoint = endpoint;
638   (void) GNUNET_SERVER_mst_receive (plugin->fragment_data_tokenizer,
639                                     &mas,
640                                     (const char *) hdr,
641                                     ntohs (hdr->size),
642                                     GNUNET_YES, GNUNET_NO);
643 }
644
645
646 /**
647  * Free a session
648  *
649  * @param cls our `struct Plugin`.
650  * @param session the session free
651  */
652 static int
653 wlan_plugin_disconnect_session (void *cls,
654                                 struct Session *session)
655 {
656   struct MacEndpoint *endpoint = session->mac;
657   struct PendingMessage *pm;
658
659   endpoint->plugin->env->session_end (endpoint->plugin->env->cls,
660                                       session->address,
661                                       session);
662   while (NULL != (pm = session->pending_message_head))
663   {
664     GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
665                                  session->pending_message_tail, pm);
666     if (GNUNET_SCHEDULER_NO_TASK != pm->timeout_task)
667     {
668       GNUNET_SCHEDULER_cancel (pm->timeout_task);
669       pm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
670     }
671     GNUNET_free (pm->msg);
672     GNUNET_free (pm);
673   }
674   GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head,
675                                endpoint->sessions_tail,
676                                session);
677   if (session->timeout_task != GNUNET_SCHEDULER_NO_TASK)
678   {
679     GNUNET_SCHEDULER_cancel (session->timeout_task);
680     session->timeout_task = GNUNET_SCHEDULER_NO_TASK;
681   }
682   GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
683                             _("# WLAN sessions allocated"), -1,
684                             GNUNET_NO);
685   GNUNET_HELLO_address_free (session->address);
686   GNUNET_free (session);
687   return GNUNET_OK;
688 }
689
690
691 /**
692  * Function that is called to get the keepalive factor.
693  * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to
694  * calculate the interval between keepalive packets.
695  *
696  * @param cls closure with the `struct Plugin`
697  * @return keepalive factor
698  */
699 static unsigned int
700 wlan_plugin_query_keepalive_factor (void *cls)
701 {
702   return 3;
703 }
704
705
706 /**
707  * A session is timing out.  Clean up.
708  *
709  * @param cls pointer to the Session
710  * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
711  */
712 static void
713 session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
714 {
715   struct Session *session = cls;
716   struct GNUNET_TIME_Relative timeout;
717
718   session->timeout_task = GNUNET_SCHEDULER_NO_TASK;
719   timeout = GNUNET_TIME_absolute_get_remaining (session->timeout);
720   if (0 == timeout.rel_value_us)
721   {
722     wlan_plugin_disconnect_session (session->mac->plugin,
723                                     session);
724     return;
725   }
726   session->timeout_task =
727     GNUNET_SCHEDULER_add_delayed (timeout, &session_timeout, session);
728 }
729
730
731
732 /**
733  * Lookup a new session
734  *
735  * @param endpoint pointer to the mac endpoint of the peer
736  * @param peer peer identity to use for this session
737  * @return returns the session or NULL
738  */
739 static struct Session *
740 lookup_session (struct MacEndpoint *endpoint,
741                 const struct GNUNET_PeerIdentity *peer)
742 {
743   struct Session *session;
744
745   for (session = endpoint->sessions_head; NULL != session; session = session->next)
746     if (0 == memcmp (peer, &session->target, sizeof (struct GNUNET_PeerIdentity)))
747     {
748       session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
749       return session;
750     }
751   return NULL;
752 }
753
754 /**
755  * Create a new session
756  *
757  * @param endpoint pointer to the mac endpoint of the peer
758  * @param peer peer identity to use for this session
759  * @return returns the session or NULL
760  */
761 static struct Session *
762 create_session (struct MacEndpoint *endpoint,
763                 const struct GNUNET_PeerIdentity *peer)
764 {
765   struct Session *session;
766
767   GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN sessions allocated"), 1,
768                             GNUNET_NO);
769   session = GNUNET_new (struct Session);
770   GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head,
771                                     endpoint->sessions_tail,
772                                     session);
773   session->address = GNUNET_HELLO_address_allocate (peer, PLUGIN_NAME,
774       &endpoint->wlan_addr, sizeof (endpoint->wlan_addr),
775       GNUNET_HELLO_ADDRESS_INFO_NONE);
776   session->mac = endpoint;
777   session->target = *peer;
778   session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
779   session->timeout_task =
780       GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, session);
781   LOG (GNUNET_ERROR_TYPE_DEBUG,
782        "Created new session %p for peer `%s' with endpoint %s\n",
783        session,
784        GNUNET_i2s (peer),
785        mac_to_string (&endpoint->wlan_addr.mac));
786
787   return session;
788 }
789
790
791 /**
792  * Look up a session for a peer and create a new session if none is found
793  *
794  * @param endpoint pointer to the mac endpoint of the peer
795  * @param peer peer identity to use for this session
796  * @return returns the session
797  */
798 static struct Session *
799 get_session (struct MacEndpoint *endpoint,
800                 const struct GNUNET_PeerIdentity *peer)
801 {
802   struct Session *session;
803   if (NULL != (session = lookup_session (endpoint, peer)))
804         return session;
805   return create_session (endpoint, peer);
806 }
807
808
809 /**
810  * Function called once we have successfully given the fragment
811  * message to the SUID helper process and we are thus ready for
812  * the next fragment.
813  *
814  * @param cls the 'struct FragmentMessage'
815  * @param result result of the operation (#GNUNET_OK on success, #GNUNET_NO if the helper died, #GNUNET_SYSERR
816  *        if the helper was stopped)
817  */
818 static void
819 fragment_transmission_done (void *cls,
820                             int result)
821 {
822   struct FragmentMessage *fm = cls;
823
824
825   fm->sh = NULL;
826   GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
827 }
828
829
830 /**
831  * Transmit a fragment of a message.
832  *
833  * @param cls 'struct FragmentMessage' this fragment message belongs to
834  * @param hdr pointer to the start of the fragment message
835  */
836 static void
837 transmit_fragment (void *cls,
838                    const struct GNUNET_MessageHeader *hdr)
839 {
840   struct FragmentMessage *fm = cls;
841   struct MacEndpoint *endpoint = fm->macendpoint;
842   size_t size;
843   uint16_t msize;
844
845   if (NULL == endpoint)
846   {
847         GNUNET_break (0);
848         return;
849   }
850
851   msize = ntohs (hdr->size);
852   size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize;
853   {
854     char buf[size];
855     struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radio_header;
856
857     radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf;
858     get_radiotap_header (endpoint, radio_header, size);
859     get_wlan_header (endpoint->plugin,
860                      &radio_header->frame,
861                      &endpoint->wlan_addr.mac,
862                      sizeof (endpoint->wlan_addr.mac));
863     memcpy (&radio_header[1], hdr, msize);
864     GNUNET_assert (NULL == fm->sh);
865     fm->sh = GNUNET_HELPER_send (endpoint->plugin->suid_helper,
866                                  &radio_header->header,
867                                  GNUNET_NO,
868                                  &fragment_transmission_done, fm);
869     fm->size_on_wire += size;
870     if (NULL != fm->sh)
871       GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN message fragments sent"),
872                                 1, GNUNET_NO);
873     else
874       GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
875     GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
876                               "# bytes currently in WLAN buffers",
877                               -msize, GNUNET_NO);
878     GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
879                               "# bytes transmitted via WLAN",
880                               msize, GNUNET_NO);
881   }
882 }
883
884
885 /**
886  * Frees the space of a message in the fragment queue (send queue)
887  *
888  * @param fm message to free
889  */
890 static void
891 free_fragment_message (struct FragmentMessage *fm)
892 {
893   struct MacEndpoint *endpoint = fm->macendpoint;
894
895   GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN messages pending (with fragmentation)"),
896                             -1, GNUNET_NO);
897   GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
898                                endpoint->sending_messages_tail, fm);
899   if (NULL != fm->sh)
900   {
901     GNUNET_HELPER_send_cancel (fm->sh);
902     fm->sh = NULL;
903   }
904   GNUNET_FRAGMENT_context_destroy (fm->fragcontext,
905                                    &endpoint->msg_delay,
906                                    &endpoint->ack_delay);
907   if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
908   {
909     GNUNET_SCHEDULER_cancel (fm->timeout_task);
910     fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
911   }
912   GNUNET_free (fm);
913 }
914
915
916 /**
917  * A FragmentMessage has timed out.  Remove it.
918  *
919  * @param cls pointer to the 'struct FragmentMessage'
920  * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
921  */
922 static void
923 fragmentmessage_timeout (void *cls,
924                          const struct GNUNET_SCHEDULER_TaskContext *tc)
925 {
926   struct FragmentMessage *fm = cls;
927
928   fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
929   if (NULL != fm->cont)
930   {
931     fm->cont (fm->cont_cls, &fm->target, GNUNET_SYSERR, fm->size_payload, fm->size_on_wire);
932     fm->cont = NULL;
933   }
934   free_fragment_message (fm);
935 }
936
937
938 /**
939  * Transmit a message to the given destination with fragmentation.
940  *
941  * @param endpoint desired destination
942  * @param timeout how long can the message wait?
943  * @param target peer that should receive the message
944  * @param msg message to transmit
945  * @param payload_size bytes of payload
946  * @param cont continuation to call once the message has
947  *        been transmitted (or if the transport is ready
948  *        for the next transmission call; or if the
949  *        peer disconnected...); can be NULL
950  * @param cont_cls closure for cont
951  */
952 static void
953 send_with_fragmentation (struct MacEndpoint *endpoint,
954                          struct GNUNET_TIME_Relative timeout,
955                          const struct GNUNET_PeerIdentity *target,
956                          const struct GNUNET_MessageHeader *msg,
957                          size_t payload_size,
958                          GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
959
960 {
961   struct FragmentMessage *fm;
962   struct Plugin *plugin;
963
964   plugin = endpoint->plugin;
965   fm = GNUNET_new (struct FragmentMessage);
966   fm->macendpoint = endpoint;
967   fm->target = *target;
968   fm->size_payload = payload_size;
969   fm->size_on_wire = 0;
970   fm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
971   fm->cont = cont;
972   fm->cont_cls = cont_cls;
973   /* 1 MBit/s typical data rate, 1430 byte fragments => ~100 ms per message */
974   fm->fragcontext =
975     GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
976                                     &plugin->tracker,
977                                     endpoint->msg_delay,
978                                     endpoint->ack_delay,
979                                     msg,
980                                     &transmit_fragment, fm);
981   fm->timeout_task =
982     GNUNET_SCHEDULER_add_delayed (timeout,
983                                   &fragmentmessage_timeout, fm);
984   GNUNET_CONTAINER_DLL_insert_tail (endpoint->sending_messages_head,
985                                     endpoint->sending_messages_tail,
986                                     fm);
987 }
988
989
990 /**
991  * Free a MAC endpoint.
992  *
993  * @param endpoint pointer to the MacEndpoint to free
994  */
995 static void
996 free_macendpoint (struct MacEndpoint *endpoint)
997 {
998   struct Plugin *plugin = endpoint->plugin;
999   struct FragmentMessage *fm;
1000   struct Session *session;
1001
1002   GNUNET_STATISTICS_update (plugin->env->stats,
1003                             _("# WLAN MAC endpoints allocated"), -1, GNUNET_NO);
1004   while (NULL != (session = endpoint->sessions_head))
1005     wlan_plugin_disconnect_session (plugin,
1006                                     session);
1007   while (NULL != (fm = endpoint->sending_messages_head))
1008     free_fragment_message (fm);
1009   GNUNET_CONTAINER_DLL_remove (plugin->mac_head,
1010                                plugin->mac_tail,
1011                                endpoint);
1012
1013   if (NULL != endpoint->defrag)
1014   {
1015     GNUNET_DEFRAGMENT_context_destroy(endpoint->defrag);
1016     endpoint->defrag = NULL;
1017   }
1018
1019   plugin->mac_count--;
1020   if (GNUNET_SCHEDULER_NO_TASK != endpoint->timeout_task)
1021   {
1022     GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
1023     endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1024   }
1025   GNUNET_free (endpoint);
1026 }
1027
1028
1029 /**
1030  * A MAC endpoint is timing out.  Clean up.
1031  *
1032  * @param cls pointer to the MacEndpoint
1033  * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
1034  */
1035 static void
1036 macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1037 {
1038   struct MacEndpoint *endpoint = cls;
1039   struct GNUNET_TIME_Relative timeout;
1040
1041   endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1042   timeout = GNUNET_TIME_absolute_get_remaining (endpoint->timeout);
1043   if (0 == timeout.rel_value_us)
1044   {
1045     free_macendpoint (endpoint);
1046     return;
1047   }
1048   endpoint->timeout_task =
1049     GNUNET_SCHEDULER_add_delayed (timeout, &macendpoint_timeout,
1050                                   endpoint);
1051 }
1052
1053
1054 /**
1055  * Find (or create) a MacEndpoint with a specific MAC address
1056  *
1057  * @param plugin pointer to the plugin struct
1058  * @param mac the MAC address of the endpoint
1059  * @return handle to our data structure for this MAC
1060  */
1061 static struct MacEndpoint *
1062 create_macendpoint (struct Plugin *plugin, struct WlanAddress *mac)
1063 {
1064   struct MacEndpoint *pos;
1065
1066   for (pos = plugin->mac_head; NULL != pos; pos = pos->next)
1067   {
1068     if (0 == memcmp (mac, &pos->wlan_addr, sizeof (pos->wlan_addr)))
1069     {
1070       LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing MAC endpoint `%s'\n",
1071         wlan_plugin_address_to_string (NULL,
1072                                        &pos->wlan_addr.mac,
1073                                        sizeof (pos->wlan_addr)));
1074       return pos;
1075     }
1076   }
1077   pos = GNUNET_new (struct MacEndpoint);
1078   pos->wlan_addr = (*mac);
1079   pos->plugin = plugin;
1080   pos->defrag =
1081     GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
1082                                       MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
1083                                       pos,
1084                                       &wlan_data_message_handler,
1085                                       &send_ack);
1086
1087   pos->msg_delay = GNUNET_TIME_UNIT_MILLISECONDS;
1088   pos->ack_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
1089   pos->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT);
1090   pos->timeout_task =
1091       GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
1092                                     pos);
1093   GNUNET_CONTAINER_DLL_insert (plugin->mac_head, plugin->mac_tail, pos);
1094   plugin->mac_count++;
1095   GNUNET_STATISTICS_update (plugin->env->stats, _("# WLAN MAC endpoints allocated"),
1096                             1, GNUNET_NO);
1097   LOG (GNUNET_ERROR_TYPE_DEBUG,
1098        "New MAC endpoint `%s'\n",
1099        wlan_plugin_address_to_string (NULL,
1100                                       &pos->wlan_addr,
1101                                       sizeof (struct WlanAddress)));
1102   return pos;
1103 }
1104
1105
1106 /**
1107  * Function obtain the network type for a session
1108  *
1109  * @param cls closure ('struct Plugin*')
1110  * @param session the session
1111  * @return the network type in HBO or GNUNET_SYSERR
1112  */
1113 static enum GNUNET_ATS_Network_Type
1114 wlan_get_network (void *cls,
1115                   struct Session *session)
1116 {
1117   GNUNET_assert (NULL != session);
1118   return GNUNET_ATS_NET_WLAN;
1119 }
1120
1121
1122 /**
1123  * Creates a new outbound session the transport service will use to send data to the
1124  * peer
1125  *
1126  * @param cls the plugin
1127  * @param address the address
1128  * @return the session or NULL of max connections exceeded
1129  */
1130 static struct Session *
1131 wlan_plugin_get_session (void *cls,
1132                          const struct GNUNET_HELLO_Address *address)
1133 {
1134   struct Plugin *plugin = cls;
1135   struct MacEndpoint *endpoint;
1136
1137   if (NULL == address)
1138     return NULL;
1139   if (sizeof (struct WlanAddress) != address->address_length)
1140   {
1141     GNUNET_break (0);
1142     return NULL;
1143   }
1144   LOG (GNUNET_ERROR_TYPE_DEBUG,
1145        "Service asked to create session for peer `%s' with MAC `%s'\n",
1146        GNUNET_i2s (&address->peer),
1147        wlan_plugin_address_to_string (NULL,
1148                                       address->address,
1149                                       address->address_length));
1150   endpoint = create_macendpoint (plugin, (struct WlanAddress *) address->address);
1151   return get_session (endpoint, &address->peer);
1152 }
1153
1154
1155 /**
1156  * Function that can be used to force the plugin to disconnect
1157  * from the given peer and cancel all previous transmissions
1158  * (and their continuation).
1159  *
1160  * @param cls closure
1161  * @param target peer from which to disconnect
1162  */
1163 static void
1164 wlan_plugin_disconnect_peer (void *cls,
1165                              const struct GNUNET_PeerIdentity *target)
1166 {
1167   struct Plugin *plugin = cls;
1168   struct Session *session;
1169   struct MacEndpoint *endpoint;
1170
1171   for (endpoint = plugin->mac_head; NULL != endpoint; endpoint = endpoint->next)
1172     for (session = endpoint->sessions_head; NULL != session; session = session->next)
1173       if (0 == memcmp (target, &session->target,
1174                        sizeof (struct GNUNET_PeerIdentity)))
1175       {
1176         wlan_plugin_disconnect_session (plugin, session);
1177         break; /* inner-loop only (in case peer has another MAC as well!) */
1178       }
1179 }
1180
1181
1182 /**
1183  * Function that can be used by the transport service to transmit
1184  * a message using the plugin.   Note that in the case of a
1185  * peer disconnecting, the continuation MUST be called
1186  * prior to the disconnect notification itself.  This function
1187  * will be called with this peer's HELLO message to initiate
1188  * a fresh connection to another peer.
1189  *
1190  * @param cls closure
1191  * @param session which session must be used
1192  * @param msgbuf the message to transmit
1193  * @param msgbuf_size number of bytes in 'msgbuf'
1194  * @param priority how important is the message (most plugins will
1195  *                 ignore message priority and just FIFO)
1196  * @param to how long to wait at most for the transmission (does not
1197  *                require plugins to discard the message after the timeout,
1198  *                just advisory for the desired delay; most plugins will ignore
1199  *                this as well)
1200  * @param cont continuation to call once the message has
1201  *        been transmitted (or if the transport is ready
1202  *        for the next transmission call; or if the
1203  *        peer disconnected...); can be NULL
1204  * @param cont_cls closure for cont
1205  * @return number of bytes used (on the physical network, with overheads);
1206  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
1207  *         and does NOT mean that the message was not transmitted (DV)
1208  */
1209 static ssize_t
1210 wlan_plugin_send (void *cls,
1211                   struct Session *session,
1212                   const char *msgbuf, size_t msgbuf_size,
1213                   unsigned int priority,
1214                   struct GNUNET_TIME_Relative to,
1215                   GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1216 {
1217   struct Plugin *plugin = cls;
1218   struct WlanHeader *wlanheader;
1219   size_t size = msgbuf_size + sizeof (struct WlanHeader);
1220   char buf[size] GNUNET_ALIGN;
1221
1222   LOG (GNUNET_ERROR_TYPE_DEBUG,
1223        "Transmitting %u bytes of payload to peer `%s' (starting with %u byte message of type %u)\n",
1224        msgbuf_size,
1225        GNUNET_i2s (&session->target),
1226        (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->size),
1227        (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->type));
1228   wlanheader = (struct WlanHeader *) buf;
1229   wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
1230   wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
1231   wlanheader->sender = *plugin->env->my_identity;
1232   wlanheader->target = session->target;
1233   wlanheader->crc = htonl (GNUNET_CRYPTO_crc32_n (msgbuf, msgbuf_size));
1234   memcpy (&wlanheader[1], msgbuf, msgbuf_size);
1235
1236   GNUNET_STATISTICS_update (plugin->env->stats,
1237                             "# bytes currently in WLAN buffers",
1238                             msgbuf_size, GNUNET_NO);
1239
1240   send_with_fragmentation (session->mac,
1241                            to,
1242                            &session->target,
1243                            &wlanheader->header,
1244                            msgbuf_size,
1245                            cont, cont_cls);
1246   return size;
1247 }
1248
1249
1250 /**
1251  * We have received data from the WLAN via some session.  Process depending
1252  * on the message type (HELLO, DATA, FRAGMENTATION or FRAGMENTATION-ACK).
1253  *
1254  * @param cls pointer to the plugin
1255  * @param client pointer to the session this message belongs to
1256  * @param hdr start of the message
1257  */
1258 static int
1259 process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
1260 {
1261   struct Plugin *plugin = cls;
1262   struct GNUNET_HELLO_Address *address;
1263   struct MacAndSession *mas = client;
1264   struct MacAndSession xmas;
1265   struct GNUNET_ATS_Information ats;
1266   struct FragmentMessage *fm;
1267   struct GNUNET_PeerIdentity tmpsource;
1268   const struct WlanHeader *wlanheader;
1269   int ret;
1270   uint16_t msize;
1271
1272   ats.type = htonl (GNUNET_ATS_NETWORK_TYPE);
1273   ats.value = htonl (GNUNET_ATS_NET_WLAN);
1274   msize = ntohs (hdr->size);
1275
1276   GNUNET_STATISTICS_update (plugin->env->stats,
1277                             "# bytes received via WLAN",
1278                             msize, GNUNET_NO);
1279
1280   switch (ntohs (hdr->type))
1281   {
1282   case GNUNET_MESSAGE_TYPE_HELLO:
1283
1284     if (GNUNET_OK !=
1285         GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource))
1286     {
1287       GNUNET_break_op (0);
1288       break;
1289     }
1290     if (NULL == mas->endpoint)
1291     {
1292       GNUNET_break (0);
1293       break;
1294     }
1295
1296     LOG (GNUNET_ERROR_TYPE_DEBUG,
1297          "Processing %u bytes of HELLO from peer `%s' at MAC %s\n",
1298          (unsigned int) msize,
1299          GNUNET_i2s (&tmpsource),
1300          wlan_plugin_address_to_string (NULL,
1301                                         &mas->endpoint->wlan_addr,
1302                                         sizeof (mas->endpoint->wlan_addr)));
1303
1304     GNUNET_STATISTICS_update (plugin->env->stats,
1305                               _("# HELLO messages received via WLAN"), 1,
1306                               GNUNET_NO);
1307
1308     address = GNUNET_HELLO_address_allocate (&tmpsource, PLUGIN_NAME,
1309         &mas->endpoint->wlan_addr, sizeof (mas->endpoint->wlan_addr),
1310         GNUNET_HELLO_ADDRESS_INFO_INBOUND);
1311     plugin->env->receive (plugin->env->cls,
1312         address, mas->session, hdr);
1313     plugin->env->update_address_metrics (plugin->env->cls,
1314         address, mas->session, &ats, 1);
1315     GNUNET_HELLO_address_free (address);
1316     break;
1317   case GNUNET_MESSAGE_TYPE_FRAGMENT:
1318     if (NULL == mas->endpoint)
1319     {
1320       GNUNET_break (0);
1321       break;
1322     }
1323     LOG (GNUNET_ERROR_TYPE_DEBUG,
1324          "Processing %u bytes of FRAGMENT from MAC %s\n",
1325          (unsigned int) msize,
1326          wlan_plugin_address_to_string (NULL,
1327                                         &mas->endpoint->wlan_addr,
1328                                         sizeof (mas->endpoint->wlan_addr)));
1329     GNUNET_STATISTICS_update (plugin->env->stats,
1330                               _("# fragments received via WLAN"), 1, GNUNET_NO);
1331     (void) GNUNET_DEFRAGMENT_process_fragment (mas->endpoint->defrag,
1332                                               hdr);
1333     break;
1334   case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK:
1335     if (NULL == mas->endpoint)
1336     {
1337       GNUNET_break (0);
1338       break;
1339     }
1340     GNUNET_STATISTICS_update (plugin->env->stats, _("# ACKs received via WLAN"),
1341                               1, GNUNET_NO);
1342     for (fm = mas->endpoint->sending_messages_head; NULL != fm; fm = fm->next)
1343     {
1344       ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
1345       if (GNUNET_OK == ret)
1346       {
1347         LOG (GNUNET_ERROR_TYPE_DEBUG,
1348              "Got last ACK, finished message transmission to `%s' (%p)\n",
1349              wlan_plugin_address_to_string (NULL,
1350                                             &mas->endpoint->wlan_addr,
1351                                             sizeof (mas->endpoint->wlan_addr)),
1352              fm);
1353         mas->endpoint->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT);
1354         if (NULL != fm->cont)
1355         {
1356           fm->cont (fm->cont_cls, &fm->target, GNUNET_OK, fm->size_payload, fm->size_on_wire);
1357           fm->cont = NULL;
1358         }
1359         free_fragment_message (fm);
1360         break;
1361       }
1362       if (GNUNET_NO == ret)
1363       {
1364         LOG (GNUNET_ERROR_TYPE_DEBUG,
1365              "Got an ACK, message transmission to `%s' not yet finished\n",
1366              wlan_plugin_address_to_string (NULL,
1367                                             &mas->endpoint->wlan_addr,
1368                                             sizeof (mas->endpoint->wlan_addr)));
1369         break;
1370       }
1371     }
1372     LOG (GNUNET_ERROR_TYPE_DEBUG,
1373          "ACK not matched against any active fragmentation with MAC `%s'\n",
1374          wlan_plugin_address_to_string (NULL,
1375                                         &mas->endpoint->wlan_addr,
1376                                         sizeof (mas->endpoint->wlan_addr)));
1377     break;
1378   case GNUNET_MESSAGE_TYPE_WLAN_DATA:
1379     if (NULL == mas->endpoint)
1380     {
1381       GNUNET_break (0);
1382       break;
1383     }
1384     if (msize < sizeof (struct WlanHeader))
1385     {
1386       GNUNET_break (0);
1387       break;
1388     }
1389     wlanheader = (const struct WlanHeader *) hdr;
1390     if (0 != memcmp (&wlanheader->target,
1391                      plugin->env->my_identity,
1392                      sizeof (struct GNUNET_PeerIdentity)))
1393     {
1394       LOG (GNUNET_ERROR_TYPE_DEBUG,
1395            "WLAN data for `%s', not for me, ignoring\n",
1396            GNUNET_i2s (&wlanheader->target));
1397       break;
1398     }
1399     if (ntohl (wlanheader->crc) !=
1400         GNUNET_CRYPTO_crc32_n (&wlanheader[1], msize - sizeof (struct WlanHeader)))
1401     {
1402       GNUNET_STATISTICS_update (plugin->env->stats,
1403                                 _("# WLAN DATA messages discarded due to CRC32 error"), 1,
1404                                 GNUNET_NO);
1405       break;
1406     }
1407     xmas.endpoint = mas->endpoint;
1408     if (NULL == (xmas.session = lookup_session (mas->endpoint, &wlanheader->sender)))
1409     {
1410       xmas.session = create_session (mas->endpoint, &wlanheader->sender);
1411       address = GNUNET_HELLO_address_allocate (&wlanheader->sender, PLUGIN_NAME,
1412           &mas->endpoint->wlan_addr, sizeof (struct WlanAddress),
1413           GNUNET_HELLO_ADDRESS_INFO_NONE);
1414       plugin->env->session_start (NULL, address, xmas.session, NULL, 0);
1415       LOG (GNUNET_ERROR_TYPE_DEBUG,
1416           "Notifying transport about peer `%s''s new session %p \n",
1417           GNUNET_i2s (&wlanheader->sender), xmas.session);
1418       GNUNET_HELLO_address_free (address);
1419     }
1420     LOG (GNUNET_ERROR_TYPE_DEBUG,
1421                 "Processing %u bytes of WLAN DATA from peer `%s'\n",
1422          (unsigned int) msize,
1423          GNUNET_i2s (&wlanheader->sender));
1424     (void) GNUNET_SERVER_mst_receive (plugin->wlan_header_payload_tokenizer,
1425                                       &xmas,
1426                                       (const char *) &wlanheader[1],
1427                                       msize - sizeof (struct WlanHeader),
1428                                       GNUNET_YES, GNUNET_NO);
1429     break;
1430   default:
1431     if (NULL == mas->endpoint)
1432     {
1433       GNUNET_break (0);
1434       break;
1435     }
1436     if (NULL == mas->session)
1437     {
1438       GNUNET_break (0);
1439       break;
1440     }
1441     LOG (GNUNET_ERROR_TYPE_DEBUG,
1442          "Received packet with %u bytes of type %u from peer %s\n",
1443          (unsigned int) msize,
1444          (unsigned int) ntohs (hdr->type),
1445          GNUNET_i2s (&mas->session->target));
1446     plugin->env->receive (plugin->env->cls,
1447         mas->session->address,
1448         mas->session,
1449         hdr);
1450     plugin->env->update_address_metrics (plugin->env->cls,
1451         mas->session->address,
1452         mas->session,
1453         &ats, 1);
1454     break;
1455   }
1456   return GNUNET_OK;
1457 }
1458
1459
1460 /**
1461  * Function used for to process the data from the suid process
1462  *
1463  * @param cls the plugin handle
1464  * @param client client that send the data (not used)
1465  * @param hdr header of the GNUNET_MessageHeader
1466  */
1467 static int
1468 handle_helper_message (void *cls, void *client,
1469                        const struct GNUNET_MessageHeader *hdr)
1470 {
1471   struct Plugin *plugin = cls;
1472   struct GNUNET_HELLO_Address *my_address;
1473   const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo;
1474   const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *cm;
1475   struct WlanAddress wa;
1476   struct MacAndSession mas;
1477   uint16_t msize;
1478
1479   msize = ntohs (hdr->size);
1480   switch (ntohs (hdr->type))
1481   {
1482   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
1483     if (msize != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
1484     {
1485       GNUNET_break (0);
1486       break;
1487     }
1488     cm = (const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *) hdr;
1489     if (GNUNET_YES == plugin->have_mac)
1490     {
1491       if (0 == memcmp (&plugin->mac_address,
1492                        &cm->mac,
1493                        sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
1494         break; /* no change */
1495       /* remove old address */
1496       memset (&wa, 0, sizeof (struct WlanAddress));
1497       wa.mac = plugin->mac_address;
1498       wa.options = htonl(plugin->options);
1499       my_address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1500           PLUGIN_NAME, &wa, sizeof (wa), GNUNET_HELLO_ADDRESS_INFO_NONE);
1501       plugin->env->notify_address (plugin->env->cls, GNUNET_NO, my_address);
1502       GNUNET_HELLO_address_free (my_address);
1503     }
1504     plugin->mac_address = cm->mac;
1505     plugin->have_mac = GNUNET_YES;
1506
1507     memset (&wa, 0, sizeof (struct WlanAddress));
1508     wa.mac = plugin->mac_address;
1509     wa.options = htonl(plugin->options);
1510     my_address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1511         PLUGIN_NAME, &wa, sizeof (wa), GNUNET_HELLO_ADDRESS_INFO_NONE);
1512
1513     LOG (GNUNET_ERROR_TYPE_DEBUG,
1514          "Received WLAN_HELPER_CONTROL message with MAC address `%s' for peer `%s'\n",
1515          mac_to_string (&cm->mac),
1516          GNUNET_i2s (plugin->env->my_identity));
1517     plugin->env->notify_address (plugin->env->cls, GNUNET_YES, my_address);
1518     GNUNET_HELLO_address_free (my_address);
1519     break;
1520   case GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER:
1521     LOG (GNUNET_ERROR_TYPE_DEBUG,
1522          "Got data message from helper with %u bytes\n",
1523          msize);
1524     GNUNET_STATISTICS_update (plugin->env->stats,
1525                               _("# DATA messages received via WLAN"), 1,
1526                               GNUNET_NO);
1527     if (msize < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage))
1528     {
1529       GNUNET_break (0);
1530       LOG (GNUNET_ERROR_TYPE_DEBUG,
1531            "Size of packet is too small (%u bytes)\n",
1532            msize);
1533       break;
1534     }
1535     rxinfo = (const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) hdr;
1536
1537     /* check if message is actually for us */
1538     if (0 != memcmp (&rxinfo->frame.addr3, &mac_bssid_gnunet,
1539                      sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
1540     {
1541       /* Not the GNUnet BSSID */
1542       break;
1543     }
1544     if ( (0 != memcmp (&rxinfo->frame.addr1, &bc_all_mac,
1545                        sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) &&
1546          (0 != memcmp (&rxinfo->frame.addr1, &plugin->mac_address,
1547                        sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) )
1548     {
1549       /* Neither broadcast nor specifically for us */
1550       break;
1551     }
1552     if (0 == memcmp (&rxinfo->frame.addr2, &plugin->mac_address,
1553                      sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
1554     {
1555       /* packet is FROM us, thus not FOR us */
1556       break;
1557     }
1558
1559     GNUNET_STATISTICS_update (plugin->env->stats,
1560                               _("# WLAN DATA messages processed"),
1561                               1, GNUNET_NO);
1562     LOG (GNUNET_ERROR_TYPE_DEBUG,
1563          "Receiving %u bytes of data from MAC `%s'\n",
1564          (unsigned int) (msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)),
1565          mac_to_string (&rxinfo->frame.addr2));
1566     wa.mac = rxinfo->frame.addr2;
1567     wa.options = htonl (0);
1568     mas.endpoint = create_macendpoint (plugin, &wa);
1569     mas.session = NULL;
1570     (void) GNUNET_SERVER_mst_receive (plugin->helper_payload_tokenizer,
1571                                       &mas,
1572                                       (const char*) &rxinfo[1],
1573                                       msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage),
1574                                       GNUNET_YES, GNUNET_NO);
1575     break;
1576   default:
1577     GNUNET_break (0);
1578     LOG (GNUNET_ERROR_TYPE_DEBUG,
1579          "Unexpected message of type %u (%u bytes)",
1580          ntohs (hdr->type), ntohs (hdr->size));
1581     break;
1582   }
1583   return GNUNET_OK;
1584 }
1585
1586
1587
1588 /**
1589  * Task to (periodically) send a HELLO beacon
1590  *
1591  * @param cls pointer to the plugin struct
1592  * @param tc scheduler context
1593  */
1594 static void
1595 send_hello_beacon (void *cls,
1596                    const struct GNUNET_SCHEDULER_TaskContext *tc)
1597 {
1598   struct Plugin *plugin = cls;
1599   uint16_t size;
1600   uint16_t hello_size;
1601   struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
1602   const struct GNUNET_MessageHeader *hello;
1603
1604   hello = plugin->env->get_our_hello ();
1605   hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
1606   GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU);
1607   size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + hello_size;
1608   {
1609     char buf[size] GNUNET_ALIGN;
1610
1611     LOG (GNUNET_ERROR_TYPE_DEBUG,
1612          "Sending %u byte HELLO beacon\n",
1613          (unsigned int) size);
1614     radioHeader = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*) buf;
1615     get_radiotap_header (NULL, radioHeader, size);
1616     get_wlan_header (plugin, &radioHeader->frame, &bc_all_mac, size);
1617     memcpy (&radioHeader[1], hello, hello_size);
1618     if (NULL !=
1619         GNUNET_HELPER_send (plugin->suid_helper,
1620                             &radioHeader->header,
1621                             GNUNET_YES /* can drop */,
1622                             NULL, NULL))
1623       GNUNET_STATISTICS_update (plugin->env->stats, _("# HELLO beacons sent via WLAN"),
1624                                 1, GNUNET_NO);
1625   }
1626   plugin->beacon_task =
1627     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1628                                   (HELLO_BEACON_SCALING_FACTOR,
1629                                    plugin->mac_count + 1),
1630                                   &send_hello_beacon,
1631                                   plugin);
1632
1633 }
1634
1635
1636 /**
1637  * Another peer has suggested an address for this
1638  * peer and transport plugin.  Check that this could be a valid
1639  * address.  If so, consider adding it to the list
1640  * of addresses.
1641  *
1642  * @param cls closure
1643  * @param addr pointer to the address
1644  * @param addrlen length of @a addr
1645  * @return #GNUNET_OK if this is a plausible address for this peer
1646  *         and transport
1647  */
1648 static int
1649 wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
1650 {
1651   struct Plugin *plugin = cls;
1652   struct WlanAddress *wa = (struct WlanAddress *) addr;
1653
1654   if (addrlen != sizeof (struct WlanAddress))
1655   {
1656     GNUNET_break_op (0);
1657     return GNUNET_SYSERR;
1658   }
1659   if (GNUNET_YES != plugin->have_mac)
1660   {
1661     LOG (GNUNET_ERROR_TYPE_DEBUG,
1662          "Rejecting MAC `%s': I don't know my MAC!\n",
1663          mac_to_string (addr));
1664     return GNUNET_NO; /* don't know my MAC */
1665   }
1666   if (0 != memcmp (&wa->mac,
1667                    &plugin->mac_address,
1668                    sizeof (wa->mac)))
1669   {
1670     LOG (GNUNET_ERROR_TYPE_DEBUG,
1671          "Rejecting MAC `%s': not my MAC!\n",
1672          mac_to_string (addr));
1673     return GNUNET_NO; /* not my MAC */
1674   }
1675   return GNUNET_OK;
1676 }
1677
1678
1679 /**
1680  * Function called for a quick conversion of the binary address to
1681  * a numeric address.  Note that the caller must not free the
1682  * address and that the next call to this function is allowed
1683  * to override the address again.
1684  *
1685  * @param cls closure
1686  * @param addr binary address
1687  * @param addrlen length of the address
1688  * @return string representing the same address
1689  */
1690 static const char *
1691 wlan_plugin_address_to_string (void *cls,
1692                                const void *addr,
1693                                size_t addrlen)
1694 {
1695   const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
1696   static char macstr[36];
1697
1698   if (sizeof (struct WlanAddress) != addrlen)
1699   {
1700     GNUNET_break (0);
1701     return NULL;
1702   }
1703   mac = &((struct WlanAddress *) addr)->mac;
1704   GNUNET_snprintf (macstr,
1705                    sizeof (macstr),
1706                    "%s.%u.%s",
1707                    PLUGIN_NAME,
1708                    ntohl (((struct WlanAddress *) addr)->options),
1709                    mac_to_string (mac));
1710   return macstr;
1711 }
1712
1713
1714 /**
1715  * Convert the transports address to a nice, human-readable format.
1716  *
1717  * @param cls closure
1718  * @param type name of the transport that generated the address
1719  * @param addr one of the addresses of the host, NULL for the last address
1720  *        the specific address format depends on the transport
1721  * @param addrlen length of the address
1722  * @param numeric should (IP) addresses be displayed in numeric form?
1723  * @param timeout after how long should we give up?
1724  * @param asc function to call on each string
1725  * @param asc_cls closure for @a asc
1726  */
1727 static void
1728 wlan_plugin_address_pretty_printer (void *cls,
1729                                     const char *type,
1730                                     const void *addr,
1731                                     size_t addrlen,
1732                                     int numeric,
1733                                     struct GNUNET_TIME_Relative timeout,
1734                                     GNUNET_TRANSPORT_AddressStringCallback asc,
1735                                     void *asc_cls)
1736 {
1737   const char *ret;
1738
1739   if (sizeof (struct WlanAddress) == addrlen)
1740     ret = wlan_plugin_address_to_string (NULL,
1741                                          addr,
1742                                          addrlen);
1743   else
1744     ret = NULL;
1745   asc (asc_cls,
1746        ret,
1747        (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
1748   asc (asc_cls, NULL, GNUNET_OK);
1749 }
1750
1751
1752 /**
1753  * Exit point from the plugin.
1754  *
1755  * @param cls pointer to the api struct
1756  */
1757 void *
1758 libgnunet_plugin_transport_wlan_done (void *cls)
1759 {
1760   struct WlanAddress wa;
1761   struct GNUNET_HELLO_Address *address;
1762   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1763   struct Plugin *plugin = api->cls;
1764   struct MacEndpoint *endpoint;
1765   struct MacEndpoint *endpoint_next;
1766
1767   if (NULL == plugin)
1768   {
1769     GNUNET_free (api);
1770     return NULL;
1771   }
1772
1773   if (GNUNET_YES == plugin->have_mac)
1774   {
1775     memset (&wa, 0, sizeof(wa));
1776     wa.options = htonl (plugin->options);
1777     wa.mac = plugin->mac_address;
1778     address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
1779         PLUGIN_NAME, &wa, sizeof (struct WlanAddress),
1780         GNUNET_HELLO_ADDRESS_INFO_NONE);
1781
1782     plugin->env->notify_address (plugin->env->cls, GNUNET_NO, address);
1783     plugin->have_mac = GNUNET_NO;
1784
1785     GNUNET_HELLO_address_free (address);
1786   }
1787
1788   if (GNUNET_SCHEDULER_NO_TASK != plugin->beacon_task)
1789   {
1790     GNUNET_SCHEDULER_cancel (plugin->beacon_task);
1791     plugin->beacon_task = GNUNET_SCHEDULER_NO_TASK;
1792   }
1793   if (NULL != plugin->suid_helper)
1794   {
1795     GNUNET_HELPER_stop (plugin->suid_helper, GNUNET_NO);
1796     plugin->suid_helper = NULL;
1797   }
1798   endpoint_next = plugin->mac_head;
1799   while (NULL != (endpoint = endpoint_next))
1800   {
1801     endpoint_next = endpoint->next;
1802     free_macendpoint (endpoint);
1803   }
1804   if (NULL != plugin->fragment_data_tokenizer)
1805   {
1806     GNUNET_SERVER_mst_destroy (plugin->fragment_data_tokenizer);
1807     plugin->fragment_data_tokenizer = NULL;
1808   }
1809   if (NULL != plugin->wlan_header_payload_tokenizer)
1810   {
1811     GNUNET_SERVER_mst_destroy (plugin->wlan_header_payload_tokenizer);
1812     plugin->wlan_header_payload_tokenizer = NULL;
1813   }
1814   if (NULL != plugin->helper_payload_tokenizer)
1815   {
1816     GNUNET_SERVER_mst_destroy (plugin->helper_payload_tokenizer);
1817     plugin->helper_payload_tokenizer = NULL;
1818   }
1819   GNUNET_free_non_null (plugin->interface);
1820   GNUNET_free (plugin);
1821   GNUNET_free (api);
1822   return NULL;
1823 }
1824
1825
1826 /**
1827  * Function called to convert a string address to
1828  * a binary address.
1829  *
1830  * @param cls closure (`struct Plugin *`)
1831  * @param addr string address
1832  * @param addrlen length of the address
1833  * @param buf location to store the buffer
1834  * @param added location to store the number of bytes in the buffer.
1835  *        If the function returns #GNUNET_SYSERR, its contents are undefined.
1836  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1837  */
1838 static int
1839 wlan_string_to_address (void *cls, const char *addr, uint16_t addrlen,
1840                         void **buf, size_t *added)
1841 {
1842   struct WlanAddress *wa;
1843   unsigned int a[6];
1844   unsigned int i;
1845   char plugin[5];
1846   uint32_t options;
1847
1848   if ((NULL == addr) || (addrlen == 0))
1849   {
1850     GNUNET_break (0);
1851     return GNUNET_SYSERR;
1852   }
1853   if ('\0' != addr[addrlen - 1])
1854   {
1855     GNUNET_break (0);
1856     return GNUNET_SYSERR;
1857   }
1858   if (strlen (addr) != addrlen - 1)
1859   {
1860     GNUNET_break (0);
1861     return GNUNET_SYSERR;
1862   }
1863
1864   if (8 != SSCANF (addr,
1865                    "%4s.%u.%X:%X:%X:%X:%X:%X",
1866                    plugin, &options,
1867                    &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
1868   {
1869     GNUNET_break (0);
1870     return GNUNET_SYSERR;
1871   }
1872   wa = GNUNET_new (struct WlanAddress);
1873   for (i=0;i<6;i++)
1874     wa->mac.mac[i] = a[i];
1875   wa->options = htonl (0);
1876   *buf = wa;
1877   *added = sizeof (struct WlanAddress);
1878   return GNUNET_OK;
1879 }
1880
1881
1882 static void
1883 wlan_plugin_update_session_timeout (void *cls,
1884                                   const struct GNUNET_PeerIdentity *peer,
1885                                   struct Session *session)
1886 {
1887   if (session->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1888     GNUNET_SCHEDULER_cancel (session->timeout_task);
1889
1890   session->timeout_task = GNUNET_SCHEDULER_add_delayed (
1891       GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, session);
1892 }
1893
1894 /**
1895  * Entry point for the plugin.
1896  *
1897  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
1898  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
1899  */
1900 void *
1901 libgnunet_plugin_transport_wlan_init (void *cls)
1902 {
1903   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1904   struct GNUNET_TRANSPORT_PluginFunctions *api;
1905   struct Plugin *plugin;
1906   char *interface;
1907   unsigned long long testmode;
1908   char *binary;
1909
1910   /* check for 'special' mode */
1911   if (NULL == env->receive)
1912   {
1913     /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
1914        initialze the plugin or the API */
1915     api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
1916     api->cls = NULL;
1917     api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
1918     api->address_to_string = &wlan_plugin_address_to_string;
1919     api->string_to_address = &wlan_string_to_address;
1920     return api;
1921   }
1922
1923   testmode = 0;
1924   /* check configuration */
1925   if ( (GNUNET_YES ==
1926         GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE")) &&
1927        ( (GNUNET_SYSERR ==
1928           GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
1929                                                  "TESTMODE", &testmode)) ||
1930          (testmode > 2) ) )
1931   {
1932     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1933                                "transport-wlan", "TESTMODE");
1934     return NULL;
1935   }
1936   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-transport-wlan");
1937   if ( (0 == testmode) &&
1938        (GNUNET_YES != GNUNET_OS_check_helper_binary (binary, GNUNET_YES, NULL)) )
1939   {
1940     LOG (GNUNET_ERROR_TYPE_ERROR,
1941          _("Helper binary `%s' not SUID, cannot run WLAN transport\n"),
1942          "gnunet-helper-transport-wlan");
1943     GNUNET_free (binary);
1944     return NULL;
1945   }
1946     GNUNET_free (binary);
1947   if (GNUNET_YES !=
1948       GNUNET_CONFIGURATION_get_value_string
1949       (env->cfg, "transport-wlan", "INTERFACE",
1950        &interface))
1951   {
1952     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1953                                "transport-wlan", "INTERFACE");
1954     return NULL;
1955   }
1956
1957   plugin = GNUNET_new (struct Plugin);
1958   plugin->interface = interface;
1959   plugin->env = env;
1960   GNUNET_STATISTICS_set (plugin->env->stats, _("# WLAN sessions allocated"),
1961                          0, GNUNET_NO);
1962   GNUNET_STATISTICS_set (plugin->env->stats, _("# WLAN MAC endpoints allocated"),
1963                          0, 0);
1964   GNUNET_BANDWIDTH_tracker_init (&plugin->tracker, NULL, NULL,
1965                                  GNUNET_BANDWIDTH_value_init (100 * 1024 *
1966                                                               1024 / 8), 100);
1967   plugin->fragment_data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
1968   plugin->wlan_header_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
1969   plugin->helper_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
1970   plugin->beacon_task = GNUNET_SCHEDULER_add_now (&send_hello_beacon,
1971                                                   plugin);
1972
1973   plugin->options = 0;
1974
1975   /* some compilers do not like switch on 'long long'... */
1976   switch ((unsigned int) testmode)
1977   {
1978   case 0: /* normal */
1979     plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan";
1980     plugin->helper_argv[1] = interface;
1981     plugin->helper_argv[2] = NULL;
1982     plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO,
1983                                                "gnunet-helper-transport-wlan",
1984                                                plugin->helper_argv,
1985                                                &handle_helper_message,
1986                                                NULL,
1987                                                plugin);
1988     break;
1989   case 1: /* testmode, peer 1 */
1990     plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy";
1991     plugin->helper_argv[1] = (char *) "1";
1992     plugin->helper_argv[2] = NULL;
1993     plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO,
1994                                                "gnunet-helper-transport-wlan-dummy",
1995                                                plugin->helper_argv,
1996                                                &handle_helper_message,
1997                                                NULL,
1998                                                plugin);
1999     break;
2000   case 2: /* testmode, peer 2 */
2001     plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy";
2002     plugin->helper_argv[1] = (char *) "2";
2003     plugin->helper_argv[2] = NULL;
2004     plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO,
2005                                                "gnunet-helper-transport-wlan-dummy",
2006                                                plugin->helper_argv,
2007                                                &handle_helper_message,
2008                                                NULL,
2009                                                plugin);
2010     break;
2011   default:
2012     GNUNET_assert (0);
2013   }
2014
2015   api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
2016   api->cls = plugin;
2017   api->send = &wlan_plugin_send;
2018   api->get_session = &wlan_plugin_get_session;
2019   api->disconnect_peer = &wlan_plugin_disconnect_peer;
2020   api->disconnect_session = &wlan_plugin_disconnect_session;
2021   api->query_keepalive_factor = &wlan_plugin_query_keepalive_factor;
2022   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2023   api->check_address = &wlan_plugin_address_suggested;
2024   api->address_to_string = &wlan_plugin_address_to_string;
2025   api->string_to_address = &wlan_string_to_address;
2026   api->get_network = &wlan_get_network;
2027   api->update_session_timeout = &wlan_plugin_update_session_timeout;
2028   return api;
2029 }
2030
2031
2032 /* end of plugin_transport_wlan.c */