1 /* 2 * Hotspot 2.0 SPP server - standalone version 3 * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 #include <time.h> 11 #include <sqlite3.h> 12 13 #include "common.h" 14 #include "xml-utils.h" 15 #include "spp_server.h" 16 17 18 static void write_timestamp(FILE *f) 19 { 20 time_t t; 21 struct tm *tm; 22 23 time(&t); 24 tm = localtime(&t); 25 26 fprintf(f, "%04u-%02u-%02u %02u:%02u:%02u ", 27 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 28 tm->tm_hour, tm->tm_min, tm->tm_sec); 29 } 30 31 32 void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...) 33 { 34 va_list ap; 35 36 if (ctx->debug_log == NULL) 37 return; 38 39 write_timestamp(ctx->debug_log); 40 va_start(ap, fmt); 41 vfprintf(ctx->debug_log, fmt, ap); 42 va_end(ap); 43 44 fprintf(ctx->debug_log, "\n"); 45 } 46 47 48 void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node) 49 { 50 char *str; 51 52 if (ctx->debug_log == NULL) 53 return; 54 str = xml_node_to_str(ctx->xml, node); 55 if (str == NULL) 56 return; 57 58 write_timestamp(ctx->debug_log); 59 fprintf(ctx->debug_log, "%s: '%s'\n", title, str); 60 os_free(str); 61 } 62 63 64 static int process(struct hs20_svc *ctx) 65 { 66 int dmacc = 0; 67 xml_node_t *soap, *spp, *resp; 68 char *user, *realm, *post, *str; 69 70 ctx->addr = getenv("HS20ADDR"); 71 if (ctx->addr) 72 debug_print(ctx, 1, "Connection from %s", ctx->addr); 73 74 user = getenv("HS20USER"); 75 if (user && strlen(user) == 0) 76 user = NULL; 77 realm = getenv("HS20REALM"); 78 if (realm == NULL) { 79 debug_print(ctx, 1, "HS20REALM not set"); 80 return -1; 81 } 82 post = getenv("HS20POST"); 83 if (post == NULL) { 84 debug_print(ctx, 1, "HS20POST not set"); 85 return -1; 86 } 87 88 soap = xml_node_from_buf(ctx->xml, post); 89 if (soap == NULL) { 90 debug_print(ctx, 1, "Could not parse SOAP data"); 91 return -1; 92 } 93 debug_dump_node(ctx, "Received SOAP message", soap); 94 spp = soap_get_body(ctx->xml, soap); 95 if (spp == NULL) { 96 debug_print(ctx, 1, "Could not get SPP message"); 97 xml_node_free(ctx->xml, soap); 98 return -1; 99 } 100 debug_dump_node(ctx, "Received SPP message", spp); 101 102 resp = hs20_spp_server_process(ctx, spp, user, realm, dmacc); 103 xml_node_free(ctx->xml, soap); 104 if (resp == NULL && user == NULL) { 105 debug_print(ctx, 1, "Request HTTP authentication"); 106 return 2; /* Request authentication */ 107 } 108 if (resp == NULL) { 109 debug_print(ctx, 1, "No response"); 110 return -1; 111 } 112 113 soap = soap_build_envelope(ctx->xml, resp); 114 if (soap == NULL) { 115 debug_print(ctx, 1, "SOAP envelope building failed"); 116 return -1; 117 } 118 str = xml_node_to_str(ctx->xml, soap); 119 xml_node_free(ctx->xml, soap); 120 if (str == NULL) { 121 debug_print(ctx, 1, "Could not get node string"); 122 return -1; 123 } 124 printf("%s", str); 125 free(str); 126 127 return 0; 128 } 129 130 131 static void usage(void) 132 { 133 printf("usage:\n" 134 "hs20_spp_server -r<root directory> [-f<debug log>]\n"); 135 } 136 137 138 int main(int argc, char *argv[]) 139 { 140 struct hs20_svc ctx; 141 int ret; 142 143 os_memset(&ctx, 0, sizeof(ctx)); 144 for (;;) { 145 int c = getopt(argc, argv, "f:r:"); 146 if (c < 0) 147 break; 148 switch (c) { 149 case 'f': 150 if (ctx.debug_log) 151 break; 152 ctx.debug_log = fopen(optarg, "a"); 153 if (ctx.debug_log == NULL) { 154 printf("Could not write to %s\n", optarg); 155 return -1; 156 } 157 break; 158 case 'r': 159 ctx.root_dir = optarg; 160 break; 161 default: 162 usage(); 163 return -1; 164 } 165 } 166 if (ctx.root_dir == NULL) { 167 usage(); 168 return -1; 169 } 170 ctx.xml = xml_node_init_ctx(&ctx, NULL); 171 if (ctx.xml == NULL) 172 return -1; 173 if (hs20_spp_server_init(&ctx) < 0) { 174 xml_node_deinit_ctx(ctx.xml); 175 return -1; 176 } 177 178 ret = process(&ctx); 179 debug_print(&ctx, 1, "process() --> %d", ret); 180 181 xml_node_deinit_ctx(ctx.xml); 182 hs20_spp_server_deinit(&ctx); 183 if (ctx.debug_log) 184 fclose(ctx.debug_log); 185 186 return ret; 187 } 188