#include <sys/times.h>
#include <lib/defs.h>
#include <sys/uio.h>
#define DRHSIZE 256
#define DRHMASK (DRHSIZE-1)
/*
* MSG_ flags that may not be implemented on a particular OS
*/
#ifndef MSG_WAITALL
#define MSG_WAITALL 0
#endif
#ifndef MSG_EOR
#define MSG_EOR 0
#endif
struct ServReq;
struct Timer;
#define THREAD_LISTEN 1 /* listening thread */
#define THREAD_DNS 2 /* dns resolver thread */
#define THREAD_READER 3 /* reader thread */
#define THREAD_SDNS 4 /* server dns resolver thread */
#define THREAD_DRCMD 5 /* drcmd listener thread */
#define THREAD_NNTP 6 /* nntp connection */
#define THREAD_SPOOL 7 /* spool connection */
#define THREAD_POST 8 /* outgoing post */
#define THREAD_FEEDER 9 /* feeder thread */
#define OVERVIEW_FMT "Subject:\r\nFrom:\r\nDate:\r\nMessage-ID:\r\nReferences:\r\nBytes:\r\nLines:\r\nXref:full\r\n"
#define DEFMAXARTSINGROUP 1024
#define DEFARTSINGROUP 512
#define OV_CACHE_MAX 8 /* open fd's for N groups */
#define MAX_OVERVIEW_CACHE_REGIONS 2 /* 256x2 = 512 articles */
#define MAX_CROSS 64
/*
* THREAD_QSIZE is the number of spool requests that can be queued to
* a spool thread before we back off to a higher d_Pri.
*
* THREAD_PSIZE is the number of post requests that can be queued to
* a spool thread before we back off to a higher d_Pri.
*/
#define THREAD_QSIZE 16 /* for spool access */
#define THREAD_PSIZE 2 /* for posting */
#define THREAD_LIMSIZE (((THREAD_QSIZE > THREAD_PSIZE) ? THREAD_QSIZE : THREAD_PSIZE) * 2)
#ifndef INET6
typedef struct sockaddr sockaddr_storage;
#endif
/*
* ForkDesc - structure used to manage descriptors for select() threads
*/
typedef struct ForkDesc {
struct Timer *d_Timer; /* active timer */
struct ForkDesc *d_Next; /* linked list @ pri */
struct ForkDesc *d_Prev; /* linked list @ pri */
char *d_Id; /* host name */
pid_t d_Pid;
int d_Slot; /* status reporting slot*/
int d_Fd;
int d_Type;
int d_FdPend; /* save pending fd */
int d_Count; /* active subthreads */
int d_Pri;
void *d_Data;
struct sockaddr_storage d_SaveRSin;
char *d_LocalSpool; /* direct spool access */
int d_Cache; /* is spooler to be locally cached */
int d_CacheMin; /* min article size to be cached */
int d_CacheMax; /* max article size to be cached */
int d_CacheableTime; /* oldest article to be cached */
double d_ReadNewRatio; /* read/new articles ratio to reach to cache a group */
double d_CacheReadRatio; /* cachehits/read articles ratio to reach to cache a group */
#ifdef DREADER_CLIENT_TIMING
clock_t d_utime;
clock_t d_stime;
#endif
} ForkDesc;
/*
* Authentication structures
*/
/*
* The current output mode of the server to the client
*/
#define DRBC_NONE 0
#define DRBC_ARTICLE 1
#define DRBC_HEAD 2
#define DRBC_BODY 3
#define DRBC_LIST 4
#define DRBC_XOVER 5
#define DRBC_XHDR 6
#define DRBC_XXXX 7 /* The last of the DRBC_ defines */
#define OPT_NONE 0
#define OPT_VSERVER 1
#define OPT_GROUPS 2
#define OPT_AUTH 3
#define OPT_READERGRP 4
#define DEFNAMELEN 128
typedef struct Vserver { /* Define a virtual server */
char vs_Name[DEFNAMELEN];
char vs_ClusterName[64];
char vs_HostName[64];
char vs_PostPath[64];
char vs_NewsAdm[64];
char vs_Org[128];
char vs_AbuseTo[64];
char vs_CryptPw[32];
struct sockaddr_storage vs_Interface;
char vs_AccessFile[128];
int vs_NoXrefHostUpdate;
int vs_NoReadPath;
char vs_Welcome[256];
char vs_Comments[256];
char vs_PostTrailer[256];
} Vserver;
typedef struct GroupDef { /* Define a group access list */
char *gr_Name;
int gr_Count;
struct GroupList *gr_Groups;
struct GroupDef *gr_Next;
} GroupDef;
typedef struct AuthDef { /* Define an authentication type */
char au_Name[DEFNAMELEN];
char au_File[255];
char au_Cdb[255];
char au_Db[255];
char au_External[255];
char au_Radius[255];
char au_User[255];
char au_Pass[255];
char au_Realm[255];
char au_AddRealm[255];
char au_NetRemote[255];
char au_LDAP[255];
char au_Perl[255];
char au_PAM[255];
int au_Ident;
} AuthDef;
typedef struct ReaderDef { /* Define a reader group */
char rd_Name[DEFNAMELEN];
char rd_Auth[DEFNAMELEN];
char rd_Groups[DEFNAMELEN];
char rd_ListGroups[DEFNAMELEN];
char rd_PostGroups[DEFNAMELEN];
char rd_Vserver[DEFNAMELEN];
int rd_Read;
int rd_Post;
int rd_Feed;
int rd_Status;
int rd_Quiet;
int rd_ControlPost;
int rd_MaxConnTotal;
int rd_MaxConnPerHost;
int rd_MaxConnPerUser;
int rd_MaxConnPerGroup;
int rd_MaxConnUniqueHostLimit;
int rd_MaxConnPerVs;
int rd_RateLimit[DRBC_XXXX];
int rd_RateLimitTax;
int rd_ByteLimit;
int rd_PathComponents;
int rd_GroupLog;
int rd_UseVerifiedDns;
int rd_DenyMismatchedDns;
int rd_DenyNoDns;
int rd_AllowNewnews;
int rd_SpoolHeaders;
int rd_IgnoreAuthInfo;
int rd_CheckPostGroups;
int rd_LogCmd;
time_t rd_IdleTimeout;
time_t rd_SessionTimeout;
} ReaderDef;
typedef struct AccessDef { /* Define the access list */
char ad_Pattern[100];
char ad_IdentUser[16];
char ad_Reader[DEFNAMELEN];
int ad_MatchExit;
} AccessDef;
typedef struct AccessMap { /* Define an access mapping */
Vserver *VServerList;
int VServerCount;
GroupDef *GroupsList;
int GroupCount;
void *GroupMap;
long GroupMapSize;
AuthDef *AuthList;
int AuthCount;
ReaderDef *ReaderList;
int ReaderCount;
AccessDef *AccessList;
int AccessCount;
} AccessMap;
/*
* DnsReq/DnsRes - structures used to manage DNS lookups
*
* At this point, I'm having doubts as to the wisdom of using
* two structures, and wonder if it wouldn't be more prudent to
* use DnsRes to talk to DnsTest. Unless dreaderd is rewritten
* with real threads, using DnsTest to handle arbitrary time-
* intensive tasks such as dealing with auth is very attractive,
* and will eventually end up requiring many DnsRes vars to be
* stuffed into DnsReq. Yech. JG200106061214
*/
typedef struct DnsReq {
struct sockaddr_storage dr_LSin; /* local interface */
struct sockaddr_storage dr_RSin; /* remote ip:port */
char dr_AuthUser[64]; /* authinfo user */
char dr_AuthPass[16]; /* authinfo pass */
int dr_ResultFlags; /* see #defines below */
double dr_ByteCount; /* how many bytes sent - stats */
int dr_GrpCount; /* number of groups entered */
int dr_ArtCount; /* number of articles fetched */
double dr_PostBytes; /* how many bytes posted */
int dr_PostCount; /* number of articles posted */
int dr_PostFailCount; /* number of failed postings */
double dr_ByteCountArticle; /* Bytes sent for art fetches */
double dr_ByteCountHead; /* Bytes sent for head fetches */
double dr_ByteCountBody; /* Bytes sent for body fetches */
double dr_ByteCountList; /* Bytes sent for list fetches */
double dr_ByteCountXover; /* Bytes sent for xover fetches */
double dr_ByteCountXhdr; /* Bytes sent for xhdr fetches */
double dr_ByteCountOther; /* Bytes sent for other fetches */
time_t dr_SessionLength; /* duration of session in secs */
} DnsReq;
/*
* Define some values used in dr_ResultFlags
*/
#define DR_REQUIRE_DNS 0x0001 /* authinfo check required */
#define DR_SERVER_STATS 0x0002 /* struct has info server stats */
#define DR_SESSEXIT_RPT 0x0004 /* reporting session term stats */
typedef struct DnsRes {
struct DnsRes *dr_HNext; /* main process hash link */
int dr_Code; /* the auth result code */
int dr_Flags; /* what options are enabled */
int dr_ArtCount; /* how many articles fetched */
int dr_PostCount; /* how many articles posted */
int dr_PostBytes; /* how many bytes posted */
int dr_PostFailCount; /* how many posts failed */
double dr_ByteCount; /* how many bytes sent */
int dr_GrpCount; /* how many groups accessed */
double dr_ByteCountArticle; /* Bytes sent for art fetches */
double dr_ByteCountHead; /* Bytes sent for head fetches */
double dr_ByteCountBody; /* Bytes sent for body fetches */
double dr_ByteCountList; /* Bytes sent for list fetches */
double dr_ByteCountXover; /* Bytes sent for xover fetches */
double dr_ByteCountXhdr; /* Bytes sent for xhdr fetches */
double dr_ByteCountOther; /* Bytes sent for other fetches */
time_t dr_TimeStart; /* Time connection was made */
int dr_ReaderPid; /* process ID of reader process */
struct sockaddr_storage dr_Addr; /* remote IP address and port */
char dr_Host[64]; /* the remote hostname */
char dr_ReaderName[DEFNAMELEN]; /* the reader group name */
char dr_VServer[DEFNAMELEN]; /* the virtual server */
char dr_IdentUser[16]; /* the ident username */
char dr_AuthUser[64]; /* the authinfo user */
char dr_AuthPass[16]; /* the authinfo pass */
int dr_DnsMismatch; /* Fwd/Rev DNS don't match */
int dr_ResultFlags; /* see #defines above */
int dr_StaticAuth; /* don't change auth details */
int dr_ConnCount; /* for rate limit calculation */
ReaderDef *dr_ReaderDef; /* reader group pointer */
Vserver *dr_VServerDef; /* vserver pointer */
GroupDef *dr_GroupDef; /* group list pointer */
GroupDef *dr_ListGroupDef; /* list group list pointer */
GroupDef *dr_PostGroupDef; /* post group list pointer */
AuthDef *dr_AuthDef; /* auth def pointer */
} DnsRes;
#define DF_FEED 0x00000001 /* can feed */
#define DF_READ 0x00000002 /* can read */
#define DF_POST 0x00000004 /* can post */
#define DF_STATUS 0x00000008 /* only want status report */
#define DF_QUIET 0x00000010 /* don't log */
#define DF_CONTROLPOST 0x00000020 /* allowed to post Control: */
#define DF_AUTHREQUIRED 0x00000040 /* authentication required */
#define DF_FEEDONLY 0x00000080 /* feed-only thread */
#define DF_GROUPLOG 0x00000100 /* log groups accessed by user */
#define DF_AUTH 0x00000200 /* user valid with AUTHINFO */
/*
* MBuf - structure used to manage read and write buffers
*/
typedef struct MBuf {
struct MBuf *mb_Next;
char *mb_Buf;
int mb_Index; /* finished index */
int mb_NLScan; /* newline scan index */
int mb_Size;
int mb_Max;
} MBuf;
typedef struct MBufHead {
MBuf *mh_MBuf;
MemPool **mh_MemPool;
MemPool **mh_BufPool;
int mh_Bytes;
int mh_Wait;
int mh_Fd;
double mh_TotalBytes;
char mh_REof;
char mh_WEof;
char mh_RError;
char mh_WError;
} MBufHead;
/*
* Timer
*/
typedef struct Timer {
struct Timer *ti_Next;
struct Timer *ti_Prev;
struct ForkDesc *ti_Desc;
struct timeval ti_To; /* requested timeout */
struct timeval ti_Tv; /* absolute time of timeout */
int ti_Flags;
} Timer;
#define TIF_READ 0x01
#define TIF_WRITE 0x02
typedef struct TimeRestrict {
time_t tr_Time;
} TimeRestrict;
#define MAX_HDR_CC 0x08
#define LF 0x01
#define CR 0x02
#define CRLF 0x03
#define FLAG_PATH 0x01
#define FLAG_XREF 0x02
#define FLAG_NEEDED 0x03
#define INBODY -1
#define JMPBDY -2
#define HDRCPY -3
#define HDRDEL -4
#define WRDDEL -5
#define BLOCK_OK 0
#define BLOCK_ERROR 1
#define BLOCK_END 2
#ifdef __linux__
#define USE_AIO 1
#define USE_LINUX_KAIO 0
#else
#define USE_AIO 0
#endif
typedef struct DirectFileAccess {
#if USE_AIO
struct aiocb *dfa_AIOcb;
int lock;
#else
int dfa_Fd;
#endif
int dfa_Size;
char dfa_Buffer[4096];
char dfa_Field[MAX_HDR_CC];
char dfa_InHdr;
char dfa_LF;
char dfa_Flag;
struct DirectFileAccess *dfa_Next;
} DirectFileAccess;
/*
* Connection - structure used to manage an NNTP connection
*
* note(1): Server requests are attached in two places: The co_SReq in a
* THREAD_NNTP connection and the co_SReq in a THREAD_SPOOL or
* THREAD_POST connection.
*/
#define CACHE_OFF 0x0000
#define CACHE_ON 0x0001
#define CACHE_LAZY 0x0002
#define CACHE_SCOREBOARD 0x0003
typedef struct Connection {
ForkDesc *co_Desc;
void (*co_Func)(struct Connection *conn);
int (*co_ArtFuncHead)(struct Connection *conn, char *buf, int len);
int (*co_ArtFuncBody)(struct Connection *conn, char *buf, int len);
const char *co_State;
MemPool *co_MemPool;
MemPool *co_BufPool;
MBufHead co_TMBuf;
MBufHead co_RMBuf;
time_t co_SessionStartTime;
time_t co_LastActiveTime;
int co_FCounter;
double co_ByteCounter;
int co_BytesHeader;
int co_Flags;
TimeRestrict co_TimeRestrict;
DnsRes co_Auth;
char *co_GroupName; /* current group or NULL */
char *co_IHaveMsgId;
Control *co_Ctl; /* control lookup cache */
struct ServReq *co_SReq; /* see note(1) */
int co_ListRec;
int co_ListRecLen;
char *co_ListPat;
char *co_ListHdrs;
int co_ListBegNo;
int co_ListEndNo;
int co_ListCacheMode;
struct activeCacheEnt *co_ListCachePtr;
struct GroupList *co_ListCacheGroups;
int co_ArtMode; /* current article mode */
int co_ArtNo; /* current article number */
int co_ArtBeg;
int co_ArtEnd;
int co_RequestFlags; /* 0x01 = art by message-id */
/* 0x02 = art by art number */
struct DirectFileAccess *co_DirectFA; /* Direct file access */
HashFeed co_RequestHash;
struct timeval co_RateTv;
int co_RateCounter;
time_t co_LastServerLog;
unsigned long co_ServerByteCount;
unsigned long co_ServerArticleCount;
unsigned long co_ServerArticleRequestedCount;
unsigned long co_ServerArticleNotFoundErrorCount;
unsigned long co_ServerArticleMiscErrorCount;
double co_ClientTotalByteCount;
unsigned long co_ClientTotalArticleCount;
double co_ClientGroupByteCount;
unsigned long co_ClientGroupArticleCount;
unsigned long co_ClientPostCount;
unsigned long co_ClientGroupCount;
int co_ByteCountType; /* Temp for by-type byte count */
MBufHead co_ArtBuf; /* article buffer */
} Connection;
#define COF_SERVER 0x00000001
#define COF_HEADFEED 0x00000002
#define COF_STREAM 0x00000004
#define COF_IHAVE 0x00000008 /* temporary ihave->takethis */
#define COF_POST 0x00000010 /* post command, else feed */
#define COF_INHEADER 0x00000020 /* post/feed, reading headers*/
#define COF_DORANGE 0x00000040 /* do article range, else msgid */
#define COF_WASCONTROL 0x00000080
#define COF_MODEREADER 0x00000100 /* spool fetch, do mode reader */
#define COF_CLOSESERVER 0x00010000 /* close server ASAP */
#define COF_PATISWILD 0x00020000 /* list pattern is wildcard */
#define COF_MAYCLOSESRV 0x00040000 /* maybe close server */
#define COF_INPROGRESS 0x00080000 /* operation in progress */
#define COF_ININIT 0x00100000 /* see server.c */
#define COF_MAYNOTCLOSE 0x00200000 /* may not close the connection */
#define COF_READONLY 0x00400000 /* send ``mode readonly'' */
#define COF_LOGIN 0x00800000 /* send ``authinfo'' to log in */
#define COF_POSTTOOBIG 0x01000000 /* posted article is too big */
#define MBUF_SIZE 1024
#define MBUF_HIWAT (MBUF_SIZE*2-256)
#define COM_ARTICLE 0
#define COM_BODY 1
#define COM_HEAD 2
#define COM_STAT 3
#define COM_BODYNOSTAT 4
#define COM_FUNC 5
#define COM_ACTIVE 6 /* list active */
#define COM_GROUPDESC 7 /* list newsgroups grouppat */
#define COM_XHDR 8
#define COM_XOVER 9
#define COM_XPAT 10
#define COM_NEWGROUPS 11 /* newgroups */
#define COM_ARTICLEWVF 12 /* verify body before output */
#define COM_BODYWVF 13 /* verify body before output */
#define COM_NEWNEWS 14
#define ARTFETCH_MSGID 0x01 /* Request was by Message-ID */
#define ARTFETCH_ARTNO 0x02 /* Request was by article number */
typedef struct ServReq {
struct ServReq *sr_Next; /* linked list of requests */
Connection *sr_CConn; /* client making request */
Connection *sr_SConn; /* server handling request */
char *sr_Group; /* request related to group */
int sr_GrpIter; /* Group iteration, for cachehits hash */
int sr_endNo; /* last group article, for cachehits */
char *sr_MsgId; /* request related to messageid */
time_t sr_Time; /* time of request for timeout calc */
FILE *sr_Cache; /* cache write (locked for duration) */
int sr_TimeRcvd; /* article received time (NNRetrieveHead) */
int sr_Rolodex; /* see server.c */
int sr_NoPass; /* see server.c */
} ServReq;
#define SREQ_RETRIEVE 1
#define SREQ_POST 2
/*
* Overview record. over.groupname (overview information - headers)
* numa.groupname (article number assignment file)
*/
typedef union OverHead {
struct {
int reserved[32];
} u;
struct {
int version;
int byteOrder;
int headSize;
int maxArts;
char gName[256];
} v;
} OverHead;
#define oh_Version v.version
#define oh_HeadSize v.headSize
#define oh_MaxArts v.maxArts /* adjusted by dexpireover -s */
#define oh_ByteOrder v.byteOrder
#define oh_Gname v.gName
#define OH_VERSION 2
#define OH_BYTEORDER ((int)0xF1E2D3C4)
typedef struct OverArt {
int oa_ArtNo; /* article number */
int oa_SeekPos; /* seek in data.grouphash file */
int oa_Bytes; /* bytes of headers in data.grphash file*/
hash_t oa_MsgHash; /* locate message-id (used by cancel) */
int oa_ArtSize; /* used for xover Bytes: header */
int oa_TimeRcvd; /* time received */
int oa_Unused2;
} OverArt;
typedef struct OverData {
struct OverData *od_Next;
int od_HFd;
int od_ArtBase;
int od_HMapPos;
int od_HMapBytes;
const char *od_HMapBase;
} OverData;
typedef struct OverInfo {
struct OverInfo *ov_Next;
int ov_Refs;
char *ov_Group;
int ov_MaxArts; /* maximum number of articles in group */
OverData *ov_HData; /* hdata file reference linked list */
OverData *ov_HCache; /* last accessed file reference */
int ov_OFd;
OverHead *ov_Head;
int ov_Size;
int ov_Iter;
int ov_endNo;
} OverInfo;
typedef struct ArtNumAss {
struct ArtNumAss *an_Next;
const char *an_GroupName; /* NOT TERMINATED */
int an_GroupLen;
int an_ArtNo;
} ArtNumAss;
/*
* Active file cache for LIST-type commands
*/
typedef struct activeCacheEnt {
struct GroupList *nglist;
int cts;
struct activeCacheEnt *next, *prev;
struct activeCacheEnt *left, *right;
struct activeCacheEnt *parent;
} activeCacheEnt;
#define ACMODE_NONE 0
#define ACMODE_READ 1
#define ACMODE_WRITE 2
/*
* This structure is to share info between the master process and
* all the child processes. The info is mainly stats gathering.
*/
struct SharedInfo {
struct in_addr dr_Addr; /* remote IP address */
int dr_Port; /* remote port */
int si_RateLimit;
double si_ServerByteCount;
double si_ServerArticleCount;
double si_ClientTotalByteCount;
double si_ClientTotalArticleCount;
double si_ClientGroupByteCount;
double si_ClientGroupArticleCount;
double si_ClientPostCount;
double si_ClientPostBytes;
double si_ClientPostFail;
double si_ClientGroupCount;
};
#include <obj/dreaderd-protos.h>
syntax highlighted by Code2HTML, v. 0.9.1