1/* ============================================================================ 2 * Copyright (C) 1998-2001 Angus Mackay. All rights reserved; 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2, or (at your option) 7 * any later version. 8 * 9 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 10 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 11 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 13 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 14 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 15 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 16 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 17 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 18 * POSSIBILITY OF SUCH DAMAGE. 19 * ============================================================================ 20 */ 21 22/* 23 * ez-ipupdate 24 * 25 * a very simple dynDNS client for the ez-ip dynamic dns service 26 * (http://www.ez-ip.net). 27 * 28 * why this program when something like: 29 * curl -u user:pass http://www.ez-ip.net/members/update/?key=val&... 30 * would do the trick? because there are nicer clients for other OSes and 31 * I don't like to see UNIX get the short end of the stick. 32 * 33 * tested under Linux and Solaris. 34 * 35 */ 36//2007.03.14 Yau add 37#ifdef ASUS_DDNS 38#include "asus_ddns.h" 39#include <bcmnvram.h> 40#endif // ASUS_DDNS 41 42#ifdef HAVE_CONFIG_H 43# include <config.h> 44#endif 45 46#ifndef EMBED 47// you man very well need to edit this, don't worry though, email is only sent 48// if bad things happend and it has to exit when in daemon mode. 49#define SEND_EMAIL_CMD "mail" 50#endif 51 52#define EZIP_DEFAULT_SERVER "www.EZ-IP.Net" 53#define EZIP_DEFAULT_PORT "80" 54#define EZIP_REQUEST "/members/update/" 55 56#define PGPOW_DEFAULT_SERVER "www.penguinpowered.com" 57#define PGPOW_DEFAULT_PORT "2345" 58#define PGPOW_REQUEST "update" 59#define PGPOW_VERSION "1.0" 60 61#define DHS_DEFAULT_SERVER "members.dhs.org" 62#define DHS_DEFAULT_PORT "80" 63#define DHS_REQUEST "/nic/hosts" 64#define DHS_SUCKY_TIMEOUT 5 //60 65 66#define DYNDNS_DEFAULT_SERVER "members.dyndns.org" 67#define DYNDNS_DEFAULT_PORT "80" 68#define DYNDNS_REQUEST "/nic/update" 69#define DYNDNS_STAT_REQUEST "/nic/update" 70#define DYNDNS_MAX_INTERVAL (25*24*3600) 71 72#define QDNS_DEFAULT_SERVER "members.3322.org" 73#define QDNS_DEFAULT_PORT "80" 74#define QDNS_REQUEST "/dyndns/update" 75#define QDNS_STAT_REQUEST "/dyndns/update" 76 77#define ODS_DEFAULT_SERVER "update.ods.org" 78#define ODS_DEFAULT_PORT "7070" 79#define ODS_REQUEST "update" 80 81#define TZO_DEFAULT_SERVER "cgi.tzo.com" 82#define TZO_DEFAULT_PORT "80" 83#define TZO_REQUEST "/webclient/signedon.html" 84 85#define GNUDIP_DEFAULT_SERVER "" 86#define GNUDIP_DEFAULT_PORT "3495" 87#define GNUDIP_REQUEST "0" 88 89#define EASYDNS_DEFAULT_SERVER "members.easydns.com" 90#define EASYDNS_DEFAULT_PORT "80" 91#define EASYDNS_REQUEST "/dyn/ez-ipupdate.php" 92 93#define EASYDNS_PARTNER_DEFAULT_SERVER "api.easydns.com" 94#define EASYDNS_PARTNER_DEFAULT_PORT "80" 95#define EASYDNS_PARTNER_REQUEST "/dyn/ez-ipupdate.php" 96 97#define JUSTL_DEFAULT_SERVER "www.justlinux.com" 98#define JUSTL_DEFAULT_PORT "80" 99#define JUSTL_REQUEST "/bin/controlpanel/dyndns/jlc.pl" 100#define JUSTL_VERSION "2.0" 101 102#define DYNS_DEFAULT_SERVER "www.dyns.cx" 103#define DYNS_DEFAULT_PORT "80" 104#define DYNS_REQUEST "/postscript.php" 105 106#define HN_DEFAULT_SERVER "dup.hn.org" 107#define HN_DEFAULT_PORT "80" 108#define HN_REQUEST "/vanity/update" 109 110#define ZONEEDIT_DEFAULT_SERVER "www.zoneedit.com" 111#define ZONEEDIT_DEFAULT_PORT "80" 112#define ZONEEDIT_REQUEST "/auth/dynamic.html" 113 114#define HEIPV6TB_DEFAULT_SERVER "ipv6tb.he.net" 115#define HEIPV6TB_DEFAULT_PORT "80" 116#define HEIPV6TB_REQUEST "/index.cgi" 117 118#define DEFAULT_TIMEOUT 5 //120 119#define DEFAULT_UPDATE_PERIOD 120 120#define DEFAULT_RESOLV_PERIOD 30 121 122#ifdef DEBUG 123# define BUFFER_SIZE (16*1024) 124#else 125# define BUFFER_SIZE (4*1024-1) 126#endif 127 128#ifdef HAVE_GETOPT_H 129# include <getopt.h> 130#endif 131#include <stdio.h> 132#include <stdlib.h> 133#include <string.h> 134#include <ctype.h> 135#include <unistd.h> 136#include <time.h> 137#if HAVE_FCNTL_H 138# include <fcntl.h> 139#endif 140#include <netinet/in.h> 141#if HAVE_ARPA_INET_H 142# include <arpa/inet.h> 143#endif 144#if HAVE_ERRNO_H 145# include <errno.h> 146#endif 147#include <netdb.h> 148#include <sys/socket.h> 149#if HAVE_SYS_TYPES_H 150# include <sys/types.h> 151#endif 152#if HAVE_SIGNAL_H 153# include <signal.h> 154#endif 155#if HAVE_SYS_TIME_H 156# include <sys/time.h> 157#endif 158#if HAVE_SYS_WAIT_H 159# include <sys/wait.h> 160#endif 161#if HAVE_SYSLOG_H 162# include <syslog.h> 163#endif 164#if HAVE_STDARG_H 165# include <stdarg.h> 166#endif 167#include <error.h> 168#if HAVE_PWD_H && HAVE_GRP_H 169# include <pwd.h> 170# include <grp.h> 171#endif 172#if defined(HAVE_FORK) && !defined(HAVE_VFORK) 173# define vfork fork 174#endif 175#if USE_MD5 176# include <md5.h> 177# define MD5_DIGEST_BYTES (16) 178#endif 179 180 181#if __linux__ || __SVR4 || __OpenBSD__ || __FreeBSD__ || __NetBSD__ 182# define IF_LOOKUP 1 183# include <sys/ioctl.h> 184# include <net/if.h> 185# ifdef HAVE_SYS_SOCKIO_H 186# include <sys/sockio.h> 187# endif 188#endif 189 190#include <dprintf.h> 191#include <conf_file.h> 192#include <cache_file.h> 193#include <pid_file.h> 194 195#if !defined(__GNUC__) && !defined(HAVE_SNPRINTF) 196#error "get gcc, fix this code, or find yourself a snprintf!" 197#else 198# if HAVE_SNPRINTF 199# define snprintf(x, y, z...) snprintf(x, y, ## z) 200# else 201# define snprintf(x, y, z...) sprintf(x, ## z) 202# endif 203#endif 204#if HAVE_VSNPRINTF 205# define vsnprintf(x, y, z...) vsnprintf(x, y, ## z) 206#else 207# define vsnprintf(x, y, z...) vsprintf(x, ## z) 208#endif 209 210#ifndef HAVE_HERROR 211# define herror(x) show_message("%s: error\n", x) 212#endif 213 214#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) 215#define N_STR(x) (x == NULL ? "(null)" : x) 216 217#ifndef OS 218# define OS "unknown" 219#endif 220 221// the min period for checking the interface 222#define MIN_UPDATE_PERIOD 10 223// the min/max time to wait if we fail to update 224#define MIN_WAIT_PERIOD 300 225#define MAX_WAIT_PERIOD (2*3600) 226// the min time that max-period can be set to 227#define MIN_MAXINTERVAL (24*3600) 228// the max time we will wait if the server tells us to 229#define MAX_WAITRESPONSE_WAIT (24*3600) 230#define MAX_MESSAGE_LEN 256 231#define ARGLENGTH 32 232#define BLOCK_FILE "/var/run/ez-ipupdate.block" 233#define PID_FILE "/var/run/ez-ipupdate.pid" 234 235/**************************************************/ 236 237struct service_t 238{ 239 char *title; 240 char *names[3]; 241 void (*init)(void); 242 int (*update_entry)(void); 243 int (*check_info)(void); 244 char **fields_used; 245 char *default_server; 246 char *default_port; 247 char *default_request; 248}; 249 250enum { 251 UPDATERES_OK = 0, 252 UPDATERES_ERROR, 253 UPDATERES_SHUTDOWN, 254}; 255 256/**************************************************/ 257 258char *program_name = NULL; 259char *cache_file = NULL; 260char *config_file = NULL; 261char *server = NULL; 262char *port = NULL; 263char user[256]; 264char auth[512]; 265char user_name[128]; 266char password[128]; 267char *address = NULL; 268char *request = NULL; 269char *request_over_ride = NULL; 270int wildcard = 0; 271char *mx = NULL; 272char *url = NULL; 273char *host = NULL; 274char *cloak_title = NULL; 275char *interface = NULL; 276int ntrys = 1; 277int update_period = DEFAULT_UPDATE_PERIOD; 278int resolv_period = DEFAULT_RESOLV_PERIOD; 279struct timeval timeout; 280int max_interval = 0; 281int service_set = 0; 282char *post_update_cmd = NULL; 283char *post_update_cmd_arg = NULL; 284int connection_type = 1; 285time_t last_update = 0; 286#ifdef SEND_EMAIL_CMD 287char *notify_email = NULL; 288#endif 289char *pid_file = NULL; 290char *partner = NULL; 291char update_entry_buf[BUFFER_SIZE+1]; 292char update_entry_putbuf[BUFFER_SIZE+1]; 293 294//2007.03.14 Yau add 295#ifdef ASUS_DDNS 296volatile int client_sockfd; 297#else // !ASUS_DDNS 298static volatile int client_sockfd; 299#endif // ASUS_DDNS 300static volatile int last_sig = 0; 301 302/* service objects for various services */ 303 304// this one is for when people don't configure a default service at build time 305int NULL_check_info(void); 306static char *NULL_fields_used[] = { NULL }; 307 308int EZIP_update_entry(void); 309int EZIP_check_info(void); 310static char *EZIP_fields_used[] = { "server", "user", "address", "wildcard", "mx", "url", "host", NULL }; 311 312#ifdef CONFIG_PGP 313int PGPOW_update_entry(void); 314int PGPOW_check_info(void); 315static char *PGPOW_fields_used[] = { "server", "host", NULL }; 316#endif 317 318int DHS_update_entry(void); 319int DHS_check_info(void); 320static char *DHS_fields_used[] = { "server", "user", "address", "wildcard", "mx", "url", "host", NULL }; 321 322void DYNDNS_init(void); 323int DYNDNS_update_entry(void); 324int DYNDNS_check_info(void); 325static char *DYNDNS_fields_used[] = { "server", "user", "address", "wildcard", "mx", "host", NULL }; 326static char *DYNDNS_STAT_fields_used[] = { "server", "user", "address", "wildcard", "mx", "host", NULL }; 327 328#ifdef CONFIG_ODS 329int ODS_update_entry(void); 330int ODS_check_info(void); 331static char *ODS_fields_used[] = { "server", "host", "address", NULL }; 332#endif 333 334int TZO_update_entry(void); 335int TZO_check_info(void); 336static char *TZO_fields_used[] = { "server", "user", "address", "host", "connection-type", NULL }; 337 338int EASYDNS_update_entry(void); 339int EASYDNS_check_info(void); 340static char *EASYDNS_fields_used[] = { "server", "user", "address", "wildcard", "mx", "host", NULL }; 341 342int EASYDNS_PARTNER_update_entry(void); 343int EASYDNS_PARTNER_check_info(void); 344static char *EASYDNS_PARTNER_fields_used[] = { "server", "partner", "user", "address", "wildcard", "host", NULL }; 345 346#ifdef USE_MD5 347int GNUDIP_update_entry(void); 348int GNUDIP_check_info(void); 349static char *GNUDIP_fields_used[] = { "server", "user", "host", "address", NULL }; 350#endif 351 352#ifdef CONFIG_PGP 353int JUSTL_update_entry(void); 354int JUSTL_check_info(void); 355static char *JUSTL_fields_used[] = { "server", "user", "host", NULL }; 356#endif 357 358int DYNS_update_entry(void); 359int DYNS_check_info(void); 360static char *DYNS_fields_used[] = { "server", "user", "host", NULL }; 361 362#ifdef CONFIG_HN 363int HN_update_entry(void); 364int HN_check_info(void); 365static char *HN_fields_used[] = { "server", "user", "address", NULL }; 366#endif 367 368int ZONEEDIT_update_entry(void); 369int ZONEEDIT_check_info(void); 370static char *ZONEEDIT_fields_used[] = { "server", "user", "address", "mx", "host", NULL }; 371 372#ifdef CONFIG_HEIP 373int HEIPV6TB_update_entry(void); 374int HEIPV6TB_check_info(void); 375static char *HEIPV6TB_fields_used[] = { "server", "user", NULL }; 376#endif 377 378struct service_t services[] = { 379 { "NULL", 380 { "null", "NULL", 0, }, 381 NULL, 382 NULL, 383 NULL_check_info, 384 NULL_fields_used, 385 "", 386 "", 387 "" 388 }, 389 { "ez-ip", 390 { "ezip", "ez-ip", 0, }, 391 NULL, 392 EZIP_update_entry, 393 EZIP_check_info, 394 EZIP_fields_used, 395 EZIP_DEFAULT_SERVER, 396 EZIP_DEFAULT_PORT, 397 EZIP_REQUEST 398 }, 399#ifdef CONFIG_PGP 400 { "justlinux v1.0 (penguinpowered)", 401 { "pgpow", "penguinpowered", 0, }, 402 NULL, 403 PGPOW_update_entry, 404 PGPOW_check_info, 405 PGPOW_fields_used, 406 PGPOW_DEFAULT_SERVER, 407 PGPOW_DEFAULT_PORT, 408 PGPOW_REQUEST 409 }, 410#endif 411#ifdef CONFIG_DHS 412 { "dhs", 413 { "dhs", 0, 0, }, 414 NULL, 415 DHS_update_entry, 416 DHS_check_info, 417 DHS_fields_used, 418 DHS_DEFAULT_SERVER, 419 DHS_DEFAULT_PORT, 420 DHS_REQUEST 421 }, 422#endif 423 { "dyndns", 424 { "dyndns", 0, 0, }, 425 DYNDNS_init, 426 DYNDNS_update_entry, 427 DYNDNS_check_info, 428 DYNDNS_fields_used, 429 DYNDNS_DEFAULT_SERVER, 430 DYNDNS_DEFAULT_PORT, 431 DYNDNS_REQUEST 432 }, 433 { "dyndns-static", 434 { "dyndns-static", "dyndns-stat", "statdns", }, 435 DYNDNS_init, 436 DYNDNS_update_entry, 437 DYNDNS_check_info, 438 DYNDNS_STAT_fields_used, 439 DYNDNS_DEFAULT_SERVER, 440 DYNDNS_DEFAULT_PORT, 441 DYNDNS_STAT_REQUEST 442 }, 443 { "dyndns-custom", 444 { "dyndns-custom", "mydyndns", 0 }, 445 DYNDNS_init, 446 DYNDNS_update_entry, 447 DYNDNS_check_info, 448 DYNDNS_STAT_fields_used, 449 DYNDNS_DEFAULT_SERVER, 450 DYNDNS_DEFAULT_PORT, 451 DYNDNS_REQUEST 452 }, 453 { "qdns", 454 { "qdns dynamic" }, 455 DYNDNS_init, 456 DYNDNS_update_entry, 457 DYNDNS_check_info, 458 DYNDNS_fields_used, 459 QDNS_DEFAULT_SERVER, 460 QDNS_DEFAULT_PORT, 461 QDNS_REQUEST 462 }, 463 { "qdns-static", 464 {"qdns-static"}, 465 DYNDNS_init, 466 DYNDNS_update_entry, 467 DYNDNS_check_info, 468 DYNDNS_STAT_fields_used, 469 QDNS_DEFAULT_SERVER, 470 QDNS_DEFAULT_PORT, 471 QDNS_STAT_REQUEST 472 }, 473#ifdef CONFIG_ODS 474 { "ods", 475 { "ods", 0, 0, }, 476 NULL, 477 ODS_update_entry, 478 ODS_check_info, 479 ODS_fields_used, 480 ODS_DEFAULT_SERVER, 481 ODS_DEFAULT_PORT, 482 ODS_REQUEST 483 }, 484#endif 485 { "tzo", 486 { "tzo", 0, 0, }, 487 NULL, 488 TZO_update_entry, 489 TZO_check_info, 490 TZO_fields_used, 491 TZO_DEFAULT_SERVER, 492 TZO_DEFAULT_PORT, 493 TZO_REQUEST 494 }, 495 { "easydns", 496 { "easydns", 0, 0, }, 497 NULL, 498 EASYDNS_update_entry, 499 EASYDNS_check_info, 500 EASYDNS_fields_used, 501 EASYDNS_DEFAULT_SERVER, 502 EASYDNS_DEFAULT_PORT, 503 EASYDNS_REQUEST 504 }, 505 { "easydns-partner", 506 { "easydns-partner", 0, 0, }, 507 NULL, 508 EASYDNS_PARTNER_update_entry, 509 EASYDNS_PARTNER_check_info, 510 EASYDNS_PARTNER_fields_used, 511 EASYDNS_PARTNER_DEFAULT_SERVER, 512 EASYDNS_PARTNER_DEFAULT_PORT, 513 EASYDNS_PARTNER_REQUEST 514 }, 515#ifdef USE_MD5 516 { "gnudip", 517 { "gnudip", 0, 0, }, 518 NULL, 519 GNUDIP_update_entry, 520 GNUDIP_check_info, 521 GNUDIP_fields_used, 522 GNUDIP_DEFAULT_SERVER, 523 GNUDIP_DEFAULT_PORT, 524 GNUDIP_REQUEST 525 }, 526#endif 527 528#ifdef CONFIG_PGP 529 { "justlinux v2.0 (penguinpowered)", 530 { "justlinux", 0, 0, }, 531 NULL, 532 JUSTL_update_entry, 533 JUSTL_check_info, 534 JUSTL_fields_used, 535 JUSTL_DEFAULT_SERVER, 536 JUSTL_DEFAULT_PORT, 537 JUSTL_REQUEST 538 }, 539#endif 540 { "dyns", 541 { "dyns", 0, 0, }, 542 NULL, 543 DYNS_update_entry, 544 DYNS_check_info, 545 DYNS_fields_used, 546 DYNS_DEFAULT_SERVER, 547 DYNS_DEFAULT_PORT, 548 DYNS_REQUEST 549 }, 550#ifdef CONFIG_HN 551 { "hammer node", 552 { "hn", 0, 0, }, 553 NULL, 554 HN_update_entry, 555 HN_check_info, 556 HN_fields_used, 557 HN_DEFAULT_SERVER, 558 HN_DEFAULT_PORT, 559 HN_REQUEST 560 }, 561#endif 562 { "zoneedit", 563 { "zoneedit", 0, 0, }, 564 NULL, 565 ZONEEDIT_update_entry, 566 ZONEEDIT_check_info, 567 ZONEEDIT_fields_used, 568 ZONEEDIT_DEFAULT_SERVER, 569 ZONEEDIT_DEFAULT_PORT, 570 ZONEEDIT_REQUEST 571 }, 572#ifdef CONFIG_HEIP 573 { "heipv6tb", 574 { "heipv6tb", 0, 0, }, 575 NULL, 576 HEIPV6TB_update_entry, 577 HEIPV6TB_check_info, 578 HEIPV6TB_fields_used, 579 HEIPV6TB_DEFAULT_SERVER, 580 HEIPV6TB_DEFAULT_PORT, 581 HEIPV6TB_REQUEST 582 }, 583#endif 584}; 585 586static struct service_t *service = NULL; 587 588int options; 589 590#define OPT_DEBUG 0x0001 591#define OPT_DAEMON 0x0004 592#define OPT_QUIET 0x0008 593#define OPT_FOREGROUND 0x0010 594#define OPT_OFFLINE 0x0020 595#define OPT_ONCE 0x0040 596 597enum { 598 CMD__start = 1, 599 CMD_service_type, 600 CMD_server, 601 CMD_request, 602 CMD_user, 603 CMD_address, 604 CMD_wildcard, 605 CMD_mx, 606 CMD_max_interval, 607 CMD_url, 608 CMD_host, 609 CMD_cloak_title, 610 CMD_interface, 611 CMD_retrys, 612 CMD_resolv_period, 613 CMD_period, 614 CMD_daemon, 615 CMD_debug, 616 CMD_execute, 617 CMD_foreground, 618 CMD_quiet, 619 CMD_timeout, 620 CMD_run_as_user, 621 CMD_run_as_euser, 622 CMD_connection_type, 623 CMD_cache_file, 624#ifdef SEND_EMAIL_CMD 625 CMD_notify_email, 626#endif 627 CMD_pid_file, 628 CMD_offline, 629 CMD_partner, 630 CMD_once, 631//2007.03.14 Yau add 632#ifdef ASUS_DDNS 633 CMD_asus, 634#endif // ASUS_DDNS 635 CMD__end 636}; 637 638int conf_handler(struct conf_cmd *cmd, char *arg); 639static struct conf_cmd conf_commands[] = { 640 { CMD_address, "address", CONF_NEED_ARG, 1, conf_handler, "%s=<ip address>" }, 641 { CMD_cache_file, "cache-file", CONF_NEED_ARG, 1, conf_handler, "%s=<cache file>" }, 642 { CMD_cloak_title, "cloak-title", CONF_NEED_ARG, 1, conf_handler, "%s=<title>" }, 643 { CMD_daemon, "daemon", CONF_NO_ARG, 1, conf_handler, "%s=<command>" }, 644 { CMD_execute, "execute", CONF_NEED_ARG, 1, conf_handler, "%s=<shell command>" }, 645 { CMD_debug, "debug", CONF_NO_ARG, 1, conf_handler, "%s" }, 646 { CMD_foreground, "foreground", CONF_NO_ARG, 1, conf_handler, "%s" }, 647 { CMD_pid_file, "pid-file", CONF_NEED_ARG, 1, conf_handler, "%s=<file>" }, 648 { CMD_host, "host", CONF_NEED_ARG, 1, conf_handler, "%s=<host>" }, 649 { CMD_interface, "interface", CONF_NEED_ARG, 1, conf_handler, "%s=<interface>" }, 650 { CMD_mx, "mx", CONF_NEED_ARG, 1, conf_handler, "%s=<mail exchanger>" }, 651 { CMD_max_interval, "max-interval", CONF_NEED_ARG, 1, conf_handler, "%s=<number of seconds between updates>" }, 652#ifdef SEND_EMAIL_CMD 653 { CMD_notify_email, "notify-email", CONF_NEED_ARG, 1, conf_handler, "%s=<address to email if bad things happen>" }, 654#endif 655 { CMD_offline, "offline", CONF_NO_ARG, 1, conf_handler, "%s" }, 656 { CMD_retrys, "retrys", CONF_NEED_ARG, 1, conf_handler, "%s=<number of trys>" }, 657 { CMD_server, "server", CONF_NEED_ARG, 1, conf_handler, "%s=<server name>" }, 658 { CMD_service_type, "service-type", CONF_NEED_ARG, 1, conf_handler, "%s=<service type>" }, 659 { CMD_timeout, "timeout", CONF_NEED_ARG, 1, conf_handler, "%s=<sec.millisec>" }, 660 { CMD_resolv_period, "resolv-period", CONF_NEED_ARG, 1, conf_handler, "%s=<time between failed resolve attempts>" }, 661 { CMD_period, "period", CONF_NEED_ARG, 1, conf_handler, "%s=<time between update attempts>" }, 662 { CMD_url, "url", CONF_NEED_ARG, 1, conf_handler, "%s=<url>" }, 663 { CMD_user, "user", CONF_NEED_ARG, 1, conf_handler, "%s=<user name>[:password]" }, 664 { CMD_run_as_user, "run-as-user", CONF_NEED_ARG, 1, conf_handler, "%s=<user>" }, 665 { CMD_run_as_euser, "run-as-euser", CONF_NEED_ARG, 1, conf_handler, "%s=<user> (this is not secure)" }, 666 { CMD_wildcard, "wildcard", CONF_NO_ARG, 1, conf_handler, "%s" }, 667 { CMD_quiet, "quiet", CONF_NO_ARG, 1, conf_handler, "%s" }, 668 { CMD_connection_type, "connection-type", CONF_NEED_ARG, 1, conf_handler, "%s=<connection type>" }, 669 { CMD_request, "request", CONF_NEED_ARG, 1, conf_handler, "%s=<request uri>" }, 670 { CMD_partner, "partner", CONF_NEED_ARG, 1, conf_handler, "%s=<easydns partner>" }, 671 { 0, 0, 0, 0, 0 } 672}; 673 674/**************************************************/ 675 676void print_usage( void ); 677void print_version( void ); 678void parse_args( int argc, char **argv ); 679int do_connect(int *sock, char *host, char *port); 680void base64Encode(char *intext, char *output); 681int main( int argc, char **argv ); 682void warn_fields(char **okay_fields); 683static int is_in_list(char *needle, char **haystack); 684 685/**************************************************/ 686 687void print_usage( void ) 688{ 689 int i; 690 int width; 691 692 fprintf(stdout, "usage: "); 693 fprintf(stdout, "%s [options] \n\n", program_name); 694 fprintf(stdout, " Options are:\n"); 695 fprintf(stdout, " -a, --address <ip address>\tstring to send as your ip address\n"); 696 fprintf(stdout, " -b, --cache-file <file>\tfile to use for caching the ipaddress\n"); 697 fprintf(stdout, " -c, --config-file <file>\tconfiguration file, almost all arguments can be\n"); 698 fprintf(stdout, "\t\t\t\tgiven with: <name>[=<value>]\n\t\t\t\tto see a list of possible config commands\n"); 699 fprintf(stdout, "\t\t\t\ttry \"echo help | %s -c -\"\n", program_name); 700 fprintf(stdout, " -d, --daemon\t\t\trun as a daemon periodicly updating if \n\t\t\t\tnecessary\n"); 701#ifdef DEBUG 702 fprintf(stdout, " -D, --debug\t\t\tturn on debuggin\n"); 703#endif 704 fprintf(stdout, " -e, --execute <command>\tshell command to execute after a successful\n\t\t\t\tupdate\n"); 705 fprintf(stdout, " -f, --foreground\t\twhen running as a daemon run in the foreground\n"); 706 fprintf(stdout, " -F, --pidfile <file>\t\tuse <file> as a pid file\n"); 707 fprintf(stdout, " -g, --request-uri <uri>\tURI to send updates to\n"); 708 fprintf(stdout, " -h, --host <host>\t\tstring to send as host parameter\n"); 709 fprintf(stdout, " -i, --interface <iface>\twhich interface to use\n"); 710 fprintf(stdout, " -L, --cloak_title <host>\tsome stupid thing for DHS only\n"); 711 fprintf(stdout, " -m, --mx <mail exchange>\tstring to send as your mail exchange\n"); 712 fprintf(stdout, " -M, --max-interval <# of sec>\tmax time in between updates\n"); 713#ifdef SEND_EMAIL_CMD 714 fprintf(stdout, " -N, --notify-email <email>\taddress to send mail to if bad things happen\n"); 715#endif 716 fprintf(stdout, " -o, --offline\t\t\tset to off line mode\n"); 717 fprintf(stdout, " -p, --resolv-period <sec>\tperiod to check IP if it can't be resolved\n"); 718 fprintf(stdout, " -P, --period <# of sec>\tperiod to check IP in daemon \n\t\t\t\tmode (default: 1800 seconds)\n"); 719 fprintf(stdout, " -q, --quiet \t\t\tbe quiet\n"); 720 fprintf(stdout, " -r, --retrys <num>\t\tnumber of trys (default: 1)\n"); 721 fprintf(stdout, " -R, --run-as-user <user>\tchange to <user> for running, be ware\n\t\t\t\tthat this can cause problems with handeling\n\t\t\t\tSIGHUP properly if that user can't read the\n\t\t\t\tconfig file. also it can't write it's pid file \n\t\t\t\tto a root directory\n"); 722 fprintf(stdout, " -Q, --run-as-euser <user>\tchange to effective <user> for running, \n\t\t\t\tthis is NOT secure but it does solve the \n\t\t\t\tproblems with run-as-user and config files and \n\t\t\t\tpid files.\n"); 723 fprintf(stdout, " -s, --server <server[:port]>\tthe server to connect to\n"); 724 fprintf(stdout, " -S, --service-type <server>\tthe type of service that you are using\n"); 725 width = fprintf(stdout, "\t\t\t\ttry one of: ") + 4*7; 726 for(i=0; i<ARRAY_LEN(services); i++) 727 { 728 if(width > 60) { width = fprintf(stdout, "\n\t\t\t\t") -1 + 4*7; } 729 width += fprintf(stdout, "%s ", services[i].names[0]); 730 } 731 fprintf(stdout, "\n"); 732 fprintf(stdout, " -t, --timeout <sec.millisec>\tthe amount of time to wait on I/O\n"); 733 fprintf(stdout, " -T, --connection-type <num>\tnumber sent to TZO as your connection \n\t\t\t\ttype (default: 1)\n"); 734 fprintf(stdout, " -U, --url <url>\t\tstring to send as the url parameter\n"); 735 fprintf(stdout, " -u, --user <user[:passwd]>\tuser ID and password, if either is left blank \n\t\t\t\tthey will be prompted for\n"); 736 fprintf(stdout, " -w, --wildcard\t\tset your domain to have a wildcard alias\n"); 737 fprintf(stdout, " -z, --partner <partner>\tspecify easyDNS partner (for easydns-partner \n\t\t\t\tservices)\n"); 738 fprintf(stdout, " -1, --once\tin daemon mode, update once then exit\n"); 739 fprintf(stdout, " --help\t\t\tdisplay this help and exit\n"); 740 fprintf(stdout, " --version\t\t\toutput version information and exit\n"); 741 fprintf(stdout, " --credits\t\t\tprint the credits and exit\n"); 742#ifndef EMBED 743 fprintf(stdout, " --signalhelp\t\tprint help about signals\n"); 744#endif 745 fprintf(stdout, "\n"); 746} 747 748void print_version( void ) 749{ 750 fprintf(stdout, "%s: - %s - $Id: ez-ipupdate.c,v 1.1.1.1 2008/10/15 03:28:47 james26_jang Exp $\n", program_name, VERSION); 751} 752 753void print_credits( void ) 754{ 755 fprintf( stdout, "AUTHORS / CONTRIBUTORS\n" 756 " Angus Mackay <amackay@gusnet.cx>\n" 757 " Jeremy Bopp <jbopp@mail.utexas.edu>\n" 758 " Mark Jeftovic <markjr@easydns.com>\n" 759 " Stefaan Ponnet <webmaster@dyns.cx>\n" 760 " Colin Viebrock <colin@easydns.com>\n" 761 " Tim Brown <timb@machine.org.uk>\n" 762 "\n" ); 763} 764 765#ifndef EMBED 766void print_signalhelp( void ) 767{ 768 fprintf(stdout, "\nsignals are only really used when in daemon mode.\n\n"); 769 fprintf(stdout, "signals: \n"); 770 fprintf(stdout, " HUP\t\tcauses it to re-read its config file\n"); 771 fprintf(stdout, " TERM\t\twake up and possibly perform an update\n"); 772 fprintf(stdout, " QUIT\t\tshutdown\n"); 773 fprintf(stdout, "\n"); 774} 775#endif 776 777#if HAVE_SIGNAL_H 778RETSIGTYPE sigint_handler(int sig) 779{ 780 char message[] = "interupted.\n"; 781 close(client_sockfd); 782 write(2, message, sizeof(message)-1); 783 784#if HAVE_GETPID 785 if(pid_file) 786 { 787 pid_file_delete(pid_file); 788 } 789#endif 790 791 exit(1); 792} 793RETSIGTYPE generic_sig_handler(int sig) 794{ 795 last_sig = sig; 796} 797#endif 798 799int get_duration(char *str) 800{ 801 char *multchar; 802 int mult; 803 char save; 804 int duration; 805 806 for(multchar=str; *multchar != '\0'; multchar++); 807 if(multchar != str) { multchar--; } 808 if(*multchar == '\0' || isdigit(*multchar)) { mult = 1; multchar++; } 809 else if(*multchar == 'M') { mult = 60; } 810 else if(*multchar == 'H') { mult = 60*60; } 811 else if(*multchar == 'd') { mult = 60*60*24; } 812 else if(*multchar == 'w') { mult = 60*60*24*7; } 813 else if(*multchar == 'f') { mult = 60*60*24*7*2; } 814 else if(*multchar == 'm') { mult = 60*60*24*30; } 815 else if(*multchar == 'y') { mult = 60*60*24*365; } 816 else 817 { 818 show_message("invalid multiplier: %c\n", *multchar); 819#ifndef EMBED 820 fprintf(stderr, "valid multipliers:\n"); 821 fprintf(stderr, " %c -> %s (%d)\n", 'M', "Minute", 60); 822 fprintf(stderr, " %c -> %s (%d)\n", 'H', "Hour", 60*60); 823 fprintf(stderr, " %c -> %s (%d)\n", 'd', "day", 60*60*24); 824 fprintf(stderr, " %c -> %s (%d)\n", 'w', "week", 60*60*24*7); 825 fprintf(stderr, " %c -> %s (%d)\n", 'f', "fortnight", 60*60*24*7*2); 826 fprintf(stderr, " %c -> %s (%d)\n", 'm', "month", 60*60*24*30); 827 fprintf(stderr, " %c -> %s (%d)\n", 'y', "year", 60*60*24*365); 828#else 829 fprintf(stderr, "valid multipliers: MHdwfmy\n"); 830#endif 831 exit(1); 832 } 833 save = *multchar; 834 *multchar = '\0'; 835 duration = strtol(str, NULL, 0) * mult; 836 *multchar = save; 837 838 return(duration); 839} 840 841const char* format_time(int seconds) 842{ 843 static char buf[16]; 844 845 snprintf(buf, sizeof(buf), "%d:%02d:%02d", seconds/(3600), 846 (seconds%(3600))/(60), (seconds%60)); 847 return(buf); 848} 849 850/* 851 * like "chomp" in perl, take off trailing newline chars 852 */ 853char *chomp(char *buf) 854{ 855 char *p; 856 857 for(p=buf; *p != '\0'; p++); 858 if(p != buf) { p--; } 859 while(p>=buf && (*p == '\n' || *p == '\r')) 860 { 861 *p-- = '\0'; 862 } 863 864 return(buf); 865} 866 867void get_input(char *prompt, char *buf, int buflen) 868{ 869 printf("%s: ", prompt); 870 fflush(stdout); 871 *buf = '\0'; 872 fgets(buf, buflen-1, stdin); 873 chomp(buf); 874} 875 876/* 877 * show_message 878 * 879 * if we are running in daemon mode then log to syslog, if not just output to 880 * stderr. 881 * 882 */ 883#ifdef REMOVE 884void show_message(char *fmt, ...) 885{ 886 va_list args; 887 va_start(args, fmt); 888 889 if((options & OPT_DAEMON) && !(options & OPT_FOREGROUND)) 890 { 891 char buf[MAX_MESSAGE_LEN]; 892 893#if defined(HAVE_VSPRINTF) || defined(HAVE_VSNPRINTF) 894 vsnprintf(buf, sizeof(buf), fmt, args); 895#else 896 sprintf(buf, "message incomplete because your OS sucks: %s\n", fmt); 897#endif 898 899 syslog(LOG_NOTICE, buf); 900 } 901 else 902 { 903#ifdef HAVE_VFPRINTF 904 vfprintf(stderr, fmt, args); 905#else 906 fprintf(stderr, "message incomplete because your OS sucks: %s\n", fmt); 907#endif 908 } 909 910 va_end(args); 911} 912#else 913/* 914 * show_message 915 * 916 */ 917void show_message(char *fmt, ...) 918{ 919 va_list args; 920 char buf[512]; 921 922 va_start(args, fmt); 923 vsnprintf(buf, sizeof(buf), fmt, args); 924 openlog("ddns update", 0, 0); 925 syslog(0, buf); 926 closelog(); 927 va_end(args); 928} 929#endif 930 931/* 932 * returns true if the string passed in is an internet address in dotted quad 933 * notation. 934 */ 935int is_dotted_quad(char *addr) 936{ 937 int q[4]; 938 char *p; 939 int i; 940 941 if(sscanf(addr, "%d.%d.%d.%d", &(q[0]), &(q[1]), &(q[2]), &(q[3])) != 4) 942 { 943 return(0); 944 } 945 946 if(q[0] > 255 || q[0] < 0 || 947 q[1] > 255 || q[1] < 0 || 948 q[2] > 255 || q[2] < 0 || 949 q[3] > 255 || q[3] < 0) 950 { 951 return(0); 952 } 953 954 /* we know there are 3 dots */ 955 p = addr; 956 if(p != NULL) { p = strchr(p, '.'); p++; } 957 if(p != NULL) { p = strchr(p, '.'); p++; } 958 if(p != NULL) { p = strchr(p, '.'); } 959 for(i=0; *p != '\0' && i<4; i++, p++); 960 if(*p != '\0') 961 { 962 return(0); 963 } 964 965 return(1); 966} 967 968void parse_service(char *str) 969{ 970 int i; 971 int width; 972 973 for(i=0; i<ARRAY_LEN(services); i++) 974 { 975 int j; 976 for(j=0; j<ARRAY_LEN(services[i].names) && services[i].names[j] != NULL; j++) 977 { 978 if(strcmp(services[i].names[j], str) == 0) 979 { 980 service = &(services[i]); 981 return; 982 } 983 } 984 } 985 show_message("unknown service type: %s\n", str); 986 fprintf(stderr, "try one of: \n"); 987 width = fprintf(stderr, " "); 988 for(i=0; i<ARRAY_LEN(services); i++) 989 { 990 if(width > 60) { width = fprintf(stderr, "\n ") -1; } 991 width += fprintf(stderr, "%s ", services[i].names[0]); 992 } 993 fprintf(stderr, "\n"); 994 exit(1); 995} 996 997int option_handler(int id, char *optarg) 998{ 999#if HAVE_PWD_H && HAVE_GRP_H 1000 struct passwd *pw; 1001#endif 1002 char *tmp; 1003 int i; 1004 1005 switch(id) 1006 { 1007 case CMD_address: 1008 if(address) { free(address); } 1009 address = strdup(optarg); 1010 dprintf((stderr, "address: %s\n", address)); 1011 break; 1012 1013//2007.03.14 Yau add 1014#ifdef ASUS_DDNS 1015 case CMD_asus: 1016 i = atoi (optarg); 1017 if (i >= 0 && i <= 2) { 1018 g_asus_ddns_mode = i; 1019 dprintf((stderr, "register domain mode %d\n", g_asus_ddns_mode)); 1020 } 1021 break; 1022#endif // ASUS_DDNS 1023 1024 case CMD_daemon: 1025 options |= OPT_DAEMON; 1026 dprintf((stderr, "daemon mode\n")); 1027#if HAVE_GETPID 1028 if(!pid_file) pid_file = strdup(PID_FILE); 1029#endif 1030 break; 1031 1032 case CMD_debug: 1033#ifdef DEBUG 1034 options |= OPT_DEBUG; 1035 dprintf((stderr, "debugging on\n")); 1036#else 1037 show_message("debugging was not enabled at compile time\n"); 1038#endif 1039 break; 1040 1041 case CMD_execute: 1042#if defined(HAVE_WAITPID) || defined(HAVE_WAIT) 1043 if(post_update_cmd) { free(post_update_cmd); } 1044 post_update_cmd = malloc(strlen(optarg) + 1 + ARGLENGTH + 1); 1045 post_update_cmd_arg = post_update_cmd + strlen(optarg) + 1; 1046 sprintf(post_update_cmd, "%s ", optarg); 1047 dprintf((stderr, "post_update_cmd: %s\n", post_update_cmd)); 1048#else 1049 show_message("command execution not enabled at compile time\n"); 1050 exit(1); 1051#endif 1052 break; 1053 1054 case CMD_foreground: 1055 options |= OPT_FOREGROUND; 1056 dprintf((stderr, "fork()ing off\n")); 1057 break; 1058 1059 case CMD_pid_file: 1060#if HAVE_GETPID 1061 if(pid_file) { free(pid_file); } 1062 pid_file = strdup(optarg); 1063 dprintf((stderr, "pid file: %s\n", pid_file)); 1064#else 1065 show_message("pid file support not enabled at compile time\n"); 1066#endif 1067 break; 1068 1069 case CMD_host: 1070 if(host) { free(host); } 1071 host = strdup(optarg); 1072 dprintf((stderr, "host: %s\n", host)); 1073 break; 1074 1075 case CMD_interface: 1076#ifdef IF_LOOKUP 1077 if(interface) { free(interface); } 1078 interface = strdup(optarg); 1079 dprintf((stderr, "interface: %s\n", interface)); 1080#else 1081 show_message("interface lookup not enabled at compile time\n"); 1082 exit(1); 1083#endif 1084 break; 1085 1086 case CMD_mx: 1087 if(mx) { free(mx); } 1088 mx = strdup(optarg); 1089 dprintf((stderr, "mx: %s\n", mx)); 1090 break; 1091 1092 case CMD_max_interval: 1093 max_interval = get_duration(optarg); 1094 if(max_interval < MIN_MAXINTERVAL) 1095 { 1096 show_message("WARNING: max-interval of %d is too short, using %d\n", 1097 max_interval, MIN_MAXINTERVAL); 1098 max_interval = MIN_MAXINTERVAL; 1099 } 1100 dprintf((stderr, "max_interval: %d\n", max_interval)); 1101 break; 1102 1103#ifdef SEND_EMAIL_CMD 1104 case CMD_notify_email: 1105 if(notify_email) { free(notify_email); } 1106 notify_email = strdup(optarg); 1107 dprintf((stderr, "notify_email: %s\n", notify_email)); 1108 break; 1109#endif 1110 1111 case CMD_offline: 1112 options |= OPT_OFFLINE; 1113 dprintf((stderr, "offline mode\n")); 1114 break; 1115 1116 case CMD_period: 1117 update_period = get_duration(optarg); 1118 if(update_period < MIN_UPDATE_PERIOD) 1119 { 1120 show_message("WARNING: period of %d is too short, using %d\n", 1121 update_period, MIN_UPDATE_PERIOD); 1122 update_period = MIN_UPDATE_PERIOD; 1123 } 1124 dprintf((stderr, "update_period: %d\n", update_period)); 1125 break; 1126 1127 case CMD_resolv_period: 1128 resolv_period = get_duration(optarg); 1129 if(resolv_period < 1) 1130 { 1131 show_message("WARNING: period of %d is too short, using %d\n", 1132 resolv_period, 1); 1133 resolv_period = 1; 1134 } 1135 dprintf((stderr, "resolv_period: %d\n", resolv_period)); 1136 break; 1137 1138 case CMD_quiet: 1139 options |= OPT_QUIET; 1140 dprintf((stderr, "quiet mode\n")); 1141 break; 1142 1143 case CMD_retrys: 1144 ntrys = atoi(optarg); 1145 dprintf((stderr, "ntrys: %d\n", ntrys)); 1146 break; 1147 1148 case CMD_server: 1149 if(server) { free(server); } 1150 server = strdup(optarg); 1151 tmp = strchr(server, ':'); 1152 if(tmp) 1153 { 1154 *tmp++ = '\0'; 1155 if(port) { free(port); } 1156 port = strdup(tmp); 1157 } 1158 dprintf((stderr, "server: %s\n", server)); 1159 dprintf((stderr, "port: %s\n", port)); 1160 break; 1161 1162 case CMD_request: 1163 if(request_over_ride) { free(request_over_ride); } 1164 request_over_ride = strdup(optarg); 1165 dprintf((stderr, "request_over_ride: %s\n", request_over_ride)); 1166 break; 1167 1168 case CMD_partner: 1169 if(partner) { free(partner); } 1170 partner = strdup(optarg); 1171 dprintf((stderr, "easyDNS partner: %s\n", partner)); 1172 break; 1173 1174 case CMD_service_type: 1175 parse_service(optarg); 1176 service_set = 1; 1177 dprintf((stderr, "service_type: %s\n", service->title)); 1178 dprintf((stderr, "service->name: %s\n", service->names[0])); 1179 break; 1180 1181 case CMD_user: 1182 strncpy(user, optarg, sizeof(user)); 1183 user[sizeof(user)-1] = '\0'; 1184 dprintf((stderr, "user: %s\n", user)); 1185 tmp = strchr(optarg, ':'); 1186 if(tmp) 1187 { 1188 tmp++; 1189 while(*tmp) { *tmp++ = '*'; } 1190 } 1191 break; 1192 1193 case CMD_run_as_user: 1194#if HAVE_PWD_H && HAVE_GRP_H 1195 if((pw=getpwnam(optarg)) == NULL) 1196 { 1197 i = atoi(optarg); 1198 } 1199 else 1200 { 1201 if(setgid(pw->pw_gid) != 0) 1202 { 1203 show_message("error changing group id\n"); 1204 } 1205 dprintf((stderr, "GID now %d\n", pw->pw_gid)); 1206 i = pw->pw_uid; 1207 } 1208 if(setuid(i) != 0) 1209 { 1210 show_message("error changing user id\n"); 1211 } 1212 dprintf((stderr, "UID now %d\n", i)); 1213#else 1214 show_message("option \"daemon-user\" not supported on this system\n"); 1215#endif 1216 break; 1217 1218 case CMD_run_as_euser: 1219#if HAVE_PWD_H && HAVE_GRP_H && HAVE_SETEUID && HAVE_SETEGID 1220 if((pw=getpwnam(optarg)) == NULL) 1221 { 1222 i = atoi(optarg); 1223 } 1224 else 1225 { 1226 if(setegid(pw->pw_gid) != 0) 1227 { 1228 show_message("error changing group id\n"); 1229 } 1230 dprintf((stderr, "GID now %d\n", pw->pw_gid)); 1231 i = pw->pw_uid; 1232 } 1233 if(seteuid(i) != 0) 1234 { 1235 show_message("error changing user id\n"); 1236 } 1237 dprintf((stderr, "UID now %d\n", i)); 1238#else 1239 show_message("option \"daemon-euser\" not supported on this system\n"); 1240#endif 1241 break; 1242 1243 case CMD_url: 1244 if(url) { free(url); } 1245 url = strdup(optarg); 1246 dprintf((stderr, "url: %s\n", url)); 1247 break; 1248 1249 case CMD_wildcard: 1250 wildcard = 1; 1251 dprintf((stderr, "wildcard: %d\n", wildcard)); 1252 break; 1253 1254 case CMD_cloak_title: 1255 if(cloak_title) { free(cloak_title); } 1256 cloak_title = strdup(optarg); 1257 dprintf((stderr, "cloak_title: %s\n", cloak_title)); 1258 break; 1259 1260 case CMD_timeout: 1261 timeout.tv_sec = atoi(optarg); 1262 timeout.tv_usec = (atof(optarg) - timeout.tv_sec) * 1000000L; 1263 dprintf((stderr, "timeout: %ld.%06ld\n", timeout.tv_sec, timeout.tv_usec)); 1264 break; 1265 1266 case CMD_connection_type: 1267 connection_type = atoi(optarg); 1268 dprintf((stderr, "connection_type: %d\n", connection_type)); 1269 break; 1270 1271 case CMD_cache_file: 1272 if(cache_file) { free(cache_file); } 1273 cache_file = strdup(optarg); 1274 dprintf((stderr, "cache_file: %s\n", cache_file)); 1275 break; 1276 1277 case CMD_once: 1278 options |= OPT_ONCE; 1279 dprintf((stderr, "update once only\n")); 1280 break; 1281 1282 default: 1283 dprintf((stderr, "case not handled: %d\n", id)); 1284 break; 1285 } 1286 1287 return 0; 1288} 1289 1290int conf_handler(struct conf_cmd *cmd, char *arg) 1291{ 1292 return(option_handler(cmd->id, arg)); 1293} 1294 1295 1296#ifdef HAVE_GETOPT_LONG 1297# define xgetopt( x1, x2, x3, x4, x5 ) getopt_long( x1, x2, x3, x4, x5 ) 1298#else 1299# define xgetopt( x1, x2, x3, x4, x5 ) getopt( x1, x2, x3 ) 1300#endif 1301 1302void parse_args( int argc, char **argv ) 1303{ 1304#ifdef HAVE_GETOPT_LONG 1305 struct option long_options[] = { 1306//2007.03.14 Yau add 1307#ifdef ASUS_DDNS 1308 {"asus", required_argument, 0, 'A'}, 1309#endif // ASUS_DDNS 1310 {"address", required_argument, 0, 'a'}, 1311 {"cache-file", required_argument, 0, 'b'}, 1312 {"config_file", required_argument, 0, 'c'}, 1313 {"config-file", required_argument, 0, 'c'}, 1314 {"daemon", no_argument, 0, 'd'}, 1315 {"debug", no_argument, 0, 'D'}, 1316 {"execute", required_argument, 0, 'e'}, 1317 {"foreground", no_argument, 0, 'f'}, 1318 {"pid-file", required_argument, 0, 'F'}, 1319 {"host", required_argument, 0, 'h'}, 1320 {"interface", required_argument, 0, 'i'}, 1321 {"cloak_title", required_argument, 0, 'L'}, 1322 {"mx", required_argument, 0, 'm'}, 1323 {"max-interval", required_argument, 0, 'M'}, 1324#ifdef SEND_EMAIL_CMD 1325 {"notify-email", required_argument, 0, 'N'}, 1326#endif 1327 {"resolv-period", required_argument, 0, 'p'}, 1328 {"period", required_argument, 0, 'P'}, 1329 {"quiet", no_argument, 0, 'q'}, 1330 {"retrys", required_argument, 0, 'r'}, 1331 {"run-as-user", required_argument, 0, 'R'}, 1332 {"run-as-euser", required_argument, 0, 'Q'}, 1333 {"server", required_argument, 0, 's'}, 1334 {"service-type", required_argument, 0, 'S'}, 1335 {"timeout", required_argument, 0, 't'}, 1336 {"connection-type", required_argument, 0, 'T'}, 1337 {"url", required_argument, 0, 'U'}, 1338 {"user", required_argument, 0, 'u'}, 1339 {"wildcard", no_argument, 0, 'w'}, 1340 {"help", no_argument, 0, 'H'}, 1341 {"version", no_argument, 0, 'V'}, 1342 {"credits", no_argument, 0, 'C'}, 1343#ifndef EMBED 1344 {"signalhelp", no_argument, 0, 'Z'}, 1345#endif 1346 {"once", no_argument, 0, '1'}, 1347 {0,0,0,0} 1348 }; 1349#else 1350# define long_options NULL 1351#endif 1352 int opt; 1353 1354//2007.03.14 Yau add 1355#ifdef ASUS_DDNS 1356 while((opt=xgetopt(argc, argv, "A:a:b:c:dDe:fF:h:i:L:m:M:N:o:p:P:qr:R:s:S:t:T:U:u:wHVCZ", long_options, NULL)) != -1) 1357#else // !ASUS_DDNS 1358 while((opt=xgetopt(argc, argv, "a:b:c:dDe:fF:h:i:L:m:M:N:o:p:P:qr:R:s:S:t:T:U:u:wHVCZ", long_options, NULL)) != -1) 1359#endif // ASUS_DDNS 1360 { 1361 switch (opt) 1362 { 1363 case 'a': 1364 option_handler(CMD_address, optarg); 1365 break; 1366 1367//2007.03.14 Yau add 1368#ifdef ASUS_DDNS 1369 case 'A': 1370 option_handler(CMD_asus, optarg); 1371 break; 1372#endif // ASUS_DDNS 1373 1374 case 'b': 1375 option_handler(CMD_cache_file, optarg); 1376 break; 1377 1378 case 'c': 1379 if(config_file) { free(config_file); } 1380 config_file = strdup(optarg); 1381 dprintf((stderr, "config_file: %s\n", config_file)); 1382 if(config_file) 1383 { 1384 if(parse_conf_file(config_file, conf_commands) != 0) 1385 { 1386 show_message("error parsing config file \"%s\"\n", config_file); 1387 exit(1); 1388 } 1389 } 1390 break; 1391 1392 case 'd': 1393 option_handler(CMD_daemon, optarg); 1394 break; 1395 1396 case 'D': 1397 option_handler(CMD_debug, optarg); 1398 break; 1399 1400 case 'e': 1401 option_handler(CMD_execute, optarg); 1402 break; 1403 1404 case 'f': 1405 option_handler(CMD_foreground, optarg); 1406 break; 1407 1408 case 'F': 1409 option_handler(CMD_pid_file, optarg); 1410 break; 1411 1412 case 'g': 1413 option_handler(CMD_request, optarg); 1414 break; 1415 1416 case 'h': 1417 option_handler(CMD_host, optarg); 1418 break; 1419 1420 case 'i': 1421 option_handler(CMD_interface, optarg); 1422 break; 1423 1424 case 'L': 1425 option_handler(CMD_cloak_title, optarg); 1426 break; 1427 1428 case 'm': 1429 option_handler(CMD_mx, optarg); 1430 break; 1431 1432 case 'M': 1433 option_handler(CMD_max_interval, optarg); 1434 break; 1435 1436#ifdef SEND_EMAIL_CMD 1437 case 'N': 1438 option_handler(CMD_notify_email, optarg); 1439 break; 1440#endif 1441 1442 case 'o': 1443 option_handler(CMD_offline, optarg); 1444 break; 1445 1446 case 'p': 1447 option_handler(CMD_resolv_period, optarg); 1448 break; 1449 1450 case 'P': 1451 option_handler(CMD_period, optarg); 1452 break; 1453 1454 case 'q': 1455 option_handler(CMD_quiet, optarg); 1456 break; 1457 1458 case 'Q': 1459 option_handler(CMD_run_as_euser, optarg); 1460 break; 1461 1462 case 'r': 1463 option_handler(CMD_retrys, optarg); 1464 break; 1465 1466 case 'R': 1467 option_handler(CMD_run_as_user, optarg); 1468 break; 1469 1470 case 's': 1471 option_handler(CMD_server, optarg); 1472 break; 1473 1474 case 'S': 1475 option_handler(CMD_service_type, optarg); 1476 break; 1477 1478 case 't': 1479 option_handler(CMD_timeout, optarg); 1480 break; 1481 1482 case 'T': 1483 option_handler(CMD_connection_type, optarg); 1484 break; 1485 1486 case 'u': 1487 option_handler(CMD_user, optarg); 1488 break; 1489 1490 case 'U': 1491 option_handler(CMD_url, optarg); 1492 break; 1493 1494 case 'w': 1495 option_handler(CMD_wildcard, optarg); 1496 break; 1497 1498 case 'H': 1499 print_usage(); 1500 exit(0); 1501 break; 1502 1503 case 'V': 1504 print_version(); 1505 exit(0); 1506 break; 1507 1508 case 'C': 1509 print_credits(); 1510 exit(0); 1511 break; 1512 1513#ifndef EMBED 1514 case 'Z': 1515 print_signalhelp(); 1516 exit(0); 1517 break; 1518#endif 1519 1520 case 'z': 1521 option_handler(CMD_partner, optarg); 1522 break; 1523 1524 case '1': 1525 option_handler(CMD_once, optarg); 1526 break; 1527 1528 default: 1529#ifdef HAVE_GETOPT_LONG 1530 fprintf(stderr, "Try `%s --help' for more information\n", argv[0]); 1531#else 1532 fprintf(stderr, "Try `%s -H' for more information\n", argv[0]); 1533 fprintf(stderr, "warning: this program was compilied without getopt_long\n"); 1534 fprintf(stderr, " as such all long options will not work!\n"); 1535#endif 1536 exit(1); 1537 break; 1538 } 1539 } 1540} 1541 1542/* 1543 * do_connect 1544 * 1545 * connect a socket and return the file descriptor 1546 * 1547 */ 1548int do_connect(int *sock, char *host, char *port) 1549{ 1550 struct sockaddr_in address; 1551 int len; 1552 int result; 1553 struct hostent *hostinfo; 1554 struct servent *servinfo; 1555 1556 // set up the socket 1557 if((*sock=socket(AF_INET, SOCK_STREAM, 0)) == -1) 1558 { 1559 if(!(options & OPT_QUIET)) 1560 { 1561 perror("socket"); 1562 } 1563 return(-1); 1564 } 1565 address.sin_family = AF_INET; 1566 1567 // get the host address 1568 hostinfo = gethostbyname(host); 1569 if(!hostinfo) 1570 { 1571 if(!(options & OPT_QUIET)) 1572 { 1573 herror("gethostbyname"); 1574 } 1575 close(*sock); 1576 return(-1); 1577 } 1578 address.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list; 1579 1580 // get the host port 1581 servinfo = getservbyname(port, "tcp"); 1582 if(servinfo) 1583 { 1584 address.sin_port = servinfo -> s_port; 1585 } 1586 else 1587 { 1588 address.sin_port = htons(atoi(port)); 1589 } 1590 1591 // connect the socket 1592 len = sizeof(address); 1593 if((result=connect(*sock, (struct sockaddr *)&address, len)) == -1) 1594 { 1595 if(!(options & OPT_QUIET)) 1596 { 1597 perror("connect"); 1598 } 1599 close(*sock); 1600 return(-1); 1601 } 1602 // print out some info 1603 if(!(options & OPT_QUIET)) 1604 { 1605 show_message( 1606 "connected to %s (%s) on port %d.\n", 1607 host, 1608 inet_ntoa(address.sin_addr), 1609 ntohs(address.sin_port)); 1610 } 1611 1612 return 0; 1613} 1614 1615static char table64[]= 1616 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 1617void base64Encode(char *intext, char *output) 1618{ 1619 unsigned char ibuf[3]; 1620 unsigned char obuf[4]; 1621 int i; 1622 int inputparts; 1623 1624 while(*intext) { 1625 for (i = inputparts = 0; i < 3; i++) { 1626 if(*intext) { 1627 inputparts++; 1628 ibuf[i] = *intext; 1629 intext++; 1630 } 1631 else 1632 ibuf[i] = 0; 1633 } 1634 1635 obuf [0] = (ibuf [0] & 0xFC) >> 2; 1636 obuf [1] = ((ibuf [0] & 0x03) << 4) | ((ibuf [1] & 0xF0) >> 4); 1637 obuf [2] = ((ibuf [1] & 0x0F) << 2) | ((ibuf [2] & 0xC0) >> 6); 1638 obuf [3] = ibuf [2] & 0x3F; 1639 1640 switch(inputparts) { 1641 case 1: /* only one byte read */ 1642 sprintf(output, "%c%c==", 1643 table64[obuf[0]], 1644 table64[obuf[1]]); 1645 break; 1646 case 2: /* two bytes read */ 1647 sprintf(output, "%c%c%c=", 1648 table64[obuf[0]], 1649 table64[obuf[1]], 1650 table64[obuf[2]]); 1651 break; 1652 default: 1653 sprintf(output, "%c%c%c%c", 1654 table64[obuf[0]], 1655 table64[obuf[1]], 1656 table64[obuf[2]], 1657 table64[obuf[3]] ); 1658 break; 1659 } 1660 output += 4; 1661 } 1662 *output=0; 1663} 1664 1665#if IF_LOOKUP 1666# if !defined(HAVE_INET_ATON) 1667# if defined(HAVE_INET_ADDR) 1668int inet_aton(const char *cp, struct in_addr *inp) 1669{ 1670 (*inp).s_addr = inet_addr(cp); 1671} 1672# else 1673# error "sorry, can't compile with IF_LOOKUP and no inet_aton" 1674# endif 1675#endif 1676#endif 1677 1678void output(void *buf) 1679{ 1680 fd_set writefds; 1681 int max_fd; 1682 struct timeval tv; 1683 int ret; 1684 1685 dprintf((stderr, "I say: %s\n", (char *)buf)); 1686 1687 // set up our fdset and timeout 1688 FD_ZERO(&writefds); 1689 FD_SET(client_sockfd, &writefds); 1690 max_fd = client_sockfd; 1691 memcpy(&tv, &timeout, sizeof(struct timeval)); 1692 1693 ret = select(max_fd + 1, NULL, &writefds, NULL, &tv); 1694 dprintf((stderr, "ret: %d\n", ret)); 1695 1696 if(ret == -1) 1697 { 1698 dprintf((stderr, "select: %s\n", error_string)); 1699 } 1700 else if(ret == 0) 1701 { 1702 show_message("timeout\n"); 1703 } 1704 else 1705 { 1706 /* if we woke up on client_sockfd do the data passing */ 1707 if(FD_ISSET(client_sockfd, &writefds)) 1708 { 1709 if(send(client_sockfd, buf, strlen(buf), 0) == -1) 1710 { 1711 show_message("error send()ing request: %s\n", error_string); 1712 } 1713 } 1714 else 1715 { 1716 dprintf((stderr, "error: case not handled.")); 1717 } 1718 } 1719} 1720 1721int read_input(char *buf, int len) 1722{ 1723 fd_set readfds; 1724 int max_fd; 1725 struct timeval tv; 1726 int ret; 1727 int bread = -1; 1728 1729 // set up our fdset and timeout 1730 FD_ZERO(&readfds); 1731 FD_SET(client_sockfd, &readfds); 1732 max_fd = client_sockfd; 1733 memcpy(&tv, &timeout, sizeof(struct timeval)); 1734 1735 ret = select(max_fd + 1, &readfds, NULL, NULL, &tv); 1736 dprintf((stderr, "ret: %d\n", ret)); 1737 1738 if(ret == -1) 1739 { 1740 dprintf((stderr, "select: %s\n", error_string)); 1741 } 1742 else if(ret == 0) 1743 { 1744 show_message("timeout\n"); 1745 } 1746 else 1747 { 1748 /* if we woke up on client_sockfd do the data passing */ 1749 if(FD_ISSET(client_sockfd, &readfds)) 1750 { 1751 bread = recv(client_sockfd, buf, len-1, 0); 1752 dprintf((stderr, "bread: %d\n", bread)); 1753 buf[bread] = '\0'; 1754 dprintf((stderr, "got: %s\n", buf)); 1755 if(bread == -1) 1756 { 1757 show_message("error recv()ing reply: %s\n", error_string); 1758 } 1759 } 1760 else 1761 { 1762 dprintf((stderr, "error: case not handled.")); 1763 } 1764 } 1765 1766 return(bread); 1767} 1768 1769int get_if_addr(int sock, char *name, struct sockaddr_in *sin) 1770{ 1771#ifdef IF_LOOKUP 1772 struct ifreq ifr; 1773 1774 memset(&ifr, 0, sizeof(ifr)); 1775 strcpy(ifr.ifr_name, name); 1776 ifr.ifr_addr.sa_family = AF_INET; 1777 if(ioctl(sock, SIOCGIFADDR, &ifr) < 0) 1778 { 1779 perror("ioctl(SIOCGIFADDR)"); 1780 memset(sin, 0, sizeof(struct sockaddr_in)); 1781 dprintf((stderr, "%s: %s\n", name, "unknown interface")); 1782 return -1; 1783 } 1784 1785 if(ifr.ifr_addr.sa_family == AF_INET) 1786 { 1787 memcpy(sin, &(ifr.ifr_addr), sizeof(struct sockaddr_in)); 1788 dprintf((stderr, "%s: %s\n", name, inet_ntoa(sin->sin_addr))); 1789 return 0; 1790 } 1791 else 1792 { 1793 memset(sin, 0, sizeof(struct sockaddr_in)); 1794 dprintf((stderr, "%s: %s\n", name, "could not resolve interface")); 1795 return -1; 1796 } 1797 return -1; 1798#else 1799 return -1; 1800#endif 1801} 1802 1803#ifdef CONFIG_PGP 1804static int PGPOW_read_response(char *buf) 1805{ 1806 int bytes; 1807 1808 bytes = read_input(buf, BUFFER_SIZE); 1809 if(bytes < 1) 1810 { 1811 close(client_sockfd); 1812 return(-1); 1813 } 1814 buf[bytes] = '\0'; 1815 1816 dprintf((stderr, "server says: %s\n", buf)); 1817 1818 if(strncmp("OK", buf, 2) != 0) 1819 { 1820 return(1); 1821 } 1822 else 1823 { 1824 return(0); 1825 } 1826} 1827#endif 1828 1829static int ODS_read_response(char *buf, int len) 1830{ 1831 int bytes = 0; 1832 int bread = 0; 1833 char* p = buf; 1834 int max_iter = 32; 1835 1836 for(; bytes < len && max_iter > 0; max_iter--) 1837 { 1838 bread = read_input(p, len-bytes); 1839 bytes += bread; 1840 if(bytes < 1) 1841 { 1842 close(client_sockfd); 1843 return(-1); 1844 } 1845 if(strstr(buf, "\r\n") > 0) 1846 { 1847 break; 1848 } 1849 1850 dprintf((stderr, "server says: %s\n", p)); 1851 p += bread; 1852 } 1853 dprintf((stderr, "server said: %s\n", buf)); 1854 1855 return(atoi(buf)); 1856} 1857 1858int NULL_check_info(void) 1859{ 1860 char buf[64]; 1861 1862 if(options & OPT_DAEMON) 1863 { 1864 show_message("no compile time default service was set therefor you must " 1865 "specify a service type.\n"); 1866 1867 return(-1); 1868 } 1869 get_input("service", buf, sizeof(buf)); 1870 option_handler(CMD_service_type, buf); 1871 1872 return(0); 1873} 1874 1875int EZIP_check_info(void) 1876{ 1877 warn_fields(service->fields_used); 1878 1879 return 0; 1880} 1881 1882int EZIP_update_entry(void) 1883{ 1884 char *buf = update_entry_buf; 1885 char *bp; 1886 int bytes; 1887 int btot; 1888 int ret; 1889 1890 buf[BUFFER_SIZE] = '\0'; 1891 1892 if(do_connect((int*)&client_sockfd, server, port) != 0) 1893 { 1894 if(!(options & OPT_QUIET)) 1895 { 1896 show_message("error connecting to %s:%s\n", server, port); 1897 } 1898 return(UPDATERES_ERROR); 1899 } 1900 1901 snprintf(buf, BUFFER_SIZE, "GET %s?mode=update&", request); 1902 output(buf); 1903 if(address) 1904 { 1905 snprintf(buf, BUFFER_SIZE, "%s=%s&", "ipaddress", address); 1906 output(buf); 1907 } 1908 snprintf(buf, BUFFER_SIZE, "%s=%s&", "wildcard", wildcard ? "yes" : "no"); 1909 output(buf); 1910 snprintf(buf, BUFFER_SIZE, "%s=%s&", "mx", mx); 1911 output(buf); 1912 snprintf(buf, BUFFER_SIZE, "%s=%s&", "url", url); 1913 output(buf); 1914 snprintf(buf, BUFFER_SIZE, "%s=%s&", "host", host); 1915 output(buf); 1916 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 1917 output(buf); 1918 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 1919 output(buf); 1920 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 1921 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 1922 output(buf); 1923 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 1924 output(buf); 1925 snprintf(buf, BUFFER_SIZE, "\015\012"); 1926 output(buf); 1927 1928 bp = buf; 1929 bytes = 0; 1930 btot = 0; 1931 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 1932 { 1933 bp += bytes; 1934 btot += bytes; 1935 dprintf((stderr, "btot: %d\n", btot)); 1936 } 1937 close(client_sockfd); 1938 buf[btot] = '\0'; 1939 1940 dprintf((stderr, "server output: %s\n", buf)); 1941 1942 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 1943 { 1944 ret = -1; 1945 } 1946 1947 switch(ret) 1948 { 1949 case -1: 1950 if(!(options & OPT_QUIET)) 1951 { 1952 show_message("strange server response, are you connecting to the right server?\n"); 1953 } 1954 return(UPDATERES_ERROR); 1955 break; 1956 1957 case 200: 1958 if(!(options & OPT_QUIET)) 1959 { 1960 show_message("request successful\n"); 1961 } 1962 break; 1963 1964 case 401: 1965 if(!(options & OPT_QUIET)) 1966 { 1967 show_message("authentication failure\n"); 1968 } 1969 return(UPDATERES_SHUTDOWN); 1970 break; 1971 1972 default: 1973 if(!(options & OPT_QUIET)) 1974 { 1975 // reuse the auth buffer 1976 *auth = '\0'; 1977 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 1978 show_message("unknown return code: %d\n", ret); 1979 show_message("server response: %s\n", auth); 1980 } 1981 return(UPDATERES_ERROR); 1982 break; 1983 } 1984 1985 return(UPDATERES_OK); 1986} 1987 1988void DYNDNS_init(void) 1989{ 1990 1991 if(options & OPT_DAEMON) 1992 { 1993 if(!(max_interval > 0)) 1994 { 1995 max_interval = DYNDNS_MAX_INTERVAL; 1996 } 1997 } 1998} 1999 2000int DYNDNS_check_info(void) 2001{ 2002 char buf[BUFSIZ+1]; 2003 2004 if((host == NULL) || (*host == '\0')) 2005 { 2006 if(options & OPT_DAEMON) 2007 { 2008 return(-1); 2009 } 2010 if(host) { free(host); } 2011 get_input("host", buf, sizeof(buf)); 2012 host = strdup(buf); 2013 } 2014 2015 if(address != NULL && !is_dotted_quad(address)) 2016 { 2017 show_message("the IP address \"%s\" is invalid\n", address); 2018 return(-1); 2019 } 2020 2021 if(interface == NULL && address == NULL) 2022 { 2023 if(options & OPT_DAEMON) 2024 { 2025 show_message("you must provide either an interface or an address\n"); 2026 return(-1); 2027 } 2028 if(interface) { free(interface); } 2029 get_input("interface", buf, sizeof(buf)); 2030 option_handler(CMD_interface, buf); 2031 } 2032 2033 warn_fields(service->fields_used); 2034 2035 return 0; 2036} 2037 2038int DYNDNS_update_entry(void) 2039{ 2040 char *buf = update_entry_buf; 2041 char *bp = buf; 2042 int bytes; 2043 int btot; 2044 int ret; 2045 int retval = UPDATERES_OK; 2046 2047 buf[BUFFER_SIZE] = '\0'; 2048 2049 if(do_connect((int*)&client_sockfd, server, port) != 0) 2050 { 2051 if(!(options & OPT_QUIET)) 2052 { 2053 show_message("error connecting to %s:%s\n", server, port); 2054 } 2055 return(UPDATERES_ERROR); 2056 } 2057 2058 snprintf(buf, BUFFER_SIZE, "GET %s?", request); 2059 output(buf); 2060 2061 if(is_in_list("dyndns-static", service->names)) 2062 { 2063 snprintf(buf, BUFFER_SIZE, "%s=%s&", "system", "statdns"); 2064 output(buf); 2065 } 2066 else if(is_in_list("dyndns-custom", service->names)) 2067 { 2068 snprintf(buf, BUFFER_SIZE, "%s=%s&", "system", "custom"); 2069 output(buf); 2070 } 2071 2072 snprintf(buf, BUFFER_SIZE, "%s=%s&", "hostname", host); 2073 output(buf); 2074 if(address != NULL) 2075 { 2076 snprintf(buf, BUFFER_SIZE, "%s=%s&", "myip", address); 2077 output(buf); 2078 } 2079 snprintf(buf, BUFFER_SIZE, "%s=%s&", "wildcard", wildcard ? "ON" : "OFF"); 2080 output(buf); 2081 if(mx != NULL && *mx != '\0') 2082 { 2083 snprintf(buf, BUFFER_SIZE, "%s=%s&", "mx", mx); 2084 output(buf); 2085 } 2086 //snprintf(buf, BUFFER_SIZE, "%s=%s&", "backmx", "NO"); 2087 //output(buf); 2088 if(options & OPT_OFFLINE) 2089 { 2090 snprintf(buf, BUFFER_SIZE, "%s=%s&", "offline", "yes"); 2091 output(buf); 2092 } 2093 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 2094 output(buf); 2095 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 2096 output(buf); 2097 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 2098 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 2099 output(buf); 2100 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 2101 output(buf); 2102 snprintf(buf, BUFFER_SIZE, "\015\012"); 2103 output(buf); 2104 2105 bp = buf; 2106 bytes = 0; 2107 btot = 0; 2108 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 2109 { 2110 bp += bytes; 2111 btot += bytes; 2112 dprintf((stderr, "btot: %d\n", btot)); 2113 } 2114 close(client_sockfd); 2115 buf[btot] = '\0'; 2116 2117 dprintf((stderr, "server output: %s\n", buf)); 2118 2119 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 2120 { 2121 ret = -1; 2122 } 2123 2124 switch(ret) 2125 { 2126 case -1: 2127 if(!(options & OPT_QUIET)) 2128 { 2129 show_message("strange server response, are you connecting to the right server?\n"); 2130 } 2131 retval = UPDATERES_ERROR; 2132 break; 2133 2134 case 200: 2135 if(strstr(buf, "\ngood ") != NULL) 2136 { 2137 if(!(options & OPT_QUIET)) 2138 { 2139 show_message("request successful\n"); 2140 } 2141 } 2142 else 2143 { 2144 if(strstr(buf, "\nnohost") != NULL) 2145 { 2146 show_message("invalid hostname: %s\n", host); 2147 retval = UPDATERES_SHUTDOWN; 2148 } 2149 else if(strstr(buf, "\nnotfqdn") != NULL) 2150 { 2151 show_message("malformed hostname: %s\n", host); 2152 retval = UPDATERES_SHUTDOWN; 2153 } 2154 else if(strstr(buf, "\n!yours") != NULL) 2155 { 2156 show_message("host \"%s\" is not under your control\n", host); 2157 retval = UPDATERES_SHUTDOWN; 2158 } 2159 else if(strstr(buf, "\nabuse") != NULL) 2160 { 2161 show_message("host \"%s\" has been blocked for abuse\n", host); 2162 retval = UPDATERES_SHUTDOWN; 2163 } 2164 else if(strstr(buf, "\nnochg") != NULL) 2165 { 2166 show_message("%s says that your IP address has not changed since the last update\n", server); 2167 // lets say that this counts as a successful update 2168 // but we'll roll back the last update time to max_interval/2 2169 if(max_interval > 0) 2170 { 2171 last_update = time(NULL) - max_interval/2; 2172 } 2173 retval = UPDATERES_OK; 2174 } 2175 else if(strstr(buf, "\nbadauth") != NULL) 2176 { 2177 show_message("authentication failure\n"); 2178 retval = UPDATERES_SHUTDOWN; 2179 } 2180 else if(strstr(buf, "\nbadsys") != NULL) 2181 { 2182 show_message("invalid system parameter\n"); 2183 retval = UPDATERES_SHUTDOWN; 2184 } 2185 else if(strstr(buf, "\nbadagent") != NULL) 2186 { 2187 show_message("this useragent has been blocked\n"); 2188 retval = UPDATERES_SHUTDOWN; 2189 } 2190 else if(strstr(buf, "\nnumhost") != NULL) 2191 { 2192 show_message("Too many or too few hosts found\n"); 2193 retval = UPDATERES_SHUTDOWN; 2194 } 2195 else if(strstr(buf, "\ndnserr") != NULL) 2196 { 2197 char *p = strstr(buf, "\ndnserr"); 2198 show_message("dyndns internal error, please report this number to " 2199 "their support people: %s\n", N_STR(p)); 2200 retval = UPDATERES_ERROR; 2201 } 2202 else if(strstr(buf, "\n911") != NULL) 2203 { 2204 show_message("Ahhhh! call 911!\n"); 2205 retval = UPDATERES_SHUTDOWN; 2206 } 2207 else if(strstr(buf, "\n999") != NULL) 2208 { 2209 show_message("Ahhhh! call 999!\n"); 2210 retval = UPDATERES_SHUTDOWN; 2211 } 2212 else if(strstr(buf, "\n!donator") != NULL) 2213 { 2214 show_message("a feature requested is only available to donators, please donate.\n", host); 2215 retval = UPDATERES_OK; 2216 } 2217 // this one should be last as it is a stupid string to signify waits 2218 // with as it is so short 2219 else if(strstr(buf, "\nw") != NULL) 2220 { 2221 int howlong = 0; 2222 char *p = strstr(buf, "\nw"); 2223 char reason[256]; 2224 char mult; 2225 2226 // get time and reason 2227 if(strlen(p) >= 2) 2228 { 2229 sscanf(p, "%d%c %255[^\r\n]", &howlong, &mult, reason); 2230 if(mult == 'h') 2231 { 2232 howlong *= 3600; 2233 } 2234 else if(mult == 'm') 2235 { 2236 howlong *= 60; 2237 } 2238 if(howlong > MAX_WAITRESPONSE_WAIT) 2239 { 2240 howlong = MAX_WAITRESPONSE_WAIT; 2241 }; 2242 } 2243 else 2244 { 2245 sprintf(reason, "problem parsing reason for wait response"); 2246 } 2247 2248 show_message("Wait response received, waiting for %s before next update.\n", 2249 format_time(howlong)); 2250 show_message("Wait response reason: %d\n", N_STR(reason)); 2251 sleep(howlong); 2252 retval = UPDATERES_ERROR; 2253 } 2254 else 2255 { 2256 show_message("error processing request\n"); 2257 if(!(options & OPT_QUIET)) 2258 { 2259 show_message("server output: %s\n", buf); 2260 } 2261 retval = UPDATERES_ERROR; 2262 } 2263 } 2264 break; 2265 2266 case 401: 2267 if(!(options & OPT_QUIET)) 2268 { 2269 show_message("authentication failure\n"); 2270 } 2271 retval = UPDATERES_SHUTDOWN; 2272 break; 2273 2274 default: 2275 if(!(options & OPT_QUIET)) 2276 { 2277 // reuse the auth buffer 2278 *auth = '\0'; 2279 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 2280 show_message("unknown return code: %d\n", ret); 2281 show_message("server response: %s\n", auth); 2282 } 2283 retval = UPDATERES_ERROR; 2284 break; 2285 } 2286 2287 return(retval); 2288} 2289 2290#ifdef CONFIG_PGP 2291int PGPOW_check_info(void) 2292{ 2293 char buf[BUFSIZ+1]; 2294 2295 if((host == NULL) || (*host == '\0')) 2296 { 2297 if(options & OPT_DAEMON) 2298 { 2299 return(-1); 2300 } 2301 if(host) { free(host); } 2302 get_input("host", buf, sizeof(buf)); 2303 host = strdup(buf); 2304 } 2305 2306 if(interface == NULL && address == NULL) 2307 { 2308 if(options & OPT_DAEMON) 2309 { 2310 show_message("you must provide either an interface or an address\n"); 2311 return(-1); 2312 } 2313 if(interface) { free(interface); } 2314 get_input("interface", buf, sizeof(buf)); 2315 option_handler(CMD_interface, buf); 2316 } 2317 2318 warn_fields(service->fields_used); 2319 2320 return 0; 2321} 2322 2323int PGPOW_update_entry(void) 2324{ 2325 char *buf = update_entry_buf; 2326 2327 buf[BUFFER_SIZE] = '\0'; 2328 2329 if(do_connect((int*)&client_sockfd, server, port) != 0) 2330 { 2331 if(!(options & OPT_QUIET)) 2332 { 2333 show_message("error connecting to %s:%s\n", server, port); 2334 } 2335 return(UPDATERES_ERROR); 2336 } 2337 2338 /* read server message */ 2339 if(PGPOW_read_response(buf) != 0) 2340 { 2341 show_message("strange server response, are you connecting to the right server?\n"); 2342 close(client_sockfd); 2343 return(UPDATERES_ERROR); 2344 } 2345 2346 /* send version command */ 2347 snprintf(buf, BUFFER_SIZE, "VER %s [%s-%s %s (%s)]\015\012", PGPOW_VERSION, 2348 "ez-update", VERSION, OS, "by Angus Mackay"); 2349 output(buf); 2350 2351 if(PGPOW_read_response(buf) != 0) 2352 { 2353 if(strncmp("ERR", buf, 3) == 0) 2354 { 2355 show_message("error talking to server: %s\n", &(buf[3])); 2356 } 2357 else 2358 { 2359 show_message("error talking to server:\n\t%s\n", buf); 2360 } 2361 close(client_sockfd); 2362 return(UPDATERES_ERROR); 2363 } 2364 2365 /* send user command */ 2366 snprintf(buf, BUFFER_SIZE, "USER %s\015\012", user_name); 2367 output(buf); 2368 2369 if(PGPOW_read_response(buf) != 0) 2370 { 2371 if(strncmp("ERR", buf, 3) == 0) 2372 { 2373 show_message("error talking to server: %s\n", &(buf[3])); 2374 } 2375 else 2376 { 2377 show_message("error talking to server:\n\t%s\n", buf); 2378 } 2379 close(client_sockfd); 2380 return(UPDATERES_ERROR); 2381 } 2382 2383 /* send pass command */ 2384 snprintf(buf, BUFFER_SIZE, "PASS %s\015\012", password); 2385 output(buf); 2386 2387 if(PGPOW_read_response(buf) != 0) 2388 { 2389 if(strncmp("ERR", buf, 3) == 0) 2390 { 2391 show_message("error talking to server: %s\n", &(buf[3])); 2392 } 2393 else 2394 { 2395 show_message("error talking to server:\n\t%s\n", buf); 2396 } 2397 close(client_sockfd); 2398 return(UPDATERES_ERROR); 2399 } 2400 2401 /* send host command */ 2402 snprintf(buf, BUFFER_SIZE, "HOST %s\015\012", host); 2403 output(buf); 2404 2405 if(PGPOW_read_response(buf) != 0) 2406 { 2407 if(strncmp("ERR", buf, 3) == 0) 2408 { 2409 show_message("error talking to server: %s\n", &(buf[3])); 2410 } 2411 else 2412 { 2413 show_message("error talking to server:\n\t%s\n", buf); 2414 } 2415 close(client_sockfd); 2416 return(UPDATERES_ERROR); 2417 } 2418 2419 /* send oper command */ 2420 snprintf(buf, BUFFER_SIZE, "OPER %s\015\012", request); 2421 output(buf); 2422 2423 if(PGPOW_read_response(buf) != 0) 2424 { 2425 if(strncmp("ERR", buf, 3) == 0) 2426 { 2427 show_message("error talking to server: %s\n", &(buf[3])); 2428 } 2429 else 2430 { 2431 show_message("error talking to server:\n\t%s\n", buf); 2432 } 2433 close(client_sockfd); 2434 return(UPDATERES_ERROR); 2435 } 2436 2437 if(strcmp("update", request) == 0) 2438 { 2439 /* send ip command */ 2440 snprintf(buf, BUFFER_SIZE, "IP %s\015\012", address); 2441 output(buf); 2442 2443 if(PGPOW_read_response(buf) != 0) 2444 { 2445 if(strncmp("ERR", buf, 3) == 0) 2446 { 2447 show_message("error talking to server: %s\n", &(buf[3])); 2448 } 2449 else 2450 { 2451 show_message("error talking to server:\n\t%s\n", buf); 2452 } 2453 close(client_sockfd); 2454 return(UPDATERES_ERROR); 2455 } 2456 } 2457 2458 /* send done command */ 2459 snprintf(buf, BUFFER_SIZE, "DONE\015\012"); 2460 output(buf); 2461 2462 if(PGPOW_read_response(buf) != 0) 2463 { 2464 if(strncmp("ERR", buf, 3) == 0) 2465 { 2466 show_message("error talking to server: %s\n", &(buf[3])); 2467 } 2468 else 2469 { 2470 show_message("error talking to server:\n\t%s\n", buf); 2471 } 2472 close(client_sockfd); 2473 return(UPDATERES_ERROR); 2474 } 2475 2476 if(!(options & OPT_QUIET)) 2477 { 2478 show_message("request successful\n"); 2479 } 2480 2481 close(client_sockfd); 2482 return(UPDATERES_OK); 2483} 2484#endif 2485 2486#ifdef CONFIG_DHS 2487int DHS_check_info(void) 2488{ 2489 char buf[BUFSIZ+1]; 2490 2491 if((host == NULL) || (*host == '\0')) 2492 { 2493 if(options & OPT_DAEMON) 2494 { 2495 return(-1); 2496 } 2497 if(host) { free(host); } 2498 get_input("host", buf, sizeof(buf)); 2499 host = strdup(buf); 2500 } 2501 2502 if(interface == NULL && address == NULL) 2503 { 2504 if(options & OPT_DAEMON) 2505 { 2506 show_message("you must provide either an interface or an address\n"); 2507 return(-1); 2508 } 2509 if(interface) { free(interface); } 2510 get_input("interface", buf, sizeof(buf)); 2511 option_handler(CMD_interface, buf); 2512 } 2513 2514 warn_fields(service->fields_used); 2515 2516 return 0; 2517} 2518 2519/* 2520 * grrrrr, it seems that dhs.org requires us to use POST 2521 * also DHS doesn't update both the mx record and the address at the same 2522 * time, this service really stinks. go with justlinix.com (penguinpowered) 2523 * instead, the only advantage is short host names. 2524 */ 2525int DHS_update_entry(void) 2526{ 2527 char *buf = update_entry_buf; 2528 char *putbuf = update_entry_putbuf; 2529 char *bp = buf; 2530 int bytes; 2531 int btot; 2532 int ret; 2533 char *domain = NULL; 2534 char *hostname = NULL; 2535 char *p; 2536 int limit; 2537 int retval = UPDATERES_OK; 2538 2539 buf[BUFFER_SIZE] = '\0'; 2540 putbuf[BUFFER_SIZE] = '\0'; 2541 2542 /* parse apart the domain and hostname */ 2543 hostname = strdup(host); 2544 if((p=strchr(hostname, '.')) == NULL) 2545 { 2546 if(!(options & OPT_QUIET)) 2547 { 2548 show_message("error parsing hostname from host %s\n", host); 2549 } 2550 return(UPDATERES_ERROR); 2551 } 2552 *p = '\0'; 2553 p++; 2554 if(*p == '\0') 2555 { 2556 if(!(options & OPT_QUIET)) 2557 { 2558 show_message("error parsing domain from host %s\n", host); 2559 } 2560 return(UPDATERES_ERROR); 2561 } 2562 domain = strdup(p); 2563 2564 dprintf((stderr, "hostname: %s, domain: %s\n", hostname, domain)); 2565 2566 if(do_connect((int*)&client_sockfd, server, port) != 0) 2567 { 2568 if(!(options & OPT_QUIET)) 2569 { 2570 show_message("error connecting to %s:%s\n", server, port); 2571 } 2572 return(UPDATERES_ERROR); 2573 } 2574 2575 snprintf(buf, BUFFER_SIZE, "POST %s HTTP/1.0\015\012", request); 2576 output(buf); 2577 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 2578 output(buf); 2579 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 2580 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 2581 output(buf); 2582 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 2583 output(buf); 2584 2585 p = putbuf; 2586 *p = '\0'; 2587 limit = BUFFER_SIZE - 1 - strlen(buf); 2588 snprintf(p, limit, "hostscmd=edit&hostscmdstage=2&type=4&"); 2589 p += strlen(p); 2590 limit = BUFFER_SIZE - 1 - strlen(buf); 2591 snprintf(p, limit, "%s=%s&", "updatetype", "Online"); 2592 p += strlen(p); 2593 limit = BUFFER_SIZE - 1 - strlen(buf); 2594 snprintf(p, limit, "%s=%s&", "ip", address); 2595 p += strlen(p); 2596 limit = BUFFER_SIZE - 1 - strlen(buf); 2597 snprintf(p, limit, "%s=%s&", "mx", mx); 2598 p += strlen(p); 2599 limit = BUFFER_SIZE - 1 - strlen(buf); 2600 snprintf(p, limit, "%s=%s&", "offline_url", url); 2601 p += strlen(p); 2602 limit = BUFFER_SIZE - 1 - strlen(buf); 2603 if(cloak_title) 2604 { 2605 snprintf(p, limit, "%s=%s&", "cloak", "Y"); 2606 p += strlen(p); 2607 limit = BUFFER_SIZE - 1 - strlen(buf); 2608 snprintf(p, limit, "%s=%s&", "cloak_title", cloak_title); 2609 p += strlen(p); 2610 limit = BUFFER_SIZE - 1 - strlen(buf); 2611 } 2612 else 2613 { 2614 snprintf(p, limit, "%s=%s&", "cloak_title", ""); 2615 p += strlen(p); 2616 limit = BUFFER_SIZE - 1 - strlen(buf); 2617 } 2618 snprintf(p, limit, "%s=%s&", "submit", "Update"); 2619 p += strlen(p); 2620 limit = BUFFER_SIZE - 1 - strlen(buf); 2621 snprintf(p, limit, "%s=%s&", "domain", domain); 2622 p += strlen(p); 2623 limit = BUFFER_SIZE - 1 - strlen(buf); 2624 snprintf(p, limit, "%s=%s", "hostname", hostname); 2625 p += strlen(p); 2626 limit = BUFFER_SIZE - 1 - strlen(buf); 2627 2628 snprintf(buf, BUFFER_SIZE, "Content-length: %d\015\012", strlen(putbuf)); 2629 output(buf); 2630 snprintf(buf, BUFFER_SIZE, "\015\012"); 2631 output(buf); 2632 2633 output(putbuf); 2634 snprintf(buf, BUFFER_SIZE, "\015\012"); 2635 output(buf); 2636 2637 bp = buf; 2638 bytes = 0; 2639 btot = 0; 2640 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 2641 { 2642 bp += bytes; 2643 btot += bytes; 2644 dprintf((stderr, "btot: %d\n", btot)); 2645 } 2646 close(client_sockfd); 2647 buf[btot] = '\0'; 2648 2649 dprintf((stderr, "server output: %s\n", buf)); 2650 2651 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 2652 { 2653 ret = -1; 2654 } 2655 2656 switch(ret) 2657 { 2658 case -1: 2659 if(!(options & OPT_QUIET)) 2660 { 2661 show_message("strange server response, are you connecting to the right server?\n"); 2662 } 2663 retval = UPDATERES_ERROR; 2664 break; 2665 2666 case 200: 2667 if(!(options & OPT_QUIET)) 2668 { 2669 show_message("request successful\n"); 2670 } 2671 break; 2672 2673 case 401: 2674 if(!(options & OPT_QUIET)) 2675 { 2676 show_message("authentication failure\n"); 2677 } 2678 retval = UPDATERES_SHUTDOWN; 2679 break; 2680 2681 default: 2682 if(!(options & OPT_QUIET)) 2683 { 2684 // reuse the auth buffer 2685 *auth = '\0'; 2686 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 2687 show_message("unknown return code: %d\n", ret); 2688 show_message("server response: %s\n", auth); 2689 } 2690 retval = UPDATERES_ERROR; 2691 break; 2692 } 2693 2694 // this stupid service requires us to do seperate request if we want to 2695 // update the mail exchanger (mx). grrrrrr 2696 if(*mx != '\0') 2697 { 2698 // okay, dhs's service is incredibly stupid and will not work with two 2699 // requests right after each other. I could care less that this is ugly, 2700 // I personally will NEVER use dhs, it is laughable. 2701 sleep(DHS_SUCKY_TIMEOUT < timeout.tv_sec ? DHS_SUCKY_TIMEOUT : timeout.tv_sec); 2702 2703 if(do_connect((int*)&client_sockfd, server, port) != 0) 2704 { 2705 if(!(options & OPT_QUIET)) 2706 { 2707 show_message("error connecting to %s:%s\n", server, port); 2708 } 2709 return(UPDATERES_ERROR); 2710 } 2711 2712 snprintf(buf, BUFFER_SIZE, "POST %s HTTP/1.0\015\012", request); 2713 output(buf); 2714 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 2715 output(buf); 2716 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 2717 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 2718 output(buf); 2719 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 2720 output(buf); 2721 2722 p = putbuf; 2723 *p = '\0'; 2724 limit = BUFFER_SIZE - 1 - strlen(buf); 2725 snprintf(p, limit, "hostscmd=edit&hostscmdstage=2&type=4&"); 2726 p += strlen(p); 2727 limit = BUFFER_SIZE - 1 - strlen(buf); 2728 snprintf(p, limit, "%s=%s&", "updatetype", "Update+Mail+Exchanger"); 2729 p += strlen(p); 2730 limit = BUFFER_SIZE - 1 - strlen(buf); 2731 snprintf(p, limit, "%s=%s&", "ip", address); 2732 p += strlen(p); 2733 limit = BUFFER_SIZE - 1 - strlen(buf); 2734 snprintf(p, limit, "%s=%s&", "mx", mx); 2735 p += strlen(p); 2736 limit = BUFFER_SIZE - 1 - strlen(buf); 2737 snprintf(p, limit, "%s=%s&", "offline_url", url); 2738 p += strlen(p); 2739 limit = BUFFER_SIZE - 1 - strlen(buf); 2740 if(cloak_title) 2741 { 2742 snprintf(p, limit, "%s=%s&", "cloak", "Y"); 2743 p += strlen(p); 2744 limit = BUFFER_SIZE - 1 - strlen(buf); 2745 snprintf(p, limit, "%s=%s&", "cloak_title", cloak_title); 2746 p += strlen(p); 2747 limit = BUFFER_SIZE - 1 - strlen(buf); 2748 } 2749 else 2750 { 2751 snprintf(p, limit, "%s=%s&", "cloak_title", ""); 2752 p += strlen(p); 2753 limit = BUFFER_SIZE - 1 - strlen(buf); 2754 } 2755 snprintf(p, limit, "%s=%s&", "submit", "Update"); 2756 p += strlen(p); 2757 limit = BUFFER_SIZE - 1 - strlen(buf); 2758 snprintf(p, limit, "%s=%s&", "domain", domain); 2759 p += strlen(p); 2760 limit = BUFFER_SIZE - 1 - strlen(buf); 2761 snprintf(p, limit, "%s=%s", "hostname", hostname); 2762 p += strlen(p); 2763 limit = BUFFER_SIZE - 1 - strlen(buf); 2764 2765 snprintf(buf, BUFFER_SIZE, "Content-length: %d\015\012", strlen(putbuf)); 2766 output(buf); 2767 snprintf(buf, BUFFER_SIZE, "\015\012"); 2768 output(buf); 2769 2770 output(putbuf); 2771 snprintf(buf, BUFFER_SIZE, "\015\012"); 2772 output(buf); 2773 2774 bp = buf; 2775 bytes = 0; 2776 btot = 0; 2777 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 2778 { 2779 bp += bytes; 2780 btot += bytes; 2781 dprintf((stderr, "btot: %d\n", btot)); 2782 } 2783 close(client_sockfd); 2784 buf[btot] = '\0'; 2785 2786 dprintf((stderr, "server output: %s\n", buf)); 2787 2788 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 2789 { 2790 ret = -1; 2791 } 2792 2793 switch(ret) 2794 { 2795 case -1: 2796 if(!(options & OPT_QUIET)) 2797 { 2798 show_message("strange server response, are you connecting to the right server?\n"); 2799 } 2800 retval = UPDATERES_ERROR; 2801 break; 2802 2803 case 200: 2804 if(!(options & OPT_QUIET)) 2805 { 2806 show_message("request successful\n"); 2807 } 2808 break; 2809 2810 case 401: 2811 if(!(options & OPT_QUIET)) 2812 { 2813 show_message("authentication failure\n"); 2814 } 2815 retval = UPDATERES_SHUTDOWN; 2816 break; 2817 2818 default: 2819 if(!(options & OPT_QUIET)) 2820 { 2821 // reuse the auth buffer 2822 *auth = '\0'; 2823 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 2824 show_message("unknown return code: %d\n", ret); 2825 show_message("server response: %s\n", auth); 2826 } 2827 retval = UPDATERES_ERROR; 2828 break; 2829 } 2830 } 2831 2832 return(retval); 2833} 2834#endif 2835 2836#ifdef CONFIG_ODS 2837int ODS_check_info(void) 2838{ 2839 char buf[BUFSIZ+1]; 2840 2841 if((host == NULL) || (*host == '\0')) 2842 { 2843 if(options & OPT_DAEMON) 2844 { 2845 return(-1); 2846 } 2847 if(host) { free(host); } 2848 get_input("host", buf, sizeof(buf)); 2849 host = strdup(buf); 2850 } 2851 2852 if(interface == NULL && address == NULL) 2853 { 2854 if(options & OPT_DAEMON) 2855 { 2856 show_message("you must provide either an interface or an address\n"); 2857 return(-1); 2858 } 2859 if(address) { free(address); } 2860 address = strdup(""); 2861 } 2862 2863 warn_fields(service->fields_used); 2864 2865 return 0; 2866} 2867 2868int ODS_update_entry(void) 2869{ 2870 char *buf = update_entry_buf; 2871 int response; 2872 2873 buf[BUFFER_SIZE] = '\0'; 2874 2875 if(do_connect((int*)&client_sockfd, server, port) != 0) 2876 { 2877 if(!(options & OPT_QUIET)) 2878 { 2879 show_message("error connecting to %s:%s\n", server, port); 2880 } 2881 return(UPDATERES_ERROR); 2882 } 2883 2884 /* read server message */ 2885 if(ODS_read_response(buf, BUFFER_SIZE) != 100) 2886 { 2887 show_message("strange server response, are you connecting to the right server?\n"); 2888 close(client_sockfd); 2889 return(UPDATERES_ERROR); 2890 } 2891 2892 /* send login command */ 2893 snprintf(buf, BUFFER_SIZE, "LOGIN %s %s\012", user_name, password); 2894 output(buf); 2895 2896 response = ODS_read_response(buf, BUFFER_SIZE); 2897 if(!(response == 225 || response == 226)) 2898 { 2899 if(strlen(buf) > 4) 2900 { 2901 show_message("error talking to server: %s\n", &(buf[4])); 2902 } 2903 else 2904 { 2905 show_message("error talking to server\n"); 2906 } 2907 close(client_sockfd); 2908 return(UPDATERES_ERROR); 2909 } 2910 2911 /* send delete command */ 2912 snprintf(buf, BUFFER_SIZE, "DELRR %s A\012", host); 2913 output(buf); 2914 2915 if(ODS_read_response(buf, BUFFER_SIZE) != 901) 2916 { 2917 if(strlen(buf) > 4) 2918 { 2919 show_message("error talking to server: %s\n", &(buf[4])); 2920 } 2921 else 2922 { 2923 show_message("error talking to server\n"); 2924 } 2925 close(client_sockfd); 2926 return(UPDATERES_ERROR); 2927 } 2928 2929 /* send address command */ 2930 snprintf(buf, BUFFER_SIZE, "ADDRR %s A %s\012", host, 2931 *address == '\0' ? "CONNIP" : address); 2932 output(buf); 2933 2934 response = ODS_read_response(buf, BUFFER_SIZE); 2935 if(!(response == 795 || response == 796)) 2936 { 2937 if(strlen(buf) > 4) 2938 { 2939 show_message("error talking to server: %s\n", &(buf[4])); 2940 } 2941 else 2942 { 2943 show_message("error talking to server\n"); 2944 } 2945 close(client_sockfd); 2946 return(UPDATERES_ERROR); 2947 } 2948 2949 if(!(options & OPT_QUIET)) 2950 { 2951 show_message("request successful\n"); 2952 } 2953 2954 close(client_sockfd); 2955 return(UPDATERES_OK); 2956} 2957#endif 2958 2959int TZO_check_info(void) 2960{ 2961 char buf[BUFSIZ+1]; 2962 2963 if((host == NULL) || (*host == '\0')) 2964 { 2965 if(options & OPT_DAEMON) 2966 { 2967 return(-1); 2968 } 2969 if(host) { free(host); } 2970 get_input("host", buf, sizeof(buf)); 2971 host = strdup(buf); 2972 } 2973 2974 if(interface == NULL && address == NULL) 2975 { 2976 if(options & OPT_DAEMON) 2977 { 2978 show_message("you must provide either an interface or an address\n"); 2979 return(-1); 2980 } 2981 if(interface) { free(interface); } 2982 get_input("interface", buf, sizeof(buf)); 2983 option_handler(CMD_interface, buf); 2984 } 2985 2986 warn_fields(service->fields_used); 2987 2988 return 0; 2989} 2990 2991int TZO_update_entry(void) 2992{ 2993 char *buf = update_entry_buf; 2994 char *bp = buf; 2995 int bytes; 2996 int btot; 2997 int ret; 2998 2999 buf[BUFFER_SIZE] = '\0'; 3000 3001 if(do_connect((int*)&client_sockfd, server, port) != 0) 3002 { 3003 if(!(options & OPT_QUIET)) 3004 { 3005 show_message("error connecting to %s:%s\n", server, port); 3006 } 3007 return(UPDATERES_ERROR); 3008 } 3009 3010 snprintf(buf, BUFFER_SIZE, "GET %s?", request); 3011 output(buf); 3012 snprintf(buf, BUFFER_SIZE, "%s=%s&", "TZOName", host); 3013 output(buf); 3014 snprintf(buf, BUFFER_SIZE, "%s=%s&", "Email", user_name); 3015 output(buf); 3016 snprintf(buf, BUFFER_SIZE, "%s=%s&", "TZOKey", password); 3017 output(buf); 3018 snprintf(buf, BUFFER_SIZE, "%s=%s&", "IPAddress", address); 3019 output(buf); 3020 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 3021 output(buf); 3022 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 3023 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 3024 output(buf); 3025 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 3026 output(buf); 3027 snprintf(buf, BUFFER_SIZE, "\015\012"); 3028 output(buf); 3029 3030 bp = buf; 3031 bytes = 0; 3032 btot = 0; 3033 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 3034 { 3035 bp += bytes; 3036 btot += bytes; 3037 dprintf((stderr, "btot: %d\n", btot)); 3038 } 3039 close(client_sockfd); 3040 buf[btot] = '\0'; 3041 3042 dprintf((stderr, "server output: %s\n", buf)); 3043 3044 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 3045 { 3046 ret = -1; 3047 } 3048 3049 switch(ret) 3050 { 3051 case -1: 3052 if(!(options & OPT_QUIET)) 3053 { 3054 show_message("strange server response, are you connecting to the right server?\n"); 3055 } 3056 return(UPDATERES_ERROR); 3057 break; 3058 3059 case 200: 3060 if(!(options & OPT_QUIET)) 3061 { 3062 show_message("request successful\n"); 3063 } 3064 break; 3065 3066 case 302: 3067 // There is no neat way to determine the exact error other than to 3068 // parse the Location part of the mime header to find where we're 3069 // being redirected. 3070 if(!(options & OPT_QUIET)) 3071 { 3072 // reuse the auth buffer 3073 *auth = '\0'; 3074 bp = strstr(buf, "Location: "); 3075 if((bp < strstr(buf, "\r\n\r\n")) && (sscanf(bp, "Location: http://%*[^/]%255[^\r\n]", auth) == 1)) 3076 { 3077 bp = strrchr(auth, '/') + 1; 3078 } 3079 else 3080 { 3081 bp = ""; 3082 } 3083 dprintf((stderr, "location: %s\n", bp)); 3084 3085 if(!(strncmp(bp, "domainmismatch.htm", strlen(bp)) && strncmp(bp, "invname.htm", strlen(bp)))) 3086 { 3087 show_message("invalid host name\n"); 3088 } 3089 else if(!strncmp(bp, "invkey.htm", strlen(bp))) 3090 { 3091 show_message("invalid password(tzo key)\n"); 3092 } 3093 else if(!(strncmp(bp, "emailmismatch.htm", strlen(bp)) && strncmp(bp, "invemail.htm", strlen(bp)))) 3094 { 3095 show_message("invalid user name(email address)\n"); 3096 } 3097 else 3098 { 3099 show_message("unknown error\n"); 3100 } 3101 } 3102 return(UPDATERES_ERROR); 3103 break; 3104 3105 default: 3106 if(!(options & OPT_QUIET)) 3107 { 3108 // reuse the auth buffer 3109 *auth = '\0'; 3110 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 3111 show_message("unknown return code: %d\n", ret); 3112 show_message("server response: %s\n", auth); 3113 } 3114 return(UPDATERES_ERROR); 3115 break; 3116 } 3117 3118 return(UPDATERES_OK); 3119} 3120 3121int EASYDNS_check_info(void) 3122{ 3123 char buf[BUFSIZ+1]; 3124 3125 if((host == NULL) || (*host == '\0')) 3126 { 3127 if(options & OPT_DAEMON) 3128 { 3129 return(-1); 3130 } 3131 if(host) { free(host); } 3132 get_input("host", buf, sizeof(buf)); 3133 host = strdup(buf); 3134 } 3135 3136 if(interface == NULL && address == NULL) 3137 { 3138 if(options & OPT_DAEMON) 3139 { 3140 show_message("you must provide either an interface or an address\n"); 3141 return(-1); 3142 } 3143 if(interface) { free(interface); } 3144 get_input("interface", buf, sizeof(buf)); 3145 option_handler(CMD_interface, buf); 3146 } 3147 3148 warn_fields(service->fields_used); 3149 3150 return 0; 3151} 3152 3153int EASYDNS_update_entry(void) 3154{ 3155 char *buf = update_entry_buf; 3156 char *bp = buf; 3157 int bytes; 3158 int btot; 3159 int ret; 3160 3161 buf[BUFFER_SIZE] = '\0'; 3162 3163 if(do_connect((int*)&client_sockfd, server, port) != 0) 3164 { 3165 if(!(options & OPT_QUIET)) 3166 { 3167 show_message("error connecting to %s:%s\n", server, port); 3168 } 3169 return(UPDATERES_ERROR); 3170 } 3171 3172 snprintf(buf, BUFFER_SIZE, "GET %s?action=edit&", request); 3173 output(buf); 3174 if(address != NULL && *address != '\0') 3175 { 3176 snprintf(buf, BUFFER_SIZE, "%s=%s&", "myip", address); 3177 output(buf); 3178 } 3179 snprintf(buf, BUFFER_SIZE, "%s=%s&", "wildcard", wildcard ? "ON" : "OFF"); 3180 output(buf); 3181 snprintf(buf, BUFFER_SIZE, "%s=%s&", "mx", mx); 3182 output(buf); 3183 snprintf(buf, BUFFER_SIZE, "%s=%s&", "backmx", *mx == '\0' ? "NO" : "YES"); 3184 output(buf); 3185 snprintf(buf, BUFFER_SIZE, "%s=%s&", "host_id", host); 3186 output(buf); 3187 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 3188 output(buf); 3189 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 3190 output(buf); 3191 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 3192 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 3193 output(buf); 3194 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 3195 output(buf); 3196 snprintf(buf, BUFFER_SIZE, "\015\012"); 3197 output(buf); 3198 3199 bp = buf; 3200 bytes = 0; 3201 btot = 0; 3202 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 3203 { 3204 bp += bytes; 3205 btot += bytes; 3206 dprintf((stderr, "btot: %d\n", btot)); 3207 } 3208 close(client_sockfd); 3209 buf[btot] = '\0'; 3210 3211 dprintf((stderr, "server output: %s\n", buf)); 3212 3213 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 3214 { 3215 ret = -1; 3216 } 3217 3218 switch(ret) 3219 { 3220 case -1: 3221 if(!(options & OPT_QUIET)) 3222 { 3223 show_message("strange server response, are you connecting to the right server?\n"); 3224 } 3225 return(UPDATERES_ERROR); 3226 break; 3227 3228 case 200: 3229 if(strstr(buf, "NOERROR\n") != NULL) 3230 { 3231 if(!(options & OPT_QUIET)) 3232 { 3233 show_message("request successful\n"); 3234 } 3235 } 3236 else 3237 { 3238 show_message("error processing request\n"); 3239 if(!(options & OPT_QUIET)) 3240 { 3241 show_message("server output: %s\n", buf); 3242 } 3243 return(UPDATERES_ERROR); 3244 } 3245 break; 3246 3247 case 401: 3248 if(!(options & OPT_QUIET)) 3249 { 3250 show_message("authentication failure\n"); 3251 } 3252 return(UPDATERES_SHUTDOWN); 3253 break; 3254 3255 default: 3256 if(!(options & OPT_QUIET)) 3257 { 3258 // reuse the auth buffer 3259 *auth = '\0'; 3260 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 3261 show_message("unknown return code: %d\n", ret); 3262 show_message("server response: %s\n", auth); 3263 } 3264 return(UPDATERES_ERROR); 3265 break; 3266 } 3267 3268 return(UPDATERES_OK); 3269} 3270 3271int EASYDNS_PARTNER_check_info(void) 3272{ 3273 char buf[BUFSIZ+1]; 3274 3275 if((host == NULL) || (*host == '\0')) 3276 { 3277 if(options & OPT_DAEMON) 3278 { 3279 return(-1); 3280 } 3281 if(host) { free(host); } 3282 get_input("host", buf, sizeof(buf)); 3283 host = strdup(buf); 3284 } 3285 3286 if((partner == NULL) || (*partner == '\0')) 3287 { 3288 if(options & OPT_DAEMON) 3289 { 3290 return(-1); 3291 } 3292 if(partner) { free(partner); } 3293 get_input("easyDNS partner", buf, sizeof(buf)); 3294 partner = strdup(buf); 3295 } 3296 3297 if(interface == NULL && address == NULL) 3298 { 3299 if(options & OPT_DAEMON) 3300 { 3301 show_message("you must provide either an interface or an address\n"); 3302 return(-1); 3303 } 3304 if(interface) { free(interface); } 3305 get_input("interface", buf, sizeof(buf)); 3306 option_handler(CMD_interface, buf); 3307 } 3308 3309 warn_fields(service->fields_used); 3310 3311 return 0; 3312} 3313 3314int EASYDNS_PARTNER_update_entry(void) 3315{ 3316 char *buf = update_entry_buf; 3317 char *bp = buf; 3318 int bytes; 3319 int btot; 3320 int ret; 3321 3322 buf[BUFFER_SIZE] = '\0'; 3323 3324 if(do_connect((int*)&client_sockfd, server, port) != 0) 3325 { 3326 if(!(options & OPT_QUIET)) 3327 { 3328 show_message("error connecting to %s:%s\n", server, port); 3329 } 3330 return(UPDATERES_ERROR); 3331 } 3332 3333 snprintf(buf, BUFFER_SIZE, "GET %s?action=edit&", request); 3334 output(buf); 3335 if(address != NULL && *address != '\0') 3336 { 3337 snprintf(buf, BUFFER_SIZE, "%s=%s&", "myip", address); 3338 output(buf); 3339 } 3340 snprintf(buf, BUFFER_SIZE, "%s=%s&", "partner", partner); 3341 output(buf); 3342 snprintf(buf, BUFFER_SIZE, "%s=%s&", "wildcard", wildcard ? "ON" : "OFF"); 3343 output(buf); 3344 snprintf(buf, BUFFER_SIZE, "%s=%s", "hostname", host); 3345 output(buf); 3346 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 3347 output(buf); 3348 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 3349 output(buf); 3350 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 3351 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 3352 output(buf); 3353 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 3354 output(buf); 3355 snprintf(buf, BUFFER_SIZE, "\015\012"); 3356 output(buf); 3357 3358 bp = buf; 3359 bytes = 0; 3360 btot = 0; 3361 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 3362 { 3363 bp += bytes; 3364 btot += bytes; 3365 dprintf((stderr, "btot: %d\n", btot)); 3366 } 3367 close(client_sockfd); 3368 buf[btot] = '\0'; 3369 3370 dprintf((stderr, "server output: %s\n", buf)); 3371 3372 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 3373 { 3374 ret = -1; 3375 } 3376 3377 switch(ret) 3378 { 3379 case -1: 3380 if(!(options & OPT_QUIET)) 3381 { 3382 show_message("strange server response, are you connecting to the right server?\n"); 3383 } 3384 return(UPDATERES_ERROR); 3385 break; 3386 3387 case 200: 3388 if(strstr(buf, "OK\n") != NULL) 3389 { 3390 if(!(options & OPT_QUIET)) 3391 { 3392 show_message("request successful\n"); 3393 } 3394 } 3395 else 3396 { 3397 show_message("error processing request\n"); 3398 if(!(options & OPT_QUIET)) 3399 { 3400 show_message("server output: %s\n", buf); 3401 } 3402 return(UPDATERES_ERROR); 3403 } 3404 break; 3405 3406 case 401: 3407 if(!(options & OPT_QUIET)) 3408 { 3409 show_message("authentication failure\n"); 3410 } 3411 return(UPDATERES_SHUTDOWN); 3412 break; 3413 3414 case 403: 3415 if(!(options & OPT_QUIET)) 3416 { 3417 show_message("updating too frequently\n"); 3418 } 3419 show_message("sleeping for %s\n", format_time(MAX_WAITRESPONSE_WAIT)); 3420 sleep(MAX_WAITRESPONSE_WAIT); 3421 return(UPDATERES_ERROR); 3422 break; 3423 3424 case 404: 3425 if(!(options & OPT_QUIET)) 3426 { 3427 show_message("no dynamic service for this host/domain\n"); 3428 } 3429 return(UPDATERES_SHUTDOWN); 3430 break; 3431 3432 case 405: 3433 if(!(options & OPT_QUIET)) 3434 { 3435 show_message("partner not supported\n"); 3436 } 3437 return(UPDATERES_SHUTDOWN); 3438 break; 3439 3440 default: 3441 if(!(options & OPT_QUIET)) 3442 { 3443 // reuse the auth buffer 3444 *auth = '\0'; 3445 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 3446 show_message("unknown return code: %d\n", ret); 3447 show_message("server response: %s\n", auth); 3448 } 3449 return(UPDATERES_ERROR); 3450 break; 3451 } 3452 3453 return(UPDATERES_OK); 3454} 3455 3456 3457#ifdef USE_MD5 3458int GNUDIP_check_info(void) 3459{ 3460 char buf[BUFSIZ+1]; 3461 3462 if((server == NULL) || (*server == '\0')) 3463 { 3464 if(options & OPT_DAEMON) 3465 { 3466 return(-1); 3467 } 3468 if(server) { free(server); } 3469 get_input("server", buf, sizeof(buf)); 3470 server = strdup(buf); 3471 } 3472 3473 if((host == NULL) || (*host == '\0')) 3474 { 3475 if(options & OPT_DAEMON) 3476 { 3477 return(-1); 3478 } 3479 if(host) { free(host); } 3480 get_input("host", buf, sizeof(buf)); 3481 host = strdup(buf); 3482 } 3483 3484 if((address) && (strcmp(address, "0.0.0.0") != 0)) 3485 { 3486 if(!(options & OPT_QUIET)) 3487 { 3488 show_message("warning: for GNUDIP the \"address\" parpameter is only used if set to \"0.0.0.0\" thus making an offline request.\n"); 3489 } 3490 } 3491 3492 warn_fields(service->fields_used); 3493 3494 return 0; 3495} 3496 3497int GNUDIP_update_entry(void) 3498{ 3499 char *buf = update_entry_buf; 3500 unsigned char digestbuf[MD5_DIGEST_BYTES]; 3501 char *p; 3502 int bytes; 3503 int ret; 3504 int i; 3505 char *domainname; 3506 char gnudip_request[2]; 3507 3508 // send an offline request if address 0.0.0.0 is used 3509 // otherwise, we ignore the address and send an update request 3510 gnudip_request[0] = strcmp(address, "0.0.0.0") == 0 ? '1' : '0'; 3511 gnudip_request[1] = '\0'; 3512 3513 // find domainname 3514 for(p=host; *p != '\0' && *p != '.'; p++); 3515 if(*p != '\0') { p++; } 3516 if(*p == '\0') 3517 { 3518 return(UPDATERES_ERROR); 3519 } 3520 domainname = p; 3521 3522 if(do_connect((int*)&client_sockfd, server, port) != 0) 3523 { 3524 if(!(options & OPT_QUIET)) 3525 { 3526 show_message("error connecting to %s:%s\n", server, port); 3527 } 3528 return(UPDATERES_ERROR); 3529 } 3530 3531 if((bytes=read_input(buf, BUFFER_SIZE)) <= 0) 3532 { 3533 close(client_sockfd); 3534 return(UPDATERES_ERROR); 3535 } 3536 buf[bytes] = '\0'; 3537 dprintf((stderr, "bytes: %d\n", bytes)); 3538 dprintf((stderr, "server output: %s\n", buf)); 3539 3540 // buf holds the shared secret 3541 chomp(buf); 3542 3543 // use the auth buffer 3544 md5_buffer(password, strlen(password), digestbuf); 3545 for(i=0, p=auth; i<MD5_DIGEST_BYTES; i++, p+=2) 3546 { 3547 sprintf(p, "%02x", digestbuf[i]); 3548 } 3549 strncat(auth, ".", 255-strlen(auth)); 3550 strncat(auth, buf, 255-strlen(auth)); 3551 dprintf((stderr, "auth: %s\n", auth)); 3552 md5_buffer(auth, strlen(auth), digestbuf); 3553 for(i=0, p=buf; i<MD5_DIGEST_BYTES; i++, p+=2) 3554 { 3555 sprintf(p, "%02x", digestbuf[i]); 3556 } 3557 strcpy(auth, buf); 3558 3559 dprintf((stderr, "auth: %s\n", auth)); 3560 3561 snprintf(buf, BUFFER_SIZE, "%s:%s:%s:%s\n", user_name, auth, domainname, 3562 gnudip_request); 3563 output(buf); 3564 3565 bytes = 0; 3566 if((bytes=read_input(buf, BUFFER_SIZE)) <= 0) 3567 { 3568 close(client_sockfd); 3569 return(UPDATERES_ERROR); 3570 } 3571 buf[bytes] = '\0'; 3572 3573 dprintf((stderr, "bytes: %d\n", bytes)); 3574 dprintf((stderr, "server output: %s\n", buf)); 3575 3576 close(client_sockfd); 3577 3578 if(sscanf(buf, "%d", &ret) != 1) 3579 { 3580 ret = -1; 3581 } 3582 3583 switch(ret) 3584 { 3585 case -1: 3586 if(!(options & OPT_QUIET)) 3587 { 3588 show_message("strange server response, are you connecting to the right server?\n"); 3589 } 3590 return(UPDATERES_ERROR); 3591 break; 3592 3593 case 0: 3594 if(!(options & OPT_QUIET)) 3595 { 3596 show_message("update request successful\n"); 3597 } 3598 break; 3599 3600 case 1: 3601 if(!(options & OPT_QUIET)) 3602 { 3603 show_message("invalid login attempt\n"); 3604 } 3605 return(UPDATERES_ERROR); 3606 break; 3607 3608 case 2: 3609 if(!(options & OPT_QUIET)) 3610 { 3611 show_message("offline request successful\n"); 3612 } 3613 break; 3614 3615 default: 3616 if(!(options & OPT_QUIET)) 3617 { 3618 show_message("unknown return code: %d\n", ret); 3619 } 3620 return(UPDATERES_ERROR); 3621 break; 3622 } 3623 3624 return(UPDATERES_OK); 3625} 3626#endif 3627 3628#ifdef CONFIG_PGP 3629int JUSTL_check_info(void) 3630{ 3631 char buf[BUFSIZ+1]; 3632 3633 if(host == NULL) 3634 { 3635 if(options & OPT_DAEMON) 3636 { 3637 return(-1); 3638 } 3639 get_input("host", buf, sizeof(buf)); 3640 host = strdup(buf); 3641 } 3642 3643 if(interface == NULL && address == NULL) 3644 { 3645 if(options & OPT_DAEMON) 3646 { 3647 show_message("you must provide either an interface or an address\n"); 3648 return(-1); 3649 } 3650 if(interface) { free(interface); } 3651 get_input("interface", buf, sizeof(buf)); 3652 option_handler(CMD_interface, buf); 3653 } 3654 3655 warn_fields(service->fields_used); 3656 3657 return 0; 3658} 3659 3660int JUSTL_update_entry(void) 3661{ 3662 char *buf = update_entry_buf; 3663 char *bp = buf; 3664 int bytes; 3665 int btot; 3666 int ret; 3667 3668 buf[BUFFER_SIZE] = '\0'; 3669 3670 if(do_connect((int*)&client_sockfd, server, port) != 0) 3671 { 3672 if(!(options & OPT_QUIET)) 3673 { 3674 show_message("error connecting to %s:%s\n", server, port); 3675 } 3676 return(UPDATERES_ERROR); 3677 } 3678 3679 snprintf(buf, BUFFER_SIZE, "GET %s?direct=1&", request); 3680 output(buf); 3681 snprintf(buf, BUFFER_SIZE, "%s=%s&", "username", user_name); 3682 output(buf); 3683 snprintf(buf, BUFFER_SIZE, "%s=%s&", "password", password); 3684 output(buf); 3685 snprintf(buf, BUFFER_SIZE, "%s=%s&", "host", host); 3686 output(buf); 3687 snprintf(buf, BUFFER_SIZE, "%s=%s&", "ip", address); 3688 output(buf); 3689 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 3690 output(buf); 3691 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 3692 output(buf); 3693 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 3694 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 3695 output(buf); 3696 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 3697 output(buf); 3698 snprintf(buf, BUFFER_SIZE, "\015\012"); 3699 output(buf); 3700 3701 bp = buf; 3702 bytes = 0; 3703 btot = 0; 3704 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 3705 { 3706 bp += bytes; 3707 btot += bytes; 3708 dprintf((stderr, "btot: %d\n", btot)); 3709 } 3710 close(client_sockfd); 3711 buf[btot] = '\0'; 3712 3713 dprintf((stderr, "server output: %s\n", buf)); 3714 3715 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 3716 { 3717 ret = -1; 3718 } 3719 3720 switch(ret) 3721 { 3722 case -1: 3723 if(!(options & OPT_QUIET)) 3724 { 3725 show_message("strange server response, are you connecting to the right server?\n"); 3726 } 3727 return(UPDATERES_ERROR); 3728 break; 3729 3730 case 200: 3731 if(strstr(buf, " set ") != NULL) 3732 { 3733 if(!(options & OPT_QUIET)) 3734 { 3735 show_message("request successful\n"); 3736 } 3737 } 3738 else 3739 { 3740 show_message("error processing request\n"); 3741 if(!(options & OPT_QUIET)) 3742 { 3743 show_message("server output: %s\n", buf); 3744 } 3745 return(UPDATERES_ERROR); 3746 } 3747 break; 3748 3749 case 401: 3750 if(!(options & OPT_QUIET)) 3751 { 3752 show_message("authentication failure\n"); 3753 } 3754 return(UPDATERES_SHUTDOWN); 3755 break; 3756 3757 default: 3758 if(!(options & OPT_QUIET)) 3759 { 3760 // reuse the auth buffer 3761 *auth = '\0'; 3762 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 3763 show_message("unknown return code: %d\n", ret); 3764 show_message("server response: %s\n", auth); 3765 } 3766 return(UPDATERES_ERROR); 3767 break; 3768 } 3769 3770 return(UPDATERES_OK); 3771} 3772#endif 3773 3774int DYNS_check_info(void) 3775{ 3776 char buf[BUFSIZ+1]; 3777 3778 if(host == NULL) 3779 { 3780 if(options & OPT_DAEMON) 3781 { 3782 return(-1); 3783 } 3784 get_input("host", buf, sizeof(buf)); 3785 host = strdup(buf); 3786 } 3787 3788 if(interface == NULL && address == NULL) 3789 { 3790 if(options & OPT_DAEMON) 3791 { 3792 show_message("you must provide either an interface or an address\n"); 3793 return(-1); 3794 } 3795 if(interface) { free(interface); } 3796 get_input("interface", buf, sizeof(buf)); 3797 option_handler(CMD_interface, buf); 3798 } 3799 3800 warn_fields(service->fields_used); 3801 3802 return 0; 3803} 3804 3805int DYNS_update_entry(void) 3806{ 3807 char *buf = update_entry_buf; 3808 char *bp = buf; 3809 int bytes; 3810 int btot; 3811 int ret; 3812 3813 buf[BUFFER_SIZE] = '\0'; 3814 3815 if(do_connect((int*)&client_sockfd, server, port) != 0) 3816 { 3817 if(!(options & OPT_QUIET)) 3818 { 3819 show_message("error connecting to %s:%s\n", server, port); 3820 } 3821 return(UPDATERES_ERROR); 3822 } 3823 3824 snprintf(buf, BUFFER_SIZE, "GET %s?", request); 3825 output(buf); 3826 snprintf(buf, BUFFER_SIZE, "%s=%s&", "username", user_name); 3827 output(buf); 3828 snprintf(buf, BUFFER_SIZE, "%s=%s&", "password", password); 3829 output(buf); 3830 snprintf(buf, BUFFER_SIZE, "%s=%s&", "host", host); 3831 output(buf); 3832 snprintf(buf, BUFFER_SIZE, "%s=%s", "ip", address); 3833 output(buf); 3834 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 3835 output(buf); 3836 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 3837 output(buf); 3838 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 3839 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 3840 output(buf); 3841 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 3842 output(buf); 3843 snprintf(buf, BUFFER_SIZE, "\015\012"); 3844 output(buf); 3845 3846 bp = buf; 3847 bytes = 0; 3848 btot = 0; 3849 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 3850 { 3851 bp += bytes; 3852 btot += bytes; 3853 dprintf((stderr, "btot: %d\n", btot)); 3854 } 3855 close(client_sockfd); 3856 buf[btot] = '\0'; 3857 3858 dprintf((stderr, "server output: %s\n", buf)); 3859 3860 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 3861 { 3862 ret = -1; 3863 } 3864 3865 switch(ret) 3866 { 3867 case -1: 3868 if(!(options & OPT_QUIET)) 3869 { 3870 show_message("strange server response, are you connecting to the right server?\n"); 3871 } 3872 return(UPDATERES_ERROR); 3873 break; 3874 3875 case 200: 3876 if(strstr(buf, "200 Host") != NULL || 3877 strstr(buf, "200 host") != NULL) 3878 { 3879 if(!(options & OPT_QUIET)) 3880 { 3881 show_message("request successful\n"); 3882 } 3883 } 3884 else if(strstr(buf, "400 Bad Request") != NULL) 3885 { 3886 if(!(options & OPT_QUIET)) 3887 { 3888 show_message("bad request\n"); 3889 } 3890 } 3891 else if(strstr(buf, "401 User") != NULL) 3892 { 3893 if(!(options & OPT_QUIET)) 3894 { 3895 show_message("authentication failure (username/password)\n"); 3896 } 3897 } 3898 else if(strstr(buf, "405 Hostname") != NULL) 3899 { 3900 if(!(options & OPT_QUIET)) 3901 { 3902 show_message("authentication failure (hostname not found)\n"); 3903 } 3904 } 3905 3906 else 3907 { 3908 show_message("error processing request\n"); 3909 if(!(options & OPT_QUIET)) 3910 { 3911 show_message("server output: %s\n", buf); 3912 } 3913 return(UPDATERES_ERROR); 3914 } 3915 3916 break; 3917 3918 case 405: 3919 if(!(options & OPT_QUIET)) 3920 { 3921 show_message("authentication failure\n"); 3922 } 3923 return(UPDATERES_ERROR); 3924 break; 3925 3926 default: 3927 if(!(options & OPT_QUIET)) 3928 { 3929 // reuse the auth buffer 3930 *auth = '\0'; 3931 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 3932 show_message("unknown return code: %d\n", ret); 3933 show_message("server response: %s\n", auth); 3934 } 3935 return(UPDATERES_ERROR); 3936 break; 3937 } 3938 3939 return(UPDATERES_OK); 3940} 3941 3942#ifdef CONFIG_HN 3943int HN_check_info(void) 3944{ 3945 warn_fields(service->fields_used); 3946 3947 return 0; 3948} 3949 3950int HN_update_entry(void) 3951{ 3952 char *buf = update_entry_buf; 3953 char *bp = buf; 3954 int bytes; 3955 int btot; 3956 int ret; 3957 3958 buf[BUFFER_SIZE] = '\0'; 3959 3960 if(do_connect((int*)&client_sockfd, server, port) != 0) 3961 { 3962 if(!(options & OPT_QUIET)) 3963 { 3964 show_message("error connecting to %s:%s\n", server, port); 3965 } 3966 return(UPDATERES_ERROR); 3967 } 3968 3969 snprintf(buf, BUFFER_SIZE, "GET %s?ver=%d&", request, 1); 3970 output(buf); 3971 if(address) 3972 { 3973 snprintf(buf, BUFFER_SIZE, "%s=%s&", "IP", address); 3974 output(buf); 3975 } 3976 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 3977 output(buf); 3978 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 3979 output(buf); 3980 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 3981 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 3982 output(buf); 3983 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 3984 output(buf); 3985 snprintf(buf, BUFFER_SIZE, "\015\012"); 3986 output(buf); 3987 3988 bp = buf; 3989 bytes = 0; 3990 btot = 0; 3991 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 3992 { 3993 bp += bytes; 3994 btot += bytes; 3995 dprintf((stderr, "btot: %d\n", btot)); 3996 } 3997 close(client_sockfd); 3998 buf[btot] = '\0'; 3999 4000 dprintf((stderr, "server output: %s\n", buf)); 4001 4002 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 4003 { 4004 ret = -1; 4005 } 4006 4007 switch(ret) 4008 { 4009 char *p; 4010 4011 case -1: 4012 if(!(options & OPT_QUIET)) 4013 { 4014 show_message("strange server response, are you connecting to the right server?\n"); 4015 } 4016 return(UPDATERES_ERROR); 4017 break; 4018 4019 case 200: 4020 ret = -1; 4021 if((p=strstr(buf, "DDNS_Response_")) != NULL) 4022 { 4023 sscanf(p, "DDNS_Response_%*code=%3d", &ret); 4024 } 4025 4026 /* 4027 * 101 - Successfully Updated 4028 * 201 - Failure because previous update occured 4029 * less than 300 seconds ago 4030 * 202 - Failure because of server error 4031 * 203 - Failure because account is frozen (by admin) 4032 * 204 - Failure because account is locked (by user) 4033 */ 4034 switch(ret) 4035 { 4036 case -1: 4037 if(!(options & OPT_QUIET)) 4038 { 4039 show_message("strange server response, are you connecting to the right server?\n"); 4040 } 4041 return(UPDATERES_ERROR); 4042 break; 4043 4044 case 101: 4045 if(!(options & OPT_QUIET)) 4046 { 4047 show_message("request successful\n"); 4048 } 4049 break; 4050 4051 case 201: 4052 show_message("Last update was less than %d seconds ago.\n", 300); 4053 return(UPDATERES_ERROR); 4054 break; 4055 4056 case 202: 4057 show_message("Server error.\n"); 4058 return(UPDATERES_ERROR); 4059 break; 4060 4061 case 203: 4062 show_message("Failure because account is frozen (by admin).\n"); 4063 return(UPDATERES_SHUTDOWN); 4064 break; 4065 4066 case 204: 4067 show_message("Failure because account is locked (by user).\n"); 4068 return(UPDATERES_SHUTDOWN); 4069 break; 4070 4071 default: 4072 if(!(options & OPT_QUIET)) 4073 { 4074 show_message("unknown return code: %d\n", ret); 4075 show_message("server response: %s\n", buf); 4076 } 4077 return(UPDATERES_ERROR); 4078 break; 4079 } 4080 break; 4081 4082 case 401: 4083 if(!(options & OPT_QUIET)) 4084 { 4085 show_message("authentication failure\n"); 4086 } 4087 return(UPDATERES_SHUTDOWN); 4088 break; 4089 4090 default: 4091 if(!(options & OPT_QUIET)) 4092 { 4093 // reuse the auth buffer 4094 *auth = '\0'; 4095 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 4096 show_message("unknown return code: %d\n", ret); 4097 show_message("server response: %s\n", auth); 4098 } 4099 return(UPDATERES_ERROR); 4100 break; 4101 } 4102 4103 return(UPDATERES_OK); 4104} 4105#endif 4106 4107int ZONEEDIT_check_info(void) 4108{ 4109 char buf[BUFSIZ+1]; 4110 4111 if((host == NULL) || (*host == '\0')) 4112 { 4113 if(options & OPT_DAEMON) 4114 { 4115 return(-1); 4116 } 4117 if(host) { free(host); } 4118 get_input("host", buf, sizeof(buf)); 4119 host = strdup(buf); 4120 } 4121 4122 warn_fields(service->fields_used); 4123 4124 return 0; 4125} 4126 4127int ZONEEDIT_update_entry(void) 4128{ 4129 char *buf = update_entry_buf; 4130 char *bp = buf; 4131 int bytes; 4132 int btot; 4133 int ret; 4134 4135 buf[BUFFER_SIZE] = '\0'; 4136 4137 if(do_connect((int*)&client_sockfd, server, port) != 0) 4138 { 4139 if(!(options & OPT_QUIET)) 4140 { 4141 show_message("error connecting to %s:%s\n", server, port); 4142 } 4143 return(UPDATERES_ERROR); 4144 } 4145 4146 snprintf(buf, BUFFER_SIZE, "GET %s?", request); 4147 output(buf); 4148 snprintf(buf, BUFFER_SIZE, "%s=%s&", "host", host); 4149 output(buf); 4150 if (address && *address) { 4151 snprintf(buf, BUFFER_SIZE, "%s=%s&", "dnsto", address); 4152 output(buf); 4153 } 4154 if (address && *mx && *mx != '0') { 4155 snprintf(buf, BUFFER_SIZE, "%s=%s&", "type", "a,mx"); 4156 output(buf); 4157 } 4158 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 4159 output(buf); 4160 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s (%s)\015\012", 4161 "zoneedit", VERSION, OS, "by Angus Mackay"); 4162 output(buf); 4163 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 4164 output(buf); 4165 snprintf(buf, BUFFER_SIZE, "Authorization: Basic %s\015\012", auth); 4166 output(buf); 4167 snprintf(buf, BUFFER_SIZE, "\015\012"); 4168 output(buf); 4169 4170 bp = buf; 4171 bytes = 0; 4172 btot = 0; 4173 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 4174 { 4175 bp += bytes; 4176 btot += bytes; 4177 dprintf((stderr, "btot: %d\n", btot)); 4178 } 4179 close(client_sockfd); 4180 buf[btot] = '\0'; 4181 4182 dprintf((stderr, "server output: %s\n", buf)); 4183 4184 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 4185 { 4186 ret = -1; 4187 } 4188 4189 switch(ret) 4190 { 4191 case -1: 4192 if(!(options & OPT_QUIET)) 4193 { 4194 show_message("strange server response, are you connecting to the right server?\n"); 4195 } 4196 return(UPDATERES_ERROR); 4197 break; 4198 4199 case 200: 4200 if(strstr(buf, "<SUCCESS") != NULL) 4201 { 4202 if(!(options & OPT_QUIET)) 4203 { 4204 show_message("request successful\n"); 4205 } 4206 } 4207 else 4208 { 4209 show_message("error processing request\n"); 4210 if(!(options & OPT_QUIET)) 4211 { 4212 show_message("server output: %s\n", buf); 4213 } 4214 return(UPDATERES_ERROR); 4215 } 4216 break; 4217 4218 case 401: 4219 if(!(options & OPT_QUIET)) 4220 { 4221 show_message("authentication failure\n"); 4222 } 4223 return(UPDATERES_SHUTDOWN); 4224 break; 4225 4226 default: 4227 if(!(options & OPT_QUIET)) 4228 { 4229 // reuse the auth buffer 4230 *auth = '\0'; 4231 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 4232 show_message("unknown return code: %d\n", ret); 4233 show_message("server response: %s\n", auth); 4234 } 4235 return(UPDATERES_ERROR); 4236 break; 4237 } 4238 4239 return(UPDATERES_OK); 4240} 4241 4242#ifdef CONFIG_HEIP 4243int HEIPV6TB_check_info(void) 4244{ 4245 char buf[BUFSIZ+1]; 4246 4247 if(interface == NULL) 4248 { 4249 if(options & OPT_DAEMON) 4250 { 4251 show_message("you must provide either an interface or an address\n"); 4252 return(-1); 4253 } 4254 if(interface) { free(interface); } 4255 get_input("interface", buf, sizeof(buf)); 4256 option_handler(CMD_interface, buf); 4257 } 4258 warn_fields(service->fields_used); 4259 4260 return 0; 4261} 4262 4263int HEIPV6TB_update_entry(void) 4264{ 4265 char *buf = update_entry_buf; 4266 char *bp = buf; 4267 int bytes; 4268 int btot; 4269 int ret; 4270 4271 buf[BUFFER_SIZE] = '\0'; 4272 4273 if(do_connect((int*)&client_sockfd, server, port) != 0) 4274 { 4275 if(!(options & OPT_QUIET)) 4276 { 4277 show_message("error connecting to %s:%s\n", server, port); 4278 } 4279 return(UPDATERES_ERROR); 4280 } 4281 4282 snprintf(buf, BUFFER_SIZE, "GET %s?menu=%s&", request, "edit_tunnel_address"); 4283 output(buf); 4284 snprintf(buf, BUFFER_SIZE, "aname=%s&", user_name); 4285 output(buf); 4286 snprintf(buf, BUFFER_SIZE, "auth=%s&", password); 4287 output(buf); 4288 snprintf(buf, BUFFER_SIZE, "ipv4b=%s", address); 4289 output(buf); 4290 snprintf(buf, BUFFER_SIZE, " HTTP/1.0\015\012"); 4291 output(buf); 4292 snprintf(buf, BUFFER_SIZE, "User-Agent: %s-%s %s [%s] (%s)\015\012", 4293 "ez-update", VERSION, OS, (options & OPT_DAEMON) ? "daemon" : "", "by Angus Mackay"); 4294 output(buf); 4295 snprintf(buf, BUFFER_SIZE, "Host: %s\015\012", server); 4296 output(buf); 4297 snprintf(buf, BUFFER_SIZE, "\015\012"); 4298 output(buf); 4299 4300 bp = buf; 4301 bytes = 0; 4302 btot = 0; 4303 while((bytes=read_input(bp, BUFFER_SIZE-btot)) > 0) 4304 { 4305 bp += bytes; 4306 btot += bytes; 4307 dprintf((stderr, "btot: %d\n", btot)); 4308 } 4309 close(client_sockfd); 4310 buf[btot] = '\0'; 4311 4312 dprintf((stderr, "server output: %s\n", buf)); 4313 if(sscanf(buf, " HTTP/1.%*c %3d", &ret) != 1) 4314 { 4315 ret = -1; 4316 } 4317 4318 switch(ret) 4319 { 4320 char *p; 4321 4322 case -1: 4323 if(!(options & OPT_QUIET)) 4324 { 4325 show_message("strange server response, are you connecting to the right server?\n"); 4326 } 4327 return(UPDATERES_ERROR); 4328 break; 4329 case 200: 4330 if(!(options & OPT_QUIET)) 4331 { 4332 show_message("request successful\n"); 4333 } 4334 break; 4335 default: 4336 if(!(options & OPT_QUIET)) 4337 { 4338 // reuse the auth buffer 4339 *auth = '\0'; 4340 sscanf(buf, " HTTP/1.%*c %*3d %255[^\r\n]", auth); 4341 show_message("unknown return code: %d\n", ret); 4342 show_message("server response: %s\n", auth); 4343 } 4344 return(UPDATERES_ERROR); 4345 break; 4346 } 4347 4348 return(UPDATERES_OK); 4349} 4350#endif 4351 4352static int is_in_list(char *needle, char **haystack) 4353{ 4354 char **p; 4355 int found = 0; 4356 4357 for(p=haystack; *p != NULL; p++) 4358 { 4359 if(strcmp(needle, *p) == 0) 4360 { 4361 found = 1; 4362 break; 4363 } 4364 } 4365 4366 return(found); 4367} 4368 4369void warn_fields(char **okay_fields) 4370{ 4371 if(wildcard != 0 && !is_in_list("wildcard", okay_fields)) 4372 { 4373 show_message("warning: this service does not support the %s option\n", 4374 "wildcard"); 4375 } 4376 if(!(mx == NULL || *mx == '\0') && !is_in_list("mx", okay_fields)) 4377 { 4378 show_message("warning: this service does not support the %s option\n", 4379 "mx"); 4380 } 4381 if(!(url == NULL || *url == '\0') && !is_in_list("url", okay_fields)) 4382 { 4383 show_message("warning: this service does not support the %s option\n", 4384 "url"); 4385 } 4386 if(!(cloak_title == NULL || *cloak_title == '\0') && !is_in_list("cloak_title", okay_fields)) 4387 { 4388 show_message("warning: this service does not support the %s option\n", 4389 "cloak_title"); 4390 } 4391 if(connection_type != 1 && !is_in_list("connection-type", okay_fields)) 4392 { 4393 show_message("warning: this service does not support the %s option\n", 4394 "connection-type"); 4395 } 4396} 4397 4398int exec_cmd(char *cmd) 4399{ 4400#if (defined(HAVE_WAITPID) || defined(HAVE_WAIT)) && (defined(HAVE_VFORK) || defined(HAVE_FORK)) 4401 int kid; 4402 int exit_code; 4403 4404 switch((kid=vfork())) 4405 { 4406 case -1: 4407 if(!(options & OPT_QUIET)) 4408 { 4409 perror("fork"); 4410 } 4411 return(-1); 4412 break; 4413 case 0: 4414 /* child */ 4415 execl("/bin/sh", "sh", "-c", cmd, (char *)0); 4416 if(!(options & OPT_QUIET)) 4417 { 4418 perror("exec"); 4419 } 4420 exit(1); 4421 break; 4422 default: 4423 /* parent */ 4424 dprintf((stderr, "forked kid: %d\n", kid)); 4425 break; 4426 } 4427 4428# ifdef HAVE_WAITPID 4429 if(waitpid(kid, &exit_code, 0) != kid) 4430 { 4431 return(1); 4432 } 4433# else 4434 if(wait(&exit_code) != kid) 4435 { 4436 return(1); 4437 } 4438# endif 4439 exit_code = WEXITSTATUS(exit_code); 4440 4441 return(exit_code); 4442#else 4443 return(-1); 4444#endif 4445} 4446 4447void handle_sig(int sig) 4448{ 4449 4450 switch(sig) 4451 { 4452 case SIGHUP: 4453 if(config_file) 4454 { 4455 show_message("SIGHUP recieved, re-reading config file\n"); 4456 if(parse_conf_file(config_file, conf_commands) != 0) 4457 { 4458 show_message("error parsing config file \"%s\"\n", config_file); 4459 } 4460 } 4461 break; 4462 case SIGTERM: 4463 /* 4464 * this is used to wake up the client so that it will perform an update 4465 */ 4466 break; 4467 case SIGQUIT: 4468 show_message("received SIGQUIT, shutting down\n"); 4469 4470#if HAVE_SYSLOG_H 4471 closelog(); 4472#endif 4473 4474#if HAVE_GETPID 4475 if(pid_file) 4476 { 4477 pid_file_delete(pid_file); 4478 } 4479#endif 4480 4481 exit(0); 4482 default: 4483 dprintf((stderr, "case not handled: %d\n", sig)); 4484 break; 4485 } 4486} 4487 4488int main(int argc, char **argv) 4489{ 4490 int ifresolve_warned = 0; 4491 int i; 4492 int retval = 1; 4493#ifdef IF_LOOKUP 4494 int sock = -1; 4495#endif 4496 4497#if defined(DEBUG) && defined(__linux__) && !defined(EMBED) 4498 //mcheck(NULL); 4499#endif 4500 4501 dprintf((stderr, "staring...\n")); 4502 4503 program_name = argv[0]; 4504 options = 0; 4505 *user = '\0'; 4506 timeout.tv_sec = DEFAULT_TIMEOUT; 4507 timeout.tv_usec = 0; 4508 parse_service(DEF_SERVICE); 4509 4510 4511#if HAVE_SIGNAL_H 4512 // catch user interupts 4513 signal(SIGINT, sigint_handler); 4514 signal(SIGHUP, generic_sig_handler); 4515 signal(SIGTERM, generic_sig_handler); 4516 signal(SIGQUIT, generic_sig_handler); 4517#endif 4518 4519 parse_args(argc, argv); 4520 4521 if(!(options & OPT_QUIET) && !(options & OPT_DAEMON)) 4522 { 4523 fprintf(stderr, "ez-ipupdate Version %s\nCopyright (C) 1998-2001 Angus Mackay.\n", VERSION); 4524 } 4525 4526#if HAVE_SYSLOG_H 4527 if(options & OPT_DAEMON) 4528 openlog(program_name, LOG_PID, LOG_USER ); 4529#endif 4530 4531 4532 dprintf((stderr, "options: 0x%04X\n", options)); 4533 dprintf((stderr, "interface: %s\n", interface)); 4534 dprintf((stderr, "ntrys: %d\n", ntrys)); 4535 dprintf((stderr, "server: %s:%s\n", server, port)); 4536 4537 dprintf((stderr, "address: %s\n", address)); 4538 dprintf((stderr, "wildcard: %d\n", wildcard)); 4539 dprintf((stderr, "mx: %s\n", mx)); 4540 dprintf((stderr, "auth: %s\n", auth)); 4541 4542 while(is_in_list("null", service->names)) 4543 { 4544 if(service->check_info() != 0) 4545 { 4546 show_message("invalid data to perform requested action.\n"); 4547 exit(1); 4548 } 4549 } 4550 4551 if(server == NULL) 4552 { 4553 server = strdup(service->default_server); 4554 } 4555 if(port == NULL) 4556 { 4557 port = strdup(service->default_port); 4558 } 4559 4560 *user_name = '\0'; 4561 *password = '\0'; 4562 4563//2007.03.14 Yau add 4564#ifdef ASUS_DDNS 4565 if (g_asus_ddns_mode == 0) { 4566#endif // ASUS_DDNS 4567 4568 if(*user != '\0') 4569 { 4570 sscanf(user, "%127[^:]:%127[^\n]", user_name, password); 4571 dprintf((stderr, "user_name: %s\n", user_name)); 4572 dprintf((stderr, "password: %s\n", password)); 4573 } 4574 if(*user_name == '\0') 4575 { 4576 get_input("user name", user_name, sizeof(user_name)); 4577 } 4578 if(*password == '\0') 4579 { 4580 strncpy(password, getpass("password: "), sizeof(password)); 4581 } 4582 sprintf(user, "%s:%s", user_name, password); 4583 4584 base64Encode(user, auth); 4585 4586//2007.03.14 Yau add 4587#ifdef ASUS_DDNS 4588 } 4589#endif // ASUS_DDNS 4590 4591 request = strdup(request_over_ride == NULL ? service->default_request : request_over_ride); 4592 dprintf((stderr, "request: %s\n", request)); 4593 4594 if(service->init != NULL) 4595 { 4596 service->init(); 4597 } 4598 4599 if(service->check_info() != 0) 4600 { 4601 show_message("invalid data to perform requested action.\n"); 4602 exit(1); 4603 } 4604 4605 if(mx == NULL) { mx = strdup(""); } 4606 if(url == NULL) { url = strdup(""); } 4607 4608#ifdef IF_LOOKUP 4609 if(options & OPT_DAEMON) 4610 { 4611 sock = socket(AF_INET, SOCK_STREAM, 0); 4612 } 4613#endif 4614 4615//2007.03.14 Yau add 4616#ifdef ASUS_DDNS 4617 if (g_asus_ddns_mode != 0) { 4618 nvram_unset ("ddns_return_code"); 4619 nvram_unset ("ddns_suggest_name"); 4620 nvram_unset ("ddns_old_name"); 4621 if (asus_private() == -1) 4622 goto exit_main; 4623 } 4624 if (g_asus_ddns_mode == 1) { 4625 asus_reg_domain (); 4626 goto exit_main; 4627 } else if (g_asus_ddns_mode == 2) { 4628 // override update_entry() method 4629 service->update_entry = asus_update_entry; 4630 } 4631#endif // ASUS_DDNS 4632 4633 if(options & OPT_DAEMON) 4634 { 4635 int local_update_period = update_period; 4636#if IF_LOOKUP 4637 struct sockaddr_in sin; 4638 struct sockaddr_in sin2; 4639 4640 if(interface == NULL) 4641 { 4642 show_message("invalid data to perform requested action.\n"); 4643 show_message("you must provide an interface for daemon mode"); 4644 exit(1); 4645 } 4646 4647 /* background our selves */ 4648 if(!(options & OPT_FOREGROUND)) 4649 { 4650# if HAVE_SYSLOG_H 4651 close(0); 4652 close(1); 4653 close(2); 4654# endif 4655# if HAVE_FORK 4656 if(fork() > 0) { exit(0); } /* parent */ 4657# endif 4658 } 4659 4660#if HAVE_GETPID 4661 if(pid_file && pid_file_create(pid_file) != 0) 4662 { 4663 show_message("exiting...\n"); 4664 exit(1); 4665 } 4666#endif 4667 4668 show_message("ez-ipupdate Version %s, Copyright (C) 1998-2001 Angus Mackay.\n", 4669 VERSION); 4670 show_message("%s started for interface %s host %s using server %s and service %s\n", 4671 program_name, N_STR(interface), N_STR(host), server, service->title); 4672 4673 memset(&sin, 0, sizeof(sin)); 4674 4675 if(cache_file) 4676 { 4677 time_t ipdate; 4678 char *ipstr; 4679 4680 if(read_cache_file(cache_file, &ipdate, &ipstr) == 0) 4681 { 4682 dprintf((stderr, "cache date: %ld\n", ipdate)); 4683 dprintf((stderr, "cache IP: %s\n", ipstr ?: "")); 4684 4685 if(ipstr && strchr(ipstr, '.')) 4686 { 4687 struct tm *ts; 4688 char timebuf[64]; 4689 4690 inet_aton(ipstr, &sin.sin_addr); 4691 last_update = ipdate; 4692 4693 ts = localtime(&ipdate); 4694 strftime(timebuf, sizeof(timebuf), "%Y/%m/%d %H:%M", ts); 4695 show_message("got last update %s on %s from cache file\n", ipstr, timebuf); 4696 } 4697 if(ipstr) { free(ipstr); ipstr = NULL; } 4698 } 4699 else 4700 { 4701 show_message("error reading cache file \"%s\": %s\n", cache_file, 4702 errno == 0 ? "malformed entry" : strerror(errno)); 4703 } 4704 } 4705 4706 for(;;) 4707 { 4708 if(options & OPT_ONCE) 4709 { 4710 int f; 4711 4712 f = open(BLOCK_FILE, O_RDONLY); 4713 if(f >= 0) 4714 { 4715 close(f); 4716 show_message("update critically failed on a previous attempt\n"); 4717 show_message("delete %s if the problem has been corrected\n", 4718 BLOCK_FILE); 4719 break; 4720 } 4721 } 4722 4723#if HAVE_SIGNAL_H 4724 /* check for signals */ 4725 if(last_sig != 0) 4726 { 4727 handle_sig(last_sig); 4728 last_sig = 0; 4729 } 4730#endif 4731printf("Get IF addr\n"); 4732 if(get_if_addr(sock, interface, &sin2) == 0) 4733 { 4734 ifresolve_warned = 0; 4735 if(memcmp(&sin.sin_addr, &sin2.sin_addr, sizeof(struct in_addr)) != 0 || 4736 (max_interval > 0 && time(NULL) - last_update > max_interval)) 4737 { 4738 int updateres; 4739 4740 // save this new ipaddr 4741 memcpy(&sin, &sin2, sizeof(sin)); 4742 4743 // update the address buffer 4744 if(address) { free(address); } 4745 address = strdup(inet_ntoa(sin.sin_addr)); 4746 4747 if((updateres=service->update_entry()) == UPDATERES_OK) 4748 { 4749 last_update = time(NULL); 4750 local_update_period = update_period; 4751 4752 show_message("successful update for %s->%s (%s)\n", 4753 interface, inet_ntoa(sin.sin_addr), N_STR(host)); 4754 4755 if(post_update_cmd) 4756 { 4757 int res; 4758 4759 if(post_update_cmd) 4760 { 4761 sprintf(post_update_cmd_arg, "%s", inet_ntoa(sin.sin_addr)); 4762 4763 if((res=exec_cmd(post_update_cmd)) != 0) 4764 { 4765 if(res == -1) 4766 { 4767 show_message("(%s) error running post update command: %s\n", 4768 N_STR(host), error_string); 4769 } 4770 else 4771 { 4772 show_message( 4773 "(%s) error running post update command, command exit code: %d\n", 4774 N_STR(host), res); 4775 } 4776 } 4777 } 4778 } 4779 4780 if(cache_file) 4781 { 4782 char ipbuf[64]; 4783 4784 snprintf(ipbuf, sizeof(ipbuf), "%s", inet_ntoa(sin.sin_addr)); 4785 4786 if(write_cache_file(cache_file, last_update, ipbuf) != 0) 4787 { 4788 show_message("unable to write cache file \"%s\": %s\n", 4789 cache_file, error_string); 4790 } 4791 } 4792 4793 if(options & OPT_ONCE) 4794 break; 4795 } 4796 else 4797 { 4798 show_message("failure to update %s->%s (%s)\n", 4799 interface, inet_ntoa(sin.sin_addr), N_STR(host)); 4800 memset(&sin, 0, sizeof(sin)); 4801 4802 // double the time between attempts between each failure to update 4803 // this gets set back to the normal value the next time we get a 4804 // successful update 4805 if(local_update_period < MIN_WAIT_PERIOD) 4806 { 4807 local_update_period = MIN_WAIT_PERIOD; 4808 } 4809 else 4810 { 4811 local_update_period *= 2; 4812 } 4813 if(local_update_period > MAX_WAIT_PERIOD) 4814 { 4815 local_update_period = MAX_WAIT_PERIOD; 4816 } 4817 dprintf((stderr, "local_update_period: %d\n", local_update_period)); 4818 4819 dprintf((stderr, "updateres: %d\n", updateres)); 4820 if(updateres == UPDATERES_SHUTDOWN) 4821 { 4822 show_message("shutting down updater for %s due to fatal error\n", 4823 N_STR(host)); 4824#ifdef SEND_MEAIL_CMD 4825 if(notify_email && *notify_email != '\0') 4826 { 4827 char buf[1024]; 4828 4829 dprintf((stderr, "sending email to %s\n", notify_email)); 4830 snprintf(buf, sizeof(buf), "echo \"ez-ipupdate shutting down" 4831 " updater for %s due to fatal error.\" | %s %s", host, 4832 SEND_EMAIL_CMD, 4833 notify_email); 4834 system(buf); 4835 } 4836#endif 4837 if(options & OPT_ONCE) 4838 { 4839 int f; 4840 4841 f = open(BLOCK_FILE, O_WRONLY|O_CREAT); 4842 if(f >= 0) 4843 close(f); 4844 } 4845 break; 4846 } 4847 } 4848 } 4849 else if(options & OPT_ONCE) 4850 break; 4851 sleep(local_update_period); 4852 } 4853 else 4854 { 4855 if(!ifresolve_warned) 4856 { 4857 ifresolve_warned = 1; 4858 show_message("(%s) unable to resolve interface %s\n", 4859 N_STR(host), interface); 4860 } 4861 sleep(resolv_period); 4862 } 4863 } 4864 4865#if HAVE_GETPID 4866 if(pid_file) 4867 { 4868 pid_file_delete(pid_file); 4869 } 4870#endif 4871 4872#else 4873 show_message("sorry, this mode is only available on platforms that the "); 4874 show_message("IP address \ncan be determined. feel free to hack the code"); 4875 show_message(" though.\n"); 4876 exit(1); 4877#endif 4878 } 4879 else 4880 { 4881 int need_update = 1; 4882 4883 if(cache_file) 4884 { 4885 time_t ipdate; 4886 char *ipstr; 4887 char ipbuf[64]; 4888 4889 if(read_cache_file(cache_file, &ipdate, &ipstr) != 0) 4890 { 4891 show_message( "error reading cache file \"%s\": %s\n", cache_file, 4892 errno == 0 ? "malformed entry" : strerror(errno)); 4893 } 4894 dprintf((stderr, "cache date: %ld\n", ipdate)); 4895 dprintf((stderr, "cache IP: %s\n", N_STR(ipstr))); 4896 4897 // check that the cache file contained something 4898 if(ipstr != NULL) 4899 { 4900 4901 if(address == NULL || *address == '\0') 4902 { 4903#ifdef IF_LOOKUP 4904 struct sockaddr_in sin; 4905 int sock; 4906 4907 sock = socket(AF_INET, SOCK_STREAM, 0); 4908 if(get_if_addr(sock, interface, &sin) != 0) 4909 { 4910 exit(1); 4911 } 4912 close(sock); 4913 snprintf(ipbuf, sizeof(ipbuf), "%s", inet_ntoa(sin.sin_addr)); 4914#else 4915 show_message("interface lookup not enabled at compile time\n"); 4916 exit(1); 4917#endif 4918 } 4919 else 4920 { 4921 snprintf(ipbuf, sizeof(ipbuf), "%s", address); 4922 } 4923 4924 // check for a change in the IP 4925 if(strcmp(ipstr, ipbuf) == 0) 4926 { 4927 dprintf((stderr, "cache IP doesn't need updating\n")); 4928 need_update = 0; 4929 } 4930 4931 // check the date 4932 if(max_interval > 0) 4933 { 4934 if(time(NULL) - ipdate > max_interval) 4935 { 4936 dprintf((stderr, "cache IP is passed max_interval of %d\n", max_interval)); 4937 need_update = 1; 4938 } 4939 } 4940 } 4941 if(ipstr) { free(ipstr); ipstr = NULL; } 4942 } 4943 4944 if(need_update) 4945 { 4946 int res; 4947 4948 if(address == NULL && interface != NULL) 4949 { 4950 struct sockaddr_in sin; 4951 int sock; 4952 4953 sock = socket(AF_INET, SOCK_STREAM, 0); 4954 if(get_if_addr(sock, interface, &sin) == 0) 4955 { 4956 if(address) { free(address); } 4957 address = strdup(inet_ntoa(sin.sin_addr)); 4958 } 4959 else 4960 { 4961 show_message("could not resolve ip address for %s.\n", interface); 4962 exit(1); 4963 } 4964 close(sock); 4965 } 4966 4967 for(i=0; i<ntrys; i++) 4968 { 4969 if(service->update_entry() == UPDATERES_OK) 4970 { 4971 retval = 0; 4972 break; 4973 } 4974 if(i+1 != ntrys) { sleep(10 + 10*i); } 4975 } 4976 4977 // write cache file 4978 if(retval == 0 && cache_file) 4979 { 4980 char ipbuf[64]; 4981 4982 if(address == NULL || *address == '\0') 4983 { 4984#ifdef IF_LOOKUP 4985 struct sockaddr_in sin; 4986 int sock; 4987 4988 sock = socket(AF_INET, SOCK_STREAM, 0); 4989 if(get_if_addr(sock, interface, &sin) != 0) 4990 { 4991 exit(1); 4992 } 4993 close(sock); 4994 snprintf(ipbuf, sizeof(ipbuf), "%s", inet_ntoa(sin.sin_addr)); 4995#else 4996 show_message("interface lookup not enabled at compile time\n"); 4997 exit(1); 4998#endif 4999 } 5000 else 5001 { 5002 snprintf(ipbuf, sizeof(ipbuf), "%s", address); 5003 } 5004 5005 if(write_cache_file(cache_file, time(NULL), ipbuf) != 0) 5006 { 5007 show_message("unable to write cache file \"%s\": %s\n", 5008 cache_file, error_string); 5009 exit(1); 5010 } 5011 } 5012 if(retval == 0 && post_update_cmd) 5013 { 5014 if((res=exec_cmd(post_update_cmd)) != 0) 5015 { 5016 if(!(options & OPT_QUIET)) 5017 { 5018 if(res == -1) 5019 { 5020 show_message("error running post update command: %s\n", 5021 error_string); 5022 } 5023 else 5024 { 5025 show_message( 5026 "error running post update command, command exit code: %d\n", 5027 res); 5028 } 5029 } 5030 } 5031 } 5032 } 5033 else 5034 { 5035 show_message("no update needed at this time\n"); 5036 } 5037 } 5038 5039//2007.03.14 Yau add 5040#ifdef ASUS_DDNS 5041exit_main: 5042#endif // ASUS_DDNS 5043 5044#ifdef IF_LOOKUP 5045 if(sock > 0) { close(sock); } 5046#endif 5047 5048 if(address) { free(address); } 5049 if(cache_file) { free(cache_file); } 5050 if(config_file) { free(config_file); } 5051 if(host) { free(host); } 5052 if(interface) { free(interface); } 5053 if(mx) { free(mx); } 5054 if(port) { free(port); } 5055 if(request) { free(request); } 5056 if(request_over_ride) { free(request_over_ride); } 5057 if(server) { free(server); } 5058 if(url) { free(url); } 5059 if(partner) { free(partner); } 5060 5061 dprintf((stderr, "done\n")); 5062 return(retval); 5063} 5064 5065