Ticket #19: auth-path-header.patch

File auth-path-header.patch, 25.6 KB (added by eagle, 14 years ago)

Patch against INN 2.2

Line 
1*** inn-STABLE_2_2-1999-04-26_03-01/doc/incoming.conf.5 Mon Jan  4 07:41:42 1999
2--- inn-2.2-devel/doc/incoming.conf.5   Sat May  8 08:22:37 1999
3***************
4*** 36,43 ****
5  .RE
6  .PP
7  The word ``peer'' is required. <name> is a label for this peer. It is
8! any string valid as a key. The body of a peer entry contains some number
9! of key/value entries.
10  .PP
11  Group entries look like:
12  .PP
13--- 36,44 ----
14  .RE
15  .PP
16  The word ``peer'' is required. <name> is a label for this peer. It is
17! any string valid as a key. (It is, however, used as the default for
18! both the ``hostname'' and ``pathmatch'' keys.) The body of a peer
19! entry contains some number of key/value entries.
20  .PP
21  Group entries look like:
22  .PP
23***************
24*** 137,142 ****
25--- 138,149 ----
26  .BI patterns:
27  This key requires a string value. It is a list of newsfeeds(5)-style list
28  of newsgroups which are to be accepted from this host. (default="*")
29+ .TP
30+ .BI pathmatch:
31+ This key requires a string value. It is a list of wildcard patterns that
32+ are matched against the first Path entry of incoming articles from this
33+ peer. Extra trace information is added to the path if no match is found.
34+ The default for this value is to use the label of the peer.
35  .TP
36  .BI email:
37  This key requires a string value. Reserved for future use. (default=empty)
38diff -rbc inn-STABLE_2_2-1999-04-26_03-01/frontends/innconfval.c inn-2.2-devel/frontends/innconfval.c
39*** inn-STABLE_2_2-1999-04-26_03-01/frontends/innconfval.c      Fri Aug 21 11:28:14 1998
40--- inn-2.2-devel/frontends/innconfval.c        Fri Apr 30 18:33:17 1999
41***************
42*** 112,117 ****
43--- 112,120 ----
44      /* First thing, set up logging and our identity. */
45      openlog("innconfval", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG);     
46 
47+     if (!(innconffile = getenv("INNCONF")))
48+       innconffile = _PATH_CONFIG;
49+
50      /* Parse JCL. */
51      File = FALSE;
52      while ((i = getopt(ac, av, "fcpsti:v")) != EOF)
53diff -rbc inn-STABLE_2_2-1999-04-26_03-01/innd/art.c inn-2.2-devel/innd/art.c
54*** inn-STABLE_2_2-1999-04-26_03-01/innd/art.c  Mon Apr 12 17:12:23 1999
55--- inn-2.2-devel/innd/art.c    Thu Jun 10 22:45:07 1999
56***************
57*** 133,144 ****
58--- 133,147 ----
59      { "Content-Type",         HTstd },
60      { "Content-Base",         HTstd },
61      { "Content-Disposition",  HTstd },
62+     { "Content-Transfer-Encoding",    HTstd },
63+     { "User-Agent",           HTstd },
64      { "X-Newsreader",         HTstd },
65      { "X-Mailer",             HTstd },
66      { "X-Newsposter",         HTstd },
67      { "X-Cancelled-By",       HTstd },
68      { "X-Canceled-By",        HTstd },
69      { "Cancel-Key",           HTstd },
70+     { "X-Cancel-ID",          HTstd },
71  };
72 
73  ARTHEADER     *ARTheadersENDOF = ENDOF(ARTheaders);
74***************
75*** 434,443 ****
76        return result;
77      }
78 
79!     size = Article->Used + 6 + ARTheaders[_xref].Length + 4 + 3 + Path.Used + Pathalias.Used + 64 + 1;
80      p = artbuff = NEW(char, size);
81     
82!     if (strncmp(Path.Data, path, Path.Used) != 0) {
83        Hassamepath = FALSE;
84        memcpy(p, Article->Data, path - Article->Data);
85        p += path - Article->Data;
86--- 437,449 ----
87        return result;
88      }
89 
90!     size = Article->Used + 6 + ARTheaders[_xref].Length + 4 + 3 + Path.Used + Pathalias.Used + Data->PathExtraLength + 64 + 1;
91      p = artbuff = NEW(char, size);
92 
93!     /* if we're adding extra gunk to the path, we ignore the existing entry,
94!      * since it may be spoofed.
95!      */
96!     if (Data->PathExtraLength || strncmp(Path.Data, path, Path.Used) != 0) {
97        Hassamepath = FALSE;
98        memcpy(p, Article->Data, path - Article->Data);
99        p += path - Article->Data;
100***************
101*** 447,452 ****
102--- 453,463 ----
103            memcpy(p, Pathalias.Data, Pathalias.Used);
104            p += Pathalias.Used;
105        }
106+       if (Data->PathExtraLength)
107+       {
108+           memcpy(p, Data->PathExtra, Data->PathExtraLength);
109+           p += Data->PathExtraLength;
110+       }
111        memcpy(p, path, Data->Body - path - 1);
112        p += Data->Body - path - 1;
113      } else {
114***************
115*** 568,574 ****
116      IOVEC             *vp;
117      long              size;
118      char              *p;
119!     IOVEC             iov[10];
120      IOVEC             *end;
121      char              bytesbuff[SMBUF];
122      int                       i;
123--- 579,585 ----
124      IOVEC             *vp;
125      long              size;
126      char              *p;
127!     IOVEC             iov[12];
128      IOVEC             *end;
129      char              bytesbuff[SMBUF];
130      int                       i;
131***************
132*** 595,602 ****
133      vp->iov_len  = p - Article->Data;
134      size += (vp++)->iov_len;
135 
136!     /* Do not append the same path twice */
137!     if (strncmp(Path.Data, p, Path.Used) != 0) {
138        Hassamepath = FALSE;
139          vp->iov_base = Path.Data;
140          vp->iov_len  = Path.Used;
141--- 606,613 ----
142      vp->iov_len  = p - Article->Data;
143      size += (vp++)->iov_len;
144 
145!     /* Do not append the same path twice (unless adding extra gunk) */
146!     if (Data->PathExtraLength || strncmp(Path.Data, p, Path.Used) != 0) {
147        Hassamepath = FALSE;
148          vp->iov_base = Path.Data;
149          vp->iov_len  = Path.Used;
150***************
151*** 606,611 ****
152--- 617,628 ----
153            vp->iov_len  = Pathalias.Used;
154            size += (vp++)->iov_len;
155        }
156+       if (Data->PathExtraLength)
157+       {
158+           vp->iov_base = Data->PathExtra;
159+           vp->iov_len  = Data->PathExtraLength;
160+           size += (vp++)->iov_len;
161+       }
162        vp->iov_base = p;
163        vp->iov_len  = Data->Body - p - (innconf->wireformat == 1);
164        size += (vp++)->iov_len;
165***************
166*** 2195,2200 ****
167--- 2213,2243 ----
168          }
169      }
170 
171+     switch (RCpathmismatch(cp, hops[0]))
172+     {
173+       case 0:
174+           /* all kosher. */
175+           Data.PathExtraLength = 0;
176+           break;
177+
178+       case 1:
179+       {
180+           /* expected a match; got none. Complain (but only once per connect) */
181+           char *adr = inet_ntoa(cp->Address);
182+           if (!cp->Mismatches++)
183+               syslog(L_NOTICE, "%s: path mismatch in %s (claimed to be %s)", adr, Data.MessageID, hops[0]);
184+           sprintf(Data.PathExtra, "%s.MISMATCH!", adr);
185+           Data.PathExtraLength = strlen(Data.PathExtra);
186+           break;
187+       }
188+
189+       default:
190+           /* didn't expect a match, so add a plain IP address. */
191+           sprintf(Data.PathExtra, "%s!", inet_ntoa(cp->Address));
192+           Data.PathExtraLength = strlen(Data.PathExtra);
193+           break;
194+     }
195+     
196  #if defined(DO_PERL)
197      pathForPerl = HeaderFindMem(article->Data, article->Used, "Path", 4) ;
198      TMRstart(TMR_PERL);
199***************
200*** 2449,2459 ****
201        j += ngp->NameLength + 1 + MAXARTFNAME + 1;
202      }
203 
204-     /* Loop over sites to find Poisons/ControlOnly and undo Sendit flags. */
205-     for (i = nSites, sp = Sites; --i >= 0; sp++)
206-       if (sp->Poison || (sp->ControlOnly && (ControlHeader < 0)) || (sp->DontWantNonExist && NonExist))
207-           sp->Sendit = FALSE;         
208-
209      /* Control messages not filed in "to" get filed only in control.name
210       * or control. */
211      if (ControlHeader >= 0 && Accepted && !ToGroup) {
212--- 2492,2497 ----
213***************
214*** 2525,2530 ****
215--- 2563,2573 ----
216      }
217      *ngptr = NULL;
218      j++;
219+
220+     /* Loop over sites to find Poisons/ControlOnly and undo Sendit flags. */
221+     for (i = nSites, sp = Sites; --i >= 0; sp++)
222+       if (sp->Poison || (sp->ControlOnly && (ControlHeader < 0)) || (sp->DontWantNonExist && NonExist))
223+           sp->Sendit = FALSE;         
224 
225      /* Allocate exactly enough space for the textual representation */
226      if (innconf->storageapi)
227diff -rbc inn-STABLE_2_2-1999-04-26_03-01/innd/innd.h inn-2.2-devel/innd/innd.h
228*** inn-STABLE_2_2-1999-04-26_03-01/innd/innd.h Tue Mar  2 03:10:48 1999
229--- inn-2.2-devel/innd/innd.h   Fri May 14 06:07:08 1999
230***************
231*** 161,166 ****
232--- 161,167 ----
233      u_long            Ihave_Deferred;
234      u_long            Ihave_SendIt;
235      u_long            Ihave_Cybercan;
236+     u_long              Mismatches;
237      int                       Reported;
238      long              Received;
239      long              Refused;
240***************
241*** 347,352 ****
242--- 348,355 ----
243      HASH      *Hash;
244      BUFFER    *Headers;
245      BUFFER    *Overview;
246+     char        PathExtra[SMBUF];
247+     int         PathExtraLength;
248  } ARTDATA;
249 
250  typedef struct _WIP {
251***************
252*** 561,570 ****
253--- 564,575 ----
254  extern BOOL           RCauthorized();
255  extern int            RCcanpost();
256  extern char           *RChostname();
257+ extern char           *RChostlabel();
258  extern void           RCclose();
259  extern void           RChandoff();
260  extern void           RCreadlist();
261  extern void           RCsetup();
262+ extern int              RCpathmismatch(CHANNEL *cp, char *pathstr);
263 
264  extern BOOL           SITEfunnelpatch();
265  extern BOOL           SITEsetup();
266diff -rbc inn-STABLE_2_2-1999-04-26_03-01/innd/rc.c inn-2.2-devel/innd/rc.c
267*** inn-STABLE_2_2-1999-04-26_03-01/innd/rc.c   Wed Jan 27 15:27:29 1999
268--- inn-2.2-devel/innd/rc.c     Fri May 14 12:08:08 1999
269***************
270*** 41,46 ****
271--- 41,48 ----
272      int               MaxCnx;         /* Max connections (per peer) */
273      char      **Patterns;     /* List of groups allowed */
274      char      *Pattern;       /* List of groups allowed (string) */
275+     char        *Pathmatch;     /* pattern to match path against (string) */
276+     char        **Pathmatches;  /* pattern to match path against */
277      char        *Email;         /* Email(s) of contact */
278      char      *Comment;       /* Commentary [max size = MAXBUFF] */
279  } REMOTEHOST;
280***************
281*** 75,84 ****
282  #define COMMENT               "comment:"
283  #define SKIP          "skip:"
284  #define NORESENDID    "noresendid:"
285 
286  typedef enum {K_END, K_BEGIN_PEER, K_BEGIN_GROUP, K_END_PEER, K_END_GROUP,
287              K_STREAM, K_HOSTNAME, K_MAX_CONN, K_PASSWORD, K_EMAIL,
288!             K_PATTERNS, K_COMMENT, K_SKIP, K_NORESENDID} _Keywords;
289 
290  typedef enum {T_STRING, T_BOOLEAN, T_INTEGER} _Types;
291 
292--- 77,87 ----
293  #define COMMENT               "comment:"
294  #define SKIP          "skip:"
295  #define NORESENDID    "noresendid:"
296+ #define PATHMATCH     "pathmatch:"
297 
298  typedef enum {K_END, K_BEGIN_PEER, K_BEGIN_GROUP, K_END_PEER, K_END_GROUP,
299              K_STREAM, K_HOSTNAME, K_MAX_CONN, K_PASSWORD, K_EMAIL,
300!             K_PATTERNS, K_COMMENT, K_SKIP, K_NORESENDID, K_PATHMATCH} _Keywords;
301 
302  typedef enum {T_STRING, T_BOOLEAN, T_INTEGER} _Types;
303 
304***************
305*** 656,661 ****
306--- 660,669 ----
307                DISPOSE(rp->Patterns[0]);
308                DISPOSE(rp->Patterns);
309            }
310+           if (rp->Pathmatches) {
311+               DISPOSE(rp->Pathmatches[0]);
312+               DISPOSE(rp->Pathmatches);
313+           }
314        }
315        DISPOSE(*list);
316        *list = NULL;
317***************
318*** 687,692 ****
319--- 695,702 ----
320      rp->Comment = COPY(NOCOMMENT);
321      rp->Password = COPY(NOPASS);
322      rp->Patterns = NULL;
323+     rp->Pathmatch = COPY("*");
324+     rp->Pathmatches = RCCommaSplit(COPY(rp->Pathmatch));
325      rp->MaxCnx = 0;
326      rp->Streaming = TRUE;
327      rp->Skip = FALSE;
328***************
329*** 707,712 ****
330--- 717,723 ----
331      default_params.Email = COPY(NOEMAIL);
332      default_params.Comment = COPY(NOCOMMENT);
333      default_params.Pattern = NULL;
334+     default_params.Pathmatch = NULL;
335 
336      /* Read the file to add all the hosts. */
337      while ((word = RCreaddata (&linecount, F)) != NULL) {
338***************
339*** 742,747 ****
340--- 753,760 ----
341          groups[groupcount - 2].Comment : default_params.Comment;
342        group_params->Pattern = groupcount > 1 ?
343          groups[groupcount - 2].Pattern : default_params.Pattern;
344+       group_params->Pathmatch = groupcount > 1 ?
345+         groups[groupcount - 2].Pathmatch : default_params.Pathmatch;
346        group_params->Password = groupcount > 1 ?
347          groups[groupcount - 2].Password : default_params.Password;
348        if ((word = RCreaddata (&linecount, F)) == NULL) {
349***************
350*** 789,794 ****
351--- 802,809 ----
352          group_params->Comment : default_params.Comment;
353        peer_params.Pattern = groupcount > 0 ?
354          group_params->Pattern : default_params.Pattern;
355+       peer_params.Pathmatch = groupcount > 0 ?
356+         group_params->Pathmatch : default_params.Pathmatch;
357        peer_params.Password = groupcount > 0 ?
358          group_params->Password : default_params.Password;
359 
360***************
361*** 839,844 ****
362--- 854,861 ----
363              rp->Comment = COPY(peer_params.Comment);
364              rp->Patterns = peer_params.Pattern != NULL ?
365                    RCCommaSplit(COPY(peer_params.Pattern)) : NULL;
366+             rp->Pathmatches = peer_params.Pathmatch != NULL ?
367+                   RCCommaSplit(COPY(peer_params.Pathmatch)) : NULL;
368              rp->MaxCnx = peer_params.MaxCnx;
369              rp++;
370              continue;
371***************
372*** 884,889 ****
373--- 901,908 ----
374                rp->Password = COPY(peer_params.Password);
375                rp->Patterns = peer_params.Pattern != NULL ?
376                  RCCommaSplit(COPY(peer_params.Pattern)) : NULL;
377+               rp->Pathmatches = peer_params.Pathmatch != NULL ?
378+                 RCCommaSplit(COPY(peer_params.Pathmatch)) : NULL;
379                rp->MaxCnx = peer_params.MaxCnx;
380                rp++;
381                t++;
382***************
383*** 901,906 ****
384--- 920,927 ----
385                rp->Password = COPY(peer_params.Password);
386                rp->Patterns = peer_params.Pattern != NULL ?
387                  RCCommaSplit(COPY(peer_params.Pattern)) : NULL;
388+               rp->Pathmatches = peer_params.Pathmatch != NULL ?
389+                 RCCommaSplit(COPY(peer_params.Pathmatch)) : NULL;
390                rp->MaxCnx = peer_params.MaxCnx;
391                rp++;
392                continue;
393***************
394*** 925,930 ****
395--- 946,953 ----
396              rp->Password = COPY(peer_params.Password);
397              rp->Patterns = peer_params.Pattern != NULL ?
398                RCCommaSplit(COPY(peer_params.Pattern)) : NULL;
399+             rp->Pathmatches = peer_params.Pathmatch != NULL ?
400+               RCCommaSplit(COPY(peer_params.Pathmatch)) : NULL;
401              rp->MaxCnx = peer_params.MaxCnx;
402              rp++;
403            }
404***************
405*** 941,946 ****
406--- 964,971 ----
407            rp->Password = COPY(peer_params.Password);
408            rp->Patterns = peer_params.Pattern != NULL ?
409              RCCommaSplit(COPY(peer_params.Pattern)) : NULL;
410+           rp->Pathmatches = peer_params.Pathmatch != NULL ?
411+             RCCommaSplit(COPY(peer_params.Pathmatch)) : NULL;
412            rp->MaxCnx = peer_params.MaxCnx;
413            rp++;
414  #endif            /* defined(h_addr) */
415***************
416*** 1106,1111 ****
417--- 1131,1153 ----
418        continue;
419        }
420 
421+       /* pathmatch */
422+       if (!strncmp (word, PATHMATCH, sizeof PATHMATCH)) {
423+       DISPOSE(word);
424+       if ((word = RCreaddata (&linecount, F)) == NULL) {
425+         break;
426+       }
427+       RCadddata(data, &infocount, K_PATHMATCH, T_STRING, word);
428+       if (peer_params.Label != NULL)
429+         peer_params.Pathmatch = word;
430+       else
431+         if (groupcount > 0 && group_params->Label != NULL)
432+           group_params->Pathmatch = word;
433+         else
434+           default_params.Pathmatch = word;
435+       continue;
436+       }
437+
438        /* email */
439        if (!strncmp (word, EMAIL, sizeof EMAIL)) {
440        DISPOSE(word);
441***************
442*** 1297,1302 ****
443--- 1339,1350 ----
444            RCwritelistvalue (F, RCpeerlistfile[i].value);
445            fputc ('\n', F);
446            break;
447+         case K_PATHMATCH:
448+           RCwritelistindent (F, inc);
449+           fprintf(F, "%s\t", PATHMATCH);
450+           RCwritelistvalue (F, RCpeerlistfile[i].value);
451+           fputc ('\n', F);
452+           break;
453          case K_COMMENT:
454            RCwritelistindent (F, inc);
455            fprintf(F, "%s\t", COMMENT);
456***************
457*** 1342,1347 ****
458--- 1390,1453 ----
459      return buff;
460  }
461 
462+ /*
463+ **  Find the label (from incoming.conf) of a remote host we've connected to.
464+ */
465+ char *
466+ RChostlabel(cp)
467+     register CHANNEL  *cp;
468+ {
469+     static char               buff[SMBUF];
470+     register REMOTEHOST       *rp;
471+     register int      i;
472+
473+     for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++)
474+       if (cp->Address.s_addr == rp->Address.s_addr)
475+           return rp->Label;
476+     (void)strcpy(buff, inet_ntoa(cp->Address));
477+     return buff;
478+ }
479+
480+
481+ int RCpathmismatch(CHANNEL *cp, char *pathstr)
482+ {
483+     REMOTEHOST                *rp;
484+     int                       i;
485+
486+     /* local sockets can use any path. note that if you don't have
487+      * unix domain sockets, you'll probably want an explicit "*" as
488+      * the path match for localhost in incoming.conf.
489+      */
490+
491+     if (!cp->Address.s_addr)
492+       return 0;
493+
494+     if (!pathstr)
495+       pathstr = "";
496+
497+     /* look through known hosts. */
498+
499+     for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) {
500+       if (cp->Address.s_addr != rp->Address.s_addr)
501+           continue;
502+       if (rp->Pathmatches == NULL)
503+           return EQ(rp->Label, pathstr) ? 0 : 1;
504+       else
505+       {
506+           char **patp;
507+           for (patp = rp->Pathmatches; *patp; ++patp)
508+               if (wildmat(pathstr, *patp))
509+                   return 0;
510+           return 1;
511+       }
512+     }
513+
514+     /* if we get this far, we're presumably in promiscuous mode.
515+      * always add the IP, but don't bother with the .MISMATCH bit.
516+      */
517+
518+     return -1;
519+ }
520 
521  /*
522  **  Is the remote site allowed to post to this group?
523***************
524*** 1458,1463 ****
525--- 1564,1573 ----
526            if (rp->Patterns) {
527                DISPOSE(rp->Patterns[0]);
528                DISPOSE(rp->Patterns);
529+           }
530+           if (rp->Pathmatches) {
531+               DISPOSE(rp->Pathmatches[0]);
532+               DISPOSE(rp->Pathmatches);
533            }
534        }
535        DISPOSE(RCpeerlist);
536diff -rbc inn-STABLE_2_2-1999-04-26_03-01/innd/site.c inn-2.2-devel/innd/site.c
537*** inn-STABLE_2_2-1999-04-26_03-01/innd/site.c Mon Apr 19 07:54:46 1999
538--- inn-2.2-devel/innd/site.c   Sat May  8 05:46:54 1999
539***************
540*** 386,394 ****
541--- 386,406 ----
542            if (Dirty)
543                BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));
544            if (!Hassamepath)
545+           {
546                BUFFappend(bp, Path.Data, Path.Used);
547                if (AddAlias)
548                    BUFFappend(bp, Pathalias.Data, Pathalias.Used);
549+               if (Data->PathExtraLength)
550+                   BUFFappend(bp, Data->PathExtra, Data->PathExtraLength);
551+               BUFFappend(bp, Data->Path, Data->PathLength);
552+           }
553+           else if (AddAlias)
554+           {
555+               BUFFappend(bp, Path.Data, Path.Used);
556+               BUFFappend(bp, Pathalias.Data, Pathalias.Used);
557+               BUFFappend(bp, Data->Path + Path.Used, Data->PathLength - Path.Used);
558+           }
559+           else
560                BUFFappend(bp, Data->Path, Data->PathLength);
561            break;
562        case FEED_REPLIC:
563diff -rbc inn-STABLE_2_2-1999-04-26_03-01/innd/status.c inn-2.2-devel/innd/status.c
564*** inn-STABLE_2_2-1999-04-26_03-01/innd/status.c       Mon Aug 24 17:29:51 1998
565--- inn-2.2-devel/innd/status.c Sat May  8 07:15:39 1999
566***************
567*** 16,22 ****
568--- 16,26 ----
569  #define MAX_PEER     100
570  #define MIN_REFRESH   60  /* 1 min */
571  #define HTML_STATUS
572+ #ifdef HTML_STATUS
573+ #define STATUS_FILE  "inn-status.html" /* will be in pathlog/pathhttp */
574+ #else
575  #define STATUS_FILE  "inn.status" /* will be in pathlog/pathhttp */
576+ #endif
577 
578  typedef struct _STATUS {
579      char           name[SMBUF];
580***************
581*** 48,53 ****
582--- 52,58 ----
583      unsigned long  Ihave_Deferred;
584      unsigned long  Ihave_SendIt;
585      unsigned long  Ihave_Cybercan;
586+     unsigned long  Mismatches;
587  } STATUS;
588 
589  static unsigned STATUSlast_time;
590***************
591*** 161,166 ****
592--- 166,172 ----
593        status[j].Duplicate = status[j].Unwanted_u = 0;
594        status[j].Unwanted_d = status[j].Unwanted_g = 0;
595        status[j].Unwanted_s = status[j].Unwanted_f = 0;
596+       status[j].Mismatches = 0;
597      }
598      if (Now.time - cp->Started > status[j].seconds)
599        status[j].seconds = Now.time - cp->Started;
600***************
601*** 192,197 ****
602--- 198,204 ----
603      status[j].Takethis += cp->Takethis;
604      status[j].Takethis_Ok += cp->Takethis_Ok;
605      status[j].Takethis_Err += cp->Takethis_Err;
606+     status[j].Mismatches += cp->Mismatches;
607      status[j].Size += cp->Size;
608      size += cp->Size;
609      if (CHANsleeping(cp)) {
610***************
611*** 283,293 ****
612      fprintf (F, "want streaming: %s\n",
613             status[j].can_stream ? "Yes" : "No");
614      fprintf (F, "   rejected: %-7ld  ",      status[j].rejected);
615!     fprintf (F, "         filtred: %-7ld ",  status[j].Unwanted_f);
616      fprintf (F, "  is streaming: %s\n",
617             (status[j].Check || status[j].Takethis) ? "Yes" : "No");
618      fprintf (F, "       size: %-8s ",        PrettySize(status[j].Size, str));
619!     fprintf (F, "       bad sites: %-7ld\n", status[j].Unwanted_s);
620      fprintf (F, "  Protocol:\n");
621      fprintf (F, "      Ihave: %-6ld SendIt[%d]: %-6ld    Got[%d]: %-6ld Deferred[%d]: %ld\n",
622             status[j].Ihave, NNTP_SENDIT_VAL, status[j].Ihave_SendIt,
623--- 290,301 ----
624      fprintf (F, "want streaming: %s\n",
625             status[j].can_stream ? "Yes" : "No");
626      fprintf (F, "   rejected: %-7ld  ",      status[j].rejected);
627!     fprintf (F, "        filtered: %-7ld ",  status[j].Unwanted_f);
628      fprintf (F, "  is streaming: %s\n",
629             (status[j].Check || status[j].Takethis) ? "Yes" : "No");
630      fprintf (F, "       size: %-8s ",        PrettySize(status[j].Size, str));
631!     fprintf (F, "       bad sites: %-7ld ", status[j].Unwanted_s);
632!     fprintf (F, "    mismatches: %-7ld\n", status[j].Mismatches);
633      fprintf (F, "  Protocol:\n");
634      fprintf (F, "      Ihave: %-6ld SendIt[%d]: %-6ld    Got[%d]: %-6ld Deferred[%d]: %ld\n",
635             status[j].Ihave, NNTP_SENDIT_VAL, status[j].Ihave_SendIt,
636diff -rbc inn-STABLE_2_2-1999-04-26_03-01/lib/localopen.c inn-2.2-devel/lib/localopen.c
637*** inn-STABLE_2_2-1999-04-26_03-01/lib/localopen.c     Wed Aug  5 06:35:17 1998
638--- inn-2.2-devel/lib/localopen.c       Thu Apr 29 22:37:18 1999
639***************
640*** 23,85 ****
641  int NNTPlocalopen(FILE **FromServerp, FILE **ToServerp, char *errbuff)
642  {
643  #if   defined(HAVE_UNIX_DOMAIN_SOCKETS)
644!     int                       i;
645!     int                       j;
646!     int                       oerrno;
647!     struct sockaddr_un        server;
648!     FILE              *F;
649!     char              mybuff[NNTP_STRLEN + 2];
650!     char              *buff;
651 
652!     buff = errbuff ? errbuff : mybuff;
653!     *buff = '\0';
654!
655!     /* Create a socket. */
656!     if ((i = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
657!       return -1;
658!
659!     /* Connect to the server. */
660!     (void)memset((POINTER)&server, 0, sizeof server);
661!     server.sun_family = AF_UNIX;
662!     (void)strcpy(server.sun_path, innconf->pathrun);
663!     (void)strcat(server.sun_path, "/");
664!     (void)strcat(server.sun_path, _PATH_NNTPCONNECT);
665!     if (connect(i, (struct sockaddr *)&server, AF_UNIX_SOCKSIZE(server)) < 0) {
666!       oerrno = errno;
667!       (void)close(i);
668!       errno = oerrno;
669!       return -1;
670!     }
671!
672!     /* Connected -- now make sure we can post. */
673!     if ((F = fdopen(i, "r")) == NULL) {
674!       oerrno = errno;
675!       (void)close(i);
676!       errno = oerrno;
677!       return -1;
678!     }
679!     if (fgets(buff, sizeof mybuff, F) == NULL) {
680!       oerrno = errno;
681!       (void)fclose(F);
682!       errno = oerrno;
683!       return -1;
684!     }
685!     j = atoi(buff);
686!     if (j != NNTP_POSTOK_VAL && j != NNTP_NOPOSTOK_VAL) {
687!       (void)fclose(F);
688!       /* This seems like a reasonable error code to use... */
689!       errno = EPERM;
690!       return -1;
691!     }
692!
693!     *FromServerp = F;
694!     if ((*ToServerp = fdopen(dup(i), "w")) == NULL) {
695!       oerrno = errno;
696!       (void)fclose(F);
697!       errno = oerrno;
698!       return -1;
699!     }
700!     return 0;
701  #else
702      return NNTPconnect(LOOPBACK_HOST, innconf->port, FromServerp, ToServerp, errbuff);
703  #endif        /* defined(HAVE_UNIX_DOMAIN_SOCKETS) */
704--- 23,34 ----
705  int NNTPlocalopen(FILE **FromServerp, FILE **ToServerp, char *errbuff)
706  {
707  #if   defined(HAVE_UNIX_DOMAIN_SOCKETS)
708!     char                addrbuf[128];
709 
710!     (void)strcpy(addrbuf, innconf->pathrun);
711!     (void)strcat(addrbuf, "/");
712!     (void)strcat(addrbuf, _PATH_NNTPCONNECT);
713!     return NNTPconnect(addrbuf, 0, FromServerp, ToServerp, errbuff);
714  #else
715      return NNTPconnect(LOOPBACK_HOST, innconf->port, FromServerp, ToServerp, errbuff);
716  #endif        /* defined(HAVE_UNIX_DOMAIN_SOCKETS) */
717diff -rbc inn-STABLE_2_2-1999-04-26_03-01/lib/remopen.c inn-2.2-devel/lib/remopen.c
718*** inn-STABLE_2_2-1999-04-26_03-01/lib/remopen.c       Wed Sep  2 16:24:31 1998
719--- inn-2.2-devel/lib/remopen.c Thu Apr 29 22:37:48 1999
720***************
721*** 46,54 ****
722--- 46,86 ----
723      struct hostent    fakehp;
724      struct in_addr    quadaddr;
725      struct sockaddr_in        server, client;
726+ #if defined(HAVE_UNIX_DOMAIN_SOCKETS)
727+     struct sockaddr_un  userver;
728+ #endif
729+     char                *saddr = (char*) &server.sin_addr;
730+     int                 dobind = 0;
731+     struct sockaddr     *pserver = (struct sockaddr *) &server;
732+     int                 socklen = sizeof(server);
733 
734      buff = errbuff ? errbuff : mybuff;
735      *buff = '\0';
736+
737+ #if defined(HAVE_UNIX_DOMAIN_SOCKETS)
738+     if (*host == '/')
739+     {
740+       if (strlen(host) >= sizeof(userver.sun_path))
741+           return -1;
742+
743+       fakehp.h_length = strlen(host)+1;
744+       fakehp.h_addrtype = AF_UNIX;
745+       fakelist[0] = host;
746+       fakelist[1] = NULL;
747+       ap = fakelist;
748+       hp = &fakehp;
749+
750+       /* Set up the socket address. */
751+       (void)memset((POINTER)&userver, 0, sizeof server);
752+       userver.sun_family = hp->h_addrtype;
753+
754+       saddr = userver.sun_path;
755+       pserver = (struct sockaddr *) &userver;
756+       socklen = sizeof(userver);
757+     }
758+     else
759+ #endif
760+     {
761        quadaddr.s_addr = inet_addr(host);
762        if (quadaddr.s_addr != (unsigned int) -1) {
763            /* Host was specified as a dotted-quad internet address.  Fill in
764***************
765*** 83,93 ****
766--- 115,127 ----
767        (void)memset((POINTER)&client, 0, sizeof client);
768        client.sin_family = AF_INET;
769        if (innconf->sourceaddress) {
770+           dobind = 1;
771            client.sin_addr.s_addr = inet_addr(innconf->sourceaddress);
772            if (server.sin_addr.s_addr == INADDR_NONE)
773                return -1;
774        } else
775            client.sin_addr.s_addr = htonl(INADDR_ANY);
776+     }
777   
778      /* Loop through the address list, trying to connect. */
779      for (; ap && *ap; ap++) {
780***************
781*** 95,101 ****
782        if ((i = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
783            break;
784        /* Bind to the source address we want. */
785!       if (bind(i, (struct sockaddr *)&client, sizeof client) < 0) {
786            oerrno = errno;
787            (void)close(i);
788            errno = oerrno;
789--- 129,135 ----
790        if ((i = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
791            break;
792        /* Bind to the source address we want. */
793!       if (dobind && bind(i, (struct sockaddr *)&client, sizeof client) < 0) {
794            oerrno = errno;
795            (void)close(i);
796            errno = oerrno;
797***************
798*** 105,113 ****
799         *      (void)memcpy((POINTER)&server.sin_addr, (POINTER)*ap,
800                        (int)hp->h_length); */
801        p = (char *)*ap;
802!       for (dest = (char *)&server.sin_addr, j = hp->h_length; --j >= 0; )
803            *dest++ = *p++;
804!       if (connect(i, (struct sockaddr *)&server, sizeof server) < 0) {
805            oerrno = errno;
806            (void)close(i);
807            errno = oerrno;
808--- 139,147 ----
809         *      (void)memcpy((POINTER)&server.sin_addr, (POINTER)*ap,
810                        (int)hp->h_length); */
811        p = (char *)*ap;
812!       for (dest = saddr, j = hp->h_length; --j >= 0; )
813            *dest++ = *p++;
814!       if (connect(i, pserver, socklen) < 0) {
815            oerrno = errno;
816            (void)close(i);
817            errno = oerrno;