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