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
write_timestamp(FILE * f)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
debug_print(struct hs20_svc * ctx,int print,const char * fmt,...)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
debug_dump_node(struct hs20_svc * ctx,const char * title,xml_node_t * node)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
process(struct hs20_svc * ctx)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
usage(void)131 static void usage(void)
132 {
133 printf("usage:\n"
134 "hs20_spp_server -r<root directory> [-f<debug log>]\n");
135 }
136
137
main(int argc,char * argv[])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