test.c
  1  // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2  //
  3  // Licensed under the Apache License, Version 2.0 (the "License");
  4  // you may not use this file except in compliance with the License.
  5  // You may obtain a copy of the License at
  6  
  7  //     http://www.apache.org/licenses/LICENSE-2.0
  8  //
  9  // Unless required by applicable law or agreed to in writing, software
 10  // distributed under the License is distributed on an "AS IS" BASIS,
 11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  // See the License for the specific language governing permissions and
 13  // limitations under the License.
 14  
 15  #include <stdio.h>
 16  #include <stdlib.h>
 17  #include <unistd.h>
 18  #include <signal.h>
 19  #include <string.h>
 20  
 21  #include "mdns.h"
 22  #include "mdns_private.h"
 23  
 24  //
 25  // Global stuctures containing packet payload, search
 26  mdns_rx_packet_t g_packet;
 27  struct pbuf mypbuf;
 28  mdns_search_once_t * search = NULL;
 29  
 30  //
 31  // Dependency injected test functions
 32  void mdns_test_execute_action(void * action);
 33  mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto);
 34  mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results);
 35  esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t * search);
 36  void mdns_test_search_free(mdns_search_once_t * search);
 37  void mdns_test_init_di(void);
 38  
 39  //
 40  // mdns function wrappers for mdns setup in test mode
 41  static int mdns_test_hostname_set(const char * mdns_hostname)
 42  {
 43      int ret = mdns_hostname_set(mdns_hostname);
 44      mdns_action_t * a = NULL;
 45      GetLastItem(&a);
 46      mdns_test_execute_action(a);
 47      return ret;
 48  }
 49  
 50  static int mdns_test_service_instance_name_set(const char * service, const char * proto, const char * instance)
 51  {
 52      int ret = mdns_service_instance_name_set(service, proto, instance);
 53      mdns_action_t * a = NULL;
 54      GetLastItem(&a);
 55      mdns_test_execute_action(a);
 56      return ret;
 57  }
 58  
 59  static int mdns_test_service_txt_set(const char * service, const char * proto,  uint8_t num_items, mdns_txt_item_t txt[])
 60  {
 61      int ret = mdns_service_txt_set(service, proto, txt, num_items);
 62      mdns_action_t * a = NULL;
 63      GetLastItem(&a);
 64      mdns_test_execute_action(a);
 65      return ret;
 66  }
 67  
 68  static int mdns_test_service_add(const char * service_name, const char * proto, uint32_t port)
 69  {
 70      if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) {
 71          // This is expected failure as the service thread is not running
 72      }
 73      mdns_action_t * a = NULL;
 74      GetLastItem(&a);
 75      mdns_test_execute_action(a);
 76  
 77      if (mdns_test_mdns_get_service_item(service_name, proto)==NULL) {
 78          return ESP_FAIL;
 79      }
 80      return ESP_OK;
 81  }
 82  
 83  static mdns_result_t* mdns_test_query(const char * service_name, const char * proto)
 84  {
 85      search = mdns_test_search_init(NULL, service_name, proto, MDNS_TYPE_PTR, 3000, 20);
 86      if (!search) {
 87          abort();
 88      }
 89  
 90      if (mdns_test_send_search_action(ACTION_SEARCH_ADD, search)) {
 91          mdns_test_search_free(search);
 92          abort();
 93      }
 94  
 95      mdns_action_t * a = NULL;
 96      GetLastItem(&a);
 97      mdns_test_execute_action(a);
 98      return NULL;
 99  }
100  
101  static void mdns_test_query_free(void)
102  {
103      mdns_test_search_free(search);
104  }
105  
106  //
107  // function "under test" where afl-mangled packets passed
108  //
109  void mdns_parse_packet(mdns_rx_packet_t * packet);
110  
111  //
112  // Test starts here
113  //
114  int main(int argc, char** argv)
115  {
116      int i;
117      const char * mdns_hostname = "minifritz";
118      const char * mdns_instance = "Hristo's Time Capsule";
119      mdns_txt_item_t arduTxtData[4] = {
120          {"board","esp32"},
121          {"tcp_check","no"},
122          {"ssh_upload","no"},
123          {"auth_upload","no"}
124      };
125  
126      const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32};
127      
128      uint8_t buf[1460];
129      char winstance[21+strlen(mdns_hostname)];
130  
131      sprintf(winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]", mdns_hostname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
132  
133      // Init depencency injected methods
134      mdns_test_init_di();
135  
136      if (mdns_init()) {
137          abort();
138      }
139  
140      if (mdns_test_hostname_set(mdns_hostname)) {
141          abort();
142      }
143  
144      if (mdns_test_service_add("_workstation", "_tcp", 9)) {
145          abort();
146      }
147      if (mdns_test_service_instance_name_set("_workstation", "_tcp", winstance)) {
148          abort();
149      }
150  
151      if (mdns_test_service_add("_arduino", "_tcp", 3232)) {
152          abort();
153      }
154  
155      if (mdns_test_service_txt_set("_arduino", "_tcp", 4, arduTxtData)) {
156          abort();
157      }
158  
159      if (mdns_test_service_add("_http", "_tcp", 80)) {
160          abort();
161      }
162  
163      if (mdns_test_service_instance_name_set("_http", "_tcp", "ESP WebServer")) {
164          abort();
165      }
166  
167      if (
168             mdns_test_service_add("_afpovertcp", "_tcp", 548)
169          || mdns_test_service_add("_rfb", "_tcp", 885)
170          || mdns_test_service_add("_smb", "_tcp", 885)
171          || mdns_test_service_add("_adisk", "_tcp", 885)
172          || mdns_test_service_add("_airport", "_tcp", 885)
173          || mdns_test_service_add("_printer", "_tcp", 885)
174          || mdns_test_service_add("_airplay", "_tcp", 885)
175          || mdns_test_service_add("_raop", "_tcp", 885)
176          || mdns_test_service_add("_uscan", "_tcp", 885)
177          || mdns_test_service_add("_uscans", "_tcp", 885)
178          || mdns_test_service_add("_ippusb", "_tcp", 885)
179          || mdns_test_service_add("_scanner", "_tcp", 885)
180          || mdns_test_service_add("_ipp", "_tcp", 885)
181          || mdns_test_service_add("_ipps", "_tcp", 885)
182          || mdns_test_service_add("_pdl-datastream", "_tcp", 885)
183          || mdns_test_service_add("_ptp", "_tcp", 885)
184          || mdns_test_service_add("_sleep-proxy", "_udp", 885))
185      {
186          abort(); 
187      }
188          
189      mdns_result_t * results = NULL;
190      FILE *file;
191      size_t nread;
192  
193  #ifdef INSTR_IS_OFF
194      size_t len = 1460;
195      memset(buf, 0, 1460);
196  
197      if (argc != 2)
198      {
199          printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n");
200          return 1;
201      }
202      else
203      {
204          //
205          // Note: parameter1 is a file (mangled packet) which caused the crash
206          file = fopen(argv[1], "r");
207          if (file) {
208              len = fread(buf, 1, 1460, file);
209          }
210          fclose(file);
211      }
212  
213      for (i=0; i<1; i++) {
214  #else
215      while (__AFL_LOOP(1000)) {
216          memset(buf, 0, 1460);
217          size_t len = read(0, buf, 1460);
218  #endif
219          mypbuf.payload = buf;
220          mypbuf.len = len;
221          g_packet.pb = &mypbuf;
222          mdns_test_query("_afpovertcp", "_tcp");
223          mdns_parse_packet(&g_packet);
224      }
225      ForceTaskDelete();
226      mdns_free();
227      return 0;
228  }