1 /* $Id: prop.c,v 1.17 2015/06/18 03:42:48 manu Exp $ */
2
3 /*
4 * Copyright (c) 2006-2012 Emmanuel Dreyfus
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Emmanuel Dreyfus
18 *
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "config.h"
33
34 #ifdef HAVE_SYS_CDEFS_H
35 #include <sys/cdefs.h>
36 #ifdef __RCSID
37 __RCSID("$Id: prop.c,v 1.17 2015/06/18 03:42:48 manu Exp $");
38 #endif
39 #endif
40
41 #include <stdio.h>
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <syslog.h>
46 #include <errno.h>
47 #include <ctype.h>
48 #include <sysexits.h>
49 #include <signal.h>
50 #include <fnmatch.h>
51
52 #if defined(HAVE_OLD_QUEUE_H) || !defined(HAVE_SYS_QUEUE_H)
53 #include "queue.h"
54 #else
55 #include <sys/queue.h>
56 #endif
57 #include <sys/types.h>
58
59 #include "milter-greylist.h"
60 #include "pending.h"
61 #include "spf.h"
62 #include "acl.h"
63 #include "conf.h"
64 #include "sync.h"
65 #include "prop.h"
66
67 #ifdef USE_DMALLOC
68 #include <dmalloc.h>
69 #endif
70
71 #ifndef FNM_CASEFOLD
72 #define FNM_CASEFOLD 0 /* non portable extension */
73 #endif
74
75 static void
_prop_push(linep,valp,clear,priv,dolower)76 _prop_push(linep, valp, clear, priv, dolower)
77 char *linep;
78 char *valp;
79 int clear;
80 struct mlfi_priv *priv;
81 int dolower;
82 {
83 char *cp;
84 struct prop *up;
85
86 if ((up = malloc(sizeof(*up))) == NULL) {
87 mg_log(LOG_ERR, "malloc failed: %s", strerror(errno));
88 exit(EX_OSERR);
89 }
90
91 if ((up->up_name = strdup(linep)) == NULL) {
92 mg_log(LOG_ERR, "strup failed: %s", strerror(errno));
93 exit(EX_OSERR);
94 }
95
96 if ((up->up_value = strdup(valp)) == NULL) {
97 mg_log(LOG_ERR, "strdup failed: %s", strerror(errno));
98 exit(EX_OSERR);
99 }
100
101 /*
102 * Convert everything to lower-case
103 */
104 if (dolower) {
105 for (cp = up->up_name; *cp; cp++)
106 *cp = (char)tolower((int)*cp);
107
108 for (cp = up->up_value; *cp; cp++)
109 *cp = (char)tolower((int)*cp);
110 }
111
112 up->up_flags = UP_PLAINPROP|UP_TMPPROP;
113 if (clear)
114 up->up_flags |= UP_CLEARPROP;
115
116 /*
117 * If called at RCPT stage, record the recipient
118 */
119 if (priv->priv_cur_rcpt[0] != '\0') {
120 if ((up->up_rcpt = strdup(priv->priv_cur_rcpt)) == NULL) {
121 mg_log(LOG_ERR, "strdup failed: %s", strerror(errno));
122 exit(EX_OSERR);
123 }
124 } else {
125 up->up_rcpt = NULL;
126 }
127
128 LIST_INSERT_HEAD(&priv->priv_prop, up, up_list);
129
130 if (conf.c_debug)
131 mg_log(LOG_DEBUG, "got prop $%s = \"%s\"", linep, valp);
132
133 return;
134 }
135
136 void
prop_push(linep,valp,clear,priv)137 prop_push(linep, valp, clear, priv)
138 char *linep;
139 char *valp;
140 int clear;
141 struct mlfi_priv *priv;
142 {
143 _prop_push(linep, valp, clear, priv, 1);
144 }
145
146
147 int
prop_string_validate(ad,stage,ap,priv)148 prop_string_validate(ad, stage, ap, priv)
149 acl_data_t *ad;
150 acl_stage_t stage;
151 struct acl_param *ap;
152 struct mlfi_priv *priv;
153 {
154 struct prop *up;
155 acl_data_t *upd;
156 char *string;
157 int retval = 0;
158
159 upd = ad->prop->upd_data;
160 string = fstring_expand(priv, NULL, upd->string, NULL);
161
162 LIST_FOREACH(up, &priv->priv_prop, up_list) {
163 if (strcasecmp(ad->prop->upd_name, up->up_name) != 0)
164 continue;
165
166 if (conf.c_debug)
167 mg_log(LOG_DEBUG, "test $%s = \"%s\" vs \"%s\"",
168 up->up_name, up->up_value, string);
169
170 if (strcasecmp(up->up_value, string) == 0) {
171 priv->priv_prop_match = up;
172 retval = 1;
173 break;
174 }
175 }
176
177 free(string);
178 return retval;
179 }
180
181 int
prop_glob_validate(ad,stage,ap,priv)182 prop_glob_validate(ad, stage, ap, priv)
183 acl_data_t *ad;
184 acl_stage_t stage;
185 struct acl_param *ap;
186 struct mlfi_priv *priv;
187 {
188 struct prop *up;
189 acl_data_t *upd;
190 char *string;
191 int retval = 0;
192
193 upd = ad->prop->upd_data;
194 string = fstring_expand(priv, NULL, upd->string, NULL);
195
196 LIST_FOREACH(up, &priv->priv_prop, up_list) {
197 if (strcasecmp(ad->prop->upd_name, up->up_name) != 0)
198 continue;
199
200 if (conf.c_debug)
201 mg_log(LOG_DEBUG, "test $%s = \"%s\" vs \"%s\"",
202 up->up_name, up->up_value, string);
203
204 if (fnmatch(up->up_value, string, FNM_CASEFOLD) == 0) {
205 priv->priv_prop_match = up;
206 retval = 1;
207 break;
208 }
209 }
210
211 free(string);
212 return retval;
213 }
214
215 void
prop_opnum_add(ad,data)216 prop_opnum_add(ad, data)
217 acl_data_t *ad;
218 void *data;
219 {
220 struct acl_opnum_prop *aonp;
221
222 aonp = (struct acl_opnum_prop *)data;
223
224 if ((ad->aonp = malloc(sizeof(*ad->aonp))) == NULL) {
225 mg_log(LOG_ERR, "malloc() failed");
226 exit(EX_OSERR);
227 }
228
229 ad->aonp->aonp_op = aonp->aonp_op;
230 ad->aonp->aonp_type = aonp->aonp_type;
231 if ((ad->aonp->aonp_name = strdup(aonp->aonp_name)) == NULL) {
232 mg_log(LOG_ERR, "strdup() failed");
233 exit(EX_OSERR);
234 }
235
236 return;
237 }
238
239 void
prop_opnum_free(ad)240 prop_opnum_free(ad)
241 acl_data_t *ad;
242 {
243 free(ad->aonp->aonp_name);
244 free(ad->aonp);
245 return;
246 }
247
248
249 char *
prop_opnum_print(ad,buf,len)250 prop_opnum_print(ad, buf, len)
251 acl_data_t *ad;
252 char *buf;
253 size_t len;
254 {
255 struct {
256 enum operator op;
257 char *str;
258 } op_to_str[] = {
259 { OP_EQ, "==" },
260 { OP_NE, "!=" },
261 { OP_GT, ">" },
262 { OP_LT, "<" },
263 { OP_GE, ">=" },
264 { OP_LE, "<=" },
265 };
266 int i;
267 char *str = NULL;
268
269 for (i = 0; i < sizeof(op_to_str) / sizeof(*op_to_str); i++) {
270 if (op_to_str[i].op == ad->aonp->aonp_op) {
271 str = op_to_str[i].str;
272 break;
273 }
274 }
275 if (str == NULL) {
276 mg_log(LOG_ERR, "unexpected operator");
277 exit(EX_SOFTWARE);
278 }
279
280 snprintf(buf, len, "%s $%s", str, ad->aonp->aonp_name);
281
282 return buf;
283 }
284
285 int
prop_rhsnum_validate(ad,stage,ap,priv)286 prop_rhsnum_validate(ad, stage, ap, priv)
287 acl_data_t *ad;
288 acl_stage_t stage;
289 struct acl_param *ap;
290 struct mlfi_priv *priv;
291 {
292 struct prop *up;
293 struct acl_opnum_prop *aonp;
294 int val1, val2;
295 int retval = 0;
296
297 aonp = ad->aonp;
298 LIST_FOREACH(up, &priv->priv_prop, up_list) {
299 if (strcasecmp(up->up_name, aonp->aonp_name) != 0)
300 continue;
301
302 if (conf.c_debug)
303 mg_log(LOG_DEBUG, "test $%s = \"%s\" vs \"%s\"",
304 up->up_name, up->up_value, aonp->aonp_name);
305
306 switch (aonp->aonp_type) {
307 case AONP_MSGSIZE:
308 val1 = priv->priv_msgcount;
309 break;
310 case AONP_RCPTCOUNT:
311 val1 = priv->priv_rcptcount;
312 break;
313 #ifdef USE_SPAMD
314 case AONP_SPAMD:
315 val1 = priv->priv_spamd_score10;
316 break;
317 #endif /* USE_SPAMD */
318 default:
319 mg_log(LOG_ERR, "unexpected aonp_type");
320 exit(EX_SOFTWARE);
321 }
322 val2 = atoi(up->up_value);
323
324 retval = acl_opnum_cmp(val1, aonp->aonp_op, val2);
325 break;
326 }
327
328 return retval;
329 }
330
331 int
prop_lhsnum_validate(ad,stage,ap,priv)332 prop_lhsnum_validate(ad, stage, ap, priv)
333 acl_data_t *ad;
334 acl_stage_t stage;
335 struct acl_param *ap;
336 struct mlfi_priv *priv;
337 {
338 struct acl_opnum_data *aond;
339 char *current;
340
341 aond = ad->prop->upd_data;
342
343 current = prop_byname(priv, ad->prop->upd_name);
344 if (current == NULL)
345 return 0;
346
347 return acl_opnum_cmp(atoi(current), aond->op, aond->num);
348 }
349
350 int
prop_pop_validate(ad,stage,ap,priv)351 prop_pop_validate(ad, stage, ap, priv)
352 acl_data_t *ad;
353 acl_stage_t stage;
354 struct acl_param *ap;
355 struct mlfi_priv *priv;
356 {
357 struct acl_prop_pop *apop;
358 char *lhs_str;
359 char *rhs_str;
360
361 apop = ad->apop;
362
363 lhs_str = prop_byname(priv, apop->apop_lhs);
364 if (lhs_str == NULL)
365 lhs_str = "0";
366
367 rhs_str = prop_byname(priv, apop->apop_rhs);
368 if (rhs_str == NULL)
369 rhs_str = "0";
370
371 return acl_opnum_cmp(atoi(lhs_str), apop->apop_op, atoi(rhs_str));
372 }
373
374
375 void
prop_delete(up)376 prop_delete(up)
377 struct prop *up;
378 {
379 free(up->up_name);
380 free(up->up_value);
381 if (up->up_rcpt != NULL)
382 free(up->up_rcpt);
383 LIST_REMOVE(up, up_list);
384 free(up);
385 }
386
387 void
prop_delete_byname(priv,name)388 prop_delete_byname(priv, name)
389 struct mlfi_priv *priv;
390 char *name;
391 {
392 struct prop *up;
393 struct prop *nup;
394
395 up = LIST_FIRST(&priv->priv_prop);
396
397 while (up != NULL) {
398 nup = LIST_NEXT(up, up_list);
399 if (strcmp(up->up_name, name) == 0)
400 prop_delete(up);
401 up = nup;
402 }
403 return;
404 }
405
406 void
prop_clear(priv,flags)407 prop_clear(priv, flags)
408 struct mlfi_priv *priv;
409 int flags;
410 {
411 struct prop *up;
412 struct prop *nup;
413
414 up = LIST_FIRST(&priv->priv_prop);
415
416 while (up != NULL) {
417 nup = LIST_NEXT(up, up_list);
418 if (up->up_flags & flags) {
419 if (priv->priv_prop_match == up)
420 priv->priv_prop_match = NULL;
421 free(up->up_name);
422 free(up->up_value);
423 if (up->up_rcpt != NULL)
424 free(up->up_rcpt);
425 LIST_REMOVE(up, up_list);
426 free(up);
427 }
428 up = nup;
429 }
430 return;
431 }
432
433 void
prop_untmp(priv)434 prop_untmp(priv)
435 struct mlfi_priv *priv;
436 {
437 struct prop *up;
438
439 LIST_FOREACH(up, &priv->priv_prop, up_list)
440 up->up_flags &= ~UP_TMPPROP;
441 return;
442 }
443
444 int
prop_regex_validate(ad,stage,ap,priv)445 prop_regex_validate(ad, stage, ap, priv)
446 acl_data_t *ad;
447 acl_stage_t stage;
448 struct acl_param *ap;
449 struct mlfi_priv *priv;
450 {
451 struct prop *up;
452 acl_data_t *upd;
453 int retval = 0;
454
455 upd = ad->prop->upd_data;
456
457 LIST_FOREACH(up, &priv->priv_prop, up_list) {
458 if (strcasecmp(ad->prop->upd_name, up->up_name) != 0)
459 continue;
460
461 if (conf.c_debug)
462 mg_log(LOG_DEBUG, "test $%s = \"%s\" vs %s",
463 up->up_name, up->up_value, upd->regex.re_copy);
464
465 if (myregexec(priv, upd, ap, up->up_value) == 0) {
466 priv->priv_prop_match = up;
467 retval = 1;
468 break;
469 }
470 }
471
472 return retval;
473 }
474
475 #define ERRLEN 1024
476 typedef enum { PBV_BODY, PBV_HEADER } pbv_t;
477
478 static int
prop_data_validate(ad,stage,ap,priv,type)479 prop_data_validate(ad, stage, ap, priv, type)
480 acl_data_t *ad;
481 acl_stage_t stage;
482 struct acl_param *ap;
483 struct mlfi_priv *priv;
484 pbv_t type;
485 {
486 struct prop *up;
487 struct line *l;
488 int retval = 0;
489 char *typestr;
490 struct bh_line *data;
491
492 if (type == PBV_BODY) {
493 typestr = "body";
494 data = &priv->priv_body;
495 } else {
496 typestr = "header";
497 data = &priv->priv_header;
498 }
499
500 if (stage != AS_DATA) {
501 mg_log(LOG_ERR, "%s filter called at non DATA stage", typestr);
502 exit(EX_SOFTWARE);
503 }
504
505 LIST_FOREACH(up, &priv->priv_prop, up_list) {
506 size_t len;
507 char *regexstr = NULL;
508 regex_t regex;
509 int is_regex;
510
511 if (strcasecmp(ad->string, up->up_name) != 0)
512 continue;
513
514 if (conf.c_debug)
515 mg_log(LOG_DEBUG, "test $%s = %s vs %s",
516 up->up_name, up->up_value, typestr);
517
518 len = strlen(up->up_value);
519 is_regex = 0;
520
521 /*
522 * Regex case
523 */
524 if (up->up_value[0] == '/' && up->up_value[len - 1] == '/') {
525 char errstr[ERRLEN + 1];
526 int fl;
527 int error;
528
529 if ((regexstr = strdup(up->up_value)) == NULL) {
530 mg_log(LOG_ERR, "strdup failed");
531 exit(EX_OSERR);
532 }
533
534 /* Strip trailing / */
535 regexstr[len - 1] = '\0';
536
537 fl = (REG_ICASE | REG_NEWLINE | REG_NOSUB);
538 if (conf.c_extendedregex)
539 fl |= REG_EXTENDED;
540
541 /* +1 to strip leading / */
542 if ((error = regcomp(®ex, regexstr + 1, fl)) != 0) {
543 regerror(error, ®ex, errstr, ERRLEN);
544 mg_log(LOG_WARNING, "bad regular expression "
545 "\"%s\": %s", regexstr, errstr);
546 free(regexstr);
547 continue;
548 }
549
550 is_regex = 1;
551 }
552
553
554 /*
555 * For each line
556 */
557 TAILQ_FOREACH(l, data, l_list) {
558 if (conf.c_debug)
559 mg_log(LOG_DEBUG, "test $%s = %s vs \"%s\"",
560 up->up_name, up->up_value, l->l_line);
561
562 /*
563 * substring match
564 */
565 if (!is_regex) {
566 if (strstr(l->l_line, up->up_value) != NULL) {
567 priv->priv_prop_match = up;
568 return 1;
569 }
570 continue;
571 }
572
573 /*
574 * regex match
575 */
576 if (regexec(®ex, l->l_line, 0, NULL, 0) == 0) {
577 priv->priv_prop_match = up;
578 retval = 1;
579 break;
580 }
581 }
582
583 if (is_regex) {
584 regfree(®ex);
585 free(regexstr);
586 }
587
588 if (retval == 1)
589 return 1;
590 }
591
592 return 0;
593 }
594
595 int
prop_body_validate(ad,stage,ap,priv)596 prop_body_validate(ad, stage, ap, priv)
597 acl_data_t *ad;
598 acl_stage_t stage;
599 struct acl_param *ap;
600 struct mlfi_priv *priv;
601 {
602 return prop_data_validate(ad, stage, ap, priv, PBV_BODY);
603 }
604
605 int
prop_header_validate(ad,stage,ap,priv)606 prop_header_validate(ad, stage, ap, priv)
607 acl_data_t *ad;
608 acl_stage_t stage;
609 struct acl_param *ap;
610 struct mlfi_priv *priv;
611 {
612 return prop_data_validate(ad, stage, ap, priv, PBV_HEADER);
613 }
614
615 /*
616 * This does not cope well with multivalued props
617 */
618 char *
prop_byname(priv,name)619 prop_byname(priv, name)
620 struct mlfi_priv *priv;
621 char *name;
622 {
623 struct prop *up;
624
625 LIST_FOREACH(up, &priv->priv_prop, up_list) {
626 if (strcasecmp(name, up->up_name) != 0)
627 continue;
628
629 return up->up_value;
630 }
631
632 return NULL;
633 }
634
635 static int
_prop_eqset_string(ad,priv,clear)636 _prop_eqset_string(ad, priv, clear)
637 acl_data_t *ad;
638 struct mlfi_priv *priv;
639 int clear;
640 {
641 acl_data_t *upd;
642 char *string;
643
644 upd = ad->prop->upd_data;
645 string = fstring_expand(priv, NULL, upd->string, NULL);
646
647 /* Delete existing value, add new one */
648 prop_delete_byname(priv, ad->prop->upd_name);
649 _prop_push(ad->prop->upd_name, string, clear, priv, 0);
650
651 free(string);
652
653 /* always match */
654 return 1;
655 }
656
657 static int
_prop_incset_string(ad,priv,clear,coef)658 _prop_incset_string(ad, priv, clear, coef)
659 acl_data_t *ad;
660 struct mlfi_priv *priv;
661 int clear;
662 int coef;
663 {
664 acl_data_t *upd;
665 char *current;
666 char *string;
667 char newval[16]; /* 16 is enough for an int */
668
669 current = prop_byname(priv, ad->prop->upd_name);
670 if (current == NULL)
671 current = "0";
672
673 upd = ad->prop->upd_data;
674 string = fstring_expand(priv, NULL, upd->string, NULL);
675
676 (void)sprintf(newval, "%d", atoi(current) + (coef * atoi(string)));
677
678 /* Delete existing value, add new one */
679 prop_delete_byname(priv, ad->prop->upd_name);
680 _prop_push(ad->prop->upd_name, newval, clear, priv, 0);
681
682 free(string);
683
684 /* always match */
685 return 1;
686 }
687
688 static int
_prop_eqset_prop(ad,priv,clear)689 _prop_eqset_prop(ad, priv, clear)
690 acl_data_t *ad;
691 struct mlfi_priv *priv;
692 int clear;
693 {
694 acl_data_t *upd;
695 char *string;
696
697 upd = ad->prop->upd_data;
698 string = prop_byname(priv, upd->string);
699
700 if (string == NULL)
701 string = "";
702
703 /* Delete existing value, add new one */
704 prop_delete_byname(priv, ad->prop->upd_name);
705 _prop_push(ad->prop->upd_name, string, clear, priv, 0);
706
707 /* always match */
708 return 1;
709 }
710
711 static int
_prop_incset_prop(ad,priv,clear,coef)712 _prop_incset_prop(ad, priv, clear, coef)
713 acl_data_t *ad;
714 struct mlfi_priv *priv;
715 int clear;
716 int coef;
717 {
718 acl_data_t *upd;
719 char *current;
720 char *string;
721 char newval[16]; /* 16 is enough for an int */
722
723 current = prop_byname(priv, ad->prop->upd_name);
724 if (current == NULL)
725 current = "0";
726
727 upd = ad->prop->upd_data;
728 string = prop_byname(priv, upd->string);
729
730 if (string == NULL)
731 goto out;
732
733 (void)sprintf(newval, "%d", atoi(current) +(coef * atoi(string)));
734
735 /* Delete existing value, add new one */
736 prop_delete_byname(priv, ad->prop->upd_name);
737 _prop_push(ad->prop->upd_name, newval, clear, priv, 0);
738
739 out:
740 /* always match */
741 return 1;
742 }
743
744 int
prop_eqset_string(ad,stage,ap,priv)745 prop_eqset_string(ad, stage, ap, priv)
746 acl_data_t *ad;
747 acl_stage_t stage;
748 struct acl_param *ap;
749 struct mlfi_priv *priv;
750 {
751 return _prop_eqset_string(ad, priv, 0);
752 }
753
754 int
prop_eqrset_string(ad,stage,ap,priv)755 prop_eqrset_string(ad, stage, ap, priv)
756 acl_data_t *ad;
757 acl_stage_t stage;
758 struct acl_param *ap;
759 struct mlfi_priv *priv;
760 {
761 return _prop_eqset_string(ad, priv, UP_CLEARPROP);
762 }
763
764 int
prop_incset_string(ad,stage,ap,priv)765 prop_incset_string(ad, stage, ap, priv)
766 acl_data_t *ad;
767 acl_stage_t stage;
768 struct acl_param *ap;
769 struct mlfi_priv *priv;
770 {
771 return _prop_incset_string(ad, priv, 0, 1);
772 }
773
774 int
prop_incrset_string(ad,stage,ap,priv)775 prop_incrset_string(ad, stage, ap, priv)
776 acl_data_t *ad;
777 acl_stage_t stage;
778 struct acl_param *ap;
779 struct mlfi_priv *priv;
780 {
781 return _prop_incset_string(ad, priv, UP_CLEARPROP, 1);
782 }
783
784 int
prop_decset_string(ad,stage,ap,priv)785 prop_decset_string(ad, stage, ap, priv)
786 acl_data_t *ad;
787 acl_stage_t stage;
788 struct acl_param *ap;
789 struct mlfi_priv *priv;
790 {
791 return _prop_incset_string(ad, priv, 0, -1);
792 }
793
794 int
prop_decrset_string(ad,stage,ap,priv)795 prop_decrset_string(ad, stage, ap, priv)
796 acl_data_t *ad;
797 acl_stage_t stage;
798 struct acl_param *ap;
799 struct mlfi_priv *priv;
800 {
801 return _prop_incset_string(ad, priv, UP_CLEARPROP, -1);
802 }
803
804 int
prop_eqset_prop(ad,stage,ap,priv)805 prop_eqset_prop(ad, stage, ap, priv)
806 acl_data_t *ad;
807 acl_stage_t stage;
808 struct acl_param *ap;
809 struct mlfi_priv *priv;
810 {
811 return _prop_eqset_prop(ad, priv, 0);
812 }
813
814 int
prop_eqrset_prop(ad,stage,ap,priv)815 prop_eqrset_prop(ad, stage, ap, priv)
816 acl_data_t *ad;
817 acl_stage_t stage;
818 struct acl_param *ap;
819 struct mlfi_priv *priv;
820 {
821 return _prop_eqset_prop(ad, priv, UP_CLEARPROP);
822 }
823
824 int
prop_incset_prop(ad,stage,ap,priv)825 prop_incset_prop(ad, stage, ap, priv)
826 acl_data_t *ad;
827 acl_stage_t stage;
828 struct acl_param *ap;
829 struct mlfi_priv *priv;
830 {
831 return _prop_incset_prop(ad, priv, 0, 1);
832 }
833
834 int
prop_incrset_prop(ad,stage,ap,priv)835 prop_incrset_prop(ad, stage, ap, priv)
836 acl_data_t *ad;
837 acl_stage_t stage;
838 struct acl_param *ap;
839 struct mlfi_priv *priv;
840 {
841 return _prop_incset_prop(ad, priv, UP_CLEARPROP, 1);
842 }
843
844 int
prop_decset_prop(ad,stage,ap,priv)845 prop_decset_prop(ad, stage, ap, priv)
846 acl_data_t *ad;
847 acl_stage_t stage;
848 struct acl_param *ap;
849 struct mlfi_priv *priv;
850 {
851 return _prop_incset_prop(ad, priv, 0, -1);
852 }
853
854 int
prop_decrset_prop(ad,stage,ap,priv)855 prop_decrset_prop(ad, stage, ap, priv)
856 acl_data_t *ad;
857 acl_stage_t stage;
858 struct acl_param *ap;
859 struct mlfi_priv *priv;
860 {
861 return _prop_incset_prop(ad, priv, UP_CLEARPROP, -1);
862 }
863