📄 filters.c
字号:
} else if ((*ipaddr & 0x80000000) == 0) { netmask = 8; } else if ((*ipaddr & 0xc0000000) == 0x80000000) { netmask = 16; } else if ((*ipaddr & 0xe0000000) == 0xc0000000) { netmask = 24; } else { netmask = 32; } } *ipaddr = htonl(*ipaddr); return netmask;}/* * ascend_parse_port: Parse a comparator and port. * * Returns -1 on error, or the comparator. */static int ascend_parse_port(uint16_t *port, char *compare, char *str){ int rcode, token = -1; /* * There MUST be a comparison string. */ rcode = fr_str2int(filterCompare, compare, -1); if (rcode < 0) return rcode; if (strspn(str, "0123456789") == strlen(str)) { token = atoi(str); } else { token = fr_str2int(filterPortType, str, -1); } if ((token < 0) || (token > 65535)) return -1; *port = token; *port = htons(*port); return rcode;}#define IP_SRC_ADDR_FLAG (1 << 0)#define IP_DEST_ADDR_FLAG (1 << 1)#define IP_SRC_PORT_FLAG (1 << 2)#define IP_DEST_PORT_FLAG (1 << 3)#define IP_PROTO_FLAG (1 << 4)#define IP_EST_FLAG (1 << 5)#define DONE_FLAGS (IP_SRC_ADDR_FLAG | IP_DEST_ADDR_FLAG | \ IP_SRC_PORT_FLAG | IP_DEST_PORT_FLAG | \ IP_PROTO_FLAG | IP_EST_FLAG)/* * ascend_parse_ip: * * This routine parses an IP filter string from a RADIUS * reply. The format of the string is: * * ip dir action [ dstip n.n.n.n/nn ] [ srcip n.n.n.n/nn ] * [ proto [ dstport cmp value ] [ srcport cmd value ] [ est ] ] * * Fields in [...] are optional. * * dstip: Keyword for destination IP address. * n.n.n.n = IP address. /nn - netmask. * * srcip: Keyword for source IP address. * n.n.n.n = IP address. /nn - netmask. * * proto: Optional protocol field. Either a name or * number. Known names are in FilterProtoName[]. * * dstport: Keyword for destination port. Only valid with tcp * or udp. 'cmp' are in FilterPortType[]. 'value' can be * a name or number. * * srcport: Keyword for source port. Only valid with tcp * or udp. 'cmp' are in FilterPortType[]. 'value' can be * a name or number. * * est: Keyword for TCP established. Valid only for tcp. * */static int ascend_parse_ip(int argc, char **argv, ascend_ip_filter_t *filter){ int rcode; int token; int flags; /* * We may have nothing, in which case we simply return. */ if (argc == 0) return 0; /* * There may, or may not, be src & dst IP's in the string. */ flags = 0; while ((argc > 0) && (flags != DONE_FLAGS)) { token = fr_str2int(filterKeywords, argv[0], -1); switch (token) { case FILTER_IP_SRC: if (flags & IP_SRC_ADDR_FLAG) return -1; if (argc < 2) return -1; rcode = ascend_parse_ipaddr(&filter->srcip, argv[1]); if (rcode < 0) return rcode; filter->srcmask = rcode; flags |= IP_SRC_ADDR_FLAG; argv += 2; argc -= 2; break; case FILTER_IP_DST: if (flags & IP_DEST_ADDR_FLAG) return -1; if (argc < 2) return -1; rcode = ascend_parse_ipaddr(&filter->dstip, argv[1]); if (rcode < 0) return rcode; filter->dstmask = rcode; flags |= IP_DEST_ADDR_FLAG; argv += 2; argc -= 2; break; case FILTER_IP_SRC_PORT: if (flags & IP_SRC_PORT_FLAG) return -1; if (argc < 3) return -1; rcode = ascend_parse_port(&filter->srcport, argv[1], argv[2]); if (rcode < 0) return rcode; filter->srcPortComp = rcode; flags |= IP_SRC_PORT_FLAG; argv += 3; argc -= 3; break; case FILTER_IP_DST_PORT: if (flags & IP_DEST_PORT_FLAG) return -1; if (argc < 3) return -1; rcode = ascend_parse_port(&filter->dstport, argv[1], argv[2]); if (rcode < 0) return rcode; filter->dstPortComp = rcode; flags |= IP_DEST_PORT_FLAG; argv += 3; argc -= 3; break; case FILTER_EST: if (flags & IP_EST_FLAG) return -1; filter->established = 1; argv++; argc--; flags |= IP_EST_FLAG; break; default: if (flags & IP_PROTO_FLAG) return -1; if (strspn(argv[0], "0123456789") == strlen(argv[0])) { token = atoi(argv[0]); } else { token = fr_str2int(filterProtoName, argv[0], -1); if (token == -1) { librad_log("Unknown IP protocol \"%s\" in IP data filter", argv[0]); return -1; } } filter->proto = token; flags |= IP_PROTO_FLAG; argv++; argc--; break; } } /* * We should have parsed everything by now. */ if (argc != 0) { librad_log("Unknown extra string \"%s\" in IP data filter", argv[0]); return -1; } return 0;}/* * ascend_parse_generic * * This routine parses a Generic filter string from a RADIUS * reply. The format of the string is: * * generic dir action offset mask value [== or != ] [more] * * Fields in [...] are optional. * * offset: A Number. Specifies an offset into a frame * to start comparing. * * mask: A hexadecimal mask of bits to compare. * * value: A value to compare with the masked data. * * compNeq: Defines type of comparison. ( "==" or "!=") * Default is "==". * * more: Optional keyword MORE, to represent the attachment * to the next entry. */static int ascend_parse_generic(int argc, char **argv, ascend_generic_filter_t *filter){ int rcode; int token; int flags; /* * We may have nothing, in which case we simply return. */ if (argc == 0) return 0; /* * We need at least "offset mask value" */ if (argc < 3) return -1; /* * No more than optional comparison and "more" */ if (argc > 5) return -1; /* * Offset is a uint16_t number. */ if (strspn(argv[0], "0123456789") != strlen(argv[0])) return -1; rcode = atoi(argv[0]); if (rcode > 65535) return -1; filter->offset = rcode; filter->offset = htons(filter->offset); rcode = fr_hex2bin(argv[1], filter->mask, sizeof(filter->mask)); if (rcode != sizeof(filter->mask)) return -1; token = fr_hex2bin(argv[2], filter->value, sizeof(filter->value)); if (token != sizeof(filter->value)) return -1; /* * The mask and value MUST be the same length. */ if (rcode != token) return -1; filter->len = rcode; filter->len = htons(filter->len); /* * Nothing more. Exit. */ if (argc == 3) return 0; argc -= 3; argv += 3; flags = 0; while (argc >= 1) { token = fr_str2int(filterKeywords, argv[0], -1); switch (token) { case FILTER_GENERIC_COMPNEQ: if (flags & 0x01) return -1; filter->compNeq = TRUE; flags |= 0x01; break; case FILTER_GENERIC_COMPEQ: if (flags & 0x01) return -1; filter->compNeq = FALSE; flags |= 0x01; break; case FILTER_MORE: if (flags & 0x02) return -1; filter->more = htons( 1 ); flags |= 0x02; break; default: librad_log("Invalid string \"%s\" in generic data filter", argv[0]); return -1; } argc--; argv++; } return 0;}/* * filterBinary: * * This routine will call routines to parse entries from an ASCII format * to a binary format recognized by the Ascend boxes. * * pair: Pointer to value_pair to place return. * * valstr: The string to parse * * return: -1 for error or 0. */intascend_parse_filter(VALUE_PAIR *pair){ int token, type; int rcode; int argc; char *argv[32]; ascend_filter_t filter; rcode = -1; /* * Rather than printing specific error messages, we create * a general one here, which won't be used if the function * returns OK. */ librad_log("Text is not in proper format"); /* * Tokenize the input string in the VP. * * Once the filter is *completelty* parsed, then we will * over-write it with the final binary filter. */ argc = str2argv(pair->vp_strvalue, argv, 32); if (argc < 3) return -1; /* * Decide which filter type it is: ip, ipx, or generic */ type = fr_str2int(filterType, argv[0], -1); memset(&filter, 0, sizeof(filter)); /* * Validate the filter type. */ switch (type) { case RAD_FILTER_GENERIC: case RAD_FILTER_IP: case RAD_FILTER_IPX: filter.type = type; break; default: librad_log("Unknown Ascend filter type \"%s\"", argv[0]); return -1; break; } /* * Parse direction */ token = fr_str2int(filterKeywords, argv[1], -1); switch (token) { case FILTER_IN: filter.direction = 1; break; case FILTER_OUT: filter.direction = 0; break; default: librad_log("Unknown Ascend filter direction \"%s\"", argv[1]); return -1; break; } /* * Parse action */ token = fr_str2int(filterKeywords, argv[2], -1); switch (token) { case FILTER_FORWARD: filter.forward = 1; break; case FILTER_DROP: filter.forward = 0; break; default: librad_log("Unknown Ascend filter action \"%s\"", argv[2]); return -1; break; } switch (type) { case RAD_FILTER_GENERIC: rcode = ascend_parse_generic(argc - 3, &argv[3], &filter.u.generic); break; case RAD_FILTER_IP: rcode = ascend_parse_ip(argc - 3, &argv[3], &filter.u.ip); break; case RAD_FILTER_IPX: rcode = ascend_parse_ipx(argc - 3, &argv[3], &filter.u.ipx); break; default: /* should never reach here. */ break; } /* * Touch the VP only if everything was OK. */ if (rcode == 0) { pair->length = sizeof(filter); memcpy(pair->vp_filter, &filter, sizeof(filter)); } return rcode;#if 0 /* * if 'more' is set then this new entry must exist, be a * FILTER_GENERIC_TYPE, direction and disposition must match for * the previous 'more' to be valid. If any should fail then TURN OFF * previous 'more' */ if( prevRadPair ) { filt = ( RadFilter * )prevRadPair->vp_strvalue; if(( tok != FILTER_GENERIC_TYPE ) || (rc == -1 ) || ( prevRadPair->attribute != pair->attribute ) || ( filt->indirection != radFil.indirection ) || ( filt->forward != radFil.forward ) ) { gen = &filt->u.generic; gen->more = FALSE; librad_log("filterBinary: 'more' for previous entry doesn't match: %s.\n", valstr); } } prevRadPair = NULL; if( rc != -1 && tok == FILTER_GENERIC_TYPE ) { if( radFil.u.generic.more ) { prevRadPair = pair; } } if( rc != -1 ) { memcpy( pair->vp_strvalue, &radFil, pair->length ); } return(rc);#endif}/* * Print an Ascend binary filter attribute to a string, * Grrr... Ascend makes the server do this work, instead * of doing it on the NAS. * * Note we don't bother checking 'len' after the snprintf's. * This function should ONLY be called with a large (~1k) buffer. */void print_abinary(VALUE_PAIR *vp, char *buffer, size_t len){ size_t i; char *p; ascend_filter_t *filter; static const char *action[] = {"drop", "forward"}; static const char *direction[] = {"out", "in"}; p = buffer; /* * Just for paranoia: wrong size filters get printed as octets */ if (vp->length != sizeof(*filter)) { strcpy(p, "0x"); p += 2; len -= 2; for (i = 0; i < vp->length; i++) { snprintf(p, len, "%02x", vp->vp_octets[i]); p += 2; len -= 2; } return; } *(p++) = '"'; len -= 3; /* account for leading & trailing quotes */ filter = (ascend_filter_t *) &(vp->vp_filter); i = snprintf(p, len, "%s %s %s", fr_int2str(filterType, filter->type, "??"), direction[filter->direction & 0x01], action[filter->forward & 0x01]); p += i; len -= i; /* * Handle IP filters */ if (filter->type == RAD_FILTER_IP) { if (filter->u.ip.srcip) { i = snprintf(p, len, " srcip %d.%d.%d.%d/%d", ((uint8_t *) &filter->u.ip.srcip)[0], ((uint8_t *) &filter->u.ip.srcip)[1], ((uint8_t *) &filter->u.ip.srcip)[2], ((uint8_t *) &filter->u.ip.srcip)[3], filter->u.ip.srcmask); p += i; len -= i; } if (filter->u.ip.dstip) { i = snprintf(p, len, " dstip %d.%d.%d.%d/%d", ((uint8_t *) &filter->u.ip.dstip)[0], ((uint8_t *) &filter->u.ip.dstip)[1], ((uint8_t *) &filter->u.ip.dstip)[2], ((uint8_t *) &filter->u.ip.dstip)[3], filter->u.ip.dstmask); p += i; len -= i; } i = snprintf(p, len, " %s", fr_int2str(filterProtoName, filter->u.ip.proto, "??")); p += i; len -= i; if (filter->u.ip.srcPortComp > RAD_NO_COMPARE) { i = snprintf(p, len, " srcport %s %d", fr_int2str(filterCompare, filter->u.ip.srcPortComp, "??"), ntohs(filter->u.ip.srcport)); p += i; len -= i; } if (filter->u.ip.dstPortComp > RAD_NO_COMPARE) { i = snprintf(p, len, " dstport %s %d", fr_int2str(filterCompare, filter->u.ip.dstPortComp, "??"), ntohs(filter->u.ip.dstport)); p += i; len -= i; } if (filter->u.ip.established) { i = snprintf(p, len, " est"); p += i; len -= i; } /* * Handle IPX filters */ } else if (filter->type == RAD_FILTER_IPX) { /* print for source */ if (filter->u.ipx.src.net) { i = snprintf(p, len, " srcipxnet 0x%04x srcipxnode 0x%02x%02x%02x%02x%02x%02x", (unsigned int)ntohl(filter->u.ipx.src.net), filter->u.ipx.src.node[0], filter->u.ipx.src.node[1], filter->u.ipx.src.node[2], filter->u.ipx.src.node[3], filter->u.ipx.src.node[4], filter->u.ipx.src.node[5]); p += i; len -= i; if (filter->u.ipx.srcSocComp > RAD_NO_COMPARE) { i = snprintf(p, len, " srcipxsock %s 0x%04x", fr_int2str(filterCompare, filter->u.ipx.srcSocComp, "??"), ntohs(filter->u.ipx.src.socket)); p += i; len -= i; } } /* same for destination */ if (filter->u.ipx.dst.net) { i = snprintf(p, len, " dstipxnet 0x%04x dstipxnode 0x%02x%02x%02x%02x%02x%02x", (unsigned int)ntohl(filter->u.ipx.dst.net), filter->u.ipx.dst.node[0], filter->u.ipx.dst.node[1], filter->u.ipx.dst.node[2], filter->u.ipx.dst.node[3], filter->u.ipx.dst.node[4], filter->u.ipx.dst.node[5]); p += i; len -= i; if (filter->u.ipx.dstSocComp > RAD_NO_COMPARE) { i = snprintf(p, len, " dstipxsock %s 0x%04x", fr_int2str(filterCompare, filter->u.ipx.dstSocComp, "??"), ntohs(filter->u.ipx.dst.socket)); p += i; len -= i; } } } else if (filter->type == RAD_FILTER_GENERIC) { int count; i = snprintf(p, len, " %u ", (unsigned int) ntohs(filter->u.generic.offset)); p += i; i -= len; /* show the mask */ for (count = 0; count < ntohs(filter->u.generic.len); count++) { i = snprintf(p, len, "%02x", filter->u.generic.mask[count]); p += i; len -= i; } strcpy(p, " "); p++; len--; /* show the value */ for (count = 0; count < ntohs(filter->u.generic.len); count++) { i = snprintf(p, len, "%02x", filter->u.generic.value[count]); p += i; len -= i; } i = snprintf(p, len, " %s", (filter->u.generic.compNeq) ? "!=" : "=="); p += i; len -= i; if (filter->u.generic.more != 0) { i = snprintf(p, len, " more"); p += i; len -= i; } } *(p++) = '"'; *p = '\0';}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -