/* RADIUS traffic sNIFFer Copyleft 2000 by FreeLSD Some portion of code from snmpsniffer.c (c) by Nuno Leitao NOTICE: You may copy, distribute or modify this code, as long as you keep this copyleft notice intact. PS. dont try to run... ;) Greets to all ADM!@#$% and w00w00 ppl. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "md5.h" #define VERSION "0.2 (lame & dirty)" #ifdef NOT_HAVE_SNPRINTF #include #define snprintf int_snprintf int int_snprintf (char *buf, int len, char *fmt,...) { va_list args; int ret; va_start (args, fmt); ret = vsprintf (buf, fmt, args); va_end (args); return (ret); } #endif /* ------------------------------------------------------------------ */ #ifdef LINUX #include #define EthernetHeader struct ethhdr #define IPHeader struct iphdr #define UDPHeader struct udphdr #define UDP_SrcPort(x) (x->source) #define UDP_DstPort(x) (x->dest) #define IP_SrcAddr(x) (x->saddr) #define IP_DstAddr(x) (x->daddr) #endif /* The default case is Solaris. */ #ifndef EthernetHeader #include #include #define EthernetHeader struct ether_header #define IPHeader struct ip #define UDPHeader struct udphdr #define UDP_SrcPort(x) (x->uh_sport) #define UDP_DstPort(x) (x->uh_dport) #define IP_SrcAddr(x) (x->ip_src) #define IP_DstAddr(x) (x->ip_dst) #endif /* EthernetHeader */ #define MAXBUFFER 65536 #ifndef DICTIONARY_FILENAME #define DICTIONARY_FILENAME "dictionary" #endif #ifndef CLIENTS_FILENAME #define CLIENTS_FILENAME "clients" #endif #define RADIUS_ATTR_STR 1 #define RADIUS_ATTR_INT 2 #define RADIUS_ATTR_DATE 3 #define RADIUS_ATTR_IPADDR 4 #define RADIUS_ATTR_ABINARY 5 /* Ascend specific */ typedef struct _DICT_VALUE { int value; char *name; char *attrname; void *next; } DICT_VALUE; typedef struct _DICT_ATTR { int value; int type; char *name; void *next; } DICT_ATTR; /* we ignore any greater */ #define MAX_SECRET_STRING 253 typedef struct _CLIENTS { struct in_addr ipaddr; char secret[MAX_SECRET_STRING]; void *next; } CLIENTS; /* radius attr packet for parsing process */ typedef struct RAD_ATTR_PACKET { int code; int type; int length; char *buff; int buff_length; char *name; void *next; } RAD_ATTR_PACKET; /* radius packet struct for parsing process */ typedef struct RAD_PACKET { time_t time; struct sockaddr_in src; struct sockaddr_in dst; unsigned char code; unsigned char ident; unsigned short length; unsigned char auth[16]; char buff[4096]; unsigned int buff_length; struct RAD_ATTR_PACKET *attr; /* parsed attr's chain */ } RAD_PACKET; /* ethernet packet */ struct etherpacket { EthernetHeader eth; IPHeader ip; UDPHeader udp; char buff[MAXBUFFER]; } eth_packet; /* The following are hooks to the positions in the struct. */ IPHeader *ip; UDPHeader *udp; /*-------------------------------------------------------------------------*/ int quiet = 0; int account = 0; /* only accounting info */ int resolve = 0; /* dont resolve hostnames as default */ int verbose = 0; /* silence as default */ pcap_t *PCAP; /* PCAP handler for interface */ char *dict_filename = DICTIONARY_FILENAME; char *clients_filename = NULL; /* individual clients secret */ CLIENTS *secret_clients = NULL; char *secret_passwd = NULL; /* global secret passwd */ DICT_ATTR *dictionary_attr = NULL; DICT_VALUE *dictionary_value = NULL; char *ParseRadiusCode(unsigned int code) { char *ret; switch (code) { case 1: ret = "Access-Request"; break; case 2: ret = "Access-Accept"; break; case 3: ret = "Access-Reject"; break; case 4: ret = "Accounting-Request"; break; case 5: ret = "Accounting-Response"; break; case 11: ret = "Access-Challenge"; break; case 12: ret = "Status-Server (experemental)"; break; case 13: ret = "Status=Client (experemental)"; break; case 255: ret = "Reserved"; break; default: return NULL; } return ret; } char *ParseRadiusAuth(char *auth) { static char ret[80]; int i; for (i = 0; i < 16; i++) { snprintf(ret+i*2, 80-i*2, "%02x", (unsigned int)*( unsigned char *)(auth+i)); } return ret; } DICT_ATTR *GetAttrFromDict(int key) { DICT_ATTR *attr = dictionary_attr; while (attr != NULL) { if (attr->value == key) return attr; attr = attr->next; } return NULL; } DICT_VALUE *GetValueFromDict(int attrkey, int key) { DICT_VALUE *value = dictionary_value; DICT_ATTR *attr; char *str; if ((attr = GetAttrFromDict(attrkey)) == NULL) return NULL; str = attr->name; while (value != NULL) { if (strlen(value->attrname) == strlen(str) && strncmp(value->attrname, str, strlen(str)) == 0 && value->value == key) return value; value = value->next; } return NULL; } char *GetHostSecret(struct in_addr *ipaddr) { CLIENTS *cur = secret_clients; while (cur != NULL) { if (memcmp(ipaddr, &cur->ipaddr, sizeof(struct in_addr)) == 0) return cur->secret; cur = cur->next; } /* if global secret passwd is setted, we use it as default for nondefined hosts */ if (secret_passwd != NULL) return secret_passwd; return NULL; } void OutHex(unsigned char *buff, unsigned int len) { printf("(%d) ", len); while (len-- != 0) { printf("%02x", (unsigned int)*buff); buff++; } } void OutAscii(unsigned char *buff, unsigned int len) { while (len-- != 0 && *buff != 0) { printf("%c", (unsigned char)*buff); buff++; } } void FreeRadiusPacketStruct(RAD_PACKET *rad) { int counter = 0; RAD_ATTR_PACKET *pkt; if (rad == NULL) return; while ((pkt = rad->attr) != NULL) { rad->attr = rad->attr->next; counter++; free(pkt); } #ifdef DEBUG_MALLOC fprintf(stderr, "free %d objects\n", counter); #endif } int OutRadiusPacket(RAD_PACKET *rad) { struct tm *curr_time; struct hostent *host; char src_str[128], dst_str[128]; RAD_ATTR_PACKET *attr = rad->attr; DICT_VALUE *value; unsigned long val; struct sockaddr_in addr; char str[4096], *code_str; int empty; curr_time = localtime(&rad->time); memset(src_str, 0, sizeof(src_str)); strncpy(src_str, (char *)inet_ntoa(rad->src.sin_addr), 127); memset(dst_str, 0, sizeof(dst_str)); strncpy(dst_str, (char *)inet_ntoa(rad->dst.sin_addr), 127); if (resolve) { if ((host = gethostbyaddr((char *) &rad->src.sin_addr, sizeof(rad->src.sin_addr), AF_INET))) strncpy(src_str, host->h_name, 127); if ((host = gethostbyaddr((char *) &rad->dst.sin_addr, sizeof(rad->dst.sin_addr), AF_INET))) strncpy(dst_str, host->h_name, 127); } if (!account) { /* out all packets */ printf("%.2d:%.2d:%.2d ", curr_time->tm_hour, curr_time->tm_min, curr_time->tm_sec); printf("%s:%u > %s:%u\n", src_str, ntohs(rad->src.sin_port), dst_str, ntohs(rad->dst.sin_port)); code_str = ParseRadiusCode(rad->code); if (code_str == NULL) { printf(" code : Undefined (%0x02X)\n\n", rad->code); return -1; } printf(" code : %s\n", ParseRadiusCode(rad->code)); if (verbose) { printf(" iden : 0x%02x\n len : 0x%03x\n auth : %s\n", rad->ident, rad->length, ParseRadiusAuth(rad->auth)); } while (attr) { printf("\t%s = ", attr->name); if (attr->buff_length <= 0) empty = 1; else empty = 0; switch (attr->type) { case RADIUS_ATTR_DATE: if (empty) break; memcpy(&val, attr->buff, sizeof(long)); val = ntohl(val); printf("%08Xh (date)\n", val); break; case RADIUS_ATTR_INT: if (empty) break; memcpy(&val, attr->buff, sizeof(long)); val = ntohl(val); if ((value = GetValueFromDict(attr->code, val)) == NULL) { printf("%d\n", val); } else { printf("%s\n", value->name); } break; case RADIUS_ATTR_IPADDR: if (empty) break; memcpy ((void *) &(addr.sin_addr), (void *)(attr->buff), sizeof(struct in_addr)); printf("%s\n", inet_ntoa(addr.sin_addr)); break; case RADIUS_ATTR_ABINARY: if (empty) printf("\"\"\n"); else { if ( attr->code == 2 && GetHostSecret(&rad->src.sin_addr) != NULL ) { /* password */ char cr[1024]; char digest[32]; char *hostsecret = GetHostSecret(&rad->src.sin_addr); int i; memcpy(cr, hostsecret, strlen(hostsecret)); memcpy(cr + strlen(hostsecret), rad->auth, 16); MD5Calc(digest, cr, strlen(hostsecret) + 16); memset(cr, 0, sizeof(cr)); printf("\""); for ( i = 0; i < attr->buff_length; i++ ) attr->buff[i] ^= digest[i % 16]; OutAscii(attr->buff, attr->buff_length); printf("\" "); } OutHex(attr->buff, attr->buff_length); printf("\n"); } break; case RADIUS_ATTR_STR: if (empty) printf("\"\"\n"); else { memcpy(str, (attr->buff), attr->buff_length); str[attr->buff_length] = 0; printf("\"%s\"\n", str); } break; default: printf("\n"); break; } attr = attr->next; } printf("\n"); } else { /* out only short accounting packets */ if (rad->code != 4 && rad->code != 5) return 0; printf("%.2d:%.2d:%.2d ", curr_time->tm_hour, curr_time->tm_min, curr_time->tm_sec); printf("%s:%u > %s:%u ", src_str, ntohs(rad->src.sin_port), dst_str, ntohs(rad->dst.sin_port)); if (rad->code == 4) printf("Req "); else printf("Res "); while (attr) { printf("%s = ", attr->name); if (attr->buff_length <= 0) empty = 1; else empty = 0; switch (attr->type) { case RADIUS_ATTR_DATE: if (empty) break; memcpy(&val, attr->buff, sizeof(long)); val = ntohl(val); printf("%08Xh (date)", val); break; case RADIUS_ATTR_INT: if (empty) break; memcpy(&val, attr->buff, sizeof(long)); val = ntohl(val); if ((value = GetValueFromDict(attr->code, val)) == NULL) { printf("%d", val); } else { printf("%s", value->name); } break; case RADIUS_ATTR_IPADDR: if (empty) break; memcpy ((void *) &(addr.sin_addr), (void *)(attr->buff), sizeof(struct in_addr)); printf("%s", inet_ntoa(addr.sin_addr)); break; case RADIUS_ATTR_ABINARY: if (empty) printf("\"\""); else { OutHex(attr->buff, attr->buff_length); } break; case RADIUS_ATTR_STR: if (empty) printf("\"\""); else { memcpy(str, (attr->buff), attr->buff_length); str[attr->buff_length] = 0; printf("\"%s\"", str); } break; default: printf(""); break; } attr = attr->next; if (attr) printf(", "); } printf("\n"); } return 0; } /* redefine type for some of non ascii attributes */ int HookAttr(int code, int type) { switch (code) { case 2: /* Password (out like md5) */ case 3: /* Challenge-Response (CHAP Password) */ case 17: /* Change-Password (only for Ascend)*/ case 19: /* Callback-Number (no ascii) */ case 20: /* Callback-Id (no ascii) */ case 24: /* State (no ascii) */ case 25: /* Class (no ascii) */ case 26: /* Vendor_Specific */ case 214: /* Ascend-Send-Secret */ case 215: /* Ascend-Receive-Secret */ return RADIUS_ATTR_ABINARY; } return type; } int ParseRadiusAttr(RAD_PACKET *rad) { DICT_ATTR *attr; DICT_VALUE *value; unsigned long val; struct sockaddr_in addr; RAD_ATTR_PACKET *rattr, *last = NULL; int counter = 0; unsigned char *buff = rad->buff; int len = rad->buff_length; if (len <= 0) return -1; while (len > 0) { rattr = malloc(sizeof(RAD_ATTR_PACKET)); if (rattr == NULL) { fprintf(stderr, "ERROR: Out of memory (while parsing in progress)\n"); return -1; } counter++; rattr->code = (unsigned char)*buff; rattr->length = (unsigned char)*(buff+1); if ((attr = GetAttrFromDict(rattr->code)) == NULL) { fprintf(stderr, "ERROR: Undefined attr (type:%02Xh, length:%d)\n", rattr->code, rattr->length); return -1; } rattr->name = attr->name; rattr->type = HookAttr(rattr->code, attr->type); rattr->buff = buff+2; rattr->buff_length = rattr->length-2; /* without code and len */ rattr->next = NULL; if (last == NULL) rad->attr = rattr; else last->next = rattr; last = rattr; /* continue for next attr */ len -= rattr->length; buff += rattr->length; } if (len != 0) { fprintf(stderr, "ERROR: wrong packet... non aligned internal struct\n"); return -1; } #ifdef DEBUG_MALLOC fprintf(stderr, "malloc %d objects\n", counter); #endif return 0; } int CheckDoublePacket(RAD_PACKET *rad) { return 0; /* not implemented yet */ } void FilterProc(char *user_data, struct pcap_pkthdr *p_header, const char *packet) { unsigned int packet_size = p_header->caplen; char *rad_pkt; int rad_pkt_len; RAD_PACKET RAD; /* Parsed RADIUS packet struct */ memset(&RAD, 0, sizeof(RAD)); /* get time incoming packet */ RAD.time = time(NULL); if (packet_size > MAXBUFFER) return; /* prevent overrun ;) */ memcpy(ð_packet, packet, packet_size); /* fill sockaddr_in */ RAD.src.sin_family = AF_INET; RAD.src.sin_port = UDP_SrcPort (udp); memcpy ((void *) &(RAD.src.sin_addr), (void *) &(IP_SrcAddr (ip)), sizeof (struct in_addr)); RAD.dst.sin_family = AF_INET; RAD.dst.sin_port = UDP_DstPort (udp); memcpy ((void *) &(RAD.dst.sin_addr), (void *) &(IP_DstAddr (ip)), sizeof (struct in_addr)); rad_pkt = (char *)((eth_packet.buff)-2); rad_pkt_len = packet_size-sizeof(eth_packet.ip)-sizeof(eth_packet.udp); /* check size of received packet and according rfc drop wrong packets */ if (rad_pkt_len < 20 || rad_pkt_len > 4096) { fprintf(stderr, "ERROR: %s:%u > %s:%u - non RADIUS packet (bad UDP length: %d)\n", (char *) inet_ntoa(RAD.src.sin_addr), ntohs(RAD.src.sin_port), (char *) inet_ntoa(RAD.dst.sin_addr), ntohs(RAD.dst.sin_port), rad_pkt_len); return; } /* fill radius packet struct */ RAD.code = *(char *)rad_pkt; RAD.ident = *(unsigned char *)(rad_pkt+1); RAD.length = ntohs(*(unsigned short *)(rad_pkt+2)); memcpy(RAD.auth, (char *)(rad_pkt+4), 16); RAD.buff_length = RAD.length - 20; /* without code,ident,length,auth */ if (RAD.buff_length >= 0 && RAD.buff_length <= 4096 - 20 ) memcpy(RAD.buff, (char *)(rad_pkt+20), RAD.buff_length); else { fprintf(stderr, "ERROR: %s:%u > %s:%u - non RADIUS packet (bad length in packet: %d)\n", (char *) inet_ntoa(RAD.src.sin_addr), ntohs(RAD.src.sin_port), (char *) inet_ntoa(RAD.dst.sin_addr), ntohs(RAD.dst.sin_port), RAD.buff_length); return; } if (quiet && CheckDoublePacket(&RAD)) return; if (ParseRadiusAttr(&RAD) == 0) OutRadiusPacket(&RAD); FreeRadiusPacketStruct(&RAD); return; } void HookProto(void) { ip = (IPHeader *) (((unsigned long) ð_packet.ip) - 2); udp = (UDPHeader *) (((unsigned long) ð_packet.udp) - 2); } pcap_t *OpenPromisc(char *eth, int snaplen, int promisc, int to_ms) { pcap_t *h; char ebuf[PCAP_ERRBUF_SIZE]; h = pcap_open_live(eth, snaplen, promisc, to_ms, ebuf); if( !h ) fprintf(stderr, "ERROR: Can't open interface %s.\n%s\n", eth, ebuf); return h; } void ClosePromisc(void) { pcap_close(PCAP); } #define MAX_FILTER_STR 4096 int MakeFilter(pcap_t *h, char *eth, unsigned short pradius, unsigned short pradacct, char *filter) { struct bpf_program bpf; bpf_u_int32 net, mask; char ebuf[PCAP_ERRBUF_SIZE]; char buf[MAX_FILTER_STR]; if (pcap_lookupnet(eth, &net, &mask, ebuf) == -1) { fprintf(stderr, "ERROR: Can't lookup interface %s\n%s\n", eth, ebuf); return -1; } snprintf(buf, MAX_FILTER_STR, "(udp and (port %d or port %d) %s)", ntohs(pradius), ntohs(pradacct), filter); if (pcap_compile(h, &bpf, buf, 1, mask) == -1) { fprintf(stderr, "ERROR: Can't compile BPF filter '%s'\n", buf); return -1; } if (pcap_setfilter(h, &bpf) == -1) { fprintf(stderr, "ERROR: Can't set BPF filter '%s'\n", buf); } return 0; } void Terminate(int signal) { ClosePromisc(); exit(0); } int LoadDictionary(char *fname) { FILE *in; char buff[1024]; int line = 0; char attrstr[512], namestr[512], valuestr[512], typestr[512]; DICT_ATTR dicta, *attr; DICT_VALUE dictv, *value; if ((in = fopen(fname,"r")) == NULL) { fprintf(stderr, "ERROR: Can't open dictionary file '%s'\n", fname); return -1; } while (fgets(buff, sizeof(buff), in) != NULL) { line++; if (*buff == 0 || *buff == '#' || *buff == '\n') continue; if (strncmp(buff, "ATTRIBUTE", 9) == 0) { if (sscanf(buff, "%s%s%s%s", attrstr, namestr, valuestr, typestr) != 4) { fprintf(stderr, "ERROR: Can't understand ATTRIBUTE on line %d\n", line); return -1; } if (strlen(namestr) > 31) { fprintf(stderr, "ERROR: Invalid name length on line %d\n", line); return -1; } if (!isdigit(*valuestr)) { fprintf(stderr, "ERROR: Invalid value on line %d\n", line); return -1; } dicta.value = atoi(valuestr); if (strcmp(typestr, "string") == 0) dicta.type = RADIUS_ATTR_STR; else if (strcmp(typestr, "integer") == 0) dicta.type = RADIUS_ATTR_INT; else if (strcmp(typestr, "ipaddr") == 0) dicta.type = RADIUS_ATTR_IPADDR; else if (strcmp(typestr, "date") == 0) dicta.type = RADIUS_ATTR_DATE; else if (strcmp(typestr, "abinary") == 0) dicta.type = RADIUS_ATTR_ABINARY; else { fprintf(stderr, "ERROR: Invalid type on line %d\n", line); return -1; } if ((dicta.name = malloc(strlen(namestr)+1)) == NULL) { fprintf(stderr, "ERROR: Out of mem\n"); return -1; } strncpy(dicta.name, namestr, strlen(namestr)+1); /* insert new ATTR */ if ((attr = malloc(sizeof(DICT_ATTR))) == NULL) { fprintf(stderr, "ERROR: Out of mem\n"); return -1; } memcpy(attr, &dicta, sizeof(DICT_ATTR)); attr->next = dictionary_attr; dictionary_attr = attr; #ifdef DEBUG fprintf(stderr,"attr: %s\n", attr->name); #endif } else if (strncmp(buff, "VALUE", 5) == 0) { if (sscanf(buff, "%s%s%s%s", typestr, attrstr, namestr, valuestr) != 4) { fprintf(stderr, "ERROR: Can't understand VALUE on line %d\n", line); return -1; } if (strlen(attrstr) > 31) { fprintf(stderr, "ERROR: Invalid attribute length on line %d\n", line); return -1; } if (strlen(namestr) > 31) { fprintf(stderr, "ERROR: Invalid name length on line %d\n", line); return -1; } if (!isdigit(*valuestr)) { fprintf(stderr, "ERROR: Invalid value on line %d\n", line); return -1; } dictv.value = atoi(valuestr); if ((dictv.name = malloc(strlen(namestr)+1)) == NULL) { fprintf(stderr, "ERROR: Out of mem\n"); return -1; } strncpy(dictv.name, namestr, strlen(namestr)+1); if ((dictv.attrname = malloc(strlen(attrstr)+1)) == NULL) { fprintf(stderr, "ERROR: Out of mem\n"); return -1; } strncpy(dictv.attrname, attrstr, strlen(attrstr)+1); /* insert net VALUE */ if ((value = malloc(sizeof(DICT_VALUE))) == NULL) { fprintf(stderr, "ERROR: Out of mem\n"); return -1; } memcpy(value, &dictv, sizeof(DICT_VALUE)); value->next = dictionary_value; dictionary_value = value; #ifdef DEBUG fprintf(stderr,"valu: %s (attr:%s)\n", value->name, value->attrname); #endif } } fclose(in); return 0; } int LoadClients(char *fname) { FILE *in = fopen(fname,"r"); char buff[1024]; CLIENTS host, *ins_host; int line = 0; char ip[128], sec[512]; if (in == NULL) { fprintf(stderr, "ERROR: Can't open clients file '%s'\n", fname); return -1; } while (fgets(buff, sizeof(buff), in) != NULL) { line++; if (*buff == 0 || *buff == '#' || *buff == '\n') continue; if (sscanf(buff, "%s%s", ip, sec) != 2) { fprintf(stderr, "ERROR: Can't understand line %d\n", line); return -1; } if (inet_aton(ip,&host.ipaddr) == 0) { fprintf(stderr, "ERROR: Can't convert ip addr on line %d\n", line); return -1; } if (sizeof(host.secret) < strlen(sec)) { fprintf(stderr, "ERROR: Too long secret on line %d\n", line); return -1; } memcpy(host.secret,sec,strlen(sec)+1); /* insert new client secret password here */ if ((ins_host = malloc(sizeof(CLIENTS))) == NULL) { fprintf(stderr, "ERROR: Out of mem\n"); return -1; } memcpy(ins_host, &host, sizeof(CLIENTS)); ins_host->next = secret_clients; secret_clients = ins_host; } fclose(in); return 0; } int main(int argc, char *argv[]) { char *filter = ""; char ebuf[PCAP_ERRBUF_SIZE]; char *eth = NULL; int arg, error = 0; struct servent *serv_ent; unsigned short radius_port, radacct_port; /* fprintf(stderr, "eth_packet size: %d\n", sizeof(eth_packet)); */ while ((arg = getopt(argc, argv, "Vavri:f:d:c:qp:")) != -1) { switch( arg ) { case 'v': /* be verbose */ verbose++; break; case 'i': /* set interface name */ eth = strdup(optarg); break; case 'f': /* pcap filter expression */ filter = strdup(optarg); break; case 'r': /* resolve hostnames */ resolve++; break; case 'd': /* set dictonary */ dict_filename = strdup(optarg); break; case 'c': /* place where i can get secret passwords */ clients_filename = strdup(optarg); break; case 's': /* there u can define default secret password */ secret_passwd = strdup(optarg); break; case 'q': /* quiet output */ quiet++; break; case 'a': /* output accounting info only */ account++; break; case 'V': fprintf(stderr, "RADIUS sNIFFer by FreeLSD. Version %s\n", VERSION); fprintf(stderr, "http://www.freelsd.net/security\n"); exit(0); default: error++; break; } } if (error) { fprintf(stderr, "Usage: radiusniff [-vVrqa] [-i interface] [-f expression]\n"); fprintf(stderr, " [-d dictionary ] [-c clients] [-s passwd]\n"); exit(1); } if (!eth) { if (!(eth = pcap_lookupdev(ebuf))) { fprintf(stderr, "ERROR: Can't find device for sniffing.\n%s\n",ebuf); exit(1); } } if (access(dict_filename, R_OK) != 0) { fprintf(stderr, "ERROR: Can't access to dictonary file '%s'\n", dict_filename); exit(1); } if (LoadDictionary(dict_filename) != 0) exit(1); if (clients_filename) { if (access(clients_filename, R_OK) != 0) { fprintf(stderr, "ERROR: Can't access to clients file '%s', ignored...\n", clients_filename); clients_filename = NULL; } else if (LoadClients(clients_filename) != 0) exit(1); } HookProto(); signal(SIGINT, Terminate); signal(SIGTERM, Terminate); signal(SIGKILL, Terminate); signal(SIGQUIT, Terminate); serv_ent = getservbyname("radius","udp"); serv_ent ? (radius_port = serv_ent->s_port) : (radius_port = htons(1645)); serv_ent = getservbyname("radacct","udp"); serv_ent ? (radacct_port = serv_ent->s_port) : (radacct_port = htons(1646)); if (!(PCAP = OpenPromisc(eth, 10000, 1, 0))) exit(1); if (MakeFilter(PCAP, eth, radius_port, radacct_port, filter) != 0) exit(1); /* Let's make STDOUT line buffered */ setlinebuf(stdout); /* start main loop */ pcap_loop(PCAP, -1, (void *)FilterProc, NULL); ClosePromisc(); }