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