static int set_general(struct sc_stream* stream, char* stream_str) { int rc = 0; uint8_t mac[6]; char* key; char* next_field = stream_str; /* General format is series of key=value pairs, separated by ",". */ while( next_field && (rc == 0) ) { char* value; char* field; field = strsep(&next_field, ","); /* Split key and value */ value = field; key = strsep(&value, "="); if( !value ) { /* Handle some key-only magic values */ if( !strcmp(key, "all") ) rc = sc_stream_all(stream); /* The following needs a strncmp because we pass the stream as * 'sniff [0,1]' */ else if( !strncmp(key, "sniff", strlen("sniff")) ) rc = sc_stream_sniff(stream, key); else if( !strcmp(key, "ip") ) rc = set_eth_type(stream, key); else if( !strcmp(key, "udp") || !strcmp(key, "tcp") ) rc = set_protocol(stream, key); else { fprintf(stderr, "%s: ERROR: No value for key %s\n", __func__, key); return -EINVAL; } } else { if( !strcmp(key, "dmac") ) { if( parse_mac(value, mac) < 0 ) { fprintf(stderr, "%s: ERROR: Failed to parse mac \"%s\"\n", __func__, key); return -EINVAL; } rc = sc_stream_eth_dhost(stream, mac); } else if( !strcmp(key, "smac") ) { if( parse_mac(value, mac) < 0 ) fprintf(stderr, "%s: ERROR: Failed to parse mac \"%s\"\n", __func__, key); return -EINVAL; rc = sc_stream_eth_shost(stream, mac); } else if( !strcmp(key, "vid") ) { rc = set_vlan_id(stream, value); } else if( !strcmp(key, "eth_type") ) { rc = set_eth_type(stream, value); } else if( !strcmp(key, "shost") ) { rc = sc_stream_ip_source_host(stream, value); } else if( !strcmp(key, "dhost") ) { rc = sc_stream_ip_dest_host(stream, value); } else if( !strcmp(key, "ip_protocol") ) { rc = set_protocol(stream, value); } else if( !strcmp(key, "sport") ) { rc = sc_stream_ip_source_port(stream, value); } else if( !strcmp(key, "dport") ) { rc = sc_stream_ip_dest_port(stream, value); } else { fprintf(stderr, "%s: ERROR: Unrecognised key \"%s\"\n", __func__, key); return -EINVAL; } } } return rc; }
int main(int argc, char* argv[]) { if( argc != 2 ) { printf("Usage: %s <intf>\n", argv[0]); exit(1); } const char* intf = argv[1]; /* Attributes are used to specify options. Examples include specifing * the sizes of buffers and tuning options. For a full list of available * attributes run "solar_capture_doc attr". * * The defaults can be changed by setting the SC_ATTR environment * variable, and can be overridden programmatically as shown below. */ struct sc_attr* attr; TRY(sc_attr_alloc(&attr)); /* A SolarCapture session binds together a set of threads and components * that are doing a particular job. */ struct sc_session* tg; TRY(sc_session_alloc(&tg, attr)); struct sc_thread* t1; TRY(sc_thread_alloc(&t1, attr, tg)); struct sc_thread* t2; TRY(sc_thread_alloc(&t2, attr, tg)); /* Set the number of packet buffers to be allocated for the VI. These * buffers are used to receive packets from the network adapter. */ int n_bufs = 8192; sc_attr_set_int(attr, "n_bufs_rx", n_bufs); sc_attr_set_int(attr, "n_bufs_rx_min", n_bufs); /* A VI is used to receive packets from the network adapter. */ struct sc_vi* vi; TRY(sc_vi_alloc(&vi, attr, t1, intf)); /* Specify which packets should be delivered to this VI. An sc_stream * object describes the set of packets wanted. * * The 'all' stream captures all packets that arrive at the interface, * excluding those explicitly steered elsewhere. (Using the 'all' stream * requires administrative privileges because it steals packets away from * the kernel stack). */ struct sc_stream* stream; TRY(sc_stream_alloc(&stream, attr, tg)); TRY(sc_stream_all(stream)); TRY(sc_vi_add_stream(vi, stream)); TRY(sc_stream_free(stream)); /* SolarCapture nodes perform packet processing functions such as * monitoring, packet modification, writing to disk, I/O etc. When * allocating nodes you can specify node-specific arguments, which may be * required or optional. * * The 'sc_rate_monitor' node measures the packet rate and bandwidth for * packets passing through it, and exports that information via * solar_capture_monitor. The 'period' argument gives the sampling * period in seconds. The 'alpha' argument controls smoothing, and must * be in the range (0,1]. Values close to 1 give more weight to recent * samples, while values close to zero give more weight to previous * samples and so provide a greater level of smoothing. */ struct sc_arg args[] = { SC_ARG_DBL("alpha", 0.5), SC_ARG_DBL("period", 0.1), }; struct sc_node* rate_mon; TRY(sc_node_alloc_named(&rate_mon, attr, t2, "sc_rate_monitor", NULL, args, sizeof(args) / sizeof(args[0]))); /* Connect the VI to the rate monitor. */ TRY(sc_vi_set_recv_node(vi, rate_mon, NULL)); /* sc_session_go() starts the threads, and so starts packet handling. */ sc_session_go(tg); while( 1 ) sleep(100000); return 0; }