⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rc.c

📁 早期freebsd实现
💻 C
字号:
/*  $Revision: 1.31 $****  Routines for the remote connect channel.  Create an Internet stream socket**  that processes connect to.  If the incoming site is not one of our feeds,**  then we pass the connection off to the standard nntp daemon.*/#include "innd.h"#include <netdb.h>#if	!defined(NETSWAP)#if	!defined(htons)extern unsigned short	htons();#endif	/* !defined(htons) */#if	!defined(htonl)extern unsigned long	htonl();#endif	/* !defined(htonl) */#endif	/* !defined(NETSWAP) */#define COPYADDR(dest, src) \	    (void)memcpy((POINTER)dest, (POINTER)src, (SIZE_T)sizeof (INADDR))/***  A remote host has an address and a password.*/typedef struct _REMOTEHOST {    char	*Name;    INADDR	Address;    char	*Password;    char	**Patterns;} REMOTEHOST;STATIC INADDR		*RCmaster;STATIC int		RCnmaster;STATIC char		*RCslaveflag;STATIC char		RCnnrpd[] = _PATH_NNRPD;STATIC char		RCnnrqd[] = _PATH_NNQRD;STATIC char		RCnntpd[] = _PATH_NNTPD;STATIC CHANNEL		*RCchan;STATIC REMOTEHOST	*RCpeerlist;STATIC int		RCnpeerlist;STATIC REMOTEHOST	*RCnolimitlist;STATIC int		RCnnolimitlist;/***  See if the site properly entered the password.*/BOOLRCauthorized(cp, pass)    register CHANNEL	*cp;    char		*pass;{    register REMOTEHOST	*rp;    register int	i;    for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++)	/* SUPPRESS 112 *//* Retrieving long where char is stored */	if (cp->Address.s_addr == rp->Address.s_addr) {	    if (rp->Password[0] == '\0' || EQ(pass, rp->Password))		return TRUE;	    syslog(L_ERROR, "%s bad_auth", inet_ntoa(cp->Address));	    return FALSE;	}    if (!AnyIncoming)	/* Not found in our table; this can't happen. */	syslog(L_ERROR, "%s not_found", inet_ntoa(cp->Address));    /* Anonymous hosts should not authenticate. */    return FALSE;}/***  See if a host is in the "nolimit" file.*/BOOLRCnolimit(cp)    register CHANNEL	*cp;{    register REMOTEHOST	*rp;    register int	i;    for (rp = RCnolimitlist, i = RCnnolimitlist; --i >= 0; rp++)	/* SUPPRESS 112 *//* Retrieving long where char is stored */	if (cp->Address.s_addr == rp->Address.s_addr)	    return TRUE;    return FALSE;}/***  Is this an address of the master?*/BOOLRCismaster(addr)    INADDR		addr;{    register INADDR	*ip;    register int	i;    if (AmSlave)	for (i = RCnmaster, ip = RCmaster; --i >= 0; ip++)	    /* SUPPRESS 112 *//* Retrieving long where char is stored */	    if (addr.s_addr == ip->s_addr)		return TRUE;    return FALSE;}/***  Hand off a descriptor to NNRPD.*/voidRChandoff(fd, h)    int		fd;    HANDOFF	h;{    STRING	argv[6];    char	buff[SMBUF];    int		i;    if (SetNonBlocking(fd, FALSE) < 0)	syslog(L_ERROR, "%s cant nonblock %d in RChandoff %m", LogName, fd);    switch (h) {    default:	syslog(L_ERROR, "%s internal RChandoff %d type %d", LogName, fd, h);	/* FALLTHROUGH */    case HOnnrpd:	argv[0] = RCnnrpd;	break;    case HOnnrqd:	argv[0] = RCnnrqd;	break;    case HOnntpd:	argv[0] = RCnntpd;	break;    }    argv[1] = "-s                                                ";    i = 2;    if (NNRPReason) {	(void)sprintf(buff, "-r%s", NNRPReason);	argv[i++] = buff;    }    if (NNRPTracing)	argv[i++] = "-t";    if (RCslaveflag)	argv[i++] = RCslaveflag;    argv[i] = NULL;    /* Call NNRP; don't send back a QUIT message if Spawn fails since       * that's a major error we want to find out about quickly. */    (void)Spawn(fd, fd, fd, argv);}/***  Read function.  Accept the connection and either create an NNTP channel**  or spawn an nnrpd to handle it.*/STATIC FUNCTYPERCreader(cp)    CHANNEL		*cp;{    int			fd;    struct sockaddr_in	remote;    int			size;    register int	i;    register REMOTEHOST	*rp;    CHANNEL		*new;    char		*name;    if (cp != RCchan) {	syslog(L_ERROR, "%s internal RCreader wrong channel 0x%x not 0x%x",	    LogName, cp, RCchan);	return;    }    /* Get the connection. */    size = sizeof remote;    if ((fd = accept(cp->fd, (struct sockaddr *)&remote, &size)) < 0) {	syslog(L_ERROR, "%s cant accept RCreader %m", LogName);	return;    }    /* See if it's one of our servers. */    for (name = NULL, rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++)	/* SUPPRESS 112 *//* Retrieving long where char is stored */	if (rp->Address.s_addr == remote.sin_addr.s_addr) {	    name = rp->Name;	    break;	}    /* If not a server, and not allowing anyone, hand him off. */    if (i >= 0)	new = NCcreate(fd, rp->Password[0] != '\0');    else if (AnyIncoming)	new = NCcreate(fd, FALSE);    else {	RChandoff(fd, HOnntpd);	if (close(fd) < 0)	    syslog(L_ERROR, "%s cant close %d %m", LogName, fd);	return;    }    /* SUPPRESS 112 *//* Retrieving long where char is stored */    new->Address.s_addr = remote.sin_addr.s_addr;    syslog(L_NOTICE, "%s connected %d",	name ? name : inet_ntoa(new->Address), new->fd);}/***  Write-done function.  Shouldn't happen.*/STATIC FUNCTYPERCwritedone(){    syslog(L_ERROR, "%s internal RCwritedone", LogName);}/***  Read in the file listing the hosts we take news from, and fill in the**  global list of their Internet addresses.  On modern systems a host can**  have multiple addresses, so we take care to add all of them to the list.**  We can distinguish between the two because h_addr is a #define for the**  first element of the address list in modern systems, while it's a field**  name in old ones.*/STATIC voidRCreadfile(list, count, filename)    REMOTEHOST		**list;    int			*count;    char		*filename;{    static char		NOPASS[] = "";    char		buff[SMBUF];    register FILE	*F;    register char	*p;    struct hostent	*hp;    register int	i;    register REMOTEHOST	*rp;    register int	j;    char		*pass;    char		*pats;    int			errors;    /* Free anything that might have been there. */    if (*list) {	for (rp = *list, i = *count; --i >= 0; rp++) {	    DISPOSE(rp->Name);	    DISPOSE(rp->Password);	    if (rp->Patterns)		DISPOSE(rp->Patterns);	}	DISPOSE(*list);	*list = NULL;	*count = 0;    }    /* Open the server file, count the lines. */    if ((F = fopen(filename, "r")) == NULL) {	syslog(L_FATAL, "%s cant read %s %m", LogName, filename);	exit(1);    }    for (i = 1; fgets(buff, sizeof buff, F) != NULL; )	if (buff[0] != COMMENT_CHAR && buff[0] != '\n')	    i++;    *count = i;    rp = *list = NEW(REMOTEHOST, *count);#if	!defined(DO_HAVE_UNIX_DOMAIN)    rp->Address.s_addr = inet_addr(LOOPBACK_HOST);    rp->Name = COPY("localhost");    rp->Password = COPY(NOPASS);    rp->Patterns = NULL;    rp++;#endif	/* !defined(DO_HAVE_UNIX_DOMAIN) */    /* Now read the file to add all the hosts. */    (void)fseek(F, (OFFSET_T)0, SEEK_SET);    for (errors = 0; fgets(buff, sizeof buff, F) != NULL; ) {	/* Ignore blank and comment lines. */	if ((p = strchr(buff, '\n')) != NULL)	    *p = '\0';	if ((p = strchr(buff, COMMENT_CHAR)) != NULL)	    *p = '\0';	if (buff[0] == '\0')	    continue;	if ((pass = strchr(buff, ':')) != NULL) {	    *pass++ = '\0';	    if ((pats = strchr(pass, ':')) != NULL)		*pats++ = '\0';	    else		pats = NULL;	}	else {	    pass = NOPASS;	    pats = NULL;	}	/* Was host specified as as dotted quad? */	if ((rp->Address.s_addr = inet_addr(buff)) != (unsigned long)-1) {	    rp->Name = COPY(buff);	    rp->Password = COPY(pass);	    rp->Patterns = pats ? CommaSplit(COPY(pats)) : NULL;	    rp++;	    continue;	}	/* Host specified as a text name? */	if ((hp = gethostbyname(buff)) == NULL) {	    syslog(L_ERROR, "%s cant gethostbyname %s %m", LogName, buff);	    errors++;	    continue;	}#if	defined(h_addr)	/* Count the addresses and see if we have to grow the list. */	for (i = 0; hp->h_addr_list[i]; i++)	    continue;	if (i == 0) {	    syslog(L_ERROR, "%s no_address %s %m", LogName, buff);	    errors++;	    continue;	}	if (i == 1) {	    /* Just one, no need to grow. */	    COPYADDR(&rp->Address, hp->h_addr_list[0]);	    rp->Name = COPY(hp->h_name);	    rp->Password = COPY(pass);	    rp->Patterns = pats ? CommaSplit(COPY(pats)) : NULL;	    rp++;	    continue;	}	/* Note the relative position, grow the array, and restore it. */	j = rp - *list;	*count += i - 1;	RENEW(*list, REMOTEHOST, *count);	rp = *list + j;	/* Add all the hosts. */	for (i = 0; hp->h_addr_list[i]; i++) {	    COPYADDR(&rp->Address, hp->h_addr_list[i]);	    rp->Name = COPY(hp->h_name);	    rp->Password = COPY(pass);	    rp->Patterns = pats ? CommaSplit(COPY(pats)) : NULL;	    rp++;	}#else	/* Old-style, single address, just add it. */	COPYADDR(&rp->Address, hp->h_addr);	rp->Name = COPY(hp->h_name);	rp->Password = COPY(pass);	rp->Patterns = pats ? CommaSplit(COPY(pats)) : NULL;	rp++;#endif	/* defined(h_addr) */    }    *count = rp - *list;    if (fclose(F) == EOF)	syslog(L_ERROR, "%s cant fclose %s %m", LogName, filename);    if (errors)	syslog(L_ERROR, "%s bad_hosts %d in %s", LogName, errors, filename);}voidRCreadlist(){    static char	INNDHOSTS[] = _PATH_INNDHOSTS;    char	name[sizeof _PATH_INNDHOSTS + sizeof ".nolimit"];    struct stat	Sb;    RCreadfile(&RCpeerlist, &RCnpeerlist, INNDHOSTS);    FileGlue(name, INNDHOSTS, '.', "nolimit");    if (stat(name, &Sb) >= 0)	RCreadfile(&RCnolimitlist, &RCnnolimitlist, name);}/***  Find the name of a remote host we've connected to.*/char *RChostname(cp)    register CHANNEL	*cp;{    static char		buff[SMBUF];    register REMOTEHOST	*rp;    register int	i;    for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++)	/* SUPPRESS 112 *//* Retrieving long where char is stored */	if (cp->Address.s_addr == rp->Address.s_addr)	    return rp->Name;    (void)strcpy(buff, inet_ntoa(cp->Address));    return buff;}/***  Is the remote site allowed to post to this group?*/BOOLRCcanpost(cp, group)    register CHANNEL	*cp;    register char	*group;{    register REMOTEHOST	*rp;    register BOOL	match;    register BOOL	subvalue;    register char	**argv;    register char	*pat;    register int	i;    for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) {	/* SUPPRESS 112 *//* Retrieving long where char is stored */	if (cp->Address.s_addr != rp->Address.s_addr)	    continue;	if (rp->Patterns == NULL)	    break;	for (match = TRUE, argv = rp->Patterns; (pat = *argv++) != NULL; ) {	    subvalue = *pat != SUB_NEGATE;	    if (!subvalue)		pat++;	    if (wildmat(group, pat))		match = subvalue;	}	return match;    }    return TRUE;}/***  Create the channel.*/voidRCsetup(i, master)    register int	i;    char		*master;{    struct sockaddr_in	server;    struct hostent	*hp;    INADDR		a;    char		buff[SMBUF];#if	defined(SO_REUSEADDR)    int			on;#endif	/* defined(SO_REUSEADDR) */    if (i < 0) {	/* Create a socket and name it. */	if ((i = socket(AF_INET, SOCK_STREAM, 0)) < 0) {	    syslog(L_FATAL, "%s cant socket RCreader %m", LogName);	    exit(1);	}#if	defined(SO_REUSEADDR)	on = 1;	if (setsockopt(i, SOL_SOCKET, SO_REUSEADDR,		(caddr_t)&on, sizeof on) < 0)	    syslog(L_ERROR, "%s cant setsockopt RCreader %m", LogName);#endif	/* defined(SO_REUSEADDR) */	(void)memset((POINTER)&server, 0, sizeof server);	server.sin_port = htons(NNTP_PORT);	server.sin_family = AF_INET;	server.sin_addr.s_addr = htonl(INADDR_ANY);	if (bind(i, (struct sockaddr *)&server, sizeof server) < 0) {	    syslog(L_FATAL, "%s cant bind RCreader %m", LogName);	    exit(1);	}    }    /* Set it up to wait for connections. */    if (listen(i, MAXLISTEN) < 0) {	syslog(L_FATAL, "%s cant listen RCreader %m", LogName);	exit(1);    }    RCchan = CHANcreate(i, CTremconn, CSwaiting, RCreader, RCwritedone);    syslog(L_NOTICE, "%s rcsetup %s", LogName, CHANname(RCchan));    RCHANadd(RCchan);    /* Get the list of hosts we handle. */    RCreadlist();    /* If we have a master, get all his addresses. */    AmSlave = master != NULL;    if (AmSlave) {	/* Dotted quad? */	if ((a.s_addr = inet_addr(master)) != (unsigned long)-1) {	    RCnmaster = 1;	    RCmaster = NEW(INADDR, 1);	    COPYADDR(&RCmaster[0], &a);	}	else {	    /* Must be a text name. */	    if ((hp = gethostbyname(master)) == NULL) {		syslog(L_FATAL, "%s cant gethostbyname %s %m", LogName, master);		exit(1);	    }#if	defined(h_addr)	    /* Count the addresses. */	    for (i = 0; hp->h_addr_list[i]; i++)		continue;	    if (i == 0) {		syslog(L_FATAL, "%s no_address %s %m", LogName, master);		exit(1);	    }	    RCnmaster = i;	    RCmaster = NEW(INADDR, RCnmaster);	    for (i = 0; hp->h_addr_list[i]; i++)		COPYADDR(&RCmaster[i], hp->h_addr_list[i]);#else	    RCnmaster = 1;	    RCmaster = NEW(INADDR, 1)	    COPYADDR(&RCmaster[0], &a);#endif	/* defined(h_addr) */	}	/* Set flag for nnrp. */	(void)sprintf(buff, "-S%s", master);	RCslaveflag = COPY(buff);    }}/***  Cleanly shut down the channel.*/voidRCclose(){    register REMOTEHOST	*rp;    register int	i;    CHANclose(RCchan, CHANname(RCchan));    RCchan = NULL;    if (RCpeerlist) {	for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) {	    DISPOSE(rp->Name);	    DISPOSE(rp->Password);	    if (rp->Patterns)		DISPOSE(rp->Patterns);	}	DISPOSE(RCpeerlist);	RCpeerlist = NULL;	RCnpeerlist = 0;    }    if (RCmaster) {	DISPOSE(RCmaster);	RCmaster = NULL;	RCnmaster = 0;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -