3 * Main header file for port forwarder
5 * (c) 1999 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the `fwd' port forwarder.
12 * `fwd' is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * `fwd' is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with `fwd'; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 /*----- Header files ------------------------------------------------------*/
36 /* --- Configuration --- */
62 #include <sys/types.h>
65 #include <sys/resource.h>
69 #include <sys/socket.h>
71 #include <netinet/in.h>
72 #include <arpa/inet.h>
82 #include <mLib/alloc.h>
83 #include <mLib/bres.h>
84 #include <mLib/conn.h>
85 #include <mLib/darray.h>
86 #include <mLib/dstr.h>
88 #include <mLib/fdflags.h>
89 #include <mLib/fdpass.h>
90 #include <mLib/ident.h>
91 #include <mLib/macros.h>
92 #include <mLib/mdup.h>
93 #include <mLib/mdwopt.h>
94 #include <mLib/quis.h>
95 #include <mLib/report.h>
97 #include <mLib/selbuf.h>
100 #include <mLib/sub.h>
101 #include <mLib/sym.h>
104 /*----- Other subtleties --------------------------------------------------*/
106 #if defined(HAVE_DECL_ENVIRON) && !HAVE_DECL_ENVIRON
107 extern char **environ;
110 /*----- Resource limit names ----------------------------------------------*/
112 #if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
113 # define RLIMIT_NOFILE RLIMIT_OFILE
117 ;;; The resource-limit name table is very boring to type and less fun to
118 ;;; maintain. To make life less awful, put the names in this list and
119 ;;; evaluate the code to get Emacs to regenerate it.
121 (let ((limits '(as core cpu data fsize locks memlock msgqueue
122 nice nofile nproc rss rtprio sigpending stack
127 (search-forward (concat "***" "BEGIN rlimitlist" "***"))
128 (beginning-of-line 2)
129 (delete-region (point)
131 (search-forward "***END***")
134 (let ((avail (make-marker))
135 (list (make-marker)))
136 (set-marker avail (point))
137 (insert "#define RLIMITS(_)")
138 (set-marker list (point))
139 (dolist (limit (sort (copy-list limits) #'string<))
140 (let* ((name (symbol-name limit))
141 (constant (concat "RLIMIT_" (upcase name)))
142 (have (concat "HAVE_" constant "_P")))
144 (insert-before-markers (format (concat "#ifdef %s\n"
151 (insert-before-markers
152 (format " \\\n MAYBE_ITEM(_, %s, (%s, %s))"
153 have name constant))))
158 /***BEGIN rlimitlist***/
160 # define HAVE_RLIMIT_AS_P t
162 # define HAVE_RLIMIT_AS_P nil
165 # define HAVE_RLIMIT_CORE_P t
167 # define HAVE_RLIMIT_CORE_P nil
170 # define HAVE_RLIMIT_CPU_P t
172 # define HAVE_RLIMIT_CPU_P nil
175 # define HAVE_RLIMIT_DATA_P t
177 # define HAVE_RLIMIT_DATA_P nil
180 # define HAVE_RLIMIT_FSIZE_P t
182 # define HAVE_RLIMIT_FSIZE_P nil
185 # define HAVE_RLIMIT_LOCKS_P t
187 # define HAVE_RLIMIT_LOCKS_P nil
189 #ifdef RLIMIT_MEMLOCK
190 # define HAVE_RLIMIT_MEMLOCK_P t
192 # define HAVE_RLIMIT_MEMLOCK_P nil
194 #ifdef RLIMIT_MSGQUEUE
195 # define HAVE_RLIMIT_MSGQUEUE_P t
197 # define HAVE_RLIMIT_MSGQUEUE_P nil
200 # define HAVE_RLIMIT_NICE_P t
202 # define HAVE_RLIMIT_NICE_P nil
205 # define HAVE_RLIMIT_NOFILE_P t
207 # define HAVE_RLIMIT_NOFILE_P nil
210 # define HAVE_RLIMIT_NPROC_P t
212 # define HAVE_RLIMIT_NPROC_P nil
215 # define HAVE_RLIMIT_RSS_P t
217 # define HAVE_RLIMIT_RSS_P nil
220 # define HAVE_RLIMIT_RTPRIO_P t
222 # define HAVE_RLIMIT_RTPRIO_P nil
224 #ifdef RLIMIT_SIGPENDING
225 # define HAVE_RLIMIT_SIGPENDING_P t
227 # define HAVE_RLIMIT_SIGPENDING_P nil
230 # define HAVE_RLIMIT_STACK_P t
232 # define HAVE_RLIMIT_STACK_P nil
235 # define HAVE_RLIMIT_VMEM_P t
237 # define HAVE_RLIMIT_VMEM_P nil
240 MAYBE_ITEM(_, HAVE_RLIMIT_AS_P, (as, RLIMIT_AS)) \
241 MAYBE_ITEM(_, HAVE_RLIMIT_CORE_P, (core, RLIMIT_CORE)) \
242 MAYBE_ITEM(_, HAVE_RLIMIT_CPU_P, (cpu, RLIMIT_CPU)) \
243 MAYBE_ITEM(_, HAVE_RLIMIT_DATA_P, (data, RLIMIT_DATA)) \
244 MAYBE_ITEM(_, HAVE_RLIMIT_FSIZE_P, (fsize, RLIMIT_FSIZE)) \
245 MAYBE_ITEM(_, HAVE_RLIMIT_LOCKS_P, (locks, RLIMIT_LOCKS)) \
246 MAYBE_ITEM(_, HAVE_RLIMIT_MEMLOCK_P, (memlock, RLIMIT_MEMLOCK)) \
247 MAYBE_ITEM(_, HAVE_RLIMIT_MSGQUEUE_P, (msgqueue, RLIMIT_MSGQUEUE)) \
248 MAYBE_ITEM(_, HAVE_RLIMIT_NICE_P, (nice, RLIMIT_NICE)) \
249 MAYBE_ITEM(_, HAVE_RLIMIT_NOFILE_P, (nofile, RLIMIT_NOFILE)) \
250 MAYBE_ITEM(_, HAVE_RLIMIT_NPROC_P, (nproc, RLIMIT_NPROC)) \
251 MAYBE_ITEM(_, HAVE_RLIMIT_RSS_P, (rss, RLIMIT_RSS)) \
252 MAYBE_ITEM(_, HAVE_RLIMIT_RTPRIO_P, (rtprio, RLIMIT_RTPRIO)) \
253 MAYBE_ITEM(_, HAVE_RLIMIT_SIGPENDING_P, (sigpending, RLIMIT_SIGPENDING)) \
254 MAYBE_ITEM(_, HAVE_RLIMIT_STACK_P, (stack, RLIMIT_STACK)) \
255 MAYBE_ITEM(_, HAVE_RLIMIT_VMEM_P, (vmem, RLIMIT_VMEM))
258 /* --- The unpleasant conditional-output machinery --- */
260 #define MAYBE_ITEM(_, emitp, args) GLUE(MAYBE_ITEM_, emitp)(_, args)
261 #define MAYBE_ITEM_t(_, args) _ args
262 #define MAYBE_ITEM_nil(_, args)
264 /*----- Main program ------------------------------------------------------*/
266 /* --- The global select state --- */
268 extern sel_state *sel;
270 /* --- Global state flags --- */
272 extern unsigned flags;
278 /* --- Help text --- */
280 extern const char grammar_text[];
281 extern const char option_text[];
283 /* --- Generally useful magic constants --- */
285 #define NOW ((time_t)-1)
287 /* --- @fw_log@ --- *
289 * Arguments: @time_t t@ = when the connection occurred or (@NOW@)
290 * @const char *fmt@ = format string to fill in
291 * @...@ = other arguments
295 * Use: Logs a connection.
298 extern void PRINTF_LIKE(2, 3)
299 fw_log(time_t /*t*/, const char */*fmt*/, ...);
301 /* --- @fw_inc@, @fw_dec@ --- *
307 * Use: Increments or decrements the active thing count. `fwd' won't
308 * quit while there are active things.
311 extern void fw_inc(void);
312 extern void fw_dec(void);
314 /*----- Channel management ------------------------------------------------*/
316 /* --- Magic numbers --- */
318 #define CHAN_BUFSZ 4096
320 /* --- Channel structure --- */
322 typedef struct chan {
323 unsigned base, len; /* Base and length of data */
324 unsigned f; /* Various interesting flags */
325 void (*func)(void */*p*/); /* Function to call on closure */
326 int err; /* What's wrong with the channel */
327 void *p; /* Argument to pass function */
328 sel_file r, w; /* Reader and writer selectors */
329 char buf[CHAN_BUFSZ]; /* The actual data buffer */
332 #define CHANF_CLOSE 1u /* Close channel when buffer empty */
333 #define CHANF_READY 2u /* The channel destination exists */
335 /* --- @chan_close@ --- *
337 * Arguments: @chan *c@ = pointer to channel
341 * Use: Closes down a channel prematurely.
344 extern void chan_close(chan */*c*/);
346 /* --- @chan_dest@ --- *
348 * Arguments: @chan *c@ = pointer to channel
349 * @int fd@ = destination file descriptor for channel
353 * Use: Sets the channel's destination so it knows where to put
357 extern void chan_dest(chan */*c*/, int /*fd*/);
359 /* --- @chan_open@ --- *
361 * Arguments: @chan *c@ = pointer to channel to open
362 * @int from, to@ = source and destination file descriptors
363 * @void (*func)(void *p)@ = function to call on closure
364 * @void *p@ = argument to pass to function
368 * Use: Opens a channel. Data is copied from the source to the
369 * destination. The @to@ argument may be @-1@ if the file
370 * descriptor isn't known yet.
373 extern void chan_open(chan */*c*/, int /*from*/, int /*to*/,
374 void (*/*func*/)(void */*p*/), void */*p*/);
376 /*----- Character scanners ------------------------------------------------*/
378 /* --- A low-level scanner source --- */
380 typedef struct scansrc {
381 struct scansrc *next; /* Next one in the list */
382 struct scansrc_ops *ops; /* Pointer to operations table */
383 char *src; /* Name of this source */
384 int line; /* Current line number */
385 dstr pushback; /* Pushback characters */
386 char *tok; /* Token pushback */
387 unsigned t; /* Token type pushback */
390 /* --- Scanner source operations --- */
392 typedef struct scansrc_ops {
393 int (*scan)(scansrc */*ss*/); /* Read another character */
394 void (*destroy)(scansrc */*ss*/); /* Destroy an unwanted source */
397 /* --- A character scanner --- */
399 typedef struct scanner {
400 scansrc *head, **tail; /* Scanner list head and tail */
401 int t; /* Token type */
402 dstr d; /* Current token value */
403 const char *wbegin, *wcont; /* Parsing exception strings */
406 /* --- @scan_file@ --- *
408 * Arguments: @FILE *fp@ = pointer to file descriptor
409 * @const char *name@ = pointer to source file name
410 * @unsigned f@ = flags
412 * Returns: A scanner source.
414 * Use: Creates a new scanner source for reading from a file.
417 #define SCF_NOCLOSE 1u /* Don't close @fp@ when finished */
419 extern scansrc *scan_file(FILE */*fp*/, const char */*name*/,
422 /* --- @scan_argv@ --- *
424 * Arguments: @char **av@ = pointer to argument array (null terminated)
426 * Returns: A scanner source.
428 * Use: Creates a new scanner source for reading from an @argv@
432 extern scansrc *scan_argv(char **/*av*/);
436 * Arguments: @scanner *sc@ = pointer to main scanner context
438 * Returns: Character read, or end-of-file.
440 * Use: Scans a character from a source of characters.
443 extern int scan(scanner */*sc*/);
445 /* --- @unscan@ --- *
447 * Arguments: @scanner *sc@ = pointer to main scanner context
448 * @int ch@ = character to unscan
452 * Use: Scans a character from a source of characters.
455 extern void unscan(scanner */*sc*/, int /*ch*/);
457 /* --- @scan_push@ --- *
459 * Arguments: @scanner *sc@ = pointer to main scanner context
460 * @scansrc *ss@ = souorce to push
464 * Use: Pushes a scanner source onto the front of the queue.
467 extern void scan_push(scanner */*sc*/, scansrc */*ss*/);
469 /* --- @scan_add@ --- *
471 * Arguments: @scanner *sc@ = pointer to main scanner context
472 * @scansrc *ss@ = souorce to push
476 * Use: Adds a scanner source onto the end of the queue.
479 extern void scan_add(scanner */*sc*/, scansrc */*ss*/);
481 /* --- @scan_create@ --- *
483 * Arguments: @scanner *sc@ = scanner context to initialize
487 * Use: Initializes a scanner block ready for use.
490 extern void scan_create(scanner */*sc*/);
492 /* --- @scan_destroy@ --- *
494 * Arguments: @scanner *sc@ = pointer to scanner context
498 * Use: Destroys a scanner and all the sources attached to it.
501 extern void scan_destroy(scanner */*sc*/);
503 /*----- Configuration parsing ---------------------------------------------*/
505 /* --- Magical constants --- */
507 #define CTOK_EOF (-1)
508 #define CTOK_WORD 256
510 /* --- @conf_undelim@ --- *
512 * Arguments: @scanner *sc@ = pointer to scanner definition
513 * @const char *d, *dd@ = pointer to characters to escape
517 * Use: Modifies the tokenizer. Characters in the first list will
518 * always be considered to begin a word. Characters in the
519 * second list will always be allowed to continue a word.
522 extern void conf_undelim(scanner */*sc*/,
523 const char */*d*/, const char */*dd*/);
527 * Arguments: @scanner *sc@ = pointer to scanner definition
529 * Returns: Type of token scanned.
531 * Use: Reads the next token from the character scanner.
534 extern int token(scanner */*sc*/);
538 * Arguments: @scanner *sc@ = pointer to scanner definition
539 * @const char *msg@ = message skeleton string
540 * @...@ = extra arguments for the skeleton
544 * Use: Reports an error at the current scanner location.
547 extern void PRINTF_LIKE(2, 3) NORETURN
548 error(scanner */*sc*/, const char */*msg*/, ...);
550 /* --- @pushback@ --- *
552 * Arguments: @scanner *sc@ = pointer to scanner definition
556 * Use: Pushes the current token back. This is normally a precursor
557 * to pushing a new scanner source.
560 extern void pushback(scanner */*sc*/);
562 /* --- @conf_enum@ --- *
564 * Arguments: @scanner *sc@ = pointer to a scanner object
565 * @const char *list@ = comma-separated things to allow
566 * @unsigned @f = flags for the search
567 * @const char *err@ = error message if not found
569 * Returns: Index into list, zero-based, or @-1@.
571 * Use: Checks whether the current token is a string which matches
572 * one of the comma-separated items given. The return value is
573 * the index (zero-based) of the matched string in the list.
575 * The flags control the behaviour if no exact match is found.
576 * If @ENUM_ABBREV@ is set, and the current token is a left
577 * substring of exactly one of the possibilities, then that one
578 * is chosen. If @ENUM_NONE@ is set, the value @-1@ is
579 * returned; otherwise an error is reported and the program is
583 #define ENUM_ABBREV 1u
586 extern int conf_enum(scanner */*sc*/, const char */*list*/,
587 unsigned /*flags*/, const char */*err*/);
589 /* --- @conf_prefix@ --- *
591 * Arguments: @scanner *sc@ = pointer to a scanner object
592 * @const char *p@ = pointer to prefix string to check
594 * Returns: Nonzero if the prefix matches.
596 * Use: If the current token is a word matching the given prefix
597 * string, then it and an optional `.' character are removed and
598 * a nonzero result is returned. Otherwise the current token is
599 * left as it is, and zero is returned.
601 * Typical options parsing code would remove an expected prefix,
602 * scan an option anyway (since qualifying prefixes are
603 * optional) and if a match is found, claim the option. If no
604 * match is found, and a prefix was stripped, then an error
605 * should be reported.
608 extern int conf_prefix(scanner */*sc*/, const char */*p*/);
610 /* --- @CONF_BEGIN@, @CONF_END@ --- *
612 * Arguments: @sc@ = scanner to read from
613 * @prefix@ = prefix to scan for
614 * @desc@ = description of what we're parsing
616 * Use: Bracket an options parsing routine. The current token is
617 * checked to see whether it matches the prefix. If so, it is
618 * removed and the following token examined. If that's a `.'
619 * then it's removed. If it's a `{' then the enclosed
620 * option-parsing code is executed in a loop until a matching
621 * '}' is found. If the options parser doesn't accept an
622 * option, the behaviour is dependent on whether a prefix was
623 * seen: if so, an error is reported; otherwse a zero return is
632 #define CONF_BEGIN(sc, prefix, desc) do { \
633 scanner *_conf_sc = (sc); \
634 const char *_conf_desc = (desc); \
635 int _conf_state = CS_PLAIN; \
637 /* --- Read the initial prefix --- */ \
639 if (_conf_sc->t == CTOK_WORD && \
640 strcmp(_conf_sc->d.buf, (prefix)) == 0) { \
642 _conf_state = CS_PREFIX; \
643 if (_conf_sc->t == '.') \
645 else if (_conf_sc->t == '{') { \
647 _conf_state = CS_BRACE; \
651 /* --- Ensure the next token is a word --- */ \
653 if (_conf_sc->t != CTOK_WORD) \
654 error(_conf_sc, "parse error, expected option keyword"); \
659 /* --- Reject an option --- * \
661 * We could get here as a result of an explicit @CONF_REJECT@ or \
662 * because the option wasn't accepted. \
667 if (_conf_state == CS_PLAIN) \
668 _conf_state = CS_UNKNOWN; \
670 error(_conf_sc, "unknown %s option `%s'", \
671 _conf_desc, _conf_sc->d.buf); \
674 /* --- Accept an option --- * \
676 * It's safe to drop through from above. Either an error will have \
677 * been reported, or the state is not @CS_BRACE@. \
681 if (_conf_state == CS_BRACE && _conf_sc->t == ';') \
683 } while (_conf_state == CS_BRACE && _conf_sc->t == CTOK_WORD); \
685 /* --- Check for a closing brace --- */ \
687 if (_conf_state == CS_BRACE) { \
688 if (_conf_sc->t == '}') \
691 error(_conf_sc, "parse error, expected `}'"); \
694 /* --- Return an appropriate value --- */ \
696 return (_conf_state != CS_UNKNOWN); \
699 /* --- @CONF_ACCEPT@, @CONF_REJECT@ --- *
703 * Use: Within an options parser (between @CONF_BEGIN@ and
704 * @CONF_END@), accept or reject an option.
707 #define CONF_ACCEPT goto _conf_accept
708 #define CONF_REJECT goto _conf_reject
710 /* --- @CONF_QUAL@ --- *
714 * Use: Evaluates to a nonzero value if the current option is
715 * qualified. This can be used to decide whether abbreviations
716 * for options should be accepted.
719 #define CONF_QUAL (_conf_state != CS_PLAIN)
721 /* --- @conf_name@ --- *
723 * Arguments: @scanner *sc@ = pointer to scanner
724 * @char delim@ = delimiter character to look for
725 * @dstr *d@ = pointer to dynamic string for output
729 * Use: Reads in a compound name consisting of words separated by
730 * delimiters. Leading and trailing delimiters are permitted,
731 * although they'll probably cause confusion if used. The name
732 * may be enclosed in square brackets if that helps at all.
734 * Examples of compound names are filenames (delimited by `/')
735 * and IP addresses (delimited by `.').
738 extern void conf_name(scanner */*sc*/, char /*delim*/, dstr */*d*/);
740 /* --- @conf_fname@ --- *
742 * Arguments: @scanner *sc@ = pointer to scanner
743 * @dstr *d@ = pointer to dynamic string for output
747 * Use: Reads a file name from the input and stores it in @d@.
750 extern void conf_fname(scanner */*sc*/, dstr */*d*/);
752 /*----- Reference-counted file descriptors --------------------------------*/
754 typedef struct reffd {
757 void (*proc)(void */*p*/);
761 /* --- @reffd_init@ --- *
763 * Arguments: @int fd@ = file descriptor
765 * Returns: Reference-counted file descriptor object.
767 * Use: Creates a refcounted file descriptor.
770 extern reffd *reffd_init(int /*fd*/);
772 /* --- @reffd_handler@ --- *
774 * Arguments: @reffd *r@ = pointer to reference counted filehandle
775 * @void (*proc)(void *p)@ = procedure to call
780 * Use: Sets the reference counted file descriptor to call @proc@
781 * when it is no longer required.
784 extern void reffd_handler(reffd */*r*/, void (*/*proc*/)(void */*p*/),
787 /* --- @reffd_inc@ --- *
789 * Arguments: @reffd *r@ = pointer to reference counted filehandle
793 * Use: Increments the reference count for a file descriptor.
796 #define REFFD_INC(r) do { (r)->ref++; } while (0)
798 extern void reffd_inc(reffd */*r*/);
800 /* --- @reffd_dec@ --- *
802 * Arguments: @reffd *r@ = pointer to reference counted filehandle
806 * Use: Decrements the reference count for a file descriptor.
809 #define REFFD_DEC(r) do { \
812 if (_r->ref == 0) { \
820 extern void reffd_dec(reffd */*r*/);
822 /*----- Sources, targets and endpoints ------------------------------------*/
824 /* --- Basic endpoint structure --- */
826 typedef struct endpt {
827 struct endpt_ops *ops; /* Pointer to operations table */
828 struct endpt *other; /* Pointer to sibling endpoint */
829 unsigned f; /* Various flags */
830 struct tango *t; /* Private data structure */
831 reffd *in, *out; /* File descriptors */
834 /* --- Endpoint flags --- */
836 #define EPF_PENDING 1u /* Endpoint creation in progress */
837 #define EPF_FILE 2u /* Endpoint smells like a file */
839 /* --- Endpoint operations table --- */
841 typedef struct endpt_ops {
843 /* --- @attach@ --- *
845 * Arguments: @endpt *e@ = pointer to endpoint to be attached
846 * @reffd *in, *out@ = input and output file descriptors
850 * Use: Instructs a non-file endpoint to attach itself to a pair of
854 void (*attach)(endpt */*e*/, reffd */*in*/, reffd */*out*/);
858 * Arguments: @endpt *e@ = pointer to endpoint in question
859 * @endpt *f@ = pointer to a file endpoint
863 * Use: Informs a non-file endpoint of a file endpoint which will
864 * want to be closed when it's finished with. At that time, the
865 * endpoint should arrange to have both itself and its partner
866 * closed. If no file is registered, the endpoint manager will
867 * close both endpoints itself.
870 void (*file)(endpt */*e*/, endpt */*f*/);
872 /* --- @wclose@ --- *
874 * Arguments: @endpt *e@ = endpoint to be partially closed
878 * Use: Announces that the endpoint will not be written to any more.
881 void (*wclose)(endpt */*e*/);
885 * Arguments: @endpt *e@ = endpoint to be closed
889 * Use: Completely closes an endpoint. The endpoint's data may be
890 * freed, although some endpoints may wish to delay freeing for
894 void (*close)(endpt */*e*/);
898 /* --- A basic target object --- */
900 typedef struct target {
901 struct target_ops *ops;
906 /* --- Forwarding target operations --- */
908 typedef struct target_ops {
909 const char *name; /* Name of this target */
911 /* --- @option@ --- *
913 * Arguments: @target *t@ = pointer to target object, or zero if global
914 * @scanner *sc@ = scanner to read from
916 * Returns: Nonzero to claim the option.
918 * Use: Handles an option string from the configuration file.
921 int (*option)(target */*t*/, scanner */*sc*/);
925 * Arguments: @scanner *sc@ = pointer to scanner to read from
927 * Returns: Pointer to a target object to claim, null to reject.
929 * Use: Parses a target description from the configuration file.
930 * Only the socket target is allowed to omit the prefix on a
931 * target specification.
934 target *(*read)(scanner */*sc*/);
936 /* --- @confirm@ --- *
938 * Arguments: @target *t@ = pointer to target
942 * Use: Confirms configuration of a target.
945 void (*confirm)(target */*t*/);
947 /* --- @create@ --- *
949 * Arguments: @target *t@ = pointer to target
950 * @const char *desc@ = description of connection
952 * Returns: Pointer to a created endpoint.
954 * Use: Generates a target endpoint for communication.
957 endpt *(*create)(target */*t*/, const char */*desc*/);
959 /* --- @destroy@ --- *
961 * Arguments: @target *t@ = pointer to target
965 * Use: Destroys a target.
968 void (*destroy)(target */*t*/);
972 /* --- A basic source object --- */
974 typedef struct source {
975 struct source *next, *prev;
976 struct source_ops *ops;
984 /* --- Forwarding source operations --- */
986 typedef struct source_ops {
987 const char *name; /* Name of this source */
989 /* --- @option@ --- *
991 * Arguments: @scanner *sc@ = scanner to read from
992 * @source *s@ = pointer to source object, or zero if global
994 * Returns: Nonzero to claim the option.
996 * Use: Handles an option string from the configuration file.
999 int (*option)(source */*s*/, scanner */*sc*/);
1003 * Arguments: @scanner *sc@ = pointer to scanner to read from
1005 * Returns: Pointer to a source object to claim, null to reject.
1007 * Use: Parses a source description from the configuration file.
1008 * Only the socket source is allowed to omit the prefix on a
1009 * source specification.
1012 source *(*read)(scanner */*sc*/);
1014 /* --- @attach@ --- *
1016 * Arguments: @source *s@ = pointer to source
1017 * @scanner *sc@ = scanner (for error reporting)
1018 * @target *t@ = pointer to target to attach
1022 * Use: Attaches a target to a source.
1025 void (*attach)(source */*s*/, scanner */*sc*/, target */*t*/);
1027 /* --- @shutdown@ --- *
1029 * Arguments: @source *s@ = pointer to source
1033 * Use: Deactivates the source so that it won't produce any more
1037 void (*shutdown)(source */*s*/);
1039 /* --- @destroy@ --- *
1041 * Arguments: @source *s@ = pointer to source
1045 * Use: Destroys a source. Used when closing the system down, for
1046 * example as a result of a signal.
1049 void (*destroy)(source */*s*/);
1053 /* --- @endpt_kill@ --- *
1055 * Arguments: @endpt *a@ = an endpoint
1059 * Use: Kills an endpoint. If the endpoint is joined to another, the
1060 * other endpoint is also killed, as is the connection between
1061 * them (and that's the tricky bit).
1064 extern void endpt_kill(endpt */*a*/);
1066 /* --- @endpt_killall@ --- *
1072 * Use: Destroys all current endpoint connections. Used when
1076 extern void endpt_killall(void);
1078 /* --- @endpt_join@ --- *
1080 * Arguments: @endpt *a@ = pointer to first endpoint
1081 * @endpt *b@ = pointer to second endpoint
1082 * @const char *desc@ = description of connection
1086 * Use: Joins two endpoints together. It's OK to join endpoints
1087 * which are already joined; in fact, the the right thing to do
1088 * when your endpoint decides that it's not pending any more is
1089 * to join it to its partner again.
1091 * If the endpoints are already connected then the description
1092 * string is ignored. The endpoint manager takes a copy of
1093 * the string, so you don't need to keep it around.
1096 extern void endpt_join(endpt */*a*/, endpt */*b*/, const char */*desc*/);
1098 /* --- @target_inc@ --- *
1100 * Arguments: @target *t@ = pointer to a source
1104 * Use: Increments a target's refcount.
1107 extern void target_inc(target */*t*/);
1109 /* --- @target_dec@ --- *
1111 * Arguments: @target *t@ = pointer to a target
1115 * Use: Decrements a target's refcount, destroying it if necessary.
1118 extern void target_dec(target */*t*/);
1120 /* --- @source_add@ --- *
1122 * Arguments: @source *s@ = pointer to a source
1126 * Use: Adds a source to the master list. Only do this for passive
1127 * sources (e.g., listening sockets), not active sources (e.g.,
1128 * executable programs).
1131 extern void source_add(source */*s*/);
1133 /* --- @source_remove@ --- *
1135 * Arguments: @source *s@ = pointer to a source
1139 * Use: Removes a source from the master list.
1142 extern void source_remove(source */*s*/);
1144 /* --- @source_inc@ --- *
1146 * Arguments: @source *s@ = pointer to a source
1150 * Use: Increments a source's refcount.
1153 extern void source_inc(source */*s*/);
1155 /* --- @source_dec@ --- *
1157 * Arguments: @source *s@ = pointer to a source
1161 * Use: Decrements a source's refcount, destroying it if necessary.
1164 extern void source_dec(source */*s*/);
1166 /* --- @source_killall@ --- *
1172 * Use: Frees all sources.
1175 extern void source_killall(void);
1177 /*----- The exec source and target ----------------------------------------*/
1179 extern source_ops xsource_ops;
1180 extern target_ops xtarget_ops;
1182 /* --- @exec_init@ --- *
1188 * Use: Initializes the executable problem source and target.
1191 extern void exec_init(void);
1193 /*----- The file source and target ----------------------------------------*/
1195 extern source_ops fsource_ops;
1196 extern target_ops ftarget_ops;
1198 /*----- The socket source and target --------------------------------------*/
1200 extern source_ops ssource_ops;
1201 extern target_ops starget_ops;
1203 /* --- @starget_connected@ --- *
1205 * Arguments: @int fd@ = file descriptor now ready for use
1206 * @void *p@ = pointer to an endpoint structure
1210 * Use: Handles successful connection of the target endpoint.
1213 extern void starget_connected(int /*fd*/, void */*p*/);
1215 /*----- Handling of file attributes ---------------------------------------*/
1217 /* --- File attribute options structure --- */
1219 typedef struct fattr {
1225 /* --- Shared global options --- */
1227 extern fattr fattr_global;
1229 /* --- @fattr_init@ --- *
1231 * Arguments: @fattr *f@ = pointer to file attributes
1235 * Use: Initializes a set of file attributes to default values.
1238 extern void fattr_init(fattr */*f*/);
1240 /* --- @fattr_option@ --- *
1242 * Arguments: @scanner *sc@ = pointer to scanner to read
1243 * @fattr *f@ = pointer to file attributes to set
1245 * Returns: Whether the option was clamed.
1247 * Use: Reads file attributes from a scanner.
1250 extern int fattr_option(scanner */*sc*/, fattr */*f*/);
1252 /* --- @fattr_apply@ --- *
1254 * Arguments: @const char *file@ = pointer to filename
1255 * @fattr *f@ = pointer to attribute set
1257 * Returns: @-1@ if it failed.
1259 * Use: Applies file attributes to a file. For best results, try to
1260 * create the file with the right permissions and so on. This
1261 * call will fix everything up, but there are potential races
1262 * which might catch you out if you're not careful.
1265 extern int fattr_apply(const char */*file*/, fattr */*f*/);
1267 /*----- Making privileged connections -------------------------------------*/
1269 /* --- @privconn_split@ --- *
1271 * Arguments: @sel_state *s@ = select state
1275 * Use: Splits off the privileged binding code into a separate
1279 extern void privconn_split(sel_state */*s*/);
1281 /* --- @privconn_adddest@ --- *
1283 * Arguments: @struct in_addr peer@ = address to connect to
1284 * @unsigned port@ = port to connect to
1286 * Returns: Index for this destination address, or @-1@ if not
1289 * Use: Adds a valid destination for a privileged connection.
1292 extern int privconn_adddest(struct in_addr /*peer*/, unsigned /*port*/);
1294 /* --- @privconn_connect@ --- *
1296 * Arguments: @conn *c@ = connection structure to fill in
1297 * @sel_state *s@ = pointer to select state to attach to
1298 * @int i@ = address index to connect to
1299 * @struct in_addr bind@ = address to bind to
1300 * @void (*func)(int, void *)@ = function to call on connect
1301 * @void *p@ = argument for the function
1303 * Returns: Zero on success, @-1@ on failure.
1305 * Use: Sets up a privileged connection job.
1308 extern int privconn_connect(conn */*c*/, sel_state */*s*/,
1309 int /*i*/, struct in_addr /*bind*/,
1310 void (*/*func*/)(int, void *), void */*p*/);
1312 /*----- Identifying remote clients ----------------------------------------*/
1314 typedef struct id_req {
1315 struct sockaddr_in lsin; /* Local address of connection */
1316 struct sockaddr_in rsin; /* Remote address of connection */
1317 const char *desc; /* Description of connection */
1318 const char *act; /* Action taken by server */
1319 reffd *r; /* Pointer to file descriptor */
1322 /* --- @identify@ --- *
1324 * Arguments: @const id_req *q@ = pointer to request block
1328 * Use: Starts a background ident lookup and reverse-resolve job
1329 * which will, eventually, report a message to the system log.
1332 extern void identify(const id_req */*q*/);
1334 /*----- Host-based access control -----------------------------------------*/
1336 /* --- An access control entry --- */
1338 typedef struct acl_entry {
1339 struct acl_entry *next; /* Next entry in the list */
1340 const struct acl_ops *ops; /* Operations for the ACL entry */
1341 unsigned act; /* What to do with matching hosts */
1344 #define ACL_DENY 0 /* Deny access to matching conns */
1345 #define ACL_ALLOW 1 /* Allow access to matching conns */
1346 #define ACL_PERM 1u /* Bit mask for permission bit */
1348 /* --- Host-based access control --- */
1350 typedef struct acl_host {
1351 acl_entry a; /* Base structure */
1352 struct in_addr addr, mask; /* Address and netmask */
1355 /* --- ACL methods --- */
1357 typedef struct acl_ops {
1358 int (*check)(void */*a*/, struct in_addr /*addr*/, unsigned /*port*/);
1359 void (*dump)(void */*a*/, FILE */*fp*/);
1360 void (*free)(void */*a*/);
1363 /* --- @acl_check@ --- *
1365 * Arguments: @acl_entry *a@ = pointer to ACL to check against
1366 * @struct in_addr addr@ = address to check
1367 * @unsigned port@ = port number to check
1368 * @int *act@ = verdict (should initially be @ACT_ALLOW@)
1370 * Returns: Zero if undecided, nonzero if a rule matched.
1372 * Use: Checks an address against an ACL.
1375 extern int acl_check(acl_entry */*a*/,
1376 struct in_addr /*addr*/, unsigned /*port*/,
1379 /* --- @acl_dump@ --- *
1381 * Arguments: @acl_entry *a@ = pointer to ACL to dump
1382 * @FILE *fp@ = pointer to stream to dump on
1386 * Use: Dumps an access control list to an output stream.
1389 extern void acl_dump(acl_entry */*a*/, FILE */*fp*/);
1391 /* --- @acl_free@ --- *
1393 * Arguments: @acl_entry *a@ = pointer to a list of ACLs
1397 * Use: Frees all of the memory used by an ACL.
1400 extern void acl_free(acl_entry */*a*/);
1402 /* --- @acl_addhost@ --- *
1404 * Arguments: @acl_entry ***a@ = address of pointer to list tail
1405 * @unsigned act@ = what to do with matching addresses
1406 * @struct in_addr addr, mask@ = address and mask to match
1410 * Use: Adds a host-authentication entry to the end of an access
1414 extern void acl_addhost(acl_entry ***/*a*/, unsigned /*act*/,
1415 struct in_addr /*addr*/, struct in_addr /*mask*/);
1417 /* --- @acl_addpriv@ --- *
1419 * Arguments: @acl_entry ***a@ = address of pointer to list tail
1420 * @unsigned act@ = what to do with matching addresses
1424 * Use: Adds a privileged-port check to the end of an access control
1428 extern void acl_addpriv(acl_entry ***/*a*/, unsigned /*act*/);
1430 /*----- Network addresses -------------------------------------------------*/
1432 /* --- A generic socket address --- *
1434 * Not all systems understand @sa_len@ fields. (In particular, Linux
1435 * doesn't.) Some fairly ugly hacking is then performed on particular
1439 typedef struct addr {
1440 struct addr_ops *ops;
1444 #define ADDRSZ(sz) (sizeof(addr) + (sz))
1446 /* --- Address configuration --- *
1448 * An address family will want to extend this.
1451 typedef struct addr_opts {
1455 #define ADDRF_NOLOG 1u
1457 /* --- Address types --- *
1459 * For things like Internet addresses, source and destinations look
1469 /* --- Description of an address type handler --- */
1471 typedef struct addr_ops {
1472 const char *name; /* Protocol's internal name */
1476 * Arguments: @scanner *sc@ = pointer to scanner to read from
1477 * @unsigned type@ = type of address to be read
1479 * Returns: A filled-in socket address.
1481 * Use: Parses a textual representation of a socket address.
1484 addr *(*read)(scanner */*sc*/, unsigned /*type*/);
1486 /* --- @destroy@ --- *
1488 * Arguments: @addr *a@ = pointer to an address block
1492 * Use: Disposes of an address block in some suitable fashion.
1495 void (*destroy)(addr */*a*/);
1497 /* --- @print@ --- *
1499 * Arguments: @addr *a@ = pointer to socket address to read
1500 * @unsigned type@ = type of address to be written
1501 * @dstr *d@ = string on which to write the description
1505 * Use: Writes a textual representation of a socket address to
1509 void (*print)(addr */*a*/, unsigned /*type*/, dstr */*d*/);
1511 /* --- @initsrcopts@ --- *
1515 * Returns: A pointer to a protocol-specific data block for a listener
1517 * Use: Creates a data block for a listener. This is attached to the
1518 * listener data structure. Options can then be requested, and
1519 * are added to the block when necessary.
1522 addr_opts *(*initsrcopts)(void);
1524 /* --- @option@ --- *
1526 * Arguments: @scanner *sc@ = pointer to a scanner to read from
1527 * @unsigned type@ = kind of option this is
1528 * @addr_opts *ao@ = data block to modify (from @init@), or null
1530 * Returns: Nonzero to claim the option.
1532 * Use: Parses a source option, either global or listener-specific.
1535 int (*option)(scanner */*sc*/, addr_opts */*ao*/, unsigned /*type*/);
1537 /* --- @confirm@ --- *
1539 * Arguments: @addr *a@ = pointer to an address structure
1540 * @unsigned type@ = kind of address this is
1541 * @addr_opts *ao@ = address options
1545 * Use: Called during initialization when an address is fully
1549 void (*confirm)(addr */*a*/, unsigned /*type*/, addr_opts */*ao*/);
1551 /* --- @freesrcopts@ --- *
1553 * Arguments: @addr_opts *ao@ = data block to remove
1557 * Use: Throws away all the configuration data for an address type.
1560 void (*freesrcopts)(addr_opts */*ao*/);
1564 * Arguments: @addr *a@ = the address to bind to
1565 * @addr_opts *ao@ = the address options
1567 * Returns: File descriptor of bound socket if OK, or @-1@ on error.
1569 * Use: Binds a listening socket. The tedious stuff with @listen@
1573 int (*bind)(addr */*a*/, addr_opts */*ao*/);
1575 /* --- @unbind@ --- *
1577 * Arguments: @addr *a@ = pointer to an address
1581 * Use: Unbinds an address. This is used when tidying up. The main
1582 * purpose is to let the Unix-domain handler remove its socket
1583 * node from the filesystem.
1586 void (*unbind)(addr */*a*/);
1588 /* --- @accept@ --- *
1590 * Arguments: @int fd@ = listening file descriptor
1591 * @addr_opts *ao@ = data block to get configuration from
1592 * @const char *desc@ = description of the listener
1594 * Returns: Pointer to a reference counted file descriptor.
1596 * Use: Accepts, verifies and logs an incoming connection.
1599 reffd *(*accept)(int /*fd*/, addr_opts */*ao*/, const char */*desc*/);
1601 /* --- @inittargopts@ --- *
1605 * Returns: A pointer to a protocol-specific data block for a connecter
1607 * Use: Creates a data block for a target. This is attached to the
1608 * target data structure. Options can then be requested, and
1609 * are added to the block when necessary.
1612 addr_opts *(*inittargopts)(void);
1614 /* --- @freetargopts@ --- *
1616 * Arguments: @addr_opts *ao@ = data block to remove
1620 * Use: Throws away all the configuration data for an address type.
1623 void (*freetargopts)(addr_opts */*ao*/);
1625 /* --- @connect@ --- *
1627 * Arguments: @addr *a@ = destination address
1628 * @addr_opts *ao@ = target address options
1629 * @conn *c@ = connection structure
1630 * @endpt *e@ = endpoint structure
1632 * Returns: Zero if OK, @-1@ on some error.
1634 * Use: Requests that a connection be made, or at least set in
1635 * motion. An address may do one of these things:
1639 * * Call @starget_connected@ with @-1@ or a connected file
1640 * descriptor and the pointer @e@.
1642 * * Call @conn_init@ or @conn_fd@, giving @starget_connected@
1643 * and @e@ as the function to call.
1646 int (*connect)(addr */*a*/, addr_opts */*ao*/, conn */*c*/, endpt */*e*/);
1650 /* --- Address types --- */
1652 extern addr_ops un_ops;
1653 extern addr_ops inet_ops;
1655 /*----- That's all, folks -------------------------------------------------*/