📄 filters.c
字号:
*/ *ipaddr |= (ip[count] << (8 * (3 - count))); } /* * We've hit the end of the IP address, and there's something * else left over: die. */ if (*str) return -1; /* * Set the default netmask. */ if (!netmask) { if (!*ipaddr) { netmask = 0; } 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 = lrad_str2int(filterCompare, compare, -1); if (rcode < 0) return rcode; if (strspn(str, "0123456789") == strlen(str)) { token = atoi(str); } else { token = lrad_str2int(filterPortType, str, -1); } if ((token < 0) || (token > 65535)) return -1; *port = token; *port = htons(*port); return rcode;}/* * 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 != 7)) { token = lrad_str2int(filterKeywords, argv[0], -1); switch (token) { case FILTER_IP_SRC: if (flags & 0x01) return -1; if (argc < 2) return -1; rcode = ascend_parse_ipaddr(&filter->srcip, argv[1]); if (rcode < 0) return rcode; filter->srcmask = rcode; flags |= 0x01; argv += 2; argc -= 2; break; case FILTER_IP_DST: if (flags & 0x02) return -1; if (argc < 2) return -1; rcode = ascend_parse_ipaddr(&filter->dstip, argv[1]); if (rcode < 0) return rcode; filter->dstmask = rcode; flags |= 0x02; argv += 2; argc -= 2; break; /* * Should be protocol, ASCII or otherwise. */ default: if (strspn(argv[0], "0123456789") == strlen(argv[0])) { token = atoi(argv[0]); } else { token = lrad_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 = 0x07; /* MUST have parsed everything. */ argv++; argc--; break; } } /* looking for src/dst IP, and proto */ /* * Done looking for everything, return. */ if (argc == 0) return 0; /* * There may, or may not, be src & dst ports in the string. */ flags = 0; while ((argc > 0) && (flags != 7)) { token = lrad_str2int(filterKeywords, argv[0], -1); switch (token) { case FILTER_IP_SRC_PORT: if (flags & 0x01) 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 |= 0x01; argv += 3; argc -= 3; break; case FILTER_IP_DST_PORT: if (flags & 0x02) 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 |= 0x02; argv += 3; argc -= 3; break; /* * Look for established connections. */ case FILTER_EST: filter->established = 1; argv++; argc--; flags = 0x07; break; /* * Unknown thingy. */ default: librad_log("Unknown string \"%s\" in IP data filter", argv[0]); return -1; break; } } /* looking for src/dst port */ /* * 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 = hex2bin(argv[1], filter->mask, sizeof(filter->mask)); if (rcode < 0) return -1; token = hex2bin(argv[2], filter->value, sizeof(filter->value)); if (token < 0) 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 = lrad_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; /* * 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->strvalue, argv, 32); if (argc < 3) return -1; /* * Decide which filter type it is: ip, ipx, or generic */ type = lrad_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 = lrad_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 = lrad_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_RADFILTER; memcpy(pair->strvalue, &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->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->strvalue, (char *) &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, u_char *buffer, int len){ int i; char *p; ascend_filter_t filter; static const char *action[] = {"drop", "forward"}; static const char *direction[] = {"out", "in"}; p = (char *)buffer; /* * Just for paranoia: wrong size filters get printed as octets */ if (vp->length > SIZEOF_RADFILTER) { strcpy(p, "0x"); p += 2; for (i = 0; i < vp->length; i++) { sprintf(p, " %02x", vp->strvalue[i]); p += 3; } return; } memcpy(&filter, vp->strvalue, SIZEOF_RADFILTER); /* alignment issues */ *(p++) = '"'; len -= 3; /* account for leading & trailing quotes */ i = snprintf(p, len, "%s %s %s", lrad_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", ((u_char *) &filter.u.ip.srcip)[0], ((u_char *) &filter.u.ip.srcip)[1], ((u_char *) &filter.u.ip.srcip)[2], ((u_char *) &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", ((u_char *) &filter.u.ip.dstip)[0], ((u_char *) &filter.u.ip.dstip)[1], ((u_char *) &filter.u.ip.dstip)[2], ((u_char *) &filter.u.ip.dstip)[3], filter.u.ip.dstmask); p += i; len -= i; } i = snprintf(p, len, " %s", lrad_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", lrad_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", lrad_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", lrad_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", lrad_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 + -