RFC 864 specifies the chargen service. The RFC recommends a recognizable
pattern, but it was also written at a time when the internet was a
kindler, gentler place. A better recommendation for the modern
internet would be to produce random data.

Diff follows. IMO the code is easier to reason about without the
ring arithmetic. Benchmarking reveals the code is slightly slower now
(8MB/s vs 10MB/s), but I think that's an acceptable tradeoff.

Index: inetd.c
===================================================================
RCS file: /cvs/src/usr.sbin/inetd/inetd.c,v
retrieving revision 1.142
diff -u -p -r1.142 inetd.c
--- inetd.c     29 Oct 2014 03:33:14 -0000      1.142
+++ inetd.c     30 Dec 2014 16:39:09 -0000
@@ -286,7 +286,6 @@ char        *CONFIG = _PATH_INETDCONF;
 
 int            dg_badinput(struct sockaddr *sa);
 void           inetd_setproctitle(char *a, int s);
-void           initring(void);
 u_int32_t      machtime(void);
 
 int
@@ -1507,47 +1506,39 @@ discard_dg(int s, struct servtab *sep)
 
 #include <ctype.h>
 #define LINESIZ 72
-char ring[128];
-char *endring;
+char charset[128];
+int numcharset;
 
 void
-initring(void)
+initcharset(void)
 {
        int i;
+       char *p;
 
-       endring = ring;
-
-       for (i = 0; i <= sizeof ring; ++i)
+       p = charset;
+       for (i = 0; i <= sizeof charset; ++i)
                if (isprint((unsigned char)i))
-                       *endring++ = i;
+                       *p++ = i;
+       numcharset = p - charset;
 }
 
 /* ARGSUSED */
 void
 chargen_stream(int s, struct servtab *sep)
 {
-       char *rs;
-       int len;
        char text[LINESIZ+2];
+       int i;
 
        inetd_setproctitle(sep->se_service, s);
 
-       if (!endring) {
-               initring();
-               rs = ring;
-       }
+       if (!numcharset)
+               initcharset();
 
        text[LINESIZ] = '\r';
        text[LINESIZ + 1] = '\n';
-       for (rs = ring;;) {
-               if ((len = endring - rs) >= LINESIZ)
-                       memmove(text, rs, LINESIZ);
-               else {
-                       memmove(text, rs, len);
-                       memmove(text + len, ring, LINESIZ - len);
-               }
-               if (++rs == endring)
-                       rs = ring;
+       while (1) {
+               for (i = 0; i < LINESIZ; i++)
+                       text[i] = charset[arc4random_uniform(numcharset)];
                if (write(s, text, sizeof(text)) != sizeof(text))
                        break;
        }
@@ -1559,15 +1550,12 @@ void
 chargen_dg(int s, struct servtab *sep)
 {
        struct sockaddr_storage ss;
-       static char *rs;
-       int len;
+       int i;
        socklen_t size;
        char text[LINESIZ+2];
 
-       if (endring == 0) {
-               initring();
-               rs = ring;
-       }
+       if (!numcharset)
+               initcharset();
 
        size = sizeof(ss);
        if (recvfrom(s, text, sizeof(text), 0, (struct sockaddr *)&ss,
@@ -1576,14 +1564,8 @@ chargen_dg(int s, struct servtab *sep)
        if (dg_badinput((struct sockaddr *)&ss))
                return;
 
-       if ((len = endring - rs) >= LINESIZ)
-               memmove(text, rs, LINESIZ);
-       else {
-               memmove(text, rs, len);
-               memmove(text + len, ring, LINESIZ - len);
-       }
-       if (++rs == endring)
-               rs = ring;
+       for (i = 0; i < LINESIZ; i++)
+               text[i] = charset[arc4random_uniform(numcharset)];
        text[LINESIZ] = '\r';
        text[LINESIZ + 1] = '\n';
        (void) sendto(s, text, sizeof(text), 0, (struct sockaddr *)&ss, size);

Reply via email to