home *** CD-ROM | disk | FTP | other *** search
- /*
- ** DYNDNS
- **
- ** HTTP Wrapper for the dyndns.org registration utility
- **
- ** Confidential Property of Tod Sambar
- ** (c) Copyright Tod Sambar 2000
- ** All rights reserved.
- **
- **
- ** Public Functions:
- **
- ** dyndns_init
- ** dyndns_ras
- **
- **
- ** History:
- ** Chg# Date Description Resp
- ** ---- ------- ------------------------------------------------------- ----
- ** 28FEB00 Created sambar
- ** 08FEB00 RAS callback added (untested!) sambar
- */
-
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <winsock.h>
- #include <errno.h>
- #include <dyndns.h>
-
- /*
- ** Local configuration variables
- */
- static SA_CHAR *service = "members.dyndns.org";
-
- static SA_INT registered = 0;
- static SA_INT wildcard_flag = 0;
- static SA_INT backmx_flag = 0;
- static SA_INT static_flag = 0;
-
- static SA_CHAR mxname[256];
- static SA_CHAR hostname[256];
- static SA_CHAR username[256];
- static SA_CHAR password[256];
-
- /*
- ** Local Prototypes
- */
- SA_RETCODE dyndns__load(SA_CTX *ctx, SA_VOID *argp,
- SA_CHAR *name, SA_CHAR *value);
- static SA_RETCODE dyndns__connect(SA_CTX *sactx, SA_CHAR *host,
- SA_INT port, SOCKET *sockp);
- static SA_RETCODE dyndns__disconnect(SA_CTX *sactx, SOCKET sock);
- static SA_RETCODE dyndns__register(SA_CTX *sactx, SOCKET sock,
- SA_CHAR *msg, SA_INT msglen);
- static SA_RETCODE dyndns__auth(SA_CHAR *username, SA_CHAR *password,
- SA_CHAR *auth);
-
- /*
- ** DYNDNS_INIT
- **
- ** Notify dyndns.org that the server is available.
- **
- ** Note: The INIT and EXIT callbacks should be used if the server
- ** has a static IP address.
- **
- ** Parameters:
- ** sactx Sambar Server context
- **
- ** Returns:
- ** SA_SUCCEED | SA_FAIL
- **
- ** Important! Use bin/serverd for debug information to ensure
- ** dyndns is working properly when initially configuring.
- */
- SA_RETCODE SA_PUBLIC
- dyndns_init(sactx)
- SA_CTX *sactx;
- {
- SA_INT len;
- SA_INT msglen;
- SOCKET sock;
- SA_CHAR ip[64];
- SA_CHAR msg[2048];
- SA_CHAR auth[256];
-
- /*
- ** Register with the DYNDNS server (only if dyndns.ini is found/loaded).
- */
- hostname[0] = '\0';
- username[0] = '\0';
- password[0] = '\0';
-
- /*
- ** Load the dyndns configuration entries.
- */
- if (sa_props_load(sactx, "dyndns.ini", "dyndns", NULL,
- (SA_PROPFUNC)dyndns__load) != SA_SUCCEED)
- {
- sa_log2(sactx, SA_LOG_WARN,
- "DYNDNS no [init] configuration (dyndns.ini)...");
- return (SA_SUCCEED);
- }
-
- /*
- ** Get the IP Address of this server.
- */
- len = 0;
- (SA_VOID)sa_ctx_props(sactx, SA_GET, SA_CTXPROP_SERVERIP,
- (SA_BYTE *)ip, 60, &len);
- ip[len] = '\0';
-
- if (dyndns__connect(sactx, service, 80, &sock) != SA_SUCCEED)
- {
- sa_log2(sactx, SA_LOG_ERROR, "DYNDNS registration failed");
- return (SA_SUCCEED);
- }
-
- sprintf(msg,
- "GET /nic/%sdns?action=edit&started=1&hostname=YES&host_id=%s&myip=%s",
- static_flag ? "stat" : "dyn", hostname, ip);
-
- msglen = strlen(msg);
-
- if (wildcard_flag)
- {
- strcpy(&msg[msglen], "&wildcard=ON");
- msglen += strlen(&msg[msglen]);
- }
-
- if (mxname[0] != '\0')
- {
- sprintf(&msg[msglen], "&mx=%s%s",
- mxname, (backmx_flag ? "&backmx=YES" : ""));
- msglen += strlen(&msg[msglen]);
- }
-
- strcpy(&msg[msglen], " HTTP/1.1\r\n");
- msglen += strlen(&msg[msglen]);
-
- (void)dyndns__auth(username, password, auth);
- sprintf(&msg[msglen], "Host: %s\r\nAuthorization: Basic %s\r\n",
- service, auth);
- msglen += strlen(&msg[msglen]);
-
- strcpy(&msg[msglen], "Content-Type: application/x-www-form-urlencoded\r\n");
- msglen += strlen(&msg[msglen]);
- strcpy(&msg[msglen], "Connection: close\r\n");
- msglen += strlen(&msg[msglen]);
- strcpy(&msg[msglen], "User-Agent: Sambar/4.3\r\n\r\n");
- msglen += strlen(&msg[msglen]);
-
- if (dyndns__register(sactx, sock, msg, msglen) != SA_SUCCEED)
- {
- sa_log2(sactx, SA_LOG_ERROR, "DYNDNS registration request failed");
- (void)dyndns__disconnect(sactx, sock);
- return (SA_SUCCEED);
- }
-
- registered = 1;
- (void)dyndns__disconnect(sactx, sock);
- sa_log2(sactx, SA_LOG_INFO, "DYNDNS registration complete");
-
- return (SA_SUCCEED);
- }
-
- /*
- ** DYNDNS_RAS
- **
- ** Called when the RAS connection is established or disconnected.
- ** Perform the appropriate dyndns.org registration.
- **
- ** Parameters:
- ** sactx Sambar Server context
- ** ip Active IP address.
- ** previp Previous IP address.
- ** connected RAS connected or disconnected.
- **
- ** Returns:
- ** SA_SUCCEED | SA_FAIL
- **
- ** Important! To prevent abuse, only re-register if the ip and previp
- ** are different.
- */
- SA_VOID SA_PUBLIC
- dyndns_ras(sactx, ip, previp, connected)
- SA_CTX *sactx;
- SA_CHAR *ip;
- SA_CHAR *previp;
- SA_BOOL connected;
- {
- SA_INT msglen;
- SOCKET sock;
- SA_CHAR msg[2048];
- SA_CHAR auth[256];
-
- if (!connected)
- return;
-
- /*
- ** If the IP address has not changed, don't re-register
- */
- if (strcmp(ip, previp) == 0)
- return;
-
- /*
- ** Load the dyndns configuration entries.
- */
- if (sa_props_load(sactx, "dyndns.ini", "dyndns", NULL,
- (SA_PROPFUNC)dyndns__load) != SA_SUCCEED)
- {
- sa_log2(sactx, SA_LOG_WARN,
- "DYNDNS-RAS no [init] configuration (dyndns.ini)...");
- return;
- }
-
- /*
- ** Re-register with dyndns.org with the new IP address (if changed)
- ** as the modem is connected/disconnected rather than server
- ** start/stop.
- */
- if (dyndns__connect(sactx, service, 80, &sock) != SA_SUCCEED)
- {
- sa_log2(sactx, SA_LOG_WARN, "DYNDNS-RAS registration failed");
- return;
- }
-
- sprintf(msg,
- "GET /nic/%sdns?action=edit&started=1&hostname=YES&host_id=%s&myip=%s",
- static_flag ? "stat" : "dyn", hostname, ip);
-
- msglen = strlen(msg);
-
- if (wildcard_flag)
- {
- strcpy(&msg[msglen], "&wildcard=ON");
- msglen += strlen(&msg[msglen]);
- }
-
- if (mxname[0] != '\0')
- {
- sprintf(&msg[msglen], "&mx=%s%s",
- mxname, (backmx_flag ? "&backmx=YES" : ""));
- msglen += strlen(&msg[msglen]);
- }
-
- strcpy(&msg[msglen], " HTTP/1.1\r\n");
- msglen += strlen(&msg[msglen]);
-
- (void)dyndns__auth(username, password, auth);
- sprintf(&msg[msglen], "Host: %s\r\nAuthorization: Basic %s\r\n",
- service, auth);
- msglen += strlen(&msg[msglen]);
-
- strcpy(&msg[msglen], "Content-Type: application/x-www-form-urlencoded\r\n");
- msglen += strlen(&msg[msglen]);
- strcpy(&msg[msglen], "Connection: close\r\n");
- msglen += strlen(&msg[msglen]);
- strcpy(&msg[msglen], "User-Agent: Sambar/4.3\r\n\r\n");
- msglen += strlen(&msg[msglen]);
-
- if (dyndns__register(sactx, sock, msg, msglen) != SA_SUCCEED)
- {
- sa_log2(sactx, SA_LOG_WARN, "DYNDNS-RAS registration request failed");
- (void)dyndns__disconnect(sactx, sock);
- return;
- }
-
- (void)dyndns__disconnect(sactx, sock);
- sprintf(msg, "DYNDNS-RAS re-registration complete: %s", ip);
- sa_log2(sactx, SA_LOG_INFO, msg);
-
- return;
- }
-
- /*
- ** DYNDNS__LOAD
- **
- ** Load a single dyndns configuration entry.
- **
- ** Parameters:
- ** sactx Sambar Server context
- ** argp unused.
- ** name Left hand argument.
- ** value Right hand argument.
- **
- ** Returns:
- ** SA_SUCCEED | SA_FAIL
- */
- SA_RETCODE
- dyndns__load(sactx, argp, name, value)
- SA_CTX *sactx;
- SA_VOID *argp;
- SA_CHAR *name;
- SA_CHAR *value;
- {
- if (strlen(value) > 255)
- return (SA_FAIL);
-
- if (stricmp(name, "wildcard") == 0)
- {
- if ((stricmp(value, "on") == 0) || (stricmp(value, "yes") == 0))
- wildcard_flag = 1;
- }
- else if (stricmp(name, "backmx") == 0)
- {
- if ((stricmp(value, "on") == 0) || (stricmp(value, "yes") == 0))
- backmx_flag = 1;
- }
- else if (stricmp(name, "static") == 0)
- {
- if ((stricmp(value, "on") == 0) || (stricmp(value, "yes") == 0))
- static_flag = 1;
- }
- else if (stricmp(name, "mx") == 0)
- {
- strcpy(mxname, value);
- }
- else if (stricmp(name, "hostname") == 0)
- {
- strcpy(hostname, value);
- }
- else if (stricmp(name, "username") == 0)
- {
- strcpy(username, value);
- }
- else if (stricmp(name, "password") == 0)
- {
- strcpy(password, value);
- }
-
- return (SA_SUCCEED);
- }
-
- static SA_RETCODE
- dyndns__connect(sactx, host, port, sockp)
- SA_CTX *sactx;
- SA_CHAR *host;
- SA_INT port;
- SOCKET *sockp;
- {
- int timeo;
- SOCKET sock;
- struct hostent *hent;
- struct sockaddr_in sin;
-
- /*
- ** Initialization
- */
- memset((void *)&sin, 0, sizeof(sin));
-
- /* Get the dyndns server address for the connect */
- hent = gethostbyname(host);
- if (hent == NULL)
- {
- sa_log2(sactx, SA_LOG_ERROR, "DYNDNS unable to lookup host name");
- return (SA_FAIL);
- }
-
- /* Create a socket */
- sock = socket(hent->h_addrtype, SOCK_STREAM, 0);
- if (sock == INVALID_SOCKET)
- {
- sa_log2(sactx, SA_LOG_ERROR, "DYNDNS socket creation failed");
- return (SA_FAIL);
- }
-
- /* Connect to the WHOIS server */
- sin.sin_family = AF_INET;
- sin.sin_port = htons((u_short)port);
- memcpy(&sin.sin_addr, hent->h_addr, hent->h_length);
-
- /* Now, connect to that WHOIS server */
- if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
- {
- closesocket(sock);
- sa_log2(sactx, SA_LOG_ERROR, "DYNDNS unable to connect to service");
- return (SA_FAIL);
- }
-
- /* Set the socket timeout to 30 seconds */
- timeo = 30000;
- (void)setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeo,
- sizeof(int));
-
- *sockp = sock;
- return (SA_SUCCEED);
- }
-
- static SA_RETCODE
- dyndns__disconnect(sactx, sock)
- SA_CTX *sactx;
- SOCKET sock;
- {
- closesocket(sock);
- return (SA_SUCCEED);
- }
-
- static SA_RETCODE
- dyndns__register(sactx, sock, msg, msglen)
- SA_CTX *sactx;
- SOCKET sock;
- SA_CHAR *msg;
- SA_INT msglen;
- {
- SA_INT len;
- SA_INT buflen;
- SA_BOOL finished;
- SA_CHAR buffer[1024];
-
- if (send(sock, msg, msglen, 0) != msglen)
- {
- sa_log2(sactx, SA_LOG_ERROR,
- "DYNDNS send of registration data failed.");
- return (SA_FAIL);
- }
-
- /* Receive the response. */
- len = 0;
- finished = 0;
- while (!finished)
- {
- buflen = recv(sock, &buffer[len], 1000 - len, 0);
- if ((buflen < 0) && (errno == EINTR))
- continue;
-
- if (buflen == SOCKET_ERROR)
- {
- sa_log2(sactx, SA_LOG_ERROR,
- "DYNDNS receive of registration request failed.");
- return (SA_FAIL);
- }
-
- if (buflen > 0)
- {
- len += buflen;
- if (len + buflen >= 1000)
- finished = 1;
- }
- else
- {
- finished = 1;
- }
- }
-
- buffer[len] = '\0';
- if (len == 0)
- {
- sa_log2(sactx, SA_LOG_ERROR,
- "DYNDNS no response received in 60 seconds");
- return (SA_FAIL);
- }
-
- if (strstr(buffer, "blocked due to abuse"))
- sa_log2(sactx, SA_LOG_WARN, "DYNDNS account blocked due to abuse.");
-
- /*
- ** FIX THIS sambar - should check for 200 header message response.
- */
- fprintf(stderr, "%s\n", buffer);
-
- return (SA_SUCCEED);
- }
-
- static SA_RETCODE
- dyndns__auth(username, password, auth)
- SA_CHAR *username;
- SA_CHAR *password;
- SA_CHAR *auth;
- {
- static unsigned char alpha[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- unsigned int bits;
- int i;
- int j;
- int authlen;
- int buflen;
- char buffer[256];
-
- sprintf(buffer, "%s:%s", username, password);
- buflen = strlen(buffer);
-
- i = 0;
- authlen = 0;
- while (i < buflen)
- {
- if (i && i % 54 == 0)
- auth[authlen++] = '\n';
-
- bits = buffer[i++];
- for (j = 0; j < 2; j++)
- {
- bits <<= 8;
- if (i < buflen)
- bits += buffer[i++];
- }
-
- auth[authlen++] = alpha[bits >> 18];
- auth[authlen++] = alpha[(bits >> 12) & 0x3f];
- auth[authlen++] = alpha[(bits >> 6) & 0x3f];
- auth[authlen++] = alpha[bits & 0x3f];
- }
-
- switch (buflen % 3)
- {
- case 1:
- auth[authlen - 2] = '=';
- case 2:
- auth[authlen - 1] = '=';
- break;
- }
- auth[authlen] = '\0';
-
- return (SA_SUCCEED);
- }
-