因为是准备用于商业用途,所以小心点。虽然是在我的知识范围内考虑过了,不过一个人的力量总是有限的
代码:
/* * ddnsd - 20CN DDNS Server Process Daemon for *BSD. * * This software is NOT free of charge, * Copyright (C) 20CN Security Group 2003. * By NetDemon <netdemon@20cn.org> * http://www.20cn.net/ * @(#)ddnsd.c 0.1 (20CN) 28/5/03 */
#define SYSLOG_NAMES
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <err.h> #include <errno.h> #include <netdb.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <unistd.h>
#include "ddnsd.h"
#define DEFAULT_SERVICE "ddnsd" #define SERVICE_PORT 553 #define MAX_PACKET 128
/* * Function prototypes. */
static void DoProcessing (int fd, int direction); static void DaemonMode (void); static void Usage (void); static void InitiateShutdown (int); static void Shutdown (int); static void RefreshAddr (int); static void ParseOption (const char* option, const char* parms); static void ReadConfigFile (const char* fileName); static void StrToAddr (const char* str, struct in_addr* addr); static u_short StrToPort (const char* str, const char* proto); static int StrToProto (const char* str); static void ParseArgs (int argc, char** argv);
/* * Globals. */
static int verbose; static int background; static int running; static char* ifName; static int assignAliasAddr; static int dynamicMode; static int logFacility;
int main (int argc, char** argv) { int sockfd; struct sockaddr_in addr; fd_set readMask; int fdMax; /* * Parse options. */ verbose = 0; ifName = NULL; background = 0; running = 1; dynamicMode = 0; logFacility = LOG_DAEMON; ParseArgs (argc, argv); /* * Open syslog channel. */ openlog ("ddnsd", LOG_CONS | LOG_PID | (verbose ? LOG_PERROR : 0), logFacility);
/* * Create sockets. */ sockfd = socket (AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) Quit ("Unable to create socket."); /* * Bind socket. */ addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(SERVICE_PORT); if (bind (sockfd,(struct sockaddr*) &addr,sizeof addr) == -1) Quit ("Unable to bind socket."); /* * Become a daemon unless verbose mode was requested. */ if (!verbose) DaemonMode (); /* * Catch signals to manage shutdown and * refresh of interface address. */ siginterrupt(SIGTERM, 1); siginterrupt(SIGHUP, 1); signal (SIGTERM, InitiateShutdown); signal (SIGHUP, RefreshAddr); /* * We need largest descriptor number for select. */
fdMax = -1;
if (sockfd > fdMax) fdMax = sockfd;
while (running) {
/* * Build read mask from socket descriptors to select. */ FD_ZERO (&readMask); /* * Check if new packets are available. */ if (sockfd != -1) FD_SET (sockfd, &readMask);
if (select (fdMax + 1, &readMask, NULL, NULL, NULL) == -1) { if (errno == EINTR) continue; Quit ("Select failed."); }
if (sockfd != -1) if (FD_ISSET (sockfd, &readMask)) DoProcessing (sockfd, DONT_KNOW); }
if (background) unlink (PIDFILE); return 0; }
static void DaemonMode () { FILE* pidFile;
daemon (0, 0); background = 1;
pidFile = fopen (PIDFILE, "w"); if (pidFile) {
fprintf (pidFile, "%d\n", getpid ()); fclose (pidFile); } }
static void ParseArgs (int argc, char** argv) { int arg; char* opt; char parmBuf[256]; int len; /* bounds checking */
for (arg = 1; arg < argc; arg++) {
opt = argv[arg]; if (*opt != '-') {
warnx ("invalid option %s", opt); Usage (); }
parmBuf[0] = '\0'; len = 0;
while (arg < argc - 1) {
if (argv[arg + 1][0] == '-') break;
if (len) { strncat (parmBuf, " ", sizeof(parmBuf) - (len + 1)); len += strlen(parmBuf + len); }
++arg; strncat (parmBuf, argv[arg], sizeof(parmBuf) - (len + 1)); len += strlen(parmBuf + len);
}
ParseOption (opt + 1, (len ? parmBuf : NULL));
} }
static void DoProcessing (int fd, int direction) { int bytes; int origBytes; char buf[MAX_PACKET]; struct sockaddr_in addr; int wrote; int status; int addrSize; struct ip* ip; char msgBuf[80]; char domain[256];
/* * Get packet from socket. */ addrSize = sizeof addr; origBytes = recvfrom (fd, buf, sizeof buf, 0, (struct sockaddr*) &addr, &addrSize); if (origBytes == -1) { if (errno != EINTR) Warn ("read from socket failed"); return; }
// if (verbose) { /* * Print All addresses msg to syslog. */
// SyslogPacket (ip, LOG_WARNING, "require"); // }
/* * Decoder Buf MSG */ //decoder(buf,status,domain,passwd); //if (status==1){ /* * check passwd. */ //}else{ /* * check ip and update ip. */
//} /* * Put packet back for processing. */ wrote = sendto (fd, buf, bytes, 0, (struct sockaddr*) &addr, sizeof addr); if (wrote != bytes) { if (errno == EACCES ) { sprintf (msgBuf, "failed to write packet back"); Warn (msgBuf); } } }
/////////////////////////////////////////// void Quit (const char* msg) { Warn (msg); exit (1); }
void Warn (const char* msg) { if (background) syslog (LOG_ALERT, "%s (%m)", msg); else warn ("%s", msg); }
static void RefreshAddr (int sig) { if (ifName) assignAliasAddr = 1; }
static void InitiateShutdown (int sig) { /* * Start timer to allow kernel gracefully * shutdown existing connections when system * is shut down. */ siginterrupt(SIGALRM, 1); signal (SIGALRM, Shutdown); alarm (10); }
static void Shutdown (int sig) { running = 0; }
/* * Different options recognized by this program. */
enum Option {
Verbose, ConfigFile, DynamicMode, LogFacility };
enum Param { YesNo, String, None, };
/* * Option information structure (used by ParseOption). */
struct OptionInfo { enum Option type; enum Param parm; const char* parmDescription; const char* description; const char* name; const char* shortName; };
/* * Table of known options. */
static struct OptionInfo optionTable[] = {
{ Verbose, YesNo, "[yes|no]", "verbose mode, dump packet information", "verbose", "v" }, { DynamicMode, YesNo, "[yes|no]", "dynamic mode, automatically detect interface address changes", "dynamic", NULL },
{ ConfigFile, String, "file_name", "read options from configuration file", "config", "f" }, { LogFacility, String, "facility", "name of syslog facility to use for logging", "log_facility", NULL }, }; static void ParseOption (const char* option, const char* parms) { int i; struct OptionInfo* info; int yesNoValue; const char* strValue; int max; char* end; CODE* fac_record = NULL; /* * Find option from table. */ max = sizeof (optionTable) / sizeof (struct OptionInfo); for (i = 0, info = optionTable; i < max; i++, info++) {
if (!strcmp (info->name, option)) break;
if (info->shortName) if (!strcmp (info->shortName, option)) break; }
if (i >= max) {
warnx ("unknown option %s", option); Usage (); }
yesNoValue = 0; strValue = NULL; /* * Check parameters. */ switch (info->parm) { case YesNo: if (!parms) parms = "yes";
if (!strcmp (parms, "yes")) yesNoValue = 1; else if (!strcmp (parms, "no")) yesNoValue = 0; else errx (1, "%s needs yes/no parameter", option); break;
case String: strValue = parms; if (!strValue) errx (1, "%s needs parameter", option); break;
case None: if (parms) errx (1, "%s does not take parameters", option); break;
}
switch (info->type) { case Verbose: verbose = yesNoValue; break;
case DynamicMode: dynamicMode = yesNoValue; break;
case ConfigFile: ReadConfigFile (strValue); break;
case LogFacility:
fac_record = facilitynames; while (fac_record->c_name != NULL) {
if (!strcmp (fac_record->c_name, strValue)) {
logFacility = fac_record->c_val; break;
} else fac_record++; }
if(fac_record->c_name == NULL) errx(1, "Unknown log facility name: %s", strValue);
break; } }
void ReadConfigFile (const char* fileName) { FILE* file; char *buf; size_t len; char *ptr, *p; char* option;
file = fopen (fileName, "r"); if (!file) err(1, "cannot open config file %s", fileName);
while ((buf = fgetln(file, &len)) != NULL) { if (buf[len - 1] == '\n') buf[len - 1] = '\0'; else errx(1, "config file format error: " "last line should end with newline");
/* * Check for comments, strip off trailing spaces. */ if ((ptr = strchr(buf, '#'))) *ptr = '\0'; for (ptr = buf; isspace(*ptr); ++ptr) continue; if (*ptr == '\0') continue; for (p = strchr(buf, '\0'); isspace(*--p);) continue; *++p = '\0';
/* * Extract option name. */ option = ptr; while (*ptr && !isspace (*ptr)) ++ptr;
if (*ptr != '\0') {
*ptr = '\0'; ++ptr; } /* * Skip white space between name and parms. */ while (*ptr && isspace (*ptr)) ++ptr;
ParseOption (option, *ptr ? ptr : NULL); }
fclose (file); }
static void Usage () { int i; int max; struct OptionInfo* info;
fprintf (stderr, "Recognized options:\n\n");
max = sizeof (optionTable) / sizeof (struct OptionInfo); for (i = 0, info = optionTable; i < max; i++, info++) {
fprintf (stderr, "-%-20s %s\n", info->name, info->parmDescription);
if (info->shortName) fprintf (stderr, "-%-20s %s\n", info->shortName, info->parmDescription);
fprintf (stderr, " %s\n\n", info->description); }
exit (1); }
void StrToAddr (const char* str, struct in_addr* addr) { struct hostent* hp;
if (inet_aton (str, addr)) return;
hp = gethostbyname (str); if (!hp) errx (1, "unknown host %s", str);
memcpy (addr, hp->h_addr, sizeof (struct in_addr)); }
u_short StrToPort (const char* str, const char* proto) { u_short port; struct servent* sp; char* end;
port = strtol (str, &end, 10); if (end != str) return htons (port);
sp = getservbyname (str, proto); if (!sp) errx (1, "unknown service %s/%s", str, proto);
return sp->s_port; }
int StrToProto (const char* str) { if (!strcmp (str, "tcp")) return IPPROTO_TCP;
if (!strcmp (str, "udp")) return IPPROTO_UDP;
errx (1, "unknown protocol %s. Expected tcp or udp", str); }
|