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);