Postfix3.3.1
全て データ構造 ファイル 関数 変数 型定義 マクロ定義
dsn_filter.c
[詳解]
1 /*++
2 /* NAME
3 /* dsn_filter 3
4 /* SUMMARY
5 /* filter delivery status code or text
6 /* SYNOPSIS
7 /* #include <dsn_filter.h>
8 /*
9 /* DSN_FILTER *dsn_filter_create(
10 /* const char *title,
11 /* const char *map_names)
12 /*
13 /* DSN *dsn_filter_lookup(
14 /* DSN_FILTER *fp,
15 /* DSN *dsn)
16 /*
17 /* void dsn_filter_free(
18 /* DSN_FILTER *fp)
19 /* DESCRIPTION
20 /* This module maps (bounce or defer non-delivery status code
21 /* and text) into replacement (bounce or defer non-delivery
22 /* status code and text), or maps (success status code and
23 /* text) into replacement (success status code and text). Other
24 /* DSN attributes are passed through without modification.
25 /*
26 /* dsn_filter_create() instantiates a delivery status filter.
27 /*
28 /* dsn_filter_lookup() queries the specified filter. The input
29 /* DSN must be a success, bounce or defer DSN. If a match is
30 /* found a non-delivery status must map to a non-delivery
31 /* status, a success status must map to a success status, and
32 /* the text must be non-empty. The result is a null pointer
33 /* when no valid match is found. Otherwise, the result is
34 /* overwritten upon each call. This function must not be
35 /* called with the result from a dsn_filter_lookup() call.
36 /*
37 /* dsn_filter_free() destroys the specified delivery status
38 /* filter.
39 /*
40 /* Arguments:
41 /* .IP title
42 /* Origin of the mapnames argument, typically a configuration
43 /* parameter name. This is reported in diagnostics.
44 /* .IP mapnames
45 /* List of lookup tables, separated by whitespace or comma.
46 /* .IP fp
47 /* filter created with dsn_filter_create()
48 /* .IP dsn
49 /* A success, bounce or defer DSN data structure. The
50 /* dsn_filter_lookup() result value is in part a shallow copy
51 /* of this argument.
52 /* SEE ALSO
53 /* maps(3) multi-table search
54 /* DIAGNOSTICS
55 /* Panic: invalid dsn argument; recursive call. Fatal error:
56 /* memory allocation problem. Warning: invalid DSN lookup
57 /* result.
58 /* LICENSE
59 /* .ad
60 /* .fi
61 /* The Secure Mailer license must be distributed with this software.
62 /* AUTHOR(S)
63 /* Wietse Venema
64 /* IBM T.J. Watson Research
65 /* P.O. Box 704
66 /* Yorktown Heights, NY 10598, USA
67 /*--*/
68 
69  /*
70  * System libraries.
71  */
72 #include <sys_defs.h>
73 
74  /*
75  * Utility library.
76  */
77 #include <msg.h>
78 #include <mymalloc.h>
79 #include <vstring.h>
80 
81  /*
82  * Global library.
83  */
84 #include <maps.h>
85 #include <dsn.h>
86 #include <dsn_util.h>
87 #include <maps.h>
88 #include <dsn_filter.h>
89 
90  /*
91  * Private data structure.
92  */
93 struct DSN_FILTER {
94  MAPS *maps; /* Replacement (status, text) */
95  VSTRING *buffer; /* Status code and text */
96  DSN_SPLIT dp; /* Parsing aid */
97  DSN dsn; /* Shallow copy */
98 };
99 
100  /*
101  * SLMs.
102  */
103 #define STR(x) vstring_str(x)
104 
105 /* dsn_filter_create - create delivery status filter */
106 
107 DSN_FILTER *dsn_filter_create(const char *title, const char *map_names)
108 {
109  static const char myname[] = "dsn_filter_create";
110  DSN_FILTER *fp;
111 
112  if (msg_verbose)
113  msg_info("%s: %s %s", myname, title, map_names);
114 
115  fp = (DSN_FILTER *) mymalloc(sizeof(*fp));
116  fp->buffer = vstring_alloc(100);
117  fp->maps = maps_create(title, map_names, DICT_FLAG_LOCK);
118  return (fp);
119 }
120 
121 /* dsn_filter_lookup - apply delivery status filter */
122 
124 {
125  static const char myname[] = "dsn_filter_lookup";
126  const char *result;
127  int ndr_dsn = 0;
128 
129  if (msg_verbose)
130  msg_info("%s: %s %s", myname, dsn->status, dsn->reason);
131 
132  /*
133  * XXX Instead of hard-coded '4' etc., use some form of encapsulation
134  * when reading or updating the status class field.
135  */
136 #define IS_SUCCESS_DSN(s) (dsn_valid(s) && (s)[0] == '2')
137 #define IS_NDR_DSN(s) (dsn_valid(s) && ((s)[0] == '4' || (s)[0] == '5'))
138 
139  /*
140  * Sanity check. We filter only success/bounce/defer DSNs.
141  */
142  if (IS_SUCCESS_DSN(dsn->status))
143  ndr_dsn = 0;
144  else if (IS_NDR_DSN(dsn->status))
145  ndr_dsn = 1;
146  else
147  msg_panic("%s: dsn argument with bad status code: %s",
148  myname, dsn->status);
149 
150  /*
151  * Sanity check. A delivery status filter must not be invoked with its
152  * own result.
153  */
154  if (dsn->reason == fp->dsn.reason)
155  msg_panic("%s: recursive call is not allowed", myname);
156 
157  /*
158  * Look up replacement status and text.
159  */
160  vstring_sprintf(fp->buffer, "%s %s", dsn->status, dsn->reason);
161  if ((result = maps_find(fp->maps, STR(fp->buffer), 0)) != 0) {
162  /* Sanity check. Do not allow success<=>error mappings. */
163  if ((ndr_dsn == 0 && !IS_SUCCESS_DSN(result))
164  || (ndr_dsn != 0 && !IS_NDR_DSN(result))) {
165  msg_warn("%s: bad status code: %s", fp->maps->title, result);
166  return (0);
167  } else {
168  vstring_strcpy(fp->buffer, result);
169  dsn_split(&fp->dp, "can't happen", STR(fp->buffer));
170  (void) DSN_ASSIGN(&fp->dsn, DSN_STATUS(fp->dp.dsn),
171  (result[0] == '4' ? "delayed" :
172  result[0] == '5' ? "failed" :
173  dsn->action),
174  fp->dp.text, dsn->dtype, dsn->dtext,
175  dsn->mtype, dsn->mname);
176  return (&fp->dsn);
177  }
178  }
179  return (0);
180 }
181 
182 /* dsn_filter_free - destroy delivery status filter */
183 
185 {
186  static const char myname[] = "dsn_filter_free";
187 
188  if (msg_verbose)
189  msg_info("%s: %s", myname, fp->maps->title);
190 
191  maps_free(fp->maps);
192  vstring_free(fp->buffer);
193  myfree((void *) fp);
194 }
int msg_verbose
Definition: msg.c:177
#define STR(x)
Definition: dsn_filter.c:103
void myfree(void *ptr)
Definition: mymalloc.c:207
const char * dtext
Definition: dsn.h:22
DSN_SPLIT * dsn_split(DSN_SPLIT *dp, const char *def_dsn, const char *text)
Definition: dsn_util.c:138
MAPS * maps
Definition: dsn_filter.c:94
DSN_SPLIT dp
Definition: dsn_filter.c:96
const char * action
Definition: dsn.h:19
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
const char * reason
Definition: dsn.h:20
#define DSN_ASSIGN(dsn, _status, _action, _reason, _dtype, _dtext, _mtype, _mname)
Definition: dsn.h:31
void dsn_filter_free(DSN_FILTER *fp)
Definition: dsn_filter.c:184
Definition: maps.h:22
#define DSN_STATUS(dsn_buf)
Definition: dsn_util.h:46
#define IS_SUCCESS_DSN(s)
DSN_FILTER * dsn_filter_create(const char *title, const char *map_names)
Definition: dsn_filter.c:107
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
const char * text
Definition: dsn_util.h:55
MAPS * maps_create(const char *title, const char *map_names, int dict_flags)
Definition: maps.c:112
char * title
Definition: maps.h:23
#define DICT_FLAG_LOCK
Definition: dict.h:116
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
const char * mname
Definition: dsn.h:24
DSN_STAT dsn
Definition: dsn_util.h:54
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
Definition: vstring.c:602
VSTRING * buffer
Definition: dsn_filter.c:95
MAPS * maps_free(MAPS *maps)
Definition: maps.c:213
const char * status
Definition: dsn.h:18
Definition: dsn.h:17
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
const char * mtype
Definition: dsn.h:23
const char * maps_find(MAPS *maps, const char *name, int flags)
Definition: maps.c:162
const char * dtype
Definition: dsn.h:21
#define IS_NDR_DSN(s)
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
void msg_info(const char *fmt,...)
Definition: msg.c:199
DSN * dsn_filter_lookup(DSN_FILTER *fp, DSN *dsn)
Definition: dsn_filter.c:123