1 /* -- updatedd: libtzo.c --
2 *
3 * Copyright (C) 2004, 2005 Philipp Benner
4 *
5 * This file is part of UpdateDD - http://updatedd.philipp-benner.de.
6 *
7 * UpdateDD is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * UpdateDD is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with UpdateDD; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <ctype.h>
28 #include <unistd.h>
29 #include <getopt.h>
30
31 #include <dprintf.h>
32 #include <get_connection.h>
33 #include <updatedd-exception.h>
34 #include <ret_codes.h>
35 #include <version.h>
36
37 #include "libtzo.h"
38
39 static void
print_usage(char * pname,FILE * fp)40 print_usage(char *pname, FILE *fp)
41 {
42 (void)fprintf(fp,
43 "\nUsage: %s [...] %s -- [OPTION]... [USERNAME:PASSWORD] HOSTNAME\n\n",
44 pname, COLORED("tzo"));
45 (void)fprintf(fp,
46 "For security reasons use the environment variable LOGIN instead of\n"
47 "passing the login information directly.\n\n"
48
49 "Options:\n"
50 " -4 --ipv4 <address> ip address version 4\n"
51 " --help print help and exit\n"
52 " --version display version information and exit\n\n"
53
54 "WARNING: This plugin has never been tested due to the fact that\n"
55 "tzo.com is not free! If you are a registered tzo user please help\n"
56 "to complete this plugin.\n\n"
57
58 "Report bugs to <"EMAIL">.\n\n");
59
60 return;
61 }
62
63 static void
print_version(FILE * fp)64 print_version(FILE *fp)
65 {
66
67 (void)fprintf(fp,
68 "\n" PNAME " plugin for tzo.com version " VERSION ",\n"
69 "Copyright (C) 2005 Philipp Benner.\n"
70 HOMEPAGE "\n\n"
71
72 "This is free software, and you are welcome to redistribute it\n"
73 "under certain conditions; see the source for copying conditions.\n"
74 "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n"
75 "FOR A PARTICULAR PURPOSE.\n\n");
76
77 return;
78
79 }
80
81 static void
ret_msg(int mode,const char * fmt,...)82 ret_msg(int mode, const char *fmt, ...)
83 {
84
85 va_list az;
86
87 va_start(az, fmt);
88 (void)vs_warn(ret_msg_buf, BUFSIZE, mode, fmt, az);
89 va_end(az);
90
91 return;
92
93 }
94
95 int
dyndns(int argc,char * argv[])96 dyndns(int argc, char *argv[])
97 {
98
99 struct arguments args;
100 const char *ptr;
101 int s, ret;
102
103 (void)memset(&args, 0, sizeof(struct arguments));
104
105 if(get_flags(&args, argc, argv) != RET_OK) {
106 return RET_WRONG_USAGE;
107 }
108
109 s = get_connection(DYNDNSHOST, PORT, &ptr);
110 if(s == -1) {
111 ret_msg(HERR, "%s: %s", ptr, DYNDNSHOST);
112 ret = RET_WARNING;
113 } else {
114 ret = update_dyndns(s, &args);
115 if(ret == RET_OK) {
116 ret = check_server_msg(s, args.hostname);
117 }
118 (void)close(s);
119 }
120
121 return ret;
122
123 }
124
125 static int
get_flags(struct arguments * args,int argc,char * argv[])126 get_flags(struct arguments *args, int argc, char *argv[])
127 {
128
129 int c;
130
131 for(;;) {
132
133 int option_index = 0;
134 static struct option long_options[] = {
135 { "ipv4", 1, 0, '4' },
136 { "help", 0, 0, 'h' },
137 { "version", 0, 0, 'v' },
138 { NULL, 0, 0, 0 }
139 };
140
141 c = getopt_long(argc, argv, "4:",
142 long_options, &option_index);
143
144 if(c == -1) break;
145
146 switch(c) {
147 case '4':
148 args->ipv4 = optarg;
149 break;
150 case 'h':
151 print_usage(argv[ARGV_PNAME], stdout);
152 exit(EXIT_SUCCESS);
153 case 'v':
154 print_version(stdout);
155 exit(EXIT_SUCCESS);
156 }
157 }
158
159 switch(argc-optind) {
160 default:
161 ret_msg(NONE, "wrong usage");
162 return RET_WRONG_USAGE;
163
164 case 2:
165 args->login = getenv("LOGIN");
166 if(args->login == NULL) {
167 ret_msg(NONE,
168 "environment variable LOGIN is empty");
169 return RET_WRONG_USAGE;
170 }
171 break;
172 case 3:
173 args->login = argv[ARGV_LOGIN];
174 }
175 args->hostname = argv[ARGV_HOSTNAME];
176
177 return RET_OK;
178
179 }
180
181 #define BUFFREE(name) BUFSIZE - strlen(name)
182
183 static int
update_dyndns(int s,struct arguments * args)184 update_dyndns(int s, struct arguments *args)
185 {
186
187 char *user, *pass;
188 char msg[BUFSIZE], server_msg[BUFSIZE];
189 int len = strlen(args->login), ret;
190 char login[len];
191
192 strcpy(login, args->login);
193 user = strtok(login, ":");
194 pass = strtok(NULL, "");
195
196 (void)snprintf(msg, BUFSIZE, "R %s,%s,%s",
197 args->hostname,
198 user, pass);
199
200 if(args->ipv4) {
201 (void)strncat(msg, ",", BUFFREE(msg));
202 (void)strncat(msg, args->ipv4, BUFFREE(msg));
203 }
204
205 (void)memset(server_msg, 0, BUFSIZE);
206 if(read(s, server_msg, BUFSIZE-1) == -1) {
207 ret_msg(PERR, "%s: read() failed",
208 args->hostname);
209 ret = RET_ERROR;
210 } else {
211 print_debug("Server Message: %s", server_msg);
212 if(strstr(server_msg, "TZO/Linksys Update Server")) {
213 print_debug("Message: %s\n", msg);
214 (void)dprintf(s, "%s\r\n", msg);
215 ret = RET_OK;
216 } else {
217 ret_msg(NONE, "%s: invalid server",
218 args->hostname);
219 ret = RET_ERROR;
220 }
221 }
222
223 return ret;
224
225 }
226
227 static int
check_server_msg(int s,const char * hostname)228 check_server_msg(int s, const char *hostname)
229 {
230
231 char server_msg[BUFSIZE];
232 int ret;
233
234 (void)memset(server_msg, 0, BUFSIZE);
235 if((ret = read(s, server_msg, BUFSIZE-1)) != -1) {
236 print_debug("Server Message: %s", server_msg);
237
238 ret_msg(NONE, "%s: %s",
239 hostname, server_msg+3);
240 if(strncmp(server_msg, "40", 2) == 0) {
241 ret = RET_OK;
242 } else {
243 ret = RET_ERROR;
244 }
245 } else {
246 ret_msg(PERR, "%s: read() failed",
247 hostname);
248 ret = RET_ERROR;
249 }
250
251 return ret;
252
253 }
254