The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
abinary.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Routines to encode / decode Ascend's filter attributes
18 *
19 * @file src/protocols/radius/abinary.c
20 *
21 * @copyright 2003,2006 The FreeRADIUS server project
22 */
23RCSID("$Id: ac5a0e0ed4ad6522eb6cdd8519bd7fff938b30bc $")
24
25#include <freeradius-devel/util/base16.h>
26#include <freeradius-devel/util/misc.h>
27#include <freeradius-devel/util/pair.h>
28
29#include "radius.h"
30
31/*
32 * Two types of filters are supported, GENERIC and IP. The identifiers
33 * are:
34 */
35
42
43/*
44 * Generic filters mask and match up to RAD_MAX_FILTER_LEN bytes
45 * starting at some offset. The length is:
46 */
47#define RAD_MAX_FILTER_LEN 6
48
49/*
50 * ASCEND extensions for ABINARY filters
51 */
52
53#define IPX_NODE_ADDR_LEN 6
54
55/*
56 * ascend_ip_filter_t
57 *
58 * The binary format of an IP filter. ALL fields are stored in
59 * network byte order.
60 *
61 * srcip: The source IP address.
62 *
63 * dstip: The destination IP address.
64 *
65 * srcmask: The number of leading one bits in the source address
66 * mask. Specifies the bits of interest.
67 *
68 * dstmask: The number of leading one bits in the destination
69 * address mask. Specifies the bits of interest.
70 *
71 * proto: The IP protocol number
72 *
73 * established: A boolean value. true when we care about the
74 * established state of a TCP connection. false when
75 * we dont care.
76 *
77 * srcport: TCP or UDP source port number.
78 *
79 * dstport: TCP or UDP destination port number.
80 *
81 * srcPortCmp: One of the values of the RadFilterComparison
82 * enumeration, specifying how to compare the
83 * srcport value.
84 *
85 * dstPortCmp: One of the values of the RadFilterComparison
86 * enumeration, specifying how to compare the
87 * dstport value.
88 *
89 * fill: Round things out to a int16_t boundary.
90 */
105
106
107/*
108 * ascend_ip_filter_t
109 *
110 * The binary format of an IP filter. ALL fields are stored in
111 * network byte order.
112 *
113 * srcip: The source IP address.
114 *
115 * dstip: The destination IP address.
116 *
117 * srcmask: The number of leading one bits in the source address
118 * mask. Specifies the bits of interest.
119 *
120 * dstmask: The number of leading one bits in the destination
121 * address mask. Specifies the bits of interest.
122 *
123 * proto: The IP protocol number
124 *
125 * established: A boolean value. true when we care about the
126 * established state of a TCP connection. false when
127 * we dont care.
128 *
129 * srcport: TCP or UDP source port number.
130 *
131 * dstport: TCP or UDP destination port number.
132 *
133 * srcPortCmp: One of the values of the RadFilterComparison
134 * enumeration, specifying how to compare the
135 * srcport value.
136 *
137 * dstPortCmp: One of the values of the RadFilterComparison
138 * enumeration, specifying how to compare the
139 * dstport value.
140 *
141 * fill: Round things out to a int16_t boundary.
142 */
157
158
159/*
160 * ascend_ipx_net_t
161 *
162 * net: IPX Net address
163 *
164 * node: IPX Node address
165 *
166 * socket: IPX socket address
167 */
173
174/*
175 * ascend_ipx_filter_t
176 *
177 * The binary format of an IPX filter. ALL fields are stored in
178 * network byte order.
179 *
180 * src: Source net, node, and socket.
181 *
182 * dst: Destination net, node, and socket.
183 *
184 * srcSocComp: Source socket compare value
185 *
186 * dstSocComp: Destination socket compare value
187 */
194
195
196/*
197 * ascend_generic_filter_t
198 *
199 * The binary format of a GENERIC filter. ALL fields are stored in
200 * network byte order.
201 *
202 * offset: Number of bytes into packet to start comparison.
203 *
204 * len: Number of bytes to mask and compare. May not
205 * exceed RAD_MAX_FILTER_LEN.
206 *
207 * more: Boolean. If non-zero the next filter entry is
208 * also to be applied to a packet.
209 *
210 * mask: A bit mask specifying the bits to compare.
211 *
212 * value: A value to compare against the masked bits at
213 * offset in a users packet.
214 *
215 * compNeq: Defines type of comparison (Equal or Notequal)
216 * default is Equal.
217 *
218 * fill: Round things out to a dword boundary
219 */
228
229/*
230 * ascend_filter_t
231 *
232 * A binary filter element. Contains one of ascend_ip_filter_t,
233 * ascend_ipx_filter_t, or ascend_generic_filter_t.
234 *
235 * All fields are stored in network byte order.
236 *
237 * type: Either ASCEND_FILTER_GENERIC or ASCEND_FILTER_IP.
238 *
239 * forward: true if we should forward packets that match this
240 * filter, false if we should drop packets that match
241 * this filter.
242 *
243 * direction: true if this is an input filter, false if this is
244 * an output filter.
245 *
246 * fill: Round things out to a dword boundary.
247 *
248 * u: A union of
249 * ip: An ip filter entry
250 * generic: A generic filter entry
251 */
264
265/*
266 * FilterPortType:
267 *
268 * Ascii names of some well known tcp/udp services.
269 * Used for filtering on a port type.
270 *
271 * ??? What the heck is wrong with getservbyname?
272 */
274 { L("cmd"), 514 },
275 { L("domain"), 53 },
276 { L("exec"), 512 },
277 { L("finger"), 79 },
278 { L("ftp"), 21 },
279 { L("ftp-data"), 20 },
280 { L("gopher"), 70 },
281 { L("hostname"), 101 },
282 { L("kerberos"), 88 },
283 { L("login"), 513 },
284 { L("nameserver"), 42 },
285 { L("nntp"), 119 },
286 { L("ntp"), 123 },
287 { L("smtp"), 25 },
288 { L("talk"), 517 },
289 { L("telnet"), 23 },
290 { L("tftp"), 69 },
291 { L("www"), 80 }
292};
294
296 { L("generic"), ASCEND_FILTER_GENERIC},
297 { L("ip"), ASCEND_FILTER_IP},
298 { L("ipv6"), ASCEND_FILTER_IPV6},
299 { L("ipx"), ASCEND_FILTER_IPX},
300};
302
324
325
327 { L("!="), FILTER_GENERIC_COMPNEQ },
328 { L("=="), FILTER_GENERIC_COMPEQ },
329 { L("drop"), FILTER_DROP },
330 { L("dstip"), FILTER_IP_DST },
331 { L("dstipxnet"), FILTER_IPX_DST_IPXNET },
332 { L("dstipxnode"), FILTER_IPX_DST_IPXNODE },
333 { L("dstipxsock"), FILTER_IPX_DST_IPXSOCK },
334 { L("dstport"), FILTER_IP_DST_PORT },
335 { L("est"), FILTER_EST },
336 { L("forward"), FILTER_FORWARD },
337 { L("in"), FILTER_IN },
338 { L("more"), FILTER_MORE },
339 { L("out"), FILTER_OUT },
340 { L("srcip"), FILTER_IP_SRC },
341 { L("srcipxnet"), FILTER_IPX_SRC_IPXNET },
342 { L("srcipxnode"), FILTER_IPX_SRC_IPXNODE },
343 { L("srcipxsock"), FILTER_IPX_SRC_IPXSOCK },
344 { L("srcport"), FILTER_IP_SRC_PORT }
345};
347
348/*
349 * FilterProtoName:
350 *
351 * Ascii name of protocols used for filtering.
352 *
353 * ??? What the heck is wrong with getprotobyname?
354 */
356 { L("0"), 0 },
357 { L("icmp"), 1 },
358 { L("ospf"), 89 },
359 { L("tcp"), 6 },
360 { L("udp"), 17 }
361};
363
364
365/*
366 * RadFilterComparison:
367 *
368 * An enumerated values for the IP filter port comparisons.
369 */
377
379 { L("!="), RAD_COMPARE_NOT_EQUAL },
380 { L("<"), RAD_COMPARE_LESS },
381 { L("="), RAD_COMPARE_EQUAL },
382 { L(">"), RAD_COMPARE_GREATER }
383};
385
386/*
387 * ascend_parse_ipx_net
388 *
389 * srcipxnet nnnn srcipxnode mmmmm [srcipxsoc cmd value ]
390 */
391static int ascend_parse_ipx_net(int argc, char **argv,
393{
394 int token;
395 char const *p;
396
397 if (argc < 3) {
398 fr_strerror_const("Insufficient arguments to parse 'abinary' IPX network type");
399 return -1;
400 }
401
402 /*
403 * Parse the net, which is a hex number.
404 */
405 net->net = htonl(strtol(argv[0], NULL, 16));
406
407 /*
408 * Parse the node.
409 */
410 token = fr_table_value_by_str(filterKeywords, argv[1], -1);
411 switch (token) {
414 break;
415
416 default:
417 fr_strerror_printf("Unknown keyword '%s' for IPX network filter", argv[1]);
418 return -1;
419 }
420
421 /*
422 * Can have a leading "0x" or "0X"
423 */
424 p = argv[2];
425 if ((memcmp(p, "0X", 2) == 0) ||
426 (memcmp(p, "0x", 2) == 0)) p += 2;
427
428 /*
429 * Node must be 6 octets long.
430 */
431 token = fr_base16_decode(NULL,
433 &FR_SBUFF_IN(p, strlen(p)), false);
434 if (token != IPX_NODE_ADDR_LEN) {
435 fr_strerror_printf("IPX network node name '%s' is the wrong size", argv[2]);
436 return -1;
437 }
438
439 /*
440 * Nothing more, die.
441 */
442 if (argc == 3) return 3;
443
444 /*
445 * Can't be too little or too much.
446 */
447 if (argc != 6) {
448 fr_strerror_const("Insufficient arguments to parse 'abinary' IPX network type");
449 return -1;
450 }
451
452 /*
453 * Parse the socket.
454 */
455 token = fr_table_value_by_str(filterKeywords, argv[3], -1);
456 switch (token) {
459 break;
460
461 default:
462 fr_strerror_printf("Unknown keyword '%s' for IPX network filter", argv[3]);
463 return -1;
464 }
465
466 /*
467 * Parse the command "<", ">", "=" or "!="
468 */
469 token = fr_table_value_by_str(filterCompare, argv[4], -1);
470 switch (token) {
471 case RAD_COMPARE_LESS:
475 *comp = token;
476 break;
477
478 default:
479 fr_strerror_printf("Unknown keyword '%s' for IPX network filter", argv[4]);
480 return -1;
481 }
482
483 /*
484 * Parse the value.
485 */
486 token = strtoul(argv[5], NULL, 16);
487 if (token > 65535) {
488 fr_strerror_printf("Socket value '%s' is too large for IPX network filter", argv[5]);
489 return -1;
490 }
491
492 net->socket = token;
493 net->socket = htons(net->socket);
494
495
496 /*
497 * Everything's OK, we parsed 6 entries.
498 */
499 return 6;
500}
501
502/*
503 * ascend_parse_ipx_filter
504 *
505 * This routine parses an IPX filter string from a string.
506 * The format of the string is:
507 *
508 * [ srcipxnet nnnn srcipxnode mmmmm [srcipxsoc cmd value ]]
509 * [ dstipxnet nnnn dstipxnode mmmmm [dstipxsoc cmd value ]]
510 *
511 * Fields in [...] are optional.
512 * where:
513 *
514 * srcipxnet: Keyword for source IPX address.
515 * nnnn = IPX Node address.
516 *
517 * srcipxnode: Keyword for source IPX Node address.
518 * mmmmm = IPX Node Address, could be FFFFFF.
519 * A vlid ipx node number should accompany ipx net number.
520 *
521 * srcipxsoc: Keyword for source IPX socket address.
522 *
523 * cmd: One of ">" or "<" or "=" or "!=".
524 *
525 * value: Socket value to be compared against, in hex.
526 *
527 * dstipxnet: Keyword for destination IPX address.
528 * nnnn = IPX Node address.
529 *
530 * dstipxnode: Keyword for destination IPX Node address.
531 * mmmmm = IPX Node Address, could be FFFFFF.
532 * A valid ipx node number should accompany ipx net number.
533 *
534 * dstipxsoc: Keyword for destination IPX socket address.
535 *
536 * cmd: One of ">" or "<" or "=" or "!=".
537 *
538 * value: Socket value to be compared against, in hex.
539 */
540static int ascend_parse_ipx(int argc, char **argv, ascend_ipx_filter_t *filter)
541{
542 int slen;
543 int token;
544 int flags = 0;
545
546 /*
547 * We may have nothing, in which case we simply return.
548 */
549 if (argc == 0) return 0;
550
551 /*
552 * Must have "net N node M"
553 */
554 if (argc < 4) {
555 fr_strerror_const("Insufficient arguments to parse 'abinary' IPX type");
556 return -1;
557 }
558
559 while ((argc > 0) && (flags != 0x03)) {
560 token = fr_table_value_by_str(filterKeywords, argv[0], -1);
561 switch (token) {
563 if (flags & 0x01) {
564duplicate:
565 fr_strerror_const("Duplicate field when parsing 'abinary' IPX type");
566 return -1;
567 }
568 slen = ascend_parse_ipx_net(argc - 1, argv + 1,
569 &(filter->src),
570 &(filter->srcSocComp));
571 if (slen < 0) return -1;
572 argc -= (slen + 1);
573 argv += slen + 1;
574 flags |= 0x01;
575 break;
576
578 if (flags & 0x02) goto duplicate;
579 slen = ascend_parse_ipx_net(argc - 1, argv + 1,
580 &(filter->dst),
581 &(filter->dstSocComp));
582 if (slen < 0) return -1;
583 argc -= (slen + 1);
584 argv += slen + 1;
585 flags |= 0x02;
586 break;
587
588 default:
589 fr_strerror_printf("Unknown string \"%s\" in IPX data filter",
590 argv[0]);
591 return -1;
592 }
593 }
594
595 /*
596 * Arguments left over: die.
597 */
598 if (argc != 0) {
599 fr_strerror_const("Too many arguments to 'abinary' IPX filter");
600 return -1;
601 }
602
603 /*
604 * Everything's OK.
605 */
606 return 0;
607}
608
609
610/*
611 * Parse an IP address and optionally a netmask, to a uint32_t.
612 *
613 * ipaddr should already be initialized to zero.
614 * ipaddr is in network byte order.
615 *
616 * Returns -1 on failure, or the number of bits in the netmask, otherwise.
617 */
618static int ascend_parse_ipaddr(uint32_t *ipaddr, char *str)
619{
620 int count = 0;
621 int ip[4];
622 int masklen;
623 uint32_t netmask = 0;
624
625 /*
626 * Look for IP's.
627 */
628 count = 0;
629 while (*str && (count < 4) && (netmask == 0)) {
630 next:
631 ip[count] = 0;
632
633 while (*str) {
634 switch (*str) {
635 case '0': case '1': case '2': case '3':
636 case '4': case '5': case '6': case '7':
637 case '8': case '9':
638 ip[count] *= 10;
639 ip[count] += (*str) - '0';
640 str++;
641 break;
642
643
644 case '.': /* dot between IP numbers. */
645 str++;
646 if (ip[count] > 255) {
647 fr_strerror_printf("Invalid IP address in '%s'", str);
648 return -1;
649 }
650
651 /*
652 * 24, 16, 8, 0, done.
653 */
654 *ipaddr |= (ip[count] << (8 * (3 - count)));
655 count++;
656 goto next;
657
658 case '/': /* netmask */
659 str++;
660 masklen = atoi(str);
661 if ((masklen < 0) || (masklen > 32)) {
662 fr_strerror_printf("Invalid mask in '%s'", str);
663 return -1;
664 }
665 str += strspn(str, "0123456789");
666 netmask = masklen;
667 goto finalize;
668
669 default:
670 fr_strerror_const("Invalid character in IP address");
671 return -1;
672 }
673 } /* loop over one character */
674 } /* loop until the count hits 4 */
675
676 if (count == 3) {
677 finalize:
678 /*
679 * Do the last one, too.
680 */
681 if (ip[count] > 255) {
682 fr_strerror_printf("Invalid mask in '%s'", str);
683 return -1;
684 }
685
686 /*
687 * 24, 16, 8, 0, done.
688 */
689 *ipaddr |= (ip[count] << (8 * (3 - count)));
690 }
691
692 /*
693 * We've hit the end of the IP address, and there's something
694 * else left over: die.
695 */
696 if (*str) return -1;
697
698 /*
699 * Set the default netmask.
700 */
701 if (!netmask) {
702 if (!*ipaddr) {
703 netmask = 0;
704 } else if ((*ipaddr & 0x80000000) == 0) {
705 netmask = 8;
706 } else if ((*ipaddr & 0xc0000000) == 0x80000000) {
707 netmask = 16;
708 } else if ((*ipaddr & 0xe0000000) == 0xc0000000) {
709 netmask = 24;
710 } else {
711 netmask = 32;
712 }
713 }
714
715 *ipaddr = htonl(*ipaddr);
716 return netmask;
717}
718
719/*
720 * ascend_parse_port: Parse a comparator and port.
721 *
722 * Returns -1 on failure, or the comparator.
723 */
724static int ascend_parse_port(uint16_t *port, char *compare, char *str)
725{
726 int slen, token;
727
728 /*
729 * There MUST be a comparison string.
730 */
731 slen = fr_table_value_by_str(filterCompare, compare, -1);
732 if (slen < 0) {
733 fr_strerror_printf("Unknown comparison operator '%s'", str);
734 return slen;
735 }
736
737 if (strspn(str, "0123456789") == strlen(str)) {
738 token = atoi(str);
739 } else {
740 token = fr_table_value_by_str(filterPortType, str, -1);
741 }
742
743 if ((token < 0) || (token > 65535)) {
744 fr_strerror_printf("Unknown port name '%s'", str);
745 return -1;
746 }
747
748 *port = token;
749 *port = htons(*port);
750
751 return slen;
752}
753
754
755#define IP_SRC_ADDR_FLAG (1 << 0)
756#define IP_DEST_ADDR_FLAG (1 << 1)
757#define IP_SRC_PORT_FLAG (1 << 2)
758#define IP_DEST_PORT_FLAG (1 << 3)
759#define IP_PROTO_FLAG (1 << 4)
760#define IP_EST_FLAG (1 << 5)
761
762#define DONE_FLAGS (IP_SRC_ADDR_FLAG | IP_DEST_ADDR_FLAG | \
763 IP_SRC_PORT_FLAG | IP_DEST_PORT_FLAG | \
764 IP_PROTO_FLAG | IP_EST_FLAG)
765
766/*
767 * ascend_parse_ip:
768 *
769 * This routine parses an IP filter string from a RADIUS
770 * reply. The format of the string is:
771 *
772 * ip dir action [ dstip n.n.n.n/nn ] [ srcip n.n.n.n/nn ]
773 * [ proto [ dstport cmp value ] [ srcport cmd value ] [ est ] ]
774 *
775 * Fields in [...] are optional.
776 *
777 * dstip: Keyword for destination IP address.
778 * n.n.n.n = IP address. /nn - netmask.
779 *
780 * srcip: Keyword for source IP address.
781 * n.n.n.n = IP address. /nn - netmask.
782 *
783 * proto: Optional protocol field. Either a name or
784 * number. Known names are in FilterProtoName[].
785 *
786 * dstport: Keyword for destination port. Only valid with tcp
787 * or udp. 'cmp' are in FilterPortType[]. 'value' can be
788 * a name or number.
789 *
790 * srcport: Keyword for source port. Only valid with tcp
791 * or udp. 'cmp' are in FilterPortType[]. 'value' can be
792 * a name or number.
793 *
794 * est: Keyword for TCP established. Valid only for tcp.
795 *
796 */
797static int ascend_parse_ip(int argc, char **argv, ascend_ip_filter_t *filter)
798{
799 int slen;
800 int token;
801 int flags;
802
803 /*
804 * We may have nothing, in which case we simply return.
805 */
806 if (argc == 0) return 0;
807
808 /*
809 * There may, or may not, be src & dst IP's in the string.
810 */
811 flags = 0;
812 while ((argc > 0) && (flags != DONE_FLAGS)) {
813 token = fr_table_value_by_str(filterKeywords, argv[0], -1);
814 switch (token) {
815 case FILTER_IP_SRC:
816 if (flags & IP_SRC_ADDR_FLAG) {
817 duplicate:
818 fr_strerror_printf("Duplicate field '%s' when parsing 'abinary' IP type", argv[0]);
819 return -1;
820 }
821 if (argc < 2) {
822 insufficient:
823 fr_strerror_printf("Insufficient arguments for '%s' when parsing 'abinary' IP type", argv[0]);
824 return -1;
825 }
826
827 slen = ascend_parse_ipaddr(&filter->srcip, argv[1]);
828 if (slen < 0) return slen;
829
830 filter->srcmask = slen;
831 flags |= IP_SRC_ADDR_FLAG;
832 argv += 2;
833 argc -= 2;
834 break;
835
836 case FILTER_IP_DST:
837 if (flags & IP_DEST_ADDR_FLAG) goto duplicate;
838 if (argc < 2) goto insufficient;
839
840 slen = ascend_parse_ipaddr(&filter->dstip, argv[1]);
841 if (slen < 0) return slen;
842
843 filter->dstmask = slen;
844 flags |= IP_DEST_ADDR_FLAG;
845 argv += 2;
846 argc -= 2;
847 break;
848
850 if (flags & IP_SRC_PORT_FLAG) goto duplicate;
851 if (argc < 3) goto insufficient;
852
853 slen = ascend_parse_port(&filter->srcport,
854 argv[1], argv[2]);
855 if (slen < 0) return slen;
856 filter->srcPortComp = slen;
857
858 flags |= IP_SRC_PORT_FLAG;
859 argv += 3;
860 argc -= 3;
861 break;
862
864 if (flags & IP_DEST_PORT_FLAG) goto duplicate;
865 if (argc < 3) goto insufficient;
866
867 slen = ascend_parse_port(&filter->dstport,
868 argv[1], argv[2]);
869 if (slen < 0) return slen;
870 filter->dstPortComp = slen;
871
872 flags |= IP_DEST_PORT_FLAG;
873 argv += 3;
874 argc -= 3;
875 break;
876
877 case FILTER_EST:
878 if (flags & IP_EST_FLAG) goto duplicate;
879 filter->established = 1;
880 argv++;
881 argc--;
882 flags |= IP_EST_FLAG;
883 break;
884
885 default:
886 if (flags & IP_PROTO_FLAG) goto duplicate;
887 if (strspn(argv[0], "0123456789") == strlen(argv[0])) {
888 token = atoi(argv[0]);
889 } else {
890 token = fr_table_value_by_str(filterProtoName, argv[0], -1);
891 if (token == -1) {
892 fr_strerror_printf("Unknown IP protocol \"%s\" in IP data filter",
893 argv[0]);
894 return -1;
895 }
896 }
897 filter->proto = token;
898 flags |= IP_PROTO_FLAG;
899
900 argv++;
901 argc--;
902 break;
903 }
904 }
905
906 /*
907 * We should have parsed everything by now.
908 */
909 if (argc != 0) {
910 fr_strerror_printf("Unknown extra string \"%s\" in IP data filter",
911 argv[0]);
912 return -1;
913 }
914
915 return 0;
916}
917
918/*
919 * ascend_parse_ipv6:
920 *
921 * Exactly like ascend_parse_ip(), but allows for IPv6 addresses.
922 *
923 * From https://www.juniper.net/documentation/en_US/junos/topics/reference/general/ascend-data-filter-fields.html
924 */
925static int ascend_parse_ipv6(int argc, char **argv, ascend_ipv6_filter_t *filter)
926{
927 ssize_t slen;
928 int token;
929 int flags;
930
931 /*
932 * We may have nothing, in which case we simply return.
933 */
934 if (argc == 0) return 0;
935
936 /*
937 * There may, or may not, be src & dst IP's in the string.
938 */
939 flags = 0;
940 while ((argc > 0) && (flags != DONE_FLAGS)) {
941 fr_ipaddr_t ipaddr;
942
943 token = fr_table_value_by_str(filterKeywords, argv[0], -1);
944 switch (token) {
945 case FILTER_IP_SRC:
946 if (flags & IP_SRC_ADDR_FLAG) {
947 duplicate:
948 fr_strerror_printf("Duplicate field '%s' when parsing 'abinary' IPv6 type", argv[0]);
949 return -1;
950 }
951 if (argc < 2) {
952 insufficient:
953 fr_strerror_printf("Insufficient arguments for '%s' when parsing 'abinary' IPv6 type", argv[0]);
954 return -1;
955 }
956
957 if (fr_inet_pton6(&ipaddr, argv[1], strlen(argv[1]), false, false, true) < 0) return -1;
958 memcpy(&filter->srcip, ipaddr.addr.v6.s6_addr, 16);
959 filter->srcmask = ipaddr.prefix;
960
961 flags |= IP_SRC_ADDR_FLAG;
962 argv += 2;
963 argc -= 2;
964 break;
965
966 case FILTER_IP_DST:
967 if (flags & IP_DEST_ADDR_FLAG) goto duplicate;
968 if (argc < 2) goto insufficient;
969
970 if (fr_inet_pton6(&ipaddr, argv[1], strlen(argv[1]), false, false, true) < 0) return -1;
971 memcpy(&filter->dstip, ipaddr.addr.v6.s6_addr, 16);
972 filter->dstmask = ipaddr.prefix;
973
974 flags |= IP_DEST_ADDR_FLAG;
975 argv += 2;
976 argc -= 2;
977 break;
978
980 if (flags & IP_SRC_PORT_FLAG) goto duplicate;
981 if (argc < 3) goto insufficient;
982
983 slen = ascend_parse_port(&filter->srcport,
984 argv[1], argv[2]);
985 if (slen < 0) return slen;
986 filter->srcPortComp = slen;
987
988 flags |= IP_SRC_PORT_FLAG;
989 argv += 3;
990 argc -= 3;
991 break;
992
994 if (flags & IP_DEST_PORT_FLAG) goto duplicate;
995 if (argc < 3) goto insufficient;
996
997 slen = ascend_parse_port(&filter->dstport,
998 argv[1], argv[2]);
999 if (slen < 0) return slen;
1000 filter->dstPortComp = slen;
1001
1002 flags |= IP_DEST_PORT_FLAG;
1003 argv += 3;
1004 argc -= 3;
1005 break;
1006
1007 case FILTER_EST:
1008 if (flags & IP_EST_FLAG) goto duplicate;
1009 filter->established = 1;
1010 argv++;
1011 argc--;
1012 flags |= IP_EST_FLAG;
1013 break;
1014
1015 default:
1016 if (flags & IP_PROTO_FLAG) goto duplicate;
1017 if (strspn(argv[0], "0123456789") == strlen(argv[0])) {
1018 token = atoi(argv[0]);
1019 } else {
1020 token = fr_table_value_by_str(filterProtoName, argv[0], -1);
1021 if (token == -1) {
1022 fr_strerror_printf("Unknown IPv6 protocol \"%s\" in IP data filter",
1023 argv[0]);
1024 return -1;
1025 }
1026 }
1027 filter->proto = token;
1028 flags |= IP_PROTO_FLAG;
1029
1030 argv++;
1031 argc--;
1032 break;
1033 }
1034 }
1035
1036 /*
1037 * We should have parsed everything by now.
1038 */
1039 if (argc != 0) {
1040 fr_strerror_printf("Unknown extra string \"%s\" in IPv6 data filter",
1041 argv[0]);
1042 return -1;
1043 }
1044
1045 return 0;
1046}
1047
1048
1049/*
1050 * ascend_parse_generic
1051 *
1052 * This routine parses a Generic filter string from a RADIUS
1053 * reply. The format of the string is:
1054 *
1055 * generic dir action offset mask value [== or != ] [more]
1056 *
1057 * Fields in [...] are optional.
1058 *
1059 * offset: A Number. Specifies an offset into a frame
1060 * to start comparing.
1061 *
1062 * mask: A hexadecimal mask of bits to compare.
1063 *
1064 * value: A value to compare with the masked data.
1065 *
1066 * compNeq: Defines type of comparison. ( "==" or "!=")
1067 * Default is "==".
1068 *
1069 * more: Optional keyword MORE, to represent the attachment
1070 * to the next entry.
1071 */
1072static int ascend_parse_generic(int argc, char **argv,
1074{
1075 int slen;
1076 int token;
1077 int flags;
1078
1079 /*
1080 * We may have nothing, in which case we simply return.
1081 */
1082 if (argc == 0) return 0;
1083
1084 /*
1085 * We need at least "offset mask value"
1086 */
1087 if (argc < 3) {
1088 fr_strerror_const("Insufficient arguments to parse 'abinary' generic type");
1089 return -1;
1090 }
1091
1092 /*
1093 * No more than optional comparison and "more"
1094 */
1095 if (argc > 5) {
1096 fr_strerror_const("Too many arguments to parse 'abinary' generic type");
1097 return -1;
1098 }
1099
1100 /*
1101 * Offset is a uint16_t number.
1102 */
1103 if (strspn(argv[0], "0123456789") != strlen(argv[0])) {
1104 invalid:
1105 fr_strerror_printf("Invalid offset '%s'", argv[0]);
1106 return -1;
1107 }
1108
1109 slen = atoi(argv[0]);
1110 if (slen > 65535) goto invalid;
1111
1112 filter->offset = slen;
1113 filter->offset = htons(filter->offset);
1114
1115 slen = fr_base16_decode(NULL,
1116 &FR_DBUFF_TMP(filter->mask, sizeof(filter->mask)),
1117 &FR_SBUFF_IN(argv[1], strlen(argv[1])), false);
1118 if (slen != sizeof(filter->mask)) {
1119 fr_strerror_printf("Invalid filter mask '%s'", argv[1]);
1120 return -1;
1121 }
1122
1123 token = fr_base16_decode(NULL,
1124 &FR_DBUFF_TMP(filter->value, sizeof(filter->value)),
1125 &FR_SBUFF_IN(argv[2], strlen(argv[2])), false);
1126 if (token != sizeof(filter->value)) {
1127 fr_strerror_printf("Invalid filter mask '%s'", argv[1]);
1128 return -1;
1129 }
1130
1131 filter->len = slen;
1132 filter->len = htons(filter->len);
1133
1134 /*
1135 * Nothing more. Exit.
1136 */
1137 if (argc == 3) return 0;
1138
1139 argc -= 3;
1140 argv += 3;
1141 flags = 0;
1142
1143 while (argc >= 1) {
1144 token = fr_table_value_by_str(filterKeywords, argv[0], -1);
1145 switch (token) {
1147 if (flags & 0x01) {
1148 duplicate:
1149 fr_strerror_printf("Duplicate field '%s' when parsing 'abinary' generic type", argv[0]);
1150 return -1;
1151 }
1152 filter->compNeq = true;
1153 flags |= 0x01;
1154 break;
1156 if (flags & 0x01) goto duplicate;
1157 filter->compNeq = false;
1158 flags |= 0x01;
1159 break;
1160
1161 case FILTER_MORE:
1162 if (flags & 0x02) goto duplicate;
1163 filter->more = htons( 1 );
1164 flags |= 0x02;
1165 break;
1166
1167 default:
1168 fr_strerror_printf("Invalid string \"%s\" in generic data filter",
1169 argv[0]);
1170 return -1;
1171 }
1172
1173 argc--;
1174 argv++;
1175 }
1176
1177 return 0;
1178}
1179
1180
1181/** Encode a string to abinary.
1182 *
1183 * This routine will call routines to parse entries from an ASCII format
1184 * to a binary format recognized by the Ascend boxes.
1185 *
1186 * @param vp VP to encode
1187 * @param dbuff where to write the VP data
1188 * @return
1189 * - >0 on success == size of the data encoded
1190 * - <=0 on failure, which is the size needed to encode the data
1191 */
1193{
1194 int token, type;
1195 int slen = 0;
1196 int argc;
1197 char *argv[32];
1198 ascend_filter_t filter;
1199 char *p;
1200 size_t size = 0;
1201
1202 /*
1203 * Tokenize the input string in the VP.
1204 *
1205 * Once the filter is *completely* parsed, then we will
1206 * over-write it with the final binary filter.
1207 */
1208 p = talloc_bstrndup(NULL, vp->vp_strvalue, vp->vp_length);
1209
1210 argc = fr_dict_str_to_argv(p, argv, 32);
1211 if (argc < 3) {
1212 fr_strerror_const("Insufficient arguments to parse 'abinary' type");
1213 fail:
1214 talloc_free(p);
1215 return 0;
1216 }
1217
1218 /*
1219 * Decide which filter type it is: ip, ipx, or generic
1220 */
1221 type = fr_table_value_by_str(filterType, argv[0], -1);
1222 memset(&filter, 0, sizeof(filter));
1223
1224 /*
1225 * Validate the filter type.
1226 */
1227 switch (type) {
1229 case ASCEND_FILTER_IP:
1230 case ASCEND_FILTER_IPX:
1231 case ASCEND_FILTER_IPV6:
1232 filter.type = type;
1233 break;
1234
1235 default:
1236 fr_strerror_printf("Unknown Ascend filter type \"%s\"", argv[0]);
1237 goto fail;
1238 }
1239
1240 /*
1241 * Parse direction
1242 */
1243 token = fr_table_value_by_str(filterKeywords, argv[1], -1);
1244 switch (token) {
1245 case FILTER_IN:
1246 filter.direction = 1;
1247 break;
1248
1249 case FILTER_OUT:
1250 filter.direction = 0;
1251 break;
1252
1253 default:
1254 fr_strerror_printf("Unknown Ascend filter direction \"%s\"", argv[1]);
1255 goto fail;
1256 }
1257
1258 /*
1259 * Parse action
1260 */
1261 token = fr_table_value_by_str(filterKeywords, argv[2], -1);
1262 switch (token) {
1263 case FILTER_FORWARD:
1264 filter.forward = 1;
1265 break;
1266
1267 case FILTER_DROP:
1268 filter.forward = 0;
1269 break;
1270
1271 default:
1272 fr_strerror_printf("Unknown Ascend filter action \"%s\"", argv[2]);
1273 goto fail;
1274 }
1275
1276 switch (type) {
1278 slen = ascend_parse_generic(argc - 3, &argv[3], &filter.generic);
1279 size = 32;
1280 break;
1281
1282 case ASCEND_FILTER_IP:
1283 slen = ascend_parse_ip(argc - 3, &argv[3], &filter.ip);
1284 size = 32;
1285 break;
1286
1287 case ASCEND_FILTER_IPX:
1288 slen = ascend_parse_ipx(argc - 3, &argv[3], &filter.ipx);
1289 size = 32;
1290 break;
1291
1292 case ASCEND_FILTER_IPV6:
1293 slen = ascend_parse_ipv6(argc - 3, &argv[3], &filter.ipv6);
1294 size = sizeof(filter);
1295 break;
1296 }
1297
1298 if (slen < 0) goto fail;
1299
1300 talloc_free(p);
1301
1302 return fr_dbuff_in_memcpy(dbuff, (uint8_t *)&filter, size);
1303}
1304
1305/** Print an Ascend binary filter attribute to a string,
1306 *
1307 * Grrr... Ascend makes the server do this work, instead of doing it on the NAS.
1308 *
1309 * @param[in,out] vp Where the decoded string will be stored.
1310 * @param[in] data binary data to decodee
1311 * @param[in] data_len length of the binary data to decodee
1312 * @return
1313 * - 0 OK
1314 * - <0 on error. VP is untouched.
1315 */
1317{
1318 ascend_filter_t const *filter;
1319 size_t size;
1320 fr_ipaddr_t ipaddr;
1322 char string[256];
1323 fr_sbuff_t sbuff = FR_SBUFF_OUT(string, sizeof(string));
1324 uint64_t aligned[256 / sizeof(uint64_t)];
1325
1326 static char const *action[] = {"drop", "forward"};
1327 static char const *direction[] = {"out", "in"};
1328
1329 /*
1330 * Just for paranoia: wrong size filters get printed as octets
1331 */
1332 if (data_len < 4) return -1;
1333
1334 /*
1335 * ascend data filters aren't concatenated across
1336 * multiple RADIUS attributes.
1337 */
1338 if (data_len > RADIUS_MAX_STRING_LENGTH) return -1;
1339
1340 memcpy(aligned, data, data_len);
1341
1342 filter = (ascend_filter_t const *) aligned;
1343
1344 switch ((ascend_filter_type_t)filter->type) {
1345 case ASCEND_FILTER_IP:
1346 size = sizeof(filter->ip);
1347 break;
1348
1349 case ASCEND_FILTER_IPX:
1350 size = sizeof(filter->ipx);
1351 break;
1352
1354 size = sizeof(filter->generic);
1355 break;
1356
1357 case ASCEND_FILTER_IPV6:
1358 size = sizeof(filter->ipv6);
1359 break;
1360
1361 default:
1362 return -1;
1363 }
1364
1365 if (data_len < size) return -size;
1366
1367 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, "%s %s %s", fr_table_str_by_value(filterType, filter->type, "??"),
1368 direction[filter->direction & 0x01], action[filter->forward & 0x01]);
1369
1370 switch ((ascend_filter_type_t)filter->type) {
1371
1372 /*
1373 * Handle IP filters
1374 */
1375 case ASCEND_FILTER_IP:
1376 if (filter->ip.srcip) {
1377 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcip %d.%d.%d.%d/%d",
1378 ((uint8_t const *) &filter->ip.srcip)[0],
1379 ((uint8_t const *) &filter->ip.srcip)[1],
1380 ((uint8_t const *) &filter->ip.srcip)[2],
1381 ((uint8_t const *) &filter->ip.srcip)[3],
1382 filter->ip.srcmask);
1383 }
1384
1385 if (filter->ip.dstip) {
1386 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstip %d.%d.%d.%d/%d",
1387 ((uint8_t const *) &filter->ip.dstip)[0],
1388 ((uint8_t const *) &filter->ip.dstip)[1],
1389 ((uint8_t const *) &filter->ip.dstip)[2],
1390 ((uint8_t const *) &filter->ip.dstip)[3],
1391 filter->ip.dstmask);
1392 }
1393
1394 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " %s", fr_table_str_by_value(filterProtoName, filter->ip.proto, "??"));
1395
1396 if (filter->ip.srcPortComp > RAD_NO_COMPARE) {
1397 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcport %s %d",
1398 fr_table_str_by_value(filterCompare, filter->ip.srcPortComp, "??"),
1399 ntohs(filter->ip.srcport));
1400 }
1401
1402 if (filter->ip.dstPortComp > RAD_NO_COMPARE) {
1403 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstport %s %d",
1404 fr_table_str_by_value(filterCompare, filter->ip.dstPortComp, "??"),
1405 ntohs(filter->ip.dstport));
1406 }
1407
1408 if (filter->ip.established) {
1409 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " est");
1410 }
1411 break;
1412
1413 /*
1414 * Handle IPX filters
1415 */
1416 case ASCEND_FILTER_IPX:
1417 /* print for source */
1418 if (filter->ipx.src.net) {
1419 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcipxnet 0x%04x srcipxnode 0x%02x%02x%02x%02x%02x%02x",
1420 (unsigned int)ntohl(filter->ipx.src.net),
1421 filter->ipx.src.node[0], filter->ipx.src.node[1],
1422 filter->ipx.src.node[2], filter->ipx.src.node[3],
1423 filter->ipx.src.node[4], filter->ipx.src.node[5]);
1424
1425 if (filter->ipx.srcSocComp > RAD_NO_COMPARE) {
1426 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcipxsock %s 0x%04x",
1427 fr_table_str_by_value(filterCompare, filter->ipx.srcSocComp, "??"),
1428 ntohs(filter->ipx.src.socket));
1429 }
1430 }
1431
1432 /* same for destination */
1433 if (filter->ipx.dst.net) {
1434 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstipxnet 0x%04x dstipxnode 0x%02x%02x%02x%02x%02x%02x",
1435 (unsigned int)ntohl(filter->ipx.dst.net),
1436 filter->ipx.dst.node[0], filter->ipx.dst.node[1],
1437 filter->ipx.dst.node[2], filter->ipx.dst.node[3],
1438 filter->ipx.dst.node[4], filter->ipx.dst.node[5]);
1439
1440 if (filter->ipx.dstSocComp > RAD_NO_COMPARE) {
1441 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstipxsock %s 0x%04x",
1442 fr_table_str_by_value(filterCompare, filter->ipx.dstSocComp, "??"),
1443 ntohs(filter->ipx.dst.socket));
1444 }
1445 }
1446 break;
1447
1449 {
1450 size_t i, len;
1451
1452 /*
1453 * Why is len 16 bits, when the masks are only 6 bytes?
1454 */
1455 len = ntohs(filter->generic.len);
1456 if (len >= sizeof(filter->generic.mask)) {
1457 return -size;
1458 }
1459
1460 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " %u ", (unsigned int) ntohs(filter->generic.offset));
1461
1462 /* show the mask */
1463 for (i = 0; i < len; i++) {
1464 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, "%02x", filter->generic.mask[i]);
1465 }
1466
1467 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " ");
1468
1469 /* show the value */
1470 for (i = 0; i < len; i++) {
1471 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, "%02x", filter->generic.value[i]);
1472 }
1473
1474 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " %s", (filter->generic.compNeq) ? "!=" : "==");
1475
1476 if (filter->generic.more != 0) {
1477 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " more");
1478 }
1479 }
1480 break;
1481
1482 /*
1483 * Handle IPv6 filters
1484 */
1485 case ASCEND_FILTER_IPV6:
1486 /*
1487 * srcip
1488 */
1489 memset(&ipaddr, 0, sizeof(ipaddr));
1490 ipaddr.af = AF_INET6;
1491 memcpy(&ipaddr.addr.v6.s6_addr, filter->ipv6.srcip, sizeof(filter->ipv6.srcip));
1492 ipaddr.prefix = filter->ipv6.srcmask;
1493
1494 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " srcip ");
1495
1496 (void) fr_inet_ntop_prefix(buffer, sizeof(buffer), &ipaddr);
1498
1499 /*
1500 * dstip
1501 */
1502 memset(&ipaddr, 0, sizeof(ipaddr));
1503 ipaddr.af = AF_INET6;
1504 memcpy(&ipaddr.addr.v6.s6_addr, filter->ipv6.dstip, sizeof(filter->ipv6.dstip));
1505 ipaddr.prefix = filter->ipv6.dstmask;
1506
1507 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " dstip ");
1508
1509 (void) fr_inet_ntop_prefix(buffer, sizeof(buffer), &ipaddr);
1511
1512 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " %s", fr_table_str_by_value(filterProtoName, filter->ipv6.proto, "??"));
1513
1514 if (filter->ipv6.srcPortComp > RAD_NO_COMPARE) {
1515 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcport %s %d",
1516 fr_table_str_by_value(filterCompare, filter->ipv6.srcPortComp, "??"),
1517 ntohs(filter->ipv6.srcport));
1518 }
1519
1520 if (filter->ipv6.dstPortComp > RAD_NO_COMPARE) {
1521 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstport %s %d",
1522 fr_table_str_by_value(filterCompare, filter->ipv6.dstPortComp, "??"),
1523 ntohs(filter->ipv6.dstport));
1524 }
1525
1526 if (filter->ipv6.established) {
1527 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " est");
1528 }
1529 break;
1530
1531 default:
1532 break;
1533 }
1534
1535 /*
1536 * Copy the finished string to the output VP.
1537 */
1538 if (fr_pair_value_strdup(vp, string, true) < 0) return -1;
1539
1540 return 0;
1541}
#define IP_DEST_ADDR_FLAG
Definition abinary.c:756
uint8_t value[RAD_MAX_FILTER_LEN]
Definition abinary.c:225
uint8_t established
Definition abinary.c:97
ascend_ipx_net_t dst
Definition abinary.c:190
#define IP_SRC_PORT_FLAG
Definition abinary.c:757
static fr_table_num_sorted_t const filterType[]
Definition abinary.c:295
#define DONE_FLAGS
Definition abinary.c:762
uint32_t net
Definition abinary.c:169
ssize_t fr_radius_decode_abinary(fr_pair_t *vp, uint8_t const *data, size_t data_len)
Print an Ascend binary filter attribute to a string,.
Definition abinary.c:1316
#define IP_PROTO_FLAG
Definition abinary.c:759
#define IP_SRC_ADDR_FLAG
Definition abinary.c:755
ascend_ipx_net_t src
Definition abinary.c:189
uint16_t socket
Definition abinary.c:171
uint8_t fill
Definition abinary.c:256
static size_t filterPortType_len
Definition abinary.c:293
FilterTokens
Definition abinary.c:303
@ FILTER_GENERIC_COMPNEQ
Definition abinary.c:308
@ FILTER_IPX_SRC_IPXNET
Definition abinary.c:320
@ FILTER_IP_SRC_PORT
Definition abinary.c:315
@ FILTER_IP_DST_PORT
Definition abinary.c:314
@ FILTER_IPX_SRC_IPXSOCK
Definition abinary.c:322
@ FILTER_OUT
Definition abinary.c:305
@ FILTER_IPX_SRC_IPXNODE
Definition abinary.c:321
@ FILTER_IPX_DST_IPXNODE
Definition abinary.c:318
@ FILTER_MORE
Definition abinary.c:310
@ FILTER_IPX_DST_IPXSOCK
Definition abinary.c:319
@ FILTER_IP_DST
Definition abinary.c:311
@ FILTER_GENERIC_COMPEQ
Definition abinary.c:309
@ FILTER_EST
Definition abinary.c:316
@ FILTER_IP_SRC
Definition abinary.c:312
@ FILTER_DROP
Definition abinary.c:307
@ FILTER_IN
Definition abinary.c:304
@ FILTER_IPX_DST_IPXNET
Definition abinary.c:317
@ FILTER_IP_PROTO
Definition abinary.c:313
@ FILTER_FORWARD
Definition abinary.c:306
uint8_t dstPortComp
Definition abinary.c:101
static int ascend_parse_ipx(int argc, char **argv, ascend_ipx_filter_t *filter)
Definition abinary.c:540
static int ascend_parse_ip(int argc, char **argv, ascend_ip_filter_t *filter)
Definition abinary.c:797
uint8_t forward
Definition abinary.c:254
uint8_t srcPortComp
Definition abinary.c:100
static size_t filterType_len
Definition abinary.c:301
static int ascend_parse_ipx_net(int argc, char **argv, ascend_ipx_net_t *net, uint8_t *comp)
Definition abinary.c:391
static size_t filterCompare_len
Definition abinary.c:384
uint32_t dstip
Definition abinary.c:93
uint8_t node[IPX_NODE_ADDR_LEN]
Definition abinary.c:170
uint8_t dstip[16]
Definition abinary.c:145
uint8_t srcip[16]
Definition abinary.c:144
uint16_t srcport
Definition abinary.c:98
static int ascend_parse_generic(int argc, char **argv, ascend_generic_filter_t *filter)
Definition abinary.c:1072
#define IPX_NODE_ADDR_LEN
Definition abinary.c:53
uint8_t mask[RAD_MAX_FILTER_LEN]
Definition abinary.c:224
#define IP_EST_FLAG
Definition abinary.c:760
static fr_table_num_sorted_t const filterPortType[]
Definition abinary.c:273
uint8_t direction
Definition abinary.c:255
uint8_t srcmask
Definition abinary.c:94
ascend_filter_type_t
Definition abinary.c:36
@ ASCEND_FILTER_IP
Definition abinary.c:38
@ ASCEND_FILTER_GENERIC
Definition abinary.c:37
@ ASCEND_FILTER_IPV6
Definition abinary.c:40
@ ASCEND_FILTER_IPX
Definition abinary.c:39
uint16_t dstport
Definition abinary.c:99
static fr_table_num_sorted_t const filterCompare[]
Definition abinary.c:378
RadFilterComparison
Definition abinary.c:370
@ RAD_NO_COMPARE
Definition abinary.c:371
@ RAD_COMPARE_LESS
Definition abinary.c:372
@ RAD_COMPARE_GREATER
Definition abinary.c:374
@ RAD_COMPARE_NOT_EQUAL
Definition abinary.c:375
@ RAD_COMPARE_EQUAL
Definition abinary.c:373
static int ascend_parse_ipv6(int argc, char **argv, ascend_ipv6_filter_t *filter)
Definition abinary.c:925
static int ascend_parse_port(uint16_t *port, char *compare, char *str)
Definition abinary.c:724
static size_t filterKeywords_len
Definition abinary.c:346
#define IP_DEST_PORT_FLAG
Definition abinary.c:758
uint8_t dstmask
Definition abinary.c:95
uint8_t type
Definition abinary.c:253
static size_t filterProtoName_len
Definition abinary.c:362
ssize_t fr_radius_encode_abinary(fr_pair_t const *vp, fr_dbuff_t *dbuff)
Encode a string to abinary.
Definition abinary.c:1192
static fr_table_num_sorted_t const filterProtoName[]
Definition abinary.c:355
static int ascend_parse_ipaddr(uint32_t *ipaddr, char *str)
Definition abinary.c:618
uint32_t srcip
Definition abinary.c:92
#define RAD_MAX_FILTER_LEN
Definition abinary.c:47
static fr_table_num_sorted_t const filterKeywords[]
Definition abinary.c:326
static int const char char buffer[256]
Definition acutest.h:576
#define fr_base16_decode(_err, _out, _in, _no_trailing)
Definition base16.h:95
#define RCSID(id)
Definition build.h:483
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define NUM_ELEMENTS(_t)
Definition build.h:337
#define fr_dbuff_in_memcpy(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into a dbuff or marker.
Definition dbuff.h:1350
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:514
int fr_dict_str_to_argv(char *str, char **argv, int max_argc)
Test enumeration values.
Definition dict_test.h:92
char * fr_inet_ntop_prefix(char out[static FR_IPADDR_PREFIX_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
Print a fr_ipaddr_t as a CIDR style network prefix.
Definition inet.c:1073
int fr_inet_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask)
Parse an IPv6 address or IPv6 prefix in presentation format (and others)
Definition inet.c:629
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
Definition inet.h:69
int af
Address family.
Definition inet.h:64
#define FR_IPADDR_PREFIX_STRLEN
Like FR_IPADDR_STRLEN but with space for a prefix.
Definition inet.h:93
union fr_ipaddr_t::@130 addr
IPv4/6 prefix.
talloc_free(reap)
unsigned short uint16_t
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2634
#define RADIUS_MAX_STRING_LENGTH
Definition radius.h:35
static int8_t comp(void const *a, void const *b)
Definition rbmonkey.c:13
static uint32_t mask
Definition rbmonkey.c:39
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
return count
Definition module.c:163
fr_aka_sim_id_type_t type
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition talloc.c:564
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
static fr_slen_t data
Definition value.h:1265