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