--- src/sflowtool.c.orig 2007-04-26 23:11:48.000000000 +0200 +++ src/sflowtool.c 2007-04-27 00:47:07.000000000 +0200 @@ -12,6 +12,11 @@ #include #include +#ifdef WITH_MYSQL +#include +#include "sql.h" +#endif + #ifdef WIN32 #include "winsock2.h" #include "fcntl.h" @@ -116,6 +121,17 @@ u_int32_t linktype; /* data link type (DLT_*) */ }; +#ifdef WITH_MYSQL +/* mysql db information */ +typedef struct _db_settings { + char *username; + char *password; + char *host; + char *database; + char *type; // "MySQL" for the moment +} db_settings; +#endif + struct pcap_pkthdr { struct timeval ts; /* time stamp */ u_int32_t caplen; /* length of portion present */ @@ -137,7 +153,7 @@ int sock; } SFForwardingTarget; -typedef enum { SFLFMT_FULL=0, SFLFMT_PCAP, SFLFMT_LINE, SFLFMT_NETFLOW, SFLFMT_FWD } EnumSFLFormat; +typedef enum { SFLFMT_FULL=0, SFLFMT_PCAP, SFLFMT_LINE, SFLFMT_LINE_EXTENDED, SFLFMT_NETFLOW, SFLFMT_FWD } EnumSFLFormat; typedef struct _SFConfig { /* sflow(R) options */ @@ -157,6 +173,10 @@ u_int32_t tcpdumpHdrPad; u_char zeroPad[100]; int pcapSwap; + #ifdef WITH_MYSQL + /* db settings */ + struct _db_settings db_settings; + #endif #ifdef SPOOFSOURCE int spoofSource; @@ -507,6 +527,128 @@ sample->meanSkipCount); } + /*_________________---------------------------__________________ + * _________________ writeFlowLineExtended __________________ + * -----------------___________________________------------------ + */ + + static void writeFlowLineExtended(SFSample *sample) + { + + char agentIP[51], srcIP[51], dstIP[51]; + // source + printf("FLOW,%s,%d,%d,", + printAddress(&sample->agent_addr, agentIP, 50), + sample->inputPort, + sample->outputPort); + // layer 2 + + printf("%02x%02x%02x%02x%02x%02x,%02x%02x%02x%02x%02x%02x,0x%04x,%d,%d", + sample->eth_src[0], + sample->eth_src[1], + sample->eth_src[2], + sample->eth_src[3], + sample->eth_src[4], + sample->eth_src[5], + sample->eth_dst[0], + sample->eth_dst[1], + sample->eth_dst[2], + sample->eth_dst[3], + sample->eth_dst[4], + sample->eth_dst[5], + sample->eth_type, + sample->in_vlan, + sample->out_vlan); + // layer 3/4 + printf(",%s,%s,%d,0x%02x,%d,%d,%d,0x%02x", + IP_to_a(sample->ipsrc.address.ip_v4.s_addr, srcIP), + IP_to_a(sample->ipdst.address.ip_v4.s_addr, dstIP), + sample->dcd_ipProtocol, + sample->dcd_ipTos, + sample->dcd_ipTTL, + sample->dcd_sport, + sample->dcd_dport, + sample->dcd_tcpFlags); + // bytes + printf(",%d,%d,%d", + sample->sampledPacketSize, + sample->sampledPacketSize - sample->stripped - + sample->offsetToIPV4, + sample->meanSkipCount); + // Extended Information + // Colin + //printf(",%d,",sample->my_as); + + printf(",%d,%d,%d,%d,%d,%d,%d,%d\n", + sample->my_as, + sample->srcMask, + sample->dstMask, + sample->src_as, + sample->src_peer_as, + sample->dst_as_path_len, + sample->dst_peer_as, + sample->dst_as); + } + + + #ifdef WITH_MYSQL + /*_________________---------------------------__________________ + _________________ writeMySQLRecord __________________ + -----------------___________________________------------------ + */ + + static void writeMySQLRecord(SFSample *sample) + { + char agentIP[51], srcIP[51], dstIP[51]; + /* do mysql insert */ + char buf[2048]; + sprintf(buf, sflow_to_mysql, + printAddress(&sample->agent_addr, agentIP, 50), + sample->inputPort, + sample->outputPort, + sample->eth_src[0], + sample->eth_src[1], + sample->eth_src[2], + sample->eth_src[3], + sample->eth_src[4], + sample->eth_src[5], + sample->eth_dst[0], + sample->eth_dst[1], + sample->eth_dst[2], + sample->eth_dst[3], + sample->eth_dst[4], + sample->eth_dst[5], + sample->eth_type, + sample->in_vlan, + sample->out_vlan, + IP_to_a(sample->ipsrc.address.ip_v4.s_addr, srcIP), + IP_to_a(sample->ipdst.address.ip_v4.s_addr, dstIP), + sample->dcd_ipProtocol, + sample->dcd_ipTos, + sample->dcd_ipTTL, + sample->dcd_sport, + sample->dcd_dport, + sample->dcd_tcpFlags, + sample->sampledPacketSize, + sample->sampledPacketSize - sample->stripped - sample->offsetToIPV4, + sample->meanSkipCount, + sample->my_as, + sample->srcMask, + sample->dstMask, + sample->src_as, + sample->src_peer_as, + sample->dst_as_path_len, + sample->dst_peer_as, + sample->dst_as); + + if(mysql_real_query(&mysql, buf, strlen(buf))){ + fprintf(stderr, "mysql_real_query() failed\n"); + fprintf(stderr, "%s\n", mysql_error(&mysql)); + } + } + #endif + + /*_________________---------------------------__________________ _________________ writeCountersLine __________________ -----------------___________________________------------------ @@ -1988,8 +2130,9 @@ case INMEXTENDED_SWITCH: readExtendedSwitch(sample); break; case INMEXTENDED_ROUTER: readExtendedRouter(sample); break; case INMEXTENDED_GATEWAY: - if(sample->datagramVersion == 2) readExtendedGateway_v2(sample); - else readExtendedGateway(sample); + if(sample->datagramVersion == 2) { + readExtendedGateway_v2(sample); + } else readExtendedGateway(sample); break; case INMEXTENDED_USER: readExtendedUser(sample); break; case INMEXTENDED_URL: readExtendedUrl(sample); break; @@ -2012,11 +2155,19 @@ /* or line-by-line output... */ writeFlowLine(sample); break; + case SFLFMT_LINE_EXTENDED: + /* or line-by-line extended output... */ + writeFlowLineExtended(sample); + break; case SFLFMT_FULL: default: /* if it was full-detail output then it was done as we went along */ break; } + #ifdef WITH_MYSQL + if(sfConfig.db_settings.type == "MySQL") + writeMySQLRecord(sample); + #endif } } @@ -2133,11 +2284,19 @@ /* or line-by-line output... */ writeFlowLine(sample); break; + case SFLFMT_LINE_EXTENDED: + /* or line-by-line extended output... */ + writeFlowLineExtended(sample); + break; case SFLFMT_FULL: default: /* if it was full-detail output then it was done as we went along */ break; } + #ifdef WITH_MYSQL + if(sfConfig.db_settings.type == "MySQL") + writeMySQLRecord(sample); + #endif } } @@ -2723,6 +2882,36 @@ return YES; } +#ifdef WITH_MYSQL + /*________________---------------------------__________________ + _________________ db connect __________________ + -----------------___________________________------------------ + */ + int db_connect() + { + printf("Conecting to Database!\n"); + printf("%s\n",sfConfig.db_settings.host); + int result; + int store_data; + store_data = 1; + + if(store_data == 1){ + /* + * Connect MySQL + */ + mysql_init(&mysql); + mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"sflow"); + result = (int)mysql_real_connect(&mysql, sfConfig.db_settings.host, sfConfig.db_settings.username, sfConfig.db_settings.password, sfConfig.db_settings.database, 0, NULL, 0); + if (result == (int)NULL){ + fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql)); + exit(1); + } + } + + return 0; + } + #endif + /*_________________---------------------------__________________ _________________ instructions __________________ -----------------___________________________------------------ @@ -2742,7 +2931,8 @@ fprintf(stderr, " - ...repeat for multiple collectors)\n"); fprintf(stderr,"\n"); fprintf(stderr,"csv output:\n"); - fprintf(stderr, " -l - (output in line-by-line format)\n"); fprintf(stderr,"\n"); + fprintf(stderr, " -l - (output in line-by-line format)\n"); + fprintf(stderr, " -a - (output in extended line-by-line format)\n"); fprintf(stderr,"\n"); fprintf(stderr,"tcpdump output:\n"); fprintf(stderr, " -t - (output in binary tcpdump(1) format)\n"); fprintf(stderr, " -r file - (read binary tcpdump(1) format)\n"); @@ -2758,6 +2948,14 @@ #ifdef SPOOFSOURCE fprintf(stderr, " -S - spoof source of netflow packets to input agent IP\n"); #endif + #ifdef WITH_MYSQL + fprintf(stderr,"\n"); + fprintf(stderr,"Mysql database connection:\n"); + fprintf(stderr, " -H host - MySQL server host IP address\n"); + fprintf(stderr, " -D database - Database name (table name is assumed to be 'sflow')\n"); + fprintf(stderr, " -U username - Database Username\n"); + fprintf(stderr, " -P password - Database Password\n"); + #endif fprintf(stderr,"\n"); fprintf(stderr,"Filters:\n"); fprintf(stderr, " +v - include vlans (e.g. +v 0-20,4091)\n"); @@ -2794,6 +2992,7 @@ case 'p': sfConfig.sFlowInputPort = atoi(argv[arg++]); break; case 't': sfConfig.outputFormat = SFLFMT_PCAP; break; case 'l': sfConfig.outputFormat = SFLFMT_LINE; break; + case 'a': sfConfig.outputFormat = SFLFMT_LINE_EXTENDED; break; case 'r': sfConfig.readPcapFileName = strdup(argv[arg++]); break; case 'x': sfConfig.removeContent = YES; break; case 'z': sfConfig.tcpdumpHdrPad = atoi(argv[arg++]); break; @@ -2814,6 +3013,13 @@ break; case 'e': sfConfig.netFlowPeerAS = YES; break; case 's': sfConfig.disableNetFlowScale = YES; break; + #ifdef WITH_MYSQL + /* db_settings part */ + case 'H': sfConfig.db_settings.host = strdup(argv[arg++]); break; + case 'D': sfConfig.db_settings.database = strdup(argv[arg++]); break; + case 'U': sfConfig.db_settings.username = strdup(argv[arg++]); break; + case 'P': sfConfig.db_settings.password = strdup(argv[arg++]); break; + #endif #ifdef SPOOFSOURCE case 'S': sfConfig.spoofSource = YES; break; #endif @@ -2842,6 +3048,18 @@ default: instructions(*argv); } } +#ifdef WITH_MYSQL + if(sfConfig.db_settings.host && sfConfig.db_settings.username && sfConfig.db_settings.database){ + /* Assume "" as default password */ + sfConfig.db_settings.password = ""; + db_connect(); + sfConfig.db_settings.type = "MySQL"; + } + else { + fprintf(stderr, "ERROR: Database settings incorrect.\n"); + instructions(*argv); + } +#endif } /*_________________---------------------------__________________