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