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: 54b36d4a0a4fdcd6f5743a9a0be5ea055caaa640 $")
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_STR(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 bool have_netmask = false;
624 uint32_t netmask = 0;
625
626 /*
627 * Look for IP's.
628 */
629 count = 0;
630 while (*str && (count < 4) && (netmask == 0)) {
631 next:
632 ip[count] = 0;
633
634 while (*str) {
635 switch (*str) {
636 case '0': case '1': case '2': case '3':
637 case '4': case '5': case '6': case '7':
638 case '8': case '9':
639 ip[count] *= 10;
640 ip[count] += (*str) - '0';
641 str++;
642 break;
643
644
645 case '.': /* dot between IP numbers. */
646 str++;
647 if (ip[count] > 255) {
648 fr_strerror_printf("Invalid IP address in '%s'", str);
649 return -1;
650 }
651
652 /*
653 * 24, 16, 8, 0, done.
654 */
655 *ipaddr |= (ip[count] << (8 * (3 - count)));
656 count++;
657 goto next;
658
659 case '/': /* netmask */
660 str++;
661 have_netmask = true;
662 masklen = atoi(str);
663 if ((masklen < 0) || (masklen > 32)) {
664 fr_strerror_printf("Invalid mask in '%s'", str);
665 return -1;
666 }
667 str += strspn(str, "0123456789");
668 netmask = masklen;
669 goto finalize;
670
671 default:
672 fr_strerror_const("Invalid character in IP address");
673 return -1;
674 }
675 } /* loop over one character */
676 } /* loop until the count hits 4 */
677
678 if (count == 3) {
679 finalize:
680 /*
681 * Do the last one, too.
682 */
683 if (ip[count] > 255) {
684 fr_strerror_printf("Invalid mask in '%s'", str);
685 return -1;
686 }
687
688 /*
689 * 24, 16, 8, 0, done.
690 */
691 *ipaddr |= (ip[count] << (8 * (3 - count)));
692 }
693
694 /*
695 * We've hit the end of the IP address, and there's something
696 * else left over: die.
697 */
698 if (*str) return -1;
699
700 /*
701 * Set the default netmask.
702 */
703 if (!have_netmask) {
704 if (!*ipaddr) {
705 netmask = 0;
706 } else if ((*ipaddr & 0x80000000) == 0) {
707 netmask = 8;
708 } else if ((*ipaddr & 0xc0000000) == 0x80000000) {
709 netmask = 16;
710 } else if ((*ipaddr & 0xe0000000) == 0xc0000000) {
711 netmask = 24;
712 } else {
713 netmask = 32;
714 }
715 }
716
717 *ipaddr = htonl(*ipaddr);
718 return netmask;
719}
720
721/*
722 * ascend_parse_port: Parse a comparator and port.
723 *
724 * Returns -1 on failure, or the comparator.
725 */
726static int ascend_parse_port(uint16_t *port, char *compare, char *str)
727{
728 int slen, token;
729
730 /*
731 * There MUST be a comparison string.
732 */
733 slen = fr_table_value_by_str(filterCompare, compare, -1);
734 if (slen < 0) {
735 fr_strerror_printf("Unknown comparison operator '%s'", compare);
736 return slen;
737 }
738
739 if (strspn(str, "0123456789") == strlen(str)) {
740 token = atoi(str);
741 } else {
742 token = fr_table_value_by_str(filterPortType, str, -1);
743 }
744
745 if ((token < 0) || (token > 65535)) {
746 fr_strerror_printf("Unknown port name '%s'", str);
747 return -1;
748 }
749
750 *port = token;
751 *port = htons(*port);
752
753 return slen;
754}
755
756
757#define IP_SRC_ADDR_FLAG (1 << 0)
758#define IP_DEST_ADDR_FLAG (1 << 1)
759#define IP_SRC_PORT_FLAG (1 << 2)
760#define IP_DEST_PORT_FLAG (1 << 3)
761#define IP_PROTO_FLAG (1 << 4)
762#define IP_EST_FLAG (1 << 5)
763
764#define DONE_FLAGS (IP_SRC_ADDR_FLAG | IP_DEST_ADDR_FLAG | \
765 IP_SRC_PORT_FLAG | IP_DEST_PORT_FLAG | \
766 IP_PROTO_FLAG | IP_EST_FLAG)
767
768/*
769 * ascend_parse_ip:
770 *
771 * This routine parses an IP filter string from a RADIUS
772 * reply. The format of the string is:
773 *
774 * ip dir action [ dstip n.n.n.n/nn ] [ srcip n.n.n.n/nn ]
775 * [ proto [ dstport cmp value ] [ srcport cmd value ] [ est ] ]
776 *
777 * Fields in [...] are optional.
778 *
779 * dstip: Keyword for destination IP address.
780 * n.n.n.n = IP address. /nn - netmask.
781 *
782 * srcip: Keyword for source IP address.
783 * n.n.n.n = IP address. /nn - netmask.
784 *
785 * proto: Optional protocol field. Either a name or
786 * number. Known names are in FilterProtoName[].
787 *
788 * dstport: Keyword for destination port. Only valid with tcp
789 * or udp. 'cmp' are in FilterPortType[]. 'value' can be
790 * a name or number.
791 *
792 * srcport: Keyword for source port. Only valid with tcp
793 * or udp. 'cmp' are in FilterPortType[]. 'value' can be
794 * a name or number.
795 *
796 * est: Keyword for TCP established. Valid only for tcp.
797 *
798 */
799static int ascend_parse_ip(int argc, char **argv, ascend_ip_filter_t *filter)
800{
801 int slen;
802 int token;
803 int flags;
804
805 /*
806 * We may have nothing, in which case we simply return.
807 */
808 if (argc == 0) return 0;
809
810 /*
811 * There may, or may not, be src & dst IP's in the string.
812 */
813 flags = 0;
814 while ((argc > 0) && (flags != DONE_FLAGS)) {
815 token = fr_table_value_by_str(filterKeywords, argv[0], -1);
816 switch (token) {
817 case FILTER_IP_SRC:
818 if (flags & IP_SRC_ADDR_FLAG) {
819 duplicate:
820 fr_strerror_printf("Duplicate field '%s' when parsing 'abinary' IP type", argv[0]);
821 return -1;
822 }
823 if (argc < 2) {
824 insufficient:
825 fr_strerror_printf("Insufficient arguments for '%s' when parsing 'abinary' IP type", argv[0]);
826 return -1;
827 }
828
829 slen = ascend_parse_ipaddr(&filter->srcip, argv[1]);
830 if (slen < 0) return slen;
831
832 filter->srcmask = slen;
833 flags |= IP_SRC_ADDR_FLAG;
834 argv += 2;
835 argc -= 2;
836 break;
837
838 case FILTER_IP_DST:
839 if (flags & IP_DEST_ADDR_FLAG) goto duplicate;
840 if (argc < 2) goto insufficient;
841
842 slen = ascend_parse_ipaddr(&filter->dstip, argv[1]);
843 if (slen < 0) return slen;
844
845 filter->dstmask = slen;
846 flags |= IP_DEST_ADDR_FLAG;
847 argv += 2;
848 argc -= 2;
849 break;
850
852 if (flags & IP_SRC_PORT_FLAG) goto duplicate;
853 if (argc < 3) goto insufficient;
854
855 slen = ascend_parse_port(&filter->srcport,
856 argv[1], argv[2]);
857 if (slen < 0) return slen;
858 filter->srcPortComp = slen;
859
860 flags |= IP_SRC_PORT_FLAG;
861 argv += 3;
862 argc -= 3;
863 break;
864
866 if (flags & IP_DEST_PORT_FLAG) goto duplicate;
867 if (argc < 3) goto insufficient;
868
869 slen = ascend_parse_port(&filter->dstport,
870 argv[1], argv[2]);
871 if (slen < 0) return slen;
872 filter->dstPortComp = slen;
873
874 flags |= IP_DEST_PORT_FLAG;
875 argv += 3;
876 argc -= 3;
877 break;
878
879 case FILTER_EST:
880 if (flags & IP_EST_FLAG) goto duplicate;
881 filter->established = 1;
882 argv++;
883 argc--;
884 flags |= IP_EST_FLAG;
885 break;
886
887 default:
888 if (flags & IP_PROTO_FLAG) goto duplicate;
889 if (strspn(argv[0], "0123456789") == strlen(argv[0])) {
890 token = atoi(argv[0]);
891 } else {
892 token = fr_table_value_by_str(filterProtoName, argv[0], -1);
893 if (token == -1) {
894 fr_strerror_printf("Unknown IP protocol \"%s\" in IP data filter",
895 argv[0]);
896 return -1;
897 }
898 }
899 filter->proto = token;
900 flags |= IP_PROTO_FLAG;
901
902 argv++;
903 argc--;
904 break;
905 }
906 }
907
908 /*
909 * We should have parsed everything by now.
910 */
911 if (argc != 0) {
912 fr_strerror_printf("Unknown extra string \"%s\" in IP data filter",
913 argv[0]);
914 return -1;
915 }
916
917 return 0;
918}
919
920/*
921 * ascend_parse_ipv6:
922 *
923 * Exactly like ascend_parse_ip(), but allows for IPv6 addresses.
924 *
925 * From https://www.juniper.net/documentation/en_US/junos/topics/reference/general/ascend-data-filter-fields.html
926 */
927static int ascend_parse_ipv6(int argc, char **argv, ascend_ipv6_filter_t *filter)
928{
929 ssize_t slen;
930 int token;
931 int flags;
932
933 /*
934 * We may have nothing, in which case we simply return.
935 */
936 if (argc == 0) return 0;
937
938 /*
939 * There may, or may not, be src & dst IP's in the string.
940 */
941 flags = 0;
942 while ((argc > 0) && (flags != DONE_FLAGS)) {
943 fr_ipaddr_t ipaddr;
944
945 token = fr_table_value_by_str(filterKeywords, argv[0], -1);
946 switch (token) {
947 case FILTER_IP_SRC:
948 if (flags & IP_SRC_ADDR_FLAG) {
949 duplicate:
950 fr_strerror_printf("Duplicate field '%s' when parsing 'abinary' IPv6 type", argv[0]);
951 return -1;
952 }
953 if (argc < 2) {
954 insufficient:
955 fr_strerror_printf("Insufficient arguments for '%s' when parsing 'abinary' IPv6 type", argv[0]);
956 return -1;
957 }
958
959 if (fr_inet_pton6(&ipaddr, argv[1], strlen(argv[1]), false, false, true) < 0) return -1;
960 memcpy(&filter->srcip, ipaddr.addr.v6.s6_addr, 16);
961 filter->srcmask = ipaddr.prefix;
962
963 flags |= IP_SRC_ADDR_FLAG;
964 argv += 2;
965 argc -= 2;
966 break;
967
968 case FILTER_IP_DST:
969 if (flags & IP_DEST_ADDR_FLAG) goto duplicate;
970 if (argc < 2) goto insufficient;
971
972 if (fr_inet_pton6(&ipaddr, argv[1], strlen(argv[1]), false, false, true) < 0) return -1;
973 memcpy(&filter->dstip, ipaddr.addr.v6.s6_addr, 16);
974 filter->dstmask = ipaddr.prefix;
975
976 flags |= IP_DEST_ADDR_FLAG;
977 argv += 2;
978 argc -= 2;
979 break;
980
982 if (flags & IP_SRC_PORT_FLAG) goto duplicate;
983 if (argc < 3) goto insufficient;
984
985 slen = ascend_parse_port(&filter->srcport,
986 argv[1], argv[2]);
987 if (slen < 0) return slen;
988 filter->srcPortComp = slen;
989
990 flags |= IP_SRC_PORT_FLAG;
991 argv += 3;
992 argc -= 3;
993 break;
994
996 if (flags & IP_DEST_PORT_FLAG) goto duplicate;
997 if (argc < 3) goto insufficient;
998
999 slen = ascend_parse_port(&filter->dstport,
1000 argv[1], argv[2]);
1001 if (slen < 0) return slen;
1002 filter->dstPortComp = slen;
1003
1004 flags |= IP_DEST_PORT_FLAG;
1005 argv += 3;
1006 argc -= 3;
1007 break;
1008
1009 case FILTER_EST:
1010 if (flags & IP_EST_FLAG) goto duplicate;
1011 filter->established = 1;
1012 argv++;
1013 argc--;
1014 flags |= IP_EST_FLAG;
1015 break;
1016
1017 default:
1018 if (flags & IP_PROTO_FLAG) goto duplicate;
1019 if (strspn(argv[0], "0123456789") == strlen(argv[0])) {
1020 token = atoi(argv[0]);
1021 } else {
1022 token = fr_table_value_by_str(filterProtoName, argv[0], -1);
1023 if (token == -1) {
1024 fr_strerror_printf("Unknown IPv6 protocol \"%s\" in IP data filter",
1025 argv[0]);
1026 return -1;
1027 }
1028 }
1029 filter->proto = token;
1030 flags |= IP_PROTO_FLAG;
1031
1032 argv++;
1033 argc--;
1034 break;
1035 }
1036 }
1037
1038 /*
1039 * We should have parsed everything by now.
1040 */
1041 if (argc != 0) {
1042 fr_strerror_printf("Unknown extra string \"%s\" in IPv6 data filter",
1043 argv[0]);
1044 return -1;
1045 }
1046
1047 return 0;
1048}
1049
1050
1051/*
1052 * ascend_parse_generic
1053 *
1054 * This routine parses a Generic filter string from a RADIUS
1055 * reply. The format of the string is:
1056 *
1057 * generic dir action offset mask value [== or != ] [more]
1058 *
1059 * Fields in [...] are optional.
1060 *
1061 * offset: A Number. Specifies an offset into a frame
1062 * to start comparing.
1063 *
1064 * mask: A hexadecimal mask of bits to compare.
1065 *
1066 * value: A value to compare with the masked data.
1067 *
1068 * compNeq: Defines type of comparison. ( "==" or "!=")
1069 * Default is "==".
1070 *
1071 * more: Optional keyword MORE, to represent the attachment
1072 * to the next entry.
1073 */
1074static int ascend_parse_generic(int argc, char **argv,
1076{
1077 int slen;
1078 int token;
1079 int flags;
1080
1081 /*
1082 * We may have nothing, in which case we simply return.
1083 */
1084 if (argc == 0) return 0;
1085
1086 /*
1087 * We need at least "offset mask value"
1088 */
1089 if (argc < 3) {
1090 fr_strerror_const("Insufficient arguments to parse 'abinary' generic type");
1091 return -1;
1092 }
1093
1094 /*
1095 * No more than optional comparison and "more"
1096 */
1097 if (argc > 5) {
1098 fr_strerror_const("Too many arguments to parse 'abinary' generic type");
1099 return -1;
1100 }
1101
1102 /*
1103 * Offset is a uint16_t number.
1104 */
1105 if (strspn(argv[0], "0123456789") != strlen(argv[0])) {
1106 invalid:
1107 fr_strerror_printf("Invalid offset '%s'", argv[0]);
1108 return -1;
1109 }
1110
1111 slen = atoi(argv[0]);
1112 if (slen > 65535) goto invalid;
1113
1114 filter->offset = slen;
1115 filter->offset = htons(filter->offset);
1116
1117 slen = fr_base16_decode(NULL,
1118 &FR_DBUFF_TMP(filter->mask, sizeof(filter->mask)),
1119 &FR_SBUFF_IN_STR(argv[1]), false);
1120 if (slen != sizeof(filter->mask)) {
1121 fr_strerror_printf("Invalid filter mask '%s'", argv[1]);
1122 return -1;
1123 }
1124
1125 token = fr_base16_decode(NULL,
1126 &FR_DBUFF_TMP(filter->value, sizeof(filter->value)),
1127 &FR_SBUFF_IN_STR(argv[2]), false);
1128 if (token != sizeof(filter->value)) {
1129 fr_strerror_printf("Invalid filter mask '%s'", argv[1]);
1130 return -1;
1131 }
1132
1133 filter->len = slen;
1134 filter->len = htons(filter->len);
1135
1136 /*
1137 * Nothing more. Exit.
1138 */
1139 if (argc == 3) return 0;
1140
1141 argc -= 3;
1142 argv += 3;
1143 flags = 0;
1144
1145 while (argc >= 1) {
1146 token = fr_table_value_by_str(filterKeywords, argv[0], -1);
1147 switch (token) {
1149 if (flags & 0x01) {
1150 duplicate:
1151 fr_strerror_printf("Duplicate field '%s' when parsing 'abinary' generic type", argv[0]);
1152 return -1;
1153 }
1154 filter->compNeq = true;
1155 flags |= 0x01;
1156 break;
1158 if (flags & 0x01) goto duplicate;
1159 filter->compNeq = false;
1160 flags |= 0x01;
1161 break;
1162
1163 case FILTER_MORE:
1164 if (flags & 0x02) goto duplicate;
1165 filter->more = htons( 1 );
1166 flags |= 0x02;
1167 break;
1168
1169 default:
1170 fr_strerror_printf("Invalid string \"%s\" in generic data filter",
1171 argv[0]);
1172 return -1;
1173 }
1174
1175 argc--;
1176 argv++;
1177 }
1178
1179 return 0;
1180}
1181
1182
1183/** Encode a string to abinary.
1184 *
1185 * This routine will call routines to parse entries from an ASCII format
1186 * to a binary format recognized by the Ascend boxes.
1187 *
1188 * @param vp VP to encode
1189 * @param dbuff where to write the VP data
1190 * @return
1191 * - >0 on success == size of the data encoded
1192 * - <=0 on failure, which is the size needed to encode the data
1193 */
1195{
1196 int token, type;
1197 int slen = 0;
1198 int argc;
1199 char *argv[32];
1200 ascend_filter_t filter;
1201 char *p;
1202 size_t size = 0;
1203
1204 /*
1205 * Tokenize the input string in the VP.
1206 *
1207 * Once the filter is *completely* parsed, then we will
1208 * over-write it with the final binary filter.
1209 */
1210 p = talloc_bstrndup(NULL, vp->vp_strvalue, vp->vp_length);
1211
1212 argc = fr_dict_str_to_argv(p, argv, 32);
1213 if (argc < 3) {
1214 fr_strerror_const("Insufficient arguments to parse 'abinary' type");
1215 fail:
1216 talloc_free(p);
1217 return 0;
1218 }
1219
1220 /*
1221 * Decide which filter type it is: ip, ipx, or generic
1222 */
1223 type = fr_table_value_by_str(filterType, argv[0], -1);
1224 memset(&filter, 0, sizeof(filter));
1225
1226 /*
1227 * Validate the filter type.
1228 */
1229 switch (type) {
1231 case ASCEND_FILTER_IP:
1232 case ASCEND_FILTER_IPX:
1233 case ASCEND_FILTER_IPV6:
1234 filter.type = type;
1235 break;
1236
1237 default:
1238 fr_strerror_printf("Unknown Ascend filter type \"%s\"", argv[0]);
1239 goto fail;
1240 }
1241
1242 /*
1243 * Parse direction
1244 */
1245 token = fr_table_value_by_str(filterKeywords, argv[1], -1);
1246 switch (token) {
1247 case FILTER_IN:
1248 filter.direction = 1;
1249 break;
1250
1251 case FILTER_OUT:
1252 filter.direction = 0;
1253 break;
1254
1255 default:
1256 fr_strerror_printf("Unknown Ascend filter direction \"%s\"", argv[1]);
1257 goto fail;
1258 }
1259
1260 /*
1261 * Parse action
1262 */
1263 token = fr_table_value_by_str(filterKeywords, argv[2], -1);
1264 switch (token) {
1265 case FILTER_FORWARD:
1266 filter.forward = 1;
1267 break;
1268
1269 case FILTER_DROP:
1270 filter.forward = 0;
1271 break;
1272
1273 default:
1274 fr_strerror_printf("Unknown Ascend filter action \"%s\"", argv[2]);
1275 goto fail;
1276 }
1277
1278 switch (type) {
1280 slen = ascend_parse_generic(argc - 3, &argv[3], &filter.generic);
1281 size = 32;
1282 break;
1283
1284 case ASCEND_FILTER_IP:
1285 slen = ascend_parse_ip(argc - 3, &argv[3], &filter.ip);
1286 size = 32;
1287 break;
1288
1289 case ASCEND_FILTER_IPX:
1290 slen = ascend_parse_ipx(argc - 3, &argv[3], &filter.ipx);
1291 size = 32;
1292 break;
1293
1294 case ASCEND_FILTER_IPV6:
1295 slen = ascend_parse_ipv6(argc - 3, &argv[3], &filter.ipv6);
1296 size = sizeof(filter);
1297 break;
1298 }
1299
1300 if (slen < 0) goto fail;
1301
1302 talloc_free(p);
1303
1304 return fr_dbuff_in_memcpy(dbuff, (uint8_t *)&filter, size);
1305}
1306
1307/** Print an Ascend binary filter attribute to a string,
1308 *
1309 * Grrr... Ascend makes the server do this work, instead of doing it on the NAS.
1310 *
1311 * @param[in,out] vp Where the decoded string will be stored.
1312 * @param[in] data binary data to decodee
1313 * @param[in] data_len length of the binary data to decodee
1314 * @return
1315 * - 0 OK
1316 * - <0 on error. VP is untouched.
1317 */
1319{
1320 ascend_filter_t const *filter;
1321 size_t size;
1322 fr_ipaddr_t ipaddr;
1324 char string[256];
1325 fr_sbuff_t sbuff = FR_SBUFF_OUT(string, sizeof(string));
1326 uint64_t aligned[256 / sizeof(uint64_t)];
1327
1328 static char const *action[] = {"drop", "forward"};
1329 static char const *direction[] = {"out", "in"};
1330
1331 /*
1332 * Just for paranoia: wrong size filters get printed as octets
1333 */
1334 if (data_len < 4) return -1;
1335
1336 /*
1337 * ascend data filters aren't concatenated across
1338 * multiple RADIUS attributes.
1339 */
1340 if (data_len > RADIUS_MAX_STRING_LENGTH) return -1;
1341
1342 memcpy(aligned, data, data_len);
1343
1344 filter = (ascend_filter_t const *) aligned;
1345
1346 switch ((ascend_filter_type_t)filter->type) {
1347 case ASCEND_FILTER_IP:
1348 size = sizeof(filter->ip);
1349 break;
1350
1351 case ASCEND_FILTER_IPX:
1352 size = sizeof(filter->ipx);
1353 break;
1354
1356 size = sizeof(filter->generic);
1357 break;
1358
1359 case ASCEND_FILTER_IPV6:
1360 size = sizeof(filter->ipv6);
1361 break;
1362
1363 default:
1364 return -1;
1365 }
1366
1367 if (data_len < size) return -size;
1368
1369 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, "%s %s %s", fr_table_str_by_value(filterType, filter->type, "??"),
1370 direction[filter->direction & 0x01], action[filter->forward & 0x01]);
1371
1372 switch ((ascend_filter_type_t)filter->type) {
1373
1374 /*
1375 * Handle IP filters
1376 */
1377 case ASCEND_FILTER_IP:
1378 if (filter->ip.srcip) {
1379 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcip %d.%d.%d.%d/%d",
1380 ((uint8_t const *) &filter->ip.srcip)[0],
1381 ((uint8_t const *) &filter->ip.srcip)[1],
1382 ((uint8_t const *) &filter->ip.srcip)[2],
1383 ((uint8_t const *) &filter->ip.srcip)[3],
1384 filter->ip.srcmask);
1385 }
1386
1387 if (filter->ip.dstip) {
1388 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstip %d.%d.%d.%d/%d",
1389 ((uint8_t const *) &filter->ip.dstip)[0],
1390 ((uint8_t const *) &filter->ip.dstip)[1],
1391 ((uint8_t const *) &filter->ip.dstip)[2],
1392 ((uint8_t const *) &filter->ip.dstip)[3],
1393 filter->ip.dstmask);
1394 }
1395
1396 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " %s", fr_table_str_by_value(filterProtoName, filter->ip.proto, "??"));
1397
1398 if (filter->ip.srcPortComp > RAD_NO_COMPARE) {
1399 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcport %s %d",
1400 fr_table_str_by_value(filterCompare, filter->ip.srcPortComp, "??"),
1401 ntohs(filter->ip.srcport));
1402 }
1403
1404 if (filter->ip.dstPortComp > RAD_NO_COMPARE) {
1405 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstport %s %d",
1406 fr_table_str_by_value(filterCompare, filter->ip.dstPortComp, "??"),
1407 ntohs(filter->ip.dstport));
1408 }
1409
1410 if (filter->ip.established) {
1411 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " est");
1412 }
1413 break;
1414
1415 /*
1416 * Handle IPX filters
1417 */
1418 case ASCEND_FILTER_IPX:
1419 /* print for source */
1420 if (filter->ipx.src.net) {
1421 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcipxnet 0x%04x srcipxnode 0x%02x%02x%02x%02x%02x%02x",
1422 (unsigned int)ntohl(filter->ipx.src.net),
1423 filter->ipx.src.node[0], filter->ipx.src.node[1],
1424 filter->ipx.src.node[2], filter->ipx.src.node[3],
1425 filter->ipx.src.node[4], filter->ipx.src.node[5]);
1426
1427 if (filter->ipx.srcSocComp > RAD_NO_COMPARE) {
1428 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcipxsock %s 0x%04x",
1429 fr_table_str_by_value(filterCompare, filter->ipx.srcSocComp, "??"),
1430 ntohs(filter->ipx.src.socket));
1431 }
1432 }
1433
1434 /* same for destination */
1435 if (filter->ipx.dst.net) {
1436 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstipxnet 0x%04x dstipxnode 0x%02x%02x%02x%02x%02x%02x",
1437 (unsigned int)ntohl(filter->ipx.dst.net),
1438 filter->ipx.dst.node[0], filter->ipx.dst.node[1],
1439 filter->ipx.dst.node[2], filter->ipx.dst.node[3],
1440 filter->ipx.dst.node[4], filter->ipx.dst.node[5]);
1441
1442 if (filter->ipx.dstSocComp > RAD_NO_COMPARE) {
1443 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstipxsock %s 0x%04x",
1444 fr_table_str_by_value(filterCompare, filter->ipx.dstSocComp, "??"),
1445 ntohs(filter->ipx.dst.socket));
1446 }
1447 }
1448 break;
1449
1451 {
1452 size_t i, len;
1453
1454 /*
1455 * Why is len 16 bits, when the masks are only 6 bytes?
1456 */
1457 len = ntohs(filter->generic.len);
1458 if (len > sizeof(filter->generic.mask)) {
1459 return -size;
1460 }
1461
1462 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " %u ", (unsigned int) ntohs(filter->generic.offset));
1463
1464 /* show the mask */
1465 for (i = 0; i < len; i++) {
1466 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, "%02x", filter->generic.mask[i]);
1467 }
1468
1469 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " ");
1470
1471 /* show the value */
1472 for (i = 0; i < len; i++) {
1473 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, "%02x", filter->generic.value[i]);
1474 }
1475
1476 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " %s", (filter->generic.compNeq) ? "!=" : "==");
1477
1478 if (filter->generic.more != 0) {
1479 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " more");
1480 }
1481 }
1482 break;
1483
1484 /*
1485 * Handle IPv6 filters
1486 */
1487 case ASCEND_FILTER_IPV6:
1488 /*
1489 * srcip
1490 */
1491 memset(&ipaddr, 0, sizeof(ipaddr));
1492 ipaddr.af = AF_INET6;
1493 memcpy(&ipaddr.addr.v6.s6_addr, filter->ipv6.srcip, sizeof(filter->ipv6.srcip));
1494 ipaddr.prefix = filter->ipv6.srcmask;
1495
1496 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " srcip ");
1497
1498 (void) fr_inet_ntop_prefix(buffer, sizeof(buffer), &ipaddr);
1500
1501 /*
1502 * dstip
1503 */
1504 memset(&ipaddr, 0, sizeof(ipaddr));
1505 ipaddr.af = AF_INET6;
1506 memcpy(&ipaddr.addr.v6.s6_addr, filter->ipv6.dstip, sizeof(filter->ipv6.dstip));
1507 ipaddr.prefix = filter->ipv6.dstmask;
1508
1509 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " dstip ");
1510
1511 (void) fr_inet_ntop_prefix(buffer, sizeof(buffer), &ipaddr);
1513
1514 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " %s", fr_table_str_by_value(filterProtoName, filter->ipv6.proto, "??"));
1515
1516 if (filter->ipv6.srcPortComp > RAD_NO_COMPARE) {
1517 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " srcport %s %d",
1518 fr_table_str_by_value(filterCompare, filter->ipv6.srcPortComp, "??"),
1519 ntohs(filter->ipv6.srcport));
1520 }
1521
1522 if (filter->ipv6.dstPortComp > RAD_NO_COMPARE) {
1523 FR_SBUFF_IN_SPRINTF_RETURN(&sbuff, " dstport %s %d",
1524 fr_table_str_by_value(filterCompare, filter->ipv6.dstPortComp, "??"),
1525 ntohs(filter->ipv6.dstport));
1526 }
1527
1528 if (filter->ipv6.established) {
1529 FR_SBUFF_IN_STRCPY_RETURN(&sbuff, " est");
1530 }
1531 break;
1532
1533 default:
1534 break;
1535 }
1536
1537 /*
1538 * Copy the finished string to the output VP.
1539 */
1540 if (fr_pair_value_strdup(vp, string, true) < 0) return -1;
1541
1542 return 0;
1543}
#define IP_DEST_ADDR_FLAG
Definition abinary.c:758
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:759
static fr_table_num_sorted_t const filterType[]
Definition abinary.c:295
#define DONE_FLAGS
Definition abinary.c:764
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:1318
#define IP_PROTO_FLAG
Definition abinary.c:761
#define IP_SRC_ADDR_FLAG
Definition abinary.c:757
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:799
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:1074
#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:762
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:927
static int ascend_parse_port(uint16_t *port, char *compare, char *str)
Definition abinary.c:726
static size_t filterKeywords_len
Definition abinary.c:346
#define IP_DEST_PORT_FLAG
Definition abinary.c:760
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:1194
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:578
#define fr_base16_decode(_err, _out, _in, _no_trailing)
Definition base16.h:95
#define RCSID(id)
Definition build.h:487
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define NUM_ELEMENTS(_t)
Definition build.h:339
#define fr_dbuff_in_memcpy(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into a dbuff or marker.
Definition dbuff.h:1361
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:524
int fr_dict_str_to_argv(char *str, char **argv, int max_argc)
Test enumeration values.
Definition dict_test.h:92
talloc_free(hp)
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:1081
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:633
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
union fr_ipaddr_t::@137 addr
#define FR_IPADDR_PREFIX_STRLEN
Like FR_IPADDR_STRLEN but with space for a prefix.
Definition inet.h:93
IPv4/6 prefix.
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:2648
#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_SPRINTF_RETURN(...)
#define FR_SBUFF_IN_STR(_start)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
return count
Definition module.c:155
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:617
#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:1337