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