1335640Shselasky/* 2335640Shselasky * pcap-sita.c: Packet capture interface additions for SITA ACN devices 3335640Shselasky * 4335640Shselasky * Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero> 5335640Shselasky * 6335640Shselasky * License: BSD 7335640Shselasky * 8335640Shselasky * Redistribution and use in source and binary forms, with or without 9335640Shselasky * modification, are permitted provided that the following conditions 10335640Shselasky * are met: 11335640Shselasky * 12335640Shselasky * 1. Redistributions of source code must retain the above copyright 13335640Shselasky * notice, this list of conditions and the following disclaimer. 14335640Shselasky * 2. Redistributions in binary form must reproduce the above copyright 15335640Shselasky * notice, this list of conditions and the following disclaimer in 16335640Shselasky * the documentation and/or other materials provided with the 17335640Shselasky * distribution. 18335640Shselasky * 3. The names of the authors may not be used to endorse or promote 19335640Shselasky * products derived from this software without specific prior 20335640Shselasky * written permission. 21335640Shselasky * 22335640Shselasky * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 23335640Shselasky * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 24335640Shselasky * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 25335640Shselasky */ 26335640Shselasky 27335640Shselasky#ifdef HAVE_CONFIG_H 28335640Shselasky#include <config.h> 29335640Shselasky#endif 30335640Shselasky 31335640Shselasky#include <stdio.h> 32335640Shselasky#include <string.h> 33335640Shselasky#include <stdlib.h> 34335640Shselasky#include <unistd.h> 35335640Shselasky#include <fcntl.h> 36335640Shselasky#include <errno.h> 37335640Shselasky#include <sys/time.h> 38335640Shselasky#include <sys/socket.h> 39335640Shselasky#include <netinet/in.h> 40335640Shselasky#include <arpa/inet.h> 41335640Shselasky#include "pcap-int.h" 42335640Shselasky 43335640Shselasky#include "pcap-sita.h" 44335640Shselasky 45335640Shselasky /* non-configureable manifests follow */ 46335640Shselasky 47335640Shselasky#define IOP_SNIFFER_PORT 49152 /* TCP port on the IOP used for 'distributed pcap' usage */ 48335640Shselasky#define MAX_LINE_SIZE 255 /* max size of a buffer/line in /etc/hosts we allow */ 49335640Shselasky#define MAX_CHASSIS 8 /* number of chassis in an ACN site */ 50335640Shselasky#define MAX_GEOSLOT 8 /* max number of access units in an ACN site */ 51335640Shselasky 52335640Shselasky#define FIND 0 53335640Shselasky#define LIVE 1 54335640Shselasky 55335640Shselaskytypedef struct iface { 56335640Shselasky struct iface *next; /* a pointer to the next interface */ 57335640Shselasky char *name; /* this interface's name */ 58335640Shselasky char *IOPname; /* this interface's name on an IOP */ 59335640Shselasky uint32_t iftype; /* the type of interface (DLT values) */ 60335640Shselasky} iface_t; 61335640Shselasky 62335640Shselaskytypedef struct unit { 63335640Shselasky char *ip; /* this unit's IP address (as extracted from /etc/hosts) */ 64335640Shselasky int fd; /* the connection to this unit (if it exists) */ 65335640Shselasky int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */ 66335640Shselasky int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */ 67335640Shselasky struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */ 68335640Shselasky int chassis; 69335640Shselasky int geoslot; 70335640Shselasky iface_t *iface; /* a pointer to a linked list of interface structures */ 71335640Shselasky char *imsg; /* a pointer to an inbound message */ 72335640Shselasky int len; /* the current size of the inbound message */ 73335640Shselasky} unit_t; 74335640Shselasky 75335640Shselaskystatic unit_t units[MAX_CHASSIS+1][MAX_GEOSLOT+1]; /* we use indexes of 1 through 8, but we reserve/waste index 0 */ 76335640Shselaskystatic fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */ 77335640Shselaskystatic int max_fs; 78335640Shselasky 79335640Shselaskypcap_if_t *acn_if_list; /* pcap's list of available interfaces */ 80335640Shselasky 81335640Shselaskystatic void dump_interface_list(void) { 82335640Shselasky pcap_if_t *iff; 83335640Shselasky pcap_addr_t *addr; 84335640Shselasky int longest_name_len = 0; 85335640Shselasky char *n, *d, *f; 86335640Shselasky int if_number = 0; 87335640Shselasky 88335640Shselasky iff = acn_if_list; 89335640Shselasky while (iff) { 90335640Shselasky if (iff->name && (strlen(iff->name) > longest_name_len)) longest_name_len = strlen(iff->name); 91335640Shselasky iff = iff->next; 92335640Shselasky } 93335640Shselasky iff = acn_if_list; 94335640Shselasky printf("Interface List:\n"); 95335640Shselasky while (iff) { 96335640Shselasky n = (iff->name) ? iff->name : ""; 97335640Shselasky d = (iff->description) ? iff->description : ""; 98335640Shselasky f = (iff->flags == PCAP_IF_LOOPBACK) ? "L" : ""; 99335640Shselasky printf("%3d: %*s %s '%s'\n", if_number++, longest_name_len, n, f, d); 100335640Shselasky addr = iff->addresses; 101335640Shselasky while (addr) { 102335640Shselasky printf("%*s ", (5 + longest_name_len), ""); /* add some indentation */ 103335640Shselasky printf("%15s ", (addr->addr) ? inet_ntoa(((struct sockaddr_in *)addr->addr)->sin_addr) : ""); 104335640Shselasky printf("%15s ", (addr->netmask) ? inet_ntoa(((struct sockaddr_in *)addr->netmask)->sin_addr) : ""); 105335640Shselasky printf("%15s ", (addr->broadaddr) ? inet_ntoa(((struct sockaddr_in *)addr->broadaddr)->sin_addr) : ""); 106335640Shselasky printf("%15s ", (addr->dstaddr) ? inet_ntoa(((struct sockaddr_in *)addr->dstaddr)->sin_addr) : ""); 107335640Shselasky printf("\n"); 108335640Shselasky addr = addr->next; 109335640Shselasky } 110335640Shselasky iff = iff->next; 111335640Shselasky } 112335640Shselasky} 113335640Shselasky 114335640Shselaskystatic void dump(unsigned char *ptr, int i, int indent) { 115335640Shselasky fprintf(stderr, "%*s", indent, " "); 116335640Shselasky for (; i > 0; i--) { 117335640Shselasky fprintf(stderr, "%2.2x ", *ptr++); 118335640Shselasky } 119335640Shselasky fprintf(stderr, "\n"); 120335640Shselasky} 121335640Shselasky 122335640Shselaskystatic void dump_interface_list_p(void) { 123335640Shselasky pcap_if_t *iff; 124335640Shselasky pcap_addr_t *addr; 125335640Shselasky int if_number = 0; 126335640Shselasky 127335640Shselasky iff = acn_if_list; 128335640Shselasky printf("Interface Pointer @ %p is %p:\n", &acn_if_list, iff); 129335640Shselasky while (iff) { 130335640Shselasky printf("%3d: %p %p next: %p\n", if_number++, iff->name, iff->description, iff->next); 131335640Shselasky dump((unsigned char *)iff, sizeof(pcap_if_t), 5); 132335640Shselasky addr = iff->addresses; 133335640Shselasky while (addr) { 134335640Shselasky printf(" %p %p %p %p, next: %p\n", addr->addr, addr->netmask, addr->broadaddr, addr->dstaddr, addr->next); 135335640Shselasky dump((unsigned char *)addr, sizeof(pcap_addr_t), 10); 136335640Shselasky addr = addr->next; 137335640Shselasky } 138335640Shselasky iff = iff->next; 139335640Shselasky } 140335640Shselasky} 141335640Shselasky 142335640Shselaskystatic void dump_unit_table(void) { 143335640Shselasky int chassis, geoslot; 144335640Shselasky iface_t *p; 145335640Shselasky 146335640Shselasky printf("%c:%c %s %s\n", 'C', 'S', "fd", "IP Address"); 147335640Shselasky for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { 148335640Shselasky for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 149335640Shselasky if (units[chassis][geoslot].ip != NULL) 150335640Shselasky printf("%d:%d %2d %s\n", chassis, geoslot, units[chassis][geoslot].fd, units[chassis][geoslot].ip); 151335640Shselasky p = units[chassis][geoslot].iface; 152335640Shselasky while (p) { 153335640Shselasky char *n = (p->name) ? p->name : ""; 154335640Shselasky char *i = (p->IOPname) ? p->IOPname : ""; 155335640Shselasky p = p->next; 156335640Shselasky printf(" %12s -> %12s\n", i, n); 157335640Shselasky } 158335640Shselasky } 159335640Shselasky } 160335640Shselasky} 161335640Shselasky 162335640Shselaskystatic int find_unit_by_fd(int fd, int *chassis, int *geoslot, unit_t **unit_ptr) { 163335640Shselasky int c, s; 164335640Shselasky 165335640Shselasky for (c = 0; c <= MAX_CHASSIS; c++) { 166335640Shselasky for (s = 0; s <= MAX_GEOSLOT; s++) { 167335640Shselasky if (units[c][s].fd == fd || units[c][s].find_fd == fd) { 168335640Shselasky if (chassis) *chassis = c; 169335640Shselasky if (geoslot) *geoslot = s; 170335640Shselasky if (unit_ptr) *unit_ptr = &units[c][s]; 171335640Shselasky return 1; 172335640Shselasky } 173335640Shselasky } 174335640Shselasky } 175335640Shselasky return 0; 176335640Shselasky} 177335640Shselasky 178335640Shselaskystatic int read_client_nbytes(int fd, int count, unsigned char *buf) { 179335640Shselasky unit_t *u; 180335640Shselasky int chassis, geoslot; 181335640Shselasky int len; 182335640Shselasky 183335640Shselasky find_unit_by_fd(fd, &chassis, &geoslot, &u); 184335640Shselasky while (count) { 185335640Shselasky if ((len = recv(fd, buf, count, 0)) <= 0) return -1; /* read in whatever data was sent to us */ 186335640Shselasky count -= len; 187335640Shselasky buf += len; 188335640Shselasky } /* till we have everything we are looking for */ 189335640Shselasky return 0; 190335640Shselasky} 191335640Shselasky 192335640Shselaskystatic void empty_unit_iface(unit_t *u) { 193335640Shselasky iface_t *p, *cur; 194335640Shselasky 195335640Shselasky cur = u->iface; 196335640Shselasky while (cur) { /* loop over all the interface entries */ 197335640Shselasky if (cur->name) free(cur->name); /* throwing away the contents if they exist */ 198335640Shselasky if (cur->IOPname) free(cur->IOPname); 199335640Shselasky p = cur->next; 200335640Shselasky free(cur); /* then throw away the structure itself */ 201335640Shselasky cur = p; 202335640Shselasky } 203335640Shselasky u->iface = 0; /* and finally remember that there are no remaining structure */ 204335640Shselasky} 205335640Shselasky 206335640Shselaskystatic void empty_unit(int chassis, int geoslot) { 207335640Shselasky unit_t *u = &units[chassis][geoslot]; 208335640Shselasky 209335640Shselasky empty_unit_iface(u); 210335640Shselasky if (u->imsg) { /* then if an inbound message buffer exists */ 211335640Shselasky void *bigger_buffer; 212335640Shselasky 213335640Shselasky bigger_buffer = (char *)realloc(u->imsg, 1); /* and re-allocate the old large buffer into a new small one */ 214335640Shselasky if (bigger_buffer == NULL) { /* oops, realloc call failed */ 215335640Shselasky fprintf(stderr, "Warning...call to realloc() failed, value of errno is %d\n", errno); 216335640Shselasky return; 217335640Shselasky } 218335640Shselasky u->imsg = bigger_buffer; 219335640Shselasky } 220335640Shselasky} 221335640Shselasky 222335640Shselaskystatic void empty_unit_table(void) { 223335640Shselasky int chassis, geoslot; 224335640Shselasky 225335640Shselasky for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { 226335640Shselasky for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 227335640Shselasky if (units[chassis][geoslot].ip != NULL) { 228335640Shselasky free(units[chassis][geoslot].ip); /* get rid of the malloc'ed space that holds the IP address */ 229335640Shselasky units[chassis][geoslot].ip = 0; /* then set the pointer to NULL */ 230335640Shselasky } 231335640Shselasky empty_unit(chassis, geoslot); 232335640Shselasky } 233335640Shselasky } 234335640Shselasky} 235335640Shselasky 236335640Shselaskystatic char *find_nth_interface_name(int n) { 237335640Shselasky int chassis, geoslot; 238335640Shselasky iface_t *p; 239335640Shselasky char *last_name = 0; 240335640Shselasky 241335640Shselasky if (n < 0) n = 0; /* ensure we are working with a valid number */ 242335640Shselasky for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */ 243335640Shselasky for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 244335640Shselasky if (units[chassis][geoslot].ip != NULL) { 245335640Shselasky p = units[chassis][geoslot].iface; 246335640Shselasky while (p) { /* and all interfaces... */ 247335640Shselasky if (p->IOPname) last_name = p->name; /* remembering the last name found */ 248335640Shselasky if (n-- == 0) return last_name; /* and if we hit the instance requested */ 249335640Shselasky p = p->next; 250335640Shselasky } 251335640Shselasky } 252335640Shselasky } 253335640Shselasky } 254335640Shselasky /* if we couldn't fine the selected entry */ 255335640Shselasky if (last_name) return last_name; /* ... but we did have at least one entry... return the last entry found */ 256335640Shselasky return ""; /* ... but if there wasn't any entry... return an empty string instead */ 257335640Shselasky} 258335640Shselasky 259335640Shselaskyint acn_parse_hosts_file(char *errbuf) { /* returns: -1 = error, 0 = OK */ 260335640Shselasky FILE *fp; 261335640Shselasky char buf[MAX_LINE_SIZE]; 262335640Shselasky char *ptr, *ptr2; 263335640Shselasky int pos; 264335640Shselasky int chassis, geoslot; 265335640Shselasky unit_t *u; 266335640Shselasky 267335640Shselasky empty_unit_table(); 268335640Shselasky if ((fp = fopen("/etc/hosts", "r")) == NULL) { /* try to open the hosts file and if it fails */ 269335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading."); /* return the nohostsfile error response */ 270335640Shselasky return -1; 271335640Shselasky } 272335640Shselasky while (fgets(buf, MAX_LINE_SIZE-1, fp)) { /* while looping over the file */ 273335640Shselasky 274335640Shselasky pos = strcspn(buf, "#\n\r"); /* find the first comment character or EOL */ 275335640Shselasky *(buf + pos) = '\0'; /* and clobber it and anything that follows it */ 276335640Shselasky 277335640Shselasky pos = strspn(buf, " \t"); /* then find the first non-white space */ 278335640Shselasky if (pos == strlen(buf)) /* if there is nothing but white space on the line */ 279335640Shselasky continue; /* ignore that empty line */ 280335640Shselasky ptr = buf + pos; /* and skip over any of that leading whitespace */ 281335640Shselasky 282335640Shselasky if ((ptr2 = strstr(ptr, "_I_")) == NULL) /* skip any lines that don't have names that look like they belong to IOPs */ 283335640Shselasky continue; 284335640Shselasky if (*(ptr2 + 4) != '_') /* and skip other lines that have names that don't look like ACN components */ 285335640Shselasky continue; 286335640Shselasky *(ptr + strcspn(ptr, " \t")) = '\0'; /* null terminate the IP address so its a standalone string */ 287335640Shselasky 288335640Shselasky chassis = *(ptr2 + 3) - '0'; /* extract the chassis number */ 289335640Shselasky geoslot = *(ptr2 + 5) - '0'; /* and geo-slot number */ 290335640Shselasky if (chassis < 1 || chassis > MAX_CHASSIS || 291335640Shselasky geoslot < 1 || geoslot > MAX_GEOSLOT) { /* if the chassis and/or slot numbers appear to be bad... */ 292335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'."); /* warn the user */ 293335640Shselasky continue; /* and ignore the entry */ 294335640Shselasky } 295335640Shselasky if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) { 296335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 297335640Shselasky errno, "malloc"); 298335640Shselasky continue; 299335640Shselasky } 300335640Shselasky strcpy(ptr2, ptr); /* copy the IP address into our malloc'ed memory */ 301335640Shselasky u = &units[chassis][geoslot]; 302335640Shselasky u->ip = ptr2; /* and remember the whole shebang */ 303335640Shselasky u->chassis = chassis; 304335640Shselasky u->geoslot = geoslot; 305335640Shselasky } 306335640Shselasky fclose(fp); 307335640Shselasky if (*errbuf) return -1; 308335640Shselasky else return 0; 309335640Shselasky} 310335640Shselasky 311335640Shselaskystatic int open_with_IOP(unit_t *u, int flag) { 312335640Shselasky int sockfd; 313335640Shselasky char *ip; 314335640Shselasky 315335640Shselasky if (u->serv_addr == NULL) { 316335640Shselasky u->serv_addr = malloc(sizeof(struct sockaddr_in)); 317335640Shselasky 318335640Shselasky /* since we called malloc(), lets check to see if we actually got the memory */ 319335640Shselasky if (u->serv_addr == NULL) { /* oops, we didn't get the memory requested */ 320335640Shselasky fprintf(stderr, "malloc() request for u->serv_addr failed, value of errno is: %d\n", errno); 321335640Shselasky return 0; 322335640Shselasky } 323335640Shselasky 324335640Shselasky } 325335640Shselasky ip = u->ip; 326335640Shselasky /* bzero() is deprecated, replaced with memset() */ 327335640Shselasky memset((char *)u->serv_addr, 0, sizeof(struct sockaddr_in)); 328335640Shselasky u->serv_addr->sin_family = AF_INET; 329335640Shselasky u->serv_addr->sin_addr.s_addr = inet_addr(ip); 330335640Shselasky u->serv_addr->sin_port = htons(IOP_SNIFFER_PORT); 331335640Shselasky 332335640Shselasky if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 333335640Shselasky fprintf(stderr, "pcap can't open a socket for connecting to IOP at %s\n", ip); 334335640Shselasky return 0; 335335640Shselasky } 336335640Shselasky if (connect(sockfd, (struct sockaddr *)u->serv_addr, sizeof(struct sockaddr_in)) < 0) { 337335640Shselasky fprintf(stderr, "pcap can't connect to IOP at %s\n", ip); 338335640Shselasky return 0; 339335640Shselasky } 340335640Shselasky if (flag == LIVE) u->fd = sockfd; 341335640Shselasky else u->find_fd = sockfd; 342335640Shselasky u->first_time = 0; 343335640Shselasky return sockfd; /* return the non-zero file descriptor as a 'success' indicator */ 344335640Shselasky} 345335640Shselasky 346335640Shselaskystatic void close_with_IOP(int chassis, int geoslot, int flag) { 347335640Shselasky int *id; 348335640Shselasky 349335640Shselasky if (flag == LIVE) id = &units[chassis][geoslot].fd; 350335640Shselasky else id = &units[chassis][geoslot].find_fd; 351335640Shselasky 352335640Shselasky if (*id) { /* this was the last time, so... if we are connected... */ 353335640Shselasky close(*id); /* disconnect us */ 354335640Shselasky *id = 0; /* and forget that the descriptor exists because we are not open */ 355335640Shselasky } 356335640Shselasky} 357335640Shselasky 358335640Shselaskystatic void pcap_cleanup_acn(pcap_t *handle) { 359335640Shselasky int chassis, geoslot; 360335640Shselasky unit_t *u; 361335640Shselasky 362335640Shselasky if (find_unit_by_fd(handle->fd, &chassis, &geoslot, &u) == 0) 363335640Shselasky return; 364335640Shselasky close_with_IOP(chassis, geoslot, LIVE); 365335640Shselasky if (u) 366335640Shselasky u->first_time = 0; 367335640Shselasky pcap_cleanup_live_common(handle); 368335640Shselasky} 369335640Shselasky 370335640Shselaskystatic void send_to_fd(int fd, int len, unsigned char *str) { 371335640Shselasky int nwritten; 372335640Shselasky int chassis, geoslot; 373335640Shselasky 374335640Shselasky while (len > 0) { 375335640Shselasky if ((nwritten = write(fd, str, len)) <= 0) { 376335640Shselasky find_unit_by_fd(fd, &chassis, &geoslot, NULL); 377335640Shselasky if (units[chassis][geoslot].fd == fd) close_with_IOP(chassis, geoslot, LIVE); 378335640Shselasky else if (units[chassis][geoslot].find_fd == fd) close_with_IOP(chassis, geoslot, FIND); 379335640Shselasky empty_unit(chassis, geoslot); 380335640Shselasky return; 381335640Shselasky } 382335640Shselasky len -= nwritten; 383335640Shselasky str += nwritten; 384335640Shselasky } 385335640Shselasky} 386335640Shselasky 387335640Shselaskystatic void acn_freealldevs(void) { 388335640Shselasky 389335640Shselasky pcap_if_t *iff, *next_iff; 390335640Shselasky pcap_addr_t *addr, *next_addr; 391335640Shselasky 392335640Shselasky for (iff = acn_if_list; iff != NULL; iff = next_iff) { 393335640Shselasky next_iff = iff->next; 394335640Shselasky for (addr = iff->addresses; addr != NULL; addr = next_addr) { 395335640Shselasky next_addr = addr->next; 396335640Shselasky if (addr->addr) free(addr->addr); 397335640Shselasky if (addr->netmask) free(addr->netmask); 398335640Shselasky if (addr->broadaddr) free(addr->broadaddr); 399335640Shselasky if (addr->dstaddr) free(addr->dstaddr); 400335640Shselasky free(addr); 401335640Shselasky } 402335640Shselasky if (iff->name) free(iff->name); 403335640Shselasky if (iff->description) free(iff->description); 404335640Shselasky free(iff); 405335640Shselasky } 406335640Shselasky} 407335640Shselasky 408335640Shselaskystatic void nonUnified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u) { 409335640Shselasky 410335640Shselasky pcap_snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot); 411335640Shselasky} 412335640Shselasky 413335640Shselaskystatic void unified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u, int IOPportnum) { 414335640Shselasky int portnum; 415335640Shselasky 416335640Shselasky portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1; 417335640Shselasky pcap_snprintf(buf, bufsize, "%s_%d", proto, portnum); 418335640Shselasky} 419335640Shselasky 420335640Shselaskystatic char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) { 421335640Shselasky iface_t *iface_ptr, *iface; 422335640Shselasky char *name; 423335640Shselasky char buf[32]; 424335640Shselasky char *proto; 425335640Shselasky char *port; 426335640Shselasky int IOPportnum = 0; 427335640Shselasky 428335640Shselasky iface = malloc(sizeof(iface_t)); /* get memory for a structure */ 429335640Shselasky if (iface == NULL) { /* oops, we didn't get the memory requested */ 430335640Shselasky fprintf(stderr, "Error...couldn't allocate memory for interface structure...value of errno is: %d\n", errno); 431335640Shselasky return NULL; 432335640Shselasky } 433335640Shselasky memset((char *)iface, 0, sizeof(iface_t)); /* bzero is deprecated(), replaced with memset() */ 434335640Shselasky 435335640Shselasky iface->iftype = iftype; /* remember the interface type of this interface */ 436335640Shselasky 437335640Shselasky name = malloc(strlen(IOPname) + 1); /* get memory for the IOP's name */ 438335640Shselasky if (name == NULL) { /* oops, we didn't get the memory requested */ 439335640Shselasky fprintf(stderr, "Error...couldn't allocate memory for IOPname...value of errno is: %d\n", errno); 440335640Shselasky return NULL; 441335640Shselasky } 442335640Shselasky 443335640Shselasky strcpy(name, IOPname); /* and copy it in */ 444335640Shselasky iface->IOPname = name; /* and stick it into the structure */ 445335640Shselasky 446335640Shselasky if (strncmp(IOPname, "lo", 2) == 0) { 447335640Shselasky IOPportnum = atoi(&IOPname[2]); 448335640Shselasky switch (iftype) { 449335640Shselasky case DLT_EN10MB: 450335640Shselasky nonUnified_IOP_port_name(buf, sizeof buf, "lo", u); 451335640Shselasky break; 452335640Shselasky default: 453335640Shselasky unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum); 454335640Shselasky break; 455335640Shselasky } 456335640Shselasky } else if (strncmp(IOPname, "eth", 3) == 0) { 457335640Shselasky IOPportnum = atoi(&IOPname[3]); 458335640Shselasky switch (iftype) { 459335640Shselasky case DLT_EN10MB: 460335640Shselasky nonUnified_IOP_port_name(buf, sizeof buf, "eth", u); 461335640Shselasky break; 462335640Shselasky default: 463335640Shselasky unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum); 464335640Shselasky break; 465335640Shselasky } 466335640Shselasky } else if (strncmp(IOPname, "wan", 3) == 0) { 467335640Shselasky IOPportnum = atoi(&IOPname[3]); 468335640Shselasky switch (iftype) { 469335640Shselasky case DLT_SITA: 470335640Shselasky unified_IOP_port_name(buf, sizeof buf, "wan", u, IOPportnum); 471335640Shselasky break; 472335640Shselasky default: 473335640Shselasky unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum); 474335640Shselasky break; 475335640Shselasky } 476335640Shselasky } else { 477335640Shselasky fprintf(stderr, "Error... invalid IOP name %s\n", IOPname); 478335640Shselasky return NULL; 479335640Shselasky } 480335640Shselasky 481335640Shselasky name = malloc(strlen(buf) + 1); /* get memory for that name */ 482335640Shselasky if (name == NULL) { /* oops, we didn't get the memory requested */ 483335640Shselasky fprintf(stderr, "Error...couldn't allocate memory for IOP port name...value of errno is: %d\n", errno); 484335640Shselasky return NULL; 485335640Shselasky } 486335640Shselasky 487335640Shselasky strcpy(name, buf); /* and copy it in */ 488335640Shselasky iface->name = name; /* and stick it into the structure */ 489335640Shselasky 490335640Shselasky if (u->iface == 0) { /* if this is the first name */ 491335640Shselasky u->iface = iface; /* stick this entry at the head of the list */ 492335640Shselasky } else { 493335640Shselasky iface_ptr = u->iface; 494335640Shselasky while (iface_ptr->next) { /* othewise scan the list */ 495335640Shselasky iface_ptr = iface_ptr->next; /* till we're at the last entry */ 496335640Shselasky } 497335640Shselasky iface_ptr->next = iface; /* then tack this entry on the end of the list */ 498335640Shselasky } 499335640Shselasky return iface->name; 500335640Shselasky} 501335640Shselasky 502335640Shselaskystatic int if_sort(char *s1, char *s2) { 503335640Shselasky char *s1_p2, *s2_p2; 504335640Shselasky char str1[MAX_LINE_SIZE], str2[MAX_LINE_SIZE]; 505335640Shselasky int s1_p1_len, s2_p1_len; 506335640Shselasky int retval; 507335640Shselasky 508335640Shselasky if ((s1_p2 = strchr(s1, '_'))) { /* if an underscore is found... */ 509335640Shselasky s1_p1_len = s1_p2 - s1; /* the prefix length is the difference in pointers */ 510335640Shselasky s1_p2++; /* the suffix actually starts _after_ the underscore */ 511335640Shselasky } else { /* otherwise... */ 512335640Shselasky s1_p1_len = strlen(s1); /* the prefix length is the length of the string itself */ 513335640Shselasky s1_p2 = 0; /* and there is no suffix */ 514335640Shselasky } 515335640Shselasky if ((s2_p2 = strchr(s2, '_'))) { /* now do the same for the second string */ 516335640Shselasky s2_p1_len = s2_p2 - s2; 517335640Shselasky s2_p2++; 518335640Shselasky } else { 519335640Shselasky s2_p1_len = strlen(s2); 520335640Shselasky s2_p2 = 0; 521335640Shselasky } 522335640Shselasky strncpy(str1, s1, (s1_p1_len > sizeof(str1)) ? s1_p1_len : sizeof(str1)); *(str1 + s1_p1_len) = 0; 523335640Shselasky strncpy(str2, s2, (s2_p1_len > sizeof(str2)) ? s2_p1_len : sizeof(str2)); *(str2 + s2_p1_len) = 0; 524335640Shselasky retval = strcmp(str1, str2); 525335640Shselasky if (retval != 0) return retval; /* if they are not identical, then we can quit now and return the indication */ 526335640Shselasky return strcmp(s1_p2, s2_p2); /* otherwise we return the result of comparing the 2nd half of the string */ 527335640Shselasky} 528335640Shselasky 529335640Shselaskystatic void sort_if_table(void) { 530335640Shselasky pcap_if_t *p1, *p2, *prev, *temp; 531335640Shselasky int has_swapped; 532335640Shselasky 533335640Shselasky if (!acn_if_list) return; /* nothing to do if the list is empty */ 534335640Shselasky 535335640Shselasky while (1) { 536335640Shselasky p1 = acn_if_list; /* start at the head of the list */ 537335640Shselasky prev = 0; 538335640Shselasky has_swapped = 0; 539335640Shselasky while ((p2 = p1->next)) { 540335640Shselasky if (if_sort(p1->name, p2->name) > 0) { 541335640Shselasky if (prev) { /* we are swapping things that are _not_ at the head of the list */ 542335640Shselasky temp = p2->next; 543335640Shselasky prev->next = p2; 544335640Shselasky p2->next = p1; 545335640Shselasky p1->next = temp; 546335640Shselasky } else { /* special treatment if we are swapping with the head of the list */ 547335640Shselasky temp = p2->next; 548335640Shselasky acn_if_list= p2; 549335640Shselasky p2->next = p1; 550335640Shselasky p1->next = temp; 551335640Shselasky } 552335640Shselasky p1 = p2; 553335640Shselasky prev = p1; 554335640Shselasky has_swapped = 1; 555335640Shselasky } 556335640Shselasky prev = p1; 557335640Shselasky p1 = p1->next; 558335640Shselasky } 559335640Shselasky if (has_swapped == 0) 560335640Shselasky return; 561335640Shselasky } 562335640Shselasky return; 563335640Shselasky} 564335640Shselasky 565335640Shselaskystatic int process_client_data (char *errbuf) { /* returns: -1 = error, 0 = OK */ 566335640Shselasky int chassis, geoslot; 567335640Shselasky unit_t *u; 568335640Shselasky pcap_if_t *iff, *prev_iff; 569335640Shselasky pcap_addr_t *addr, *prev_addr; 570335640Shselasky char *ptr; 571335640Shselasky int address_count; 572335640Shselasky struct sockaddr_in *s; 573335640Shselasky char *newname; 574335640Shselasky bpf_u_int32 interfaceType; 575335640Shselasky unsigned char flags; 576335640Shselasky void *bigger_buffer; 577335640Shselasky 578335640Shselasky prev_iff = 0; 579335640Shselasky for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { 580335640Shselasky for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { /* now loop over all the devices */ 581335640Shselasky u = &units[chassis][geoslot]; 582335640Shselasky empty_unit_iface(u); 583335640Shselasky ptr = u->imsg; /* point to the start of the msg for this IOP */ 584335640Shselasky while (ptr < (u->imsg + u->len)) { 585335640Shselasky if ((iff = malloc(sizeof(pcap_if_t))) == NULL) { 586335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, 587335640Shselasky PCAP_ERRBUF_SIZE, errno, "malloc"); 588335640Shselasky return -1; 589335640Shselasky } 590335640Shselasky memset((char *)iff, 0, sizeof(pcap_if_t)); /* bzero() is deprecated, replaced with memset() */ 591335640Shselasky if (acn_if_list == 0) acn_if_list = iff; /* remember the head of the list */ 592335640Shselasky if (prev_iff) prev_iff->next = iff; /* insert a forward link */ 593335640Shselasky 594335640Shselasky if (*ptr) { /* if there is a count for the name */ 595335640Shselasky if ((iff->name = malloc(*ptr + 1)) == NULL) { /* get that amount of space */ 596335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, 597335640Shselasky PCAP_ERRBUF_SIZE, errno, 598335640Shselasky "malloc"); 599335640Shselasky return -1; 600335640Shselasky } 601335640Shselasky memcpy(iff->name, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */ 602335640Shselasky *(iff->name + *ptr) = 0; /* and null terminate the string */ 603335640Shselasky ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */ 604335640Shselasky } 605335640Shselasky ptr++; 606335640Shselasky 607335640Shselasky if (*ptr) { /* if there is a count for the description */ 608335640Shselasky if ((iff->description = malloc(*ptr + 1)) == NULL) { /* get that amount of space */ 609335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, 610335640Shselasky PCAP_ERRBUF_SIZE, errno, 611335640Shselasky "malloc"); 612335640Shselasky return -1; 613335640Shselasky } 614335640Shselasky memcpy(iff->description, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */ 615335640Shselasky *(iff->description + *ptr) = 0; /* and null terminate the string */ 616335640Shselasky ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */ 617335640Shselasky } 618335640Shselasky ptr++; 619335640Shselasky 620335640Shselasky interfaceType = ntohl(*(bpf_u_int32 *)ptr); 621335640Shselasky ptr += 4; /* skip over the interface type */ 622335640Shselasky 623335640Shselasky flags = *ptr++; 624335640Shselasky if (flags) iff->flags = PCAP_IF_LOOPBACK; /* if this is a loopback style interface, lets mark it as such */ 625335640Shselasky 626335640Shselasky address_count = *ptr++; 627335640Shselasky 628335640Shselasky prev_addr = 0; 629335640Shselasky while (address_count--) { 630335640Shselasky if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) { 631335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, 632335640Shselasky PCAP_ERRBUF_SIZE, errno, 633335640Shselasky "malloc"); 634335640Shselasky return -1; 635335640Shselasky } 636335640Shselasky memset((char *)addr, 0, sizeof(pcap_addr_t)); /* bzero() is deprecated, replaced with memset() */ 637335640Shselasky if (iff->addresses == 0) iff->addresses = addr; 638335640Shselasky if (prev_addr) prev_addr->next = addr; /* insert a forward link */ 639335640Shselasky if (*ptr) { /* if there is a count for the address */ 640335640Shselasky if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { /* get that amount of space */ 641335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, 642335640Shselasky PCAP_ERRBUF_SIZE, 643335640Shselasky errno, "malloc"); 644335640Shselasky return -1; 645335640Shselasky } 646335640Shselasky memset((char *)s, 0, sizeof(struct sockaddr_in)); /* bzero() is deprecated, replaced with memset() */ 647335640Shselasky addr->addr = (struct sockaddr *)s; 648335640Shselasky s->sin_family = AF_INET; 649335640Shselasky s->sin_addr.s_addr = *(bpf_u_int32 *)(ptr + 1); /* copy the address in */ 650335640Shselasky ptr += *ptr; /* now move the pointer forwards according to the specified length of the address */ 651335640Shselasky } 652335640Shselasky ptr++; /* then forwards one more for the 'length of the address' field */ 653335640Shselasky if (*ptr) { /* process any netmask */ 654335640Shselasky if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { 655335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, 656335640Shselasky PCAP_ERRBUF_SIZE, 657335640Shselasky errno, "malloc"); 658335640Shselasky return -1; 659335640Shselasky } 660335640Shselasky /* bzero() is deprecated, replaced with memset() */ 661335640Shselasky memset((char *)s, 0, sizeof(struct sockaddr_in)); 662335640Shselasky 663335640Shselasky addr->netmask = (struct sockaddr *)s; 664335640Shselasky s->sin_family = AF_INET; 665335640Shselasky s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1); 666335640Shselasky ptr += *ptr; 667335640Shselasky } 668335640Shselasky ptr++; 669335640Shselasky if (*ptr) { /* process any broadcast address */ 670335640Shselasky if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { 671335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, 672335640Shselasky PCAP_ERRBUF_SIZE, 673335640Shselasky errno, "malloc"); 674335640Shselasky return -1; 675335640Shselasky } 676335640Shselasky /* bzero() is deprecated, replaced with memset() */ 677335640Shselasky memset((char *)s, 0, sizeof(struct sockaddr_in)); 678335640Shselasky 679335640Shselasky addr->broadaddr = (struct sockaddr *)s; 680335640Shselasky s->sin_family = AF_INET; 681335640Shselasky s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1); 682335640Shselasky ptr += *ptr; 683335640Shselasky } 684335640Shselasky ptr++; 685335640Shselasky if (*ptr) { /* process any destination address */ 686335640Shselasky if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { 687335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, 688335640Shselasky PCAP_ERRBUF_SIZE, 689335640Shselasky errno, "malloc"); 690335640Shselasky return -1; 691335640Shselasky } 692335640Shselasky /* bzero() is deprecated, replaced with memset() */ 693335640Shselasky memset((char *)s, 0, sizeof(struct sockaddr_in)); 694335640Shselasky 695335640Shselasky addr->dstaddr = (struct sockaddr *)s; 696335640Shselasky s->sin_family = AF_INET; 697335640Shselasky s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1); 698335640Shselasky ptr += *ptr; 699335640Shselasky } 700335640Shselasky ptr++; 701335640Shselasky prev_addr = addr; 702335640Shselasky } 703335640Shselasky prev_iff = iff; 704335640Shselasky 705335640Shselasky newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType); /* add a translation entry and get a point to the mangled name */ 706335640Shselasky bigger_buffer = realloc(iff->name, strlen(newname) + 1)); 707335640Shselasky if (bigger_buffer == NULL) { /* we now re-write the name stored in the interface list */ 708335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, 709335640Shselasky PCAP_ERRBUF_SIZE, errno, "realloc"); 710335640Shselasky return -1; 711335640Shselasky } 712335640Shselasky iff->name = bigger_buffer; 713335640Shselasky strcpy(iff->name, newname); /* to this new name */ 714335640Shselasky } 715335640Shselasky } 716335640Shselasky } 717335640Shselasky return 0; 718335640Shselasky} 719335640Shselasky 720335640Shselaskystatic int read_client_data (int fd) { 721335640Shselasky unsigned char buf[256]; 722335640Shselasky int chassis, geoslot; 723335640Shselasky unit_t *u; 724335640Shselasky int len; 725335640Shselasky 726335640Shselasky find_unit_by_fd(fd, &chassis, &geoslot, &u); 727335640Shselasky 728335640Shselasky if ((len = recv(fd, buf, sizeof(buf), 0)) <= 0) return 0; /* read in whatever data was sent to us */ 729335640Shselasky 730335640Shselasky if ((u->imsg = realloc(u->imsg, (u->len + len))) == NULL) /* extend the buffer for the new data */ 731335640Shselasky return 0; 732335640Shselasky memcpy((u->imsg + u->len), buf, len); /* append the new data */ 733335640Shselasky u->len += len; 734335640Shselasky return 1; 735335640Shselasky} 736335640Shselasky 737335640Shselaskystatic void wait_for_all_answers(void) { 738335640Shselasky int retval; 739335640Shselasky struct timeval tv; 740335640Shselasky int fd; 741335640Shselasky int chassis, geoslot; 742335640Shselasky 743335640Shselasky tv.tv_sec = 2; 744335640Shselasky tv.tv_usec = 0; 745335640Shselasky 746335640Shselasky while (1) { 747335640Shselasky int flag = 0; 748335640Shselasky fd_set working_set; 749335640Shselasky 750335640Shselasky for (fd = 0; fd <= max_fs; fd++) { /* scan the list of descriptors we may be listening to */ 751335640Shselasky if (FD_ISSET(fd, &readfds)) flag = 1; /* and see if there are any still set */ 752335640Shselasky } 753335640Shselasky if (flag == 0) return; /* we are done, when they are all gone */ 754335640Shselasky 755335640Shselasky memcpy(&working_set, &readfds, sizeof(readfds)); /* otherwise, we still have to listen for more stuff, till we timeout */ 756335640Shselasky retval = select(max_fs + 1, &working_set, NULL, NULL, &tv); 757335640Shselasky if (retval == -1) { /* an error occured !!!!! */ 758335640Shselasky return; 759335640Shselasky } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */ 760335640Shselasky printf("timeout\n"); 761335640Shselasky return; 762335640Shselasky } else { 763335640Shselasky for (fd = 0; fd <= max_fs; fd++) { /* scan the list of things to do, and do them */ 764335640Shselasky if (FD_ISSET(fd, &working_set)) { 765335640Shselasky if (read_client_data(fd) == 0) { /* if the socket has closed */ 766335640Shselasky FD_CLR(fd, &readfds); /* and descriptors we listen to for errors */ 767335640Shselasky find_unit_by_fd(fd, &chassis, &geoslot, NULL); 768335640Shselasky close_with_IOP(chassis, geoslot, FIND); /* and close out connection to him */ 769335640Shselasky } 770335640Shselasky } 771335640Shselasky } 772335640Shselasky } 773335640Shselasky } 774335640Shselasky} 775335640Shselasky 776335640Shselaskystatic char *get_error_response(int fd, char *errbuf) { /* return a pointer on error, NULL on no error */ 777335640Shselasky char byte; 778335640Shselasky int len = 0; 779335640Shselasky 780335640Shselasky while (1) { 781335640Shselasky recv(fd, &byte, 1, 0); /* read another byte in */ 782335640Shselasky if (errbuf && (len++ < PCAP_ERRBUF_SIZE)) { /* and if there is still room in the buffer */ 783335640Shselasky *errbuf++ = byte; /* stick it in */ 784335640Shselasky *errbuf = '\0'; /* ensure the string is null terminated just in case we might exceed the buffer's size */ 785335640Shselasky } 786335640Shselasky if (byte == '\0') { 787335640Shselasky if (len > 1) { return errbuf; } 788335640Shselasky else { return NULL; } 789335640Shselasky } 790335640Shselasky } 791335640Shselasky} 792335640Shselasky 793335640Shselaskyint acn_findalldevs(char *errbuf) { /* returns: -1 = error, 0 = OK */ 794335640Shselasky int chassis, geoslot; 795335640Shselasky unit_t *u; 796335640Shselasky 797335640Shselasky FD_ZERO(&readfds); 798335640Shselasky max_fs = 0; 799335640Shselasky for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { 800335640Shselasky for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 801335640Shselasky u = &units[chassis][geoslot]; 802335640Shselasky if (u->ip && (open_with_IOP(u, FIND))) { /* connect to the remote IOP */ 803335640Shselasky send_to_fd(u->find_fd, 1, (unsigned char *)"\0"); 804335640Shselasky if (get_error_response(u->find_fd, errbuf)) 805335640Shselasky close_with_IOP(chassis, geoslot, FIND); 806335640Shselasky else { 807335640Shselasky if (u->find_fd > max_fs) 808335640Shselasky max_fs = u->find_fd; /* remember the highest number currently in use */ 809335640Shselasky FD_SET(u->find_fd, &readfds); /* we are going to want to read this guy's response to */ 810335640Shselasky u->len = 0; 811335640Shselasky send_to_fd(u->find_fd, 1, (unsigned char *)"Q"); /* this interface query request */ 812335640Shselasky } 813335640Shselasky } 814335640Shselasky } 815335640Shselasky } 816335640Shselasky wait_for_all_answers(); 817335640Shselasky if (process_client_data(errbuf)) 818335640Shselasky return -1; 819335640Shselasky sort_if_table(); 820335640Shselasky return 0; 821335640Shselasky} 822335640Shselasky 823335640Shselaskystatic int pcap_stats_acn(pcap_t *handle, struct pcap_stat *ps) { 824335640Shselasky unsigned char buf[12]; 825335640Shselasky 826335640Shselasky send_to_fd(handle->fd, 1, (unsigned char *)"S"); /* send the get_stats command to the IOP */ 827335640Shselasky 828335640Shselasky if (read_client_nbytes(handle->fd, sizeof(buf), buf) == -1) return -1; /* try reading the required bytes */ 829335640Shselasky 830335640Shselasky ps->ps_recv = ntohl(*(uint32_t *)&buf[0]); /* break the buffer into its three 32 bit components */ 831335640Shselasky ps->ps_drop = ntohl(*(uint32_t *)&buf[4]); 832335640Shselasky ps->ps_ifdrop = ntohl(*(uint32_t *)&buf[8]); 833335640Shselasky 834335640Shselasky return 0; 835335640Shselasky} 836335640Shselasky 837335640Shselaskystatic int acn_open_live(const char *name, char *errbuf, int *linktype) { /* returns 0 on error, else returns the file descriptor */ 838335640Shselasky int chassis, geoslot; 839335640Shselasky unit_t *u; 840335640Shselasky iface_t *p; 841335640Shselasky pcap_if_list_t devlist; 842335640Shselasky 843335640Shselasky pcap_platform_finddevs(&devlist, errbuf); 844335640Shselasky for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */ 845335640Shselasky for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 846335640Shselasky u = &units[chassis][geoslot]; 847335640Shselasky if (u->ip != NULL) { 848335640Shselasky p = u->iface; 849335640Shselasky while (p) { /* and all interfaces... */ 850335640Shselasky if (p->IOPname && p->name && (strcmp(p->name, name) == 0)) { /* and if we found the interface we want... */ 851335640Shselasky *linktype = p->iftype; 852335640Shselasky open_with_IOP(u, LIVE); /* start a connection with that IOP */ 853335640Shselasky send_to_fd(u->fd, strlen(p->IOPname)+1, (unsigned char *)p->IOPname); /* send the IOP's interface name, and a terminating null */ 854335640Shselasky if (get_error_response(u->fd, errbuf)) { 855335640Shselasky return -1; 856335640Shselasky } 857335640Shselasky return u->fd; /* and return that open descriptor */ 858335640Shselasky } 859335640Shselasky p = p->next; 860335640Shselasky } 861335640Shselasky } 862335640Shselasky } 863335640Shselasky } 864335640Shselasky return -1; /* if the interface wasn't found, return an error */ 865335640Shselasky} 866335640Shselasky 867335640Shselaskystatic void acn_start_monitor(int fd, int snaplen, int timeout, int promiscuous, int direction) { 868335640Shselasky unsigned char buf[8]; 869335640Shselasky unit_t *u; 870335640Shselasky 871335640Shselasky //printf("acn_start_monitor()\n"); // fulko 872335640Shselasky find_unit_by_fd(fd, NULL, NULL, &u); 873335640Shselasky if (u->first_time == 0) { 874335640Shselasky buf[0] = 'M'; 875335640Shselasky *(uint32_t *)&buf[1] = htonl(snaplen); 876335640Shselasky buf[5] = timeout; 877335640Shselasky buf[6] = promiscuous; 878335640Shselasky buf[7] = direction; 879335640Shselasky //printf("acn_start_monitor() first time\n"); // fulko 880335640Shselasky send_to_fd(fd, 8, buf); /* send the start monitor command with its parameters to the IOP */ 881335640Shselasky u->first_time = 1; 882335640Shselasky } 883335640Shselasky //printf("acn_start_monitor() complete\n"); // fulko 884335640Shselasky} 885335640Shselasky 886335640Shselaskystatic int pcap_inject_acn(pcap_t *p, const void *buf _U_, size_t size _U_) { 887356341Scy pcap_strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters", 888335640Shselasky PCAP_ERRBUF_SIZE); 889335640Shselasky return (-1); 890335640Shselasky} 891335640Shselasky 892335640Shselaskystatic int pcap_setfilter_acn(pcap_t *handle, struct bpf_program *bpf) { 893335640Shselasky int fd = handle->fd; 894335640Shselasky int count; 895335640Shselasky struct bpf_insn *p; 896335640Shselasky uint16_t shortInt; 897335640Shselasky uint32_t longInt; 898335640Shselasky 899335640Shselasky send_to_fd(fd, 1, (unsigned char *)"F"); /* BPF filter follows command */ 900335640Shselasky count = bpf->bf_len; 901335640Shselasky longInt = htonl(count); 902335640Shselasky send_to_fd(fd, 4, (unsigned char *)&longInt); /* send the instruction sequence count */ 903335640Shselasky p = bpf->bf_insns; 904335640Shselasky while (count--) { /* followed by the list of instructions */ 905335640Shselasky shortInt = htons(p->code); 906335640Shselasky longInt = htonl(p->k); 907335640Shselasky send_to_fd(fd, 2, (unsigned char *)&shortInt); 908335640Shselasky send_to_fd(fd, 1, (unsigned char *)&p->jt); 909335640Shselasky send_to_fd(fd, 1, (unsigned char *)&p->jf); 910335640Shselasky send_to_fd(fd, 4, (unsigned char *)&longInt); 911335640Shselasky p++; 912335640Shselasky } 913335640Shselasky if (get_error_response(fd, NULL)) 914335640Shselasky return -1; 915335640Shselasky return 0; 916335640Shselasky} 917335640Shselasky 918335640Shselaskystatic int pcap_setdirection_acn(pcap_t *handle, pcap_direction_t d) { 919335640Shselasky pcap_snprintf(handle->errbuf, sizeof(handle->errbuf), 920335640Shselasky "Setting direction is not supported on ACN adapters"); 921335640Shselasky return -1; 922335640Shselasky} 923335640Shselasky 924335640Shselaskystatic int acn_read_n_bytes_with_timeout(pcap_t *handle, int count) { 925335640Shselasky struct timeval tv; 926335640Shselasky int retval, fd; 927335640Shselasky fd_set r_fds; 928335640Shselasky fd_set w_fds; 929335640Shselasky u_char *bp; 930335640Shselasky int len = 0; 931335640Shselasky int offset = 0; 932335640Shselasky 933335640Shselasky tv.tv_sec = 5; 934335640Shselasky tv.tv_usec = 0; 935335640Shselasky 936335640Shselasky fd = handle->fd; 937335640Shselasky FD_ZERO(&r_fds); 938335640Shselasky FD_SET(fd, &r_fds); 939335640Shselasky memcpy(&w_fds, &r_fds, sizeof(r_fds)); 940335640Shselasky bp = handle->bp; 941335640Shselasky while (count) { 942335640Shselasky retval = select(fd + 1, &w_fds, NULL, NULL, &tv); 943335640Shselasky if (retval == -1) { /* an error occured !!!!! */ 944335640Shselasky// fprintf(stderr, "error during packet data read\n"); 945335640Shselasky return -1; /* but we need to return a good indication to prevent unneccessary popups */ 946335640Shselasky } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */ 947335640Shselasky// fprintf(stderr, "timeout during packet data read\n"); 948335640Shselasky return -1; 949335640Shselasky } else { 950335640Shselasky if ((len = recv(fd, (bp + offset), count, 0)) <= 0) { 951335640Shselasky// fprintf(stderr, "premature exit during packet data rx\n"); 952335640Shselasky return -1; 953335640Shselasky } 954335640Shselasky count -= len; 955335640Shselasky offset += len; 956335640Shselasky } 957335640Shselasky } 958335640Shselasky return 0; 959335640Shselasky} 960335640Shselasky 961335640Shselaskystatic int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { 962335640Shselasky #define HEADER_SIZE (4 * 4) 963335640Shselasky unsigned char packet_header[HEADER_SIZE]; 964335640Shselasky struct pcap_pkthdr pcap_header; 965335640Shselasky 966335640Shselasky //printf("pcap_read_acn()\n"); // fulko 967335640Shselasky acn_start_monitor(handle->fd, handle->snapshot, handle->opt.timeout, handle->opt.promisc, handle->direction); /* maybe tell him to start monitoring */ 968335640Shselasky //printf("pcap_read_acn() after start monitor\n"); // fulko 969335640Shselasky 970335640Shselasky handle->bp = packet_header; 971335640Shselasky if (acn_read_n_bytes_with_timeout(handle, HEADER_SIZE) == -1) return 0; /* try to read a packet header in so we can get the sizeof the packet data */ 972335640Shselasky 973335640Shselasky pcap_header.ts.tv_sec = ntohl(*(uint32_t *)&packet_header[0]); /* tv_sec */ 974335640Shselasky pcap_header.ts.tv_usec = ntohl(*(uint32_t *)&packet_header[4]); /* tv_usec */ 975335640Shselasky pcap_header.caplen = ntohl(*(uint32_t *)&packet_header[8]); /* caplen */ 976335640Shselasky pcap_header.len = ntohl(*(uint32_t *)&packet_header[12]); /* len */ 977335640Shselasky 978335640Shselasky handle->bp = (u_char *)handle->buffer + handle->offset; /* start off the receive pointer at the right spot */ 979335640Shselasky if (acn_read_n_bytes_with_timeout(handle, pcap_header.caplen) == -1) return 0; /* then try to read in the rest of the data */ 980335640Shselasky 981335640Shselasky callback(user, &pcap_header, handle->bp); /* call the user supplied callback function */ 982335640Shselasky return 1; 983335640Shselasky} 984335640Shselasky 985335640Shselaskystatic int pcap_activate_sita(pcap_t *handle) { 986335640Shselasky int fd; 987335640Shselasky 988335640Shselasky if (handle->opt.rfmon) { 989335640Shselasky /* 990335640Shselasky * No monitor mode on SITA devices (they're not Wi-Fi 991335640Shselasky * devices). 992335640Shselasky */ 993335640Shselasky return PCAP_ERROR_RFMON_NOTSUP; 994335640Shselasky } 995335640Shselasky 996335640Shselasky /* Initialize some components of the pcap structure. */ 997335640Shselasky 998335640Shselasky handle->inject_op = pcap_inject_acn; 999335640Shselasky handle->setfilter_op = pcap_setfilter_acn; 1000335640Shselasky handle->setdirection_op = pcap_setdirection_acn; 1001335640Shselasky handle->set_datalink_op = NULL; /* can't change data link type */ 1002335640Shselasky handle->getnonblock_op = pcap_getnonblock_fd; 1003335640Shselasky handle->setnonblock_op = pcap_setnonblock_fd; 1004335640Shselasky handle->cleanup_op = pcap_cleanup_acn; 1005335640Shselasky handle->read_op = pcap_read_acn; 1006335640Shselasky handle->stats_op = pcap_stats_acn; 1007335640Shselasky 1008335640Shselasky fd = acn_open_live(handle->opt.device, handle->errbuf, 1009335640Shselasky &handle->linktype); 1010335640Shselasky if (fd == -1) 1011335640Shselasky return PCAP_ERROR; 1012335640Shselasky 1013335640Shselasky /* 1014335640Shselasky * Turn a negative snapshot value (invalid), a snapshot value of 1015335640Shselasky * 0 (unspecified), or a value bigger than the normal maximum 1016335640Shselasky * value, into the maximum allowed value. 1017335640Shselasky * 1018335640Shselasky * If some application really *needs* a bigger snapshot 1019335640Shselasky * length, we should just increase MAXIMUM_SNAPLEN. 1020335640Shselasky */ 1021335640Shselasky if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN) 1022335640Shselasky handle->snapshot = MAXIMUM_SNAPLEN; 1023335640Shselasky 1024335640Shselasky handle->fd = fd; 1025335640Shselasky handle->bufsize = handle->snapshot; 1026335640Shselasky 1027335640Shselasky /* Allocate the buffer */ 1028335640Shselasky 1029335640Shselasky handle->buffer = malloc(handle->bufsize + handle->offset); 1030335640Shselasky if (!handle->buffer) { 1031335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 1032335640Shselasky errno, "malloc"); 1033335640Shselasky pcap_cleanup_acn(handle); 1034335640Shselasky return PCAP_ERROR; 1035335640Shselasky } 1036335640Shselasky 1037335640Shselasky /* 1038335640Shselasky * "handle->fd" is a socket, so "select()" and "poll()" 1039335640Shselasky * should work on it. 1040335640Shselasky */ 1041335640Shselasky handle->selectable_fd = handle->fd; 1042335640Shselasky 1043335640Shselasky return 0; 1044335640Shselasky} 1045335640Shselasky 1046335640Shselaskypcap_t *pcap_create_interface(const char *device _U_, char *ebuf) { 1047335640Shselasky pcap_t *p; 1048335640Shselasky 1049335640Shselasky p = pcap_create_common(ebuf, 0); 1050335640Shselasky if (p == NULL) 1051335640Shselasky return (NULL); 1052335640Shselasky 1053335640Shselasky p->activate_op = pcap_activate_sita; 1054335640Shselasky return (p); 1055335640Shselasky} 1056335640Shselasky 1057335640Shselaskyint pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) { 1058335640Shselasky 1059335640Shselasky //printf("pcap_findalldevs()\n"); // fulko 1060335640Shselasky 1061335640Shselasky *alldevsp = 0; /* initialize the returned variables before we do anything */ 1062335640Shselasky strcpy(errbuf, ""); 1063335640Shselasky if (acn_parse_hosts_file(errbuf)) /* scan the hosts file for potential IOPs */ 1064335640Shselasky { 1065335640Shselasky //printf("pcap_findalldevs() returning BAD after parsehosts\n"); // fulko 1066335640Shselasky return -1; 1067335640Shselasky } 1068335640Shselasky //printf("pcap_findalldevs() got hostlist now finding devs\n"); // fulko 1069335640Shselasky if (acn_findalldevs(errbuf)) /* then ask the IOPs for their monitorable devices */ 1070335640Shselasky { 1071335640Shselasky //printf("pcap_findalldevs() returning BAD after findalldevs\n"); // fulko 1072335640Shselasky return -1; 1073335640Shselasky } 1074335640Shselasky devlistp->beginning = acn_if_list; 1075335640Shselasky acn_if_list = 0; /* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */ 1076335640Shselasky //printf("pcap_findalldevs() returning ZERO OK\n"); // fulko 1077335640Shselasky return 0; 1078335640Shselasky} 1079335640Shselasky 1080335640Shselasky/* 1081335640Shselasky * Libpcap version string. 1082335640Shselasky */ 1083335640Shselaskyconst char * 1084335640Shselaskypcap_lib_version(void) 1085335640Shselasky{ 1086335640Shselasky return PCAP_VERSION_STRING " (SITA-only)"; 1087335640Shselasky} 1088