1190214Srpaulo/* 2190214Srpaulo * pcap-sita.c: Packet capture interface additions for SITA ACN devices 3190214Srpaulo * 4190214Srpaulo * Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero> 5190214Srpaulo * 6190214Srpaulo * License: BSD 7190214Srpaulo * 8190214Srpaulo * Redistribution and use in source and binary forms, with or without 9190214Srpaulo * modification, are permitted provided that the following conditions 10190214Srpaulo * are met: 11190214Srpaulo * 12190214Srpaulo * 1. Redistributions of source code must retain the above copyright 13190214Srpaulo * notice, this list of conditions and the following disclaimer. 14190214Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 15190214Srpaulo * notice, this list of conditions and the following disclaimer in 16190214Srpaulo * the documentation and/or other materials provided with the 17190214Srpaulo * distribution. 18190214Srpaulo * 3. The names of the authors may not be used to endorse or promote 19190214Srpaulo * products derived from this software without specific prior 20190214Srpaulo * written permission. 21190214Srpaulo * 22190214Srpaulo * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 23190214Srpaulo * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 24190214Srpaulo * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 25190214Srpaulo */ 26190214Srpaulo 27190214Srpaulo /* $Id: pcap-sita.c */ 28190214Srpaulo 29190214Srpaulo#ifdef HAVE_CONFIG_H 30190214Srpaulo#include "config.h" 31190214Srpaulo#endif 32190214Srpaulo 33190214Srpaulo#include <stdio.h> 34190214Srpaulo#include <string.h> 35190214Srpaulo#include <stdlib.h> 36190214Srpaulo#include <unistd.h> 37190214Srpaulo#include <fcntl.h> 38190214Srpaulo#include <errno.h> 39190214Srpaulo#include <sys/time.h> 40190214Srpaulo#include <sys/socket.h> 41190214Srpaulo#include <netinet/in.h> 42190214Srpaulo#include <arpa/inet.h> 43190214Srpaulo#include "pcap-int.h" 44190214Srpaulo 45190214Srpaulo#include "pcap-sita.h" 46190214Srpaulo 47190214Srpaulo /* non-configureable manifests follow */ 48190214Srpaulo 49190214Srpaulo#define IOP_SNIFFER_PORT 49152 /* TCP port on the IOP used for 'distributed pcap' usage */ 50190214Srpaulo#define MAX_LINE_SIZE 255 /* max size of a buffer/line in /etc/hosts we allow */ 51190214Srpaulo#define MAX_CHASSIS 8 /* number of chassis in an ACN site */ 52190214Srpaulo#define MAX_GEOSLOT 8 /* max number of access units in an ACN site */ 53190214Srpaulo 54190214Srpaulo#define FIND 0 55190214Srpaulo#define LIVE 1 56190214Srpaulo 57190214Srpaulotypedef struct iface { 58190214Srpaulo struct iface *next; /* a pointer to the next interface */ 59190214Srpaulo char *name; /* this interface's name on Wireshark */ 60190214Srpaulo char *IOPname; /* this interface's name on an IOP */ 61190214Srpaulo uint32_t iftype; /* the type of interface (DLT values) */ 62190214Srpaulo} iface_t; 63190214Srpaulo 64190214Srpaulotypedef struct unit { 65190214Srpaulo char *ip; /* this unit's IP address (as extracted from /etc/hosts) */ 66190214Srpaulo int fd; /* the connection to this unit (if it exists) */ 67190214Srpaulo int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */ 68190214Srpaulo int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */ 69190214Srpaulo struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */ 70190214Srpaulo int chassis; 71190214Srpaulo int geoslot; 72190214Srpaulo iface_t *iface; /* a pointer to a linked list of interface structures */ 73190214Srpaulo char *imsg; /* a pointer to an inbound message */ 74190214Srpaulo int len; /* the current size of the inbound message */ 75190214Srpaulo} unit_t; 76190214Srpaulo 77190214Srpaulostatic char *errorString; 78190214Srpaulostatic unit_t units[MAX_CHASSIS+1][MAX_GEOSLOT+1]; /* we use indexes of 1 through 8, but we reserve/waste index 0 */ 79190214Srpaulostatic fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */ 80190214Srpaulostatic fd_set working_set; 81190214Srpaulostatic int max_fs; 82190214Srpaulostatic char static_buf[32]; 83190214Srpaulo 84190214Srpaulopcap_if_t *acn_if_list; /* pcap's list of available interfaces */ 85190214Srpaulo 86190214Srpaulostatic void dump_interface_list(void) { 87190214Srpaulo pcap_if_t *iff; 88190214Srpaulo pcap_addr_t *addr; 89190214Srpaulo int longest_name_len = 0; 90190214Srpaulo char *n, *d, *f; 91190214Srpaulo int if_number = 0; 92190214Srpaulo 93190214Srpaulo iff = acn_if_list; 94190214Srpaulo while (iff) { 95190214Srpaulo if (iff->name && (strlen(iff->name) > longest_name_len)) longest_name_len = strlen(iff->name); 96190214Srpaulo iff = iff->next; 97190214Srpaulo } 98190214Srpaulo iff = acn_if_list; 99190214Srpaulo printf("Interface List:\n"); 100190214Srpaulo while (iff) { 101190214Srpaulo n = (iff->name) ? iff->name : ""; 102190214Srpaulo d = (iff->description) ? iff->description : ""; 103190214Srpaulo f = (iff->flags == PCAP_IF_LOOPBACK) ? "L" : ""; 104190214Srpaulo printf("%3d: %*s %s '%s'\n", if_number++, longest_name_len, n, f, d); 105190214Srpaulo addr = iff->addresses; 106190214Srpaulo while (addr) { 107190214Srpaulo printf("%*s ", (5 + longest_name_len), ""); /* add some indentation */ 108190214Srpaulo printf("%15s ", (addr->addr) ? inet_ntoa(((struct sockaddr_in *)addr->addr)->sin_addr) : ""); 109190214Srpaulo printf("%15s ", (addr->netmask) ? inet_ntoa(((struct sockaddr_in *)addr->netmask)->sin_addr) : ""); 110190214Srpaulo printf("%15s ", (addr->broadaddr) ? inet_ntoa(((struct sockaddr_in *)addr->broadaddr)->sin_addr) : ""); 111190214Srpaulo printf("%15s ", (addr->dstaddr) ? inet_ntoa(((struct sockaddr_in *)addr->dstaddr)->sin_addr) : ""); 112190214Srpaulo printf("\n"); 113190214Srpaulo addr = addr->next; 114190214Srpaulo } 115190214Srpaulo iff = iff->next; 116190214Srpaulo } 117190214Srpaulo} 118190214Srpaulo 119190214Srpaulostatic void dump(unsigned char *ptr, int i, int indent) { 120190214Srpaulo fprintf(stderr, "%*s", indent, " "); 121190214Srpaulo for (; i > 0; i--) { 122190214Srpaulo fprintf(stderr, "%2.2x ", *ptr++); 123190214Srpaulo } 124190214Srpaulo fprintf(stderr, "\n"); 125190214Srpaulo} 126190214Srpaulo 127190214Srpaulostatic void dump_interface_list_p(void) { 128190214Srpaulo pcap_if_t *iff; 129190214Srpaulo pcap_addr_t *addr; 130190214Srpaulo int if_number = 0; 131190214Srpaulo 132190214Srpaulo iff = acn_if_list; 133190214Srpaulo printf("Interface Pointer @ %p is %p:\n", &acn_if_list, iff); 134190214Srpaulo while (iff) { 135190214Srpaulo printf("%3d: %p %p next: %p\n", if_number++, iff->name, iff->description, iff->next); 136190214Srpaulo dump((unsigned char *)iff, sizeof(pcap_if_t), 5); 137190214Srpaulo addr = iff->addresses; 138190214Srpaulo while (addr) { 139190214Srpaulo printf(" %p %p %p %p, next: %p\n", addr->addr, addr->netmask, addr->broadaddr, addr->dstaddr, addr->next); 140190214Srpaulo dump((unsigned char *)addr, sizeof(pcap_addr_t), 10); 141190214Srpaulo addr = addr->next; 142190214Srpaulo } 143190214Srpaulo iff = iff->next; 144190214Srpaulo } 145190214Srpaulo} 146190214Srpaulo 147190214Srpaulostatic void dump_unit_table(void) { 148190214Srpaulo int chassis, geoslot; 149190214Srpaulo iface_t *p; 150190214Srpaulo 151190214Srpaulo printf("%c:%c %s %s\n", 'C', 'S', "fd", "IP Address"); 152190214Srpaulo for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { 153190214Srpaulo for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 154190214Srpaulo if (units[chassis][geoslot].ip != NULL) 155190214Srpaulo printf("%d:%d %2d %s\n", chassis, geoslot, units[chassis][geoslot].fd, units[chassis][geoslot].ip); 156190214Srpaulo p = units[chassis][geoslot].iface; 157190214Srpaulo while (p) { 158190214Srpaulo char *n = (p->name) ? p->name : ""; 159190214Srpaulo char *i = (p->IOPname) ? p->IOPname : ""; 160190214Srpaulo p = p->next; 161190214Srpaulo printf(" %12s -> %12s\n", i, n); 162190214Srpaulo } 163190214Srpaulo } 164190214Srpaulo } 165190214Srpaulo} 166190214Srpaulo 167190214Srpaulostatic int find_unit_by_fd(int fd, int *chassis, int *geoslot, unit_t **unit_ptr) { 168190214Srpaulo int c, s; 169190214Srpaulo 170190214Srpaulo for (c = 0; c <= MAX_CHASSIS; c++) { 171190214Srpaulo for (s = 0; s <= MAX_GEOSLOT; s++) { 172190214Srpaulo if (units[c][s].fd == fd || units[c][s].find_fd == fd) { 173190214Srpaulo if (chassis) *chassis = c; 174190214Srpaulo if (geoslot) *geoslot = s; 175190214Srpaulo if (unit_ptr) *unit_ptr = &units[c][s]; 176190214Srpaulo return 1; 177190214Srpaulo } 178190214Srpaulo } 179190214Srpaulo } 180190214Srpaulo return 0; 181190214Srpaulo} 182190214Srpaulo 183190214Srpaulostatic int read_client_nbytes(int fd, int count, unsigned char *buf) { 184190214Srpaulo unit_t *u; 185190214Srpaulo int chassis, geoslot; 186190214Srpaulo int len; 187190214Srpaulo 188190214Srpaulo find_unit_by_fd(fd, &chassis, &geoslot, &u); 189190214Srpaulo while (count) { 190190214Srpaulo if ((len = recv(fd, buf, count, 0)) <= 0) return -1; /* read in whatever data was sent to us */ 191190214Srpaulo count -= len; 192190214Srpaulo buf += len; 193190214Srpaulo } /* till we have everything we are looking for */ 194190214Srpaulo return 0; 195190214Srpaulo} 196190214Srpaulo 197190214Srpaulostatic void empty_unit_iface(unit_t *u) { 198190214Srpaulo iface_t *p, *cur; 199190214Srpaulo 200190214Srpaulo cur = u->iface; 201190214Srpaulo while (cur) { /* loop over all the interface entries */ 202190214Srpaulo if (cur->name) free(cur->name); /* throwing away the contents if they exist */ 203190214Srpaulo if (cur->IOPname) free(cur->IOPname); 204190214Srpaulo p = cur->next; 205190214Srpaulo free(cur); /* then throw away the structure itself */ 206190214Srpaulo cur = p; 207190214Srpaulo } 208190214Srpaulo u->iface = 0; /* and finally remember that there are no remaining structure */ 209190214Srpaulo} 210190214Srpaulo 211190214Srpaulostatic void empty_unit(int chassis, int geoslot) { 212190214Srpaulo unit_t *u = &units[chassis][geoslot]; 213190214Srpaulo 214190214Srpaulo empty_unit_iface(u); 215190214Srpaulo if (u->imsg) { /* then if an inbound message buffer exists */ 216190214Srpaulo u->imsg = (char *)realloc(u->imsg, 1); /* and re-allocate the old large buffer into a new small one */ 217251129Sdelphij if (u->imsg == NULL) { /* oops, realloc call failed */ 218251129Sdelphij fprintf(stderr, "Warning...call to realloc() failed, value of errno is %d\n", errno); 219251129Sdelphij 220190214Srpaulo } 221190214Srpaulo} 222190214Srpaulo 223190214Srpaulostatic void empty_unit_table(void) { 224190214Srpaulo int chassis, geoslot; 225190214Srpaulo 226190214Srpaulo for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { 227190214Srpaulo for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 228190214Srpaulo if (units[chassis][geoslot].ip != NULL) { 229190214Srpaulo free(units[chassis][geoslot].ip); /* get rid of the malloc'ed space that holds the IP address */ 230190214Srpaulo units[chassis][geoslot].ip = 0; /* then set the pointer to NULL */ 231190214Srpaulo } 232190214Srpaulo empty_unit(chassis, geoslot); 233190214Srpaulo } 234190214Srpaulo } 235190214Srpaulo} 236190214Srpaulo 237190214Srpaulostatic char *find_nth_interface_name(int n) { 238190214Srpaulo int chassis, geoslot; 239190214Srpaulo iface_t *p; 240190214Srpaulo char *last_name = 0; 241190214Srpaulo 242190214Srpaulo if (n < 0) n = 0; /* ensure we are working with a valid number */ 243190214Srpaulo for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */ 244190214Srpaulo for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 245190214Srpaulo if (units[chassis][geoslot].ip != NULL) { 246190214Srpaulo p = units[chassis][geoslot].iface; 247190214Srpaulo while (p) { /* and all interfaces... */ 248190214Srpaulo if (p->IOPname) last_name = p->name; /* remembering the last name found */ 249190214Srpaulo if (n-- == 0) return last_name; /* and if we hit the instance requested */ 250190214Srpaulo p = p->next; 251190214Srpaulo } 252190214Srpaulo } 253190214Srpaulo } 254190214Srpaulo } 255190214Srpaulo /* if we couldn't fine the selected entry */ 256190214Srpaulo if (last_name) return last_name; /* ... but we did have at least one entry... return the last entry found */ 257190214Srpaulo return ""; /* ... but if there wasn't any entry... return an empty string instead */ 258190214Srpaulo} 259190214Srpaulo 260190214Srpauloint acn_parse_hosts_file(char *errbuf) { /* returns: -1 = error, 0 = OK */ 261190214Srpaulo FILE *fp; 262190214Srpaulo char buf[MAX_LINE_SIZE]; 263190214Srpaulo char *ptr, *ptr2; 264190214Srpaulo int pos; 265190214Srpaulo int chassis, geoslot; 266190214Srpaulo unit_t *u; 267190214Srpaulo 268190214Srpaulo empty_unit_table(); 269190214Srpaulo if ((fp = fopen("/etc/hosts", "r")) == NULL) { /* try to open the hosts file and if it fails */ 270190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading."); /* return the nohostsfile error response */ 271190214Srpaulo return -1; 272190214Srpaulo } 273190214Srpaulo while (fgets(buf, MAX_LINE_SIZE-1, fp)) { /* while looping over the file */ 274190214Srpaulo 275190214Srpaulo pos = strcspn(buf, "#\n\r"); /* find the first comment character or EOL */ 276190214Srpaulo *(buf + pos) = '\0'; /* and clobber it and anything that follows it */ 277190214Srpaulo 278190214Srpaulo pos = strspn(buf, " \t"); /* then find the first non-white space */ 279190214Srpaulo if (pos == strlen(buf)) /* if there is nothing but white space on the line */ 280190214Srpaulo continue; /* ignore that empty line */ 281190214Srpaulo ptr = buf + pos; /* and skip over any of that leading whitespace */ 282190214Srpaulo 283190214Srpaulo if ((ptr2 = strstr(ptr, "_I_")) == NULL) /* skip any lines that don't have names that look like they belong to IOPs */ 284190214Srpaulo continue; 285190214Srpaulo if (*(ptr2 + 4) != '_') /* and skip other lines that have names that don't look like ACN components */ 286190214Srpaulo continue; 287190214Srpaulo *(ptr + strcspn(ptr, " \t")) = '\0'; /* null terminate the IP address so its a standalone string */ 288190214Srpaulo 289190214Srpaulo chassis = *(ptr2 + 3) - '0'; /* extract the chassis number */ 290190214Srpaulo geoslot = *(ptr2 + 5) - '0'; /* and geo-slot number */ 291190214Srpaulo if (chassis < 1 || chassis > MAX_CHASSIS || 292190214Srpaulo geoslot < 1 || geoslot > MAX_GEOSLOT) { /* if the chassis and/or slot numbers appear to be bad... */ 293190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'."); /* warn the user */ 294190214Srpaulo continue; /* and ignore the entry */ 295190214Srpaulo } 296190214Srpaulo if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) { 297190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 298190214Srpaulo continue; 299190214Srpaulo } 300190214Srpaulo strcpy(ptr2, ptr); /* copy the IP address into our malloc'ed memory */ 301190214Srpaulo u = &units[chassis][geoslot]; 302190214Srpaulo u->ip = ptr2; /* and remember the whole shebang */ 303190214Srpaulo u->chassis = chassis; 304190214Srpaulo u->geoslot = geoslot; 305190214Srpaulo } 306190214Srpaulo fclose(fp); 307190214Srpaulo if (*errbuf) return -1; 308190214Srpaulo else return 0; 309190214Srpaulo} 310190214Srpaulo 311190214Srpaulostatic int open_with_IOP(unit_t *u, int flag) { 312190214Srpaulo int sockfd; 313190214Srpaulo char *ip; 314190214Srpaulo 315190214Srpaulo if (u->serv_addr == NULL) { 316190214Srpaulo u->serv_addr = malloc(sizeof(struct sockaddr_in)); 317251129Sdelphij 318251129Sdelphij /* since we called malloc(), lets check to see if we actually got the memory */ 319251129Sdelphij if (u->serv_addr == NULL) { /* oops, we didn't get the memory requested */ 320251129Sdelphij fprintf(stderr, "malloc() request for u->serv_addr failed, value of errno is: %d\n", errno); 321251129Sdelphij return 0; 322251129Sdelphij } 323251129Sdelphij 324190214Srpaulo } 325190214Srpaulo ip = u->ip; 326251129Sdelphij /* bzero() is deprecated, replaced with memset() */ 327251129Sdelphij memset((char *)u->serv_addr, 0, sizeof(struct sockaddr_in)); 328190214Srpaulo u->serv_addr->sin_family = AF_INET; 329190214Srpaulo u->serv_addr->sin_addr.s_addr = inet_addr(ip); 330190214Srpaulo u->serv_addr->sin_port = htons(IOP_SNIFFER_PORT); 331190214Srpaulo 332190214Srpaulo if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 333190214Srpaulo fprintf(stderr, "pcap can't open a socket for connecting to IOP at %s\n", ip); 334190214Srpaulo return 0; 335190214Srpaulo } 336190214Srpaulo if (connect(sockfd, (struct sockaddr *)u->serv_addr, sizeof(struct sockaddr_in)) < 0) { 337190214Srpaulo fprintf(stderr, "pcap can't connect to IOP at %s\n", ip); 338190214Srpaulo return 0; 339190214Srpaulo } 340190214Srpaulo if (flag == LIVE) u->fd = sockfd; 341190214Srpaulo else u->find_fd = sockfd; 342190214Srpaulo u->first_time = 0; 343190214Srpaulo return sockfd; /* return the non-zero file descriptor as a 'success' indicator */ 344190214Srpaulo} 345190214Srpaulo 346190214Srpaulostatic void close_with_IOP(int chassis, int geoslot, int flag) { 347190214Srpaulo int *id; 348190214Srpaulo 349190214Srpaulo if (flag == LIVE) id = &units[chassis][geoslot].fd; 350190214Srpaulo else id = &units[chassis][geoslot].find_fd; 351190214Srpaulo 352190214Srpaulo if (*id) { /* this was the last time, so... if we are connected... */ 353190214Srpaulo close(*id); /* disconnect us */ 354190214Srpaulo *id = 0; /* and forget that the descriptor exists because we are not open */ 355190214Srpaulo } 356190214Srpaulo} 357190214Srpaulo 358190214Srpaulostatic void pcap_cleanup_acn(pcap_t *handle) { 359190214Srpaulo int chassis, geoslot; 360190214Srpaulo unit_t *u; 361190214Srpaulo 362190214Srpaulo if (find_unit_by_fd(handle->fd, &chassis, &geoslot, &u) == 0) 363190214Srpaulo return; 364190214Srpaulo close_with_IOP(chassis, geoslot, LIVE); 365190214Srpaulo if (u) 366190214Srpaulo u->first_time = 0; 367190214Srpaulo pcap_cleanup_live_common(handle); 368190214Srpaulo} 369190214Srpaulo 370190214Srpaulostatic void send_to_fd(int fd, int len, unsigned char *str) { 371190214Srpaulo int nwritten; 372190214Srpaulo int chassis, geoslot; 373190214Srpaulo 374190214Srpaulo while (len > 0) { 375190214Srpaulo if ((nwritten = write(fd, str, len)) <= 0) { 376190214Srpaulo find_unit_by_fd(fd, &chassis, &geoslot, NULL); 377190214Srpaulo if (units[chassis][geoslot].fd == fd) close_with_IOP(chassis, geoslot, LIVE); 378190214Srpaulo else if (units[chassis][geoslot].find_fd == fd) close_with_IOP(chassis, geoslot, FIND); 379190214Srpaulo empty_unit(chassis, geoslot); 380190214Srpaulo return; 381190214Srpaulo } 382190214Srpaulo len -= nwritten; 383190214Srpaulo str += nwritten; 384190214Srpaulo } 385190214Srpaulo} 386190214Srpaulo 387190214Srpaulostatic void acn_freealldevs(void) { 388190214Srpaulo 389190214Srpaulo pcap_if_t *iff, *next_iff; 390190214Srpaulo pcap_addr_t *addr, *next_addr; 391190214Srpaulo 392190214Srpaulo for (iff = acn_if_list; iff != NULL; iff = next_iff) { 393190214Srpaulo next_iff = iff->next; 394190214Srpaulo for (addr = iff->addresses; addr != NULL; addr = next_addr) { 395190214Srpaulo next_addr = addr->next; 396190214Srpaulo if (addr->addr) free(addr->addr); 397190214Srpaulo if (addr->netmask) free(addr->netmask); 398190214Srpaulo if (addr->broadaddr) free(addr->broadaddr); 399190214Srpaulo if (addr->dstaddr) free(addr->dstaddr); 400190214Srpaulo free(addr); 401190214Srpaulo } 402190214Srpaulo if (iff->name) free(iff->name); 403190214Srpaulo if (iff->description) free(iff->description); 404190214Srpaulo free(iff); 405190214Srpaulo } 406190214Srpaulo} 407190214Srpaulo 408190214Srpaulostatic char *nonUnified_port_num(unit_t *u, int IOPportnum) { 409190214Srpaulo 410190214Srpaulo sprintf(static_buf, "%d_%d", u->chassis, u->geoslot); 411190214Srpaulo return static_buf; 412190214Srpaulo} 413190214Srpaulo 414190214Srpaulostatic char *unified_port_num(unit_t *u, int IOPportnum) { 415190214Srpaulo int portnum; 416190214Srpaulo 417190214Srpaulo portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1; 418190214Srpaulo sprintf(static_buf, "%d", portnum); 419190214Srpaulo return static_buf; 420190214Srpaulo} 421190214Srpaulo 422190214Srpaulostatic char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) { 423190214Srpaulo iface_t *iface_ptr, *iface; 424190214Srpaulo char *name; 425190214Srpaulo char buf[32]; 426190214Srpaulo char *proto; 427190214Srpaulo char *port; 428190214Srpaulo int IOPportnum = 0; 429190214Srpaulo 430190214Srpaulo iface = malloc(sizeof(iface_t)); /* get memory for a structure */ 431251129Sdelphij if (iface == NULL) { /* oops, we didn't get the memory requested */ 432251129Sdelphij fprintf(stderr, "Error...couldn't allocate memory for interface structure...value of errno is: %d\n", errno); 433251129Sdelphij return NULL; 434251129Sdelphij } 435251129Sdelphij memset((char *)iface, 0, sizeof(iface_t)); /* bzero is deprecated(), replaced with memset() */ 436190214Srpaulo 437190214Srpaulo iface->iftype = iftype; /* remember the interface type of this interface */ 438190214Srpaulo 439190214Srpaulo name = malloc(strlen(IOPname) + 1); /* get memory for the IOP's name */ 440251129Sdelphij if (name == NULL) { /* oops, we didn't get the memory requested */ 441251129Sdelphij fprintf(stderr, "Error...couldn't allocate memory for IOPname...value of errno is: %d\n", errno); 442251129Sdelphij return NULL; 443251129Sdelphij } 444251129Sdelphij 445190214Srpaulo strcpy(name, IOPname); /* and copy it in */ 446190214Srpaulo iface->IOPname = name; /* and stick it into the structure */ 447190214Srpaulo 448190214Srpaulo if (strncmp(IOPname, "lo", 2) == 0) { 449190214Srpaulo IOPportnum = atoi(&IOPname[2]); 450190214Srpaulo switch (iftype) { 451190214Srpaulo case DLT_EN10MB: proto = "lo"; port = nonUnified_port_num(u, IOPportnum); break; 452190214Srpaulo default: proto = "???"; port = unified_port_num(u, IOPportnum); break; 453190214Srpaulo } 454190214Srpaulo } else if (strncmp(IOPname, "eth", 3) == 0) { 455190214Srpaulo IOPportnum = atoi(&IOPname[3]); 456190214Srpaulo switch (iftype) { 457190214Srpaulo case DLT_EN10MB: proto = "eth"; port = nonUnified_port_num(u, IOPportnum); break; 458190214Srpaulo default: proto = "???"; port = unified_port_num(u, IOPportnum); break; 459190214Srpaulo } 460190214Srpaulo } else if (strncmp(IOPname, "wan", 3) == 0) { 461190214Srpaulo IOPportnum = atoi(&IOPname[3]); 462190214Srpaulo switch (iftype) { 463190214Srpaulo case DLT_SITA: proto = "wan"; port = unified_port_num(u, IOPportnum); break; 464190214Srpaulo default: proto = "???"; port = unified_port_num(u, IOPportnum); break; 465190214Srpaulo } 466190214Srpaulo } 467190214Srpaulo 468190214Srpaulo sprintf(buf, "%s_%s", proto, port); /* compose the user's name for that IOP port name */ 469190214Srpaulo name = malloc(strlen(buf) + 1); /* get memory for that name */ 470251129Sdelphij if (name == NULL) { /* oops, we didn't get the memory requested */ 471251129Sdelphij fprintf(stderr, "Error...couldn't allocate memory for IOP port name...value of errno is: %d\n", errno); 472251129Sdelphij return NULL; 473251129Sdelphij } 474251129Sdelphij 475190214Srpaulo strcpy(name, buf); /* and copy it in */ 476190214Srpaulo iface->name = name; /* and stick it into the structure */ 477190214Srpaulo 478190214Srpaulo if (u->iface == 0) { /* if this is the first name */ 479190214Srpaulo u->iface = iface; /* stick this entry at the head of the list */ 480190214Srpaulo } else { 481190214Srpaulo iface_ptr = u->iface; 482190214Srpaulo while (iface_ptr->next) { /* othewise scan the list */ 483190214Srpaulo iface_ptr = iface_ptr->next; /* till we're at the last entry */ 484190214Srpaulo } 485190214Srpaulo iface_ptr->next = iface; /* then tack this entry on the end of the list */ 486190214Srpaulo } 487190214Srpaulo return iface->name; 488190214Srpaulo} 489190214Srpaulo 490190214Srpaulostatic int if_sort(char *s1, char *s2) { 491190214Srpaulo char *s1_p2, *s2_p2; 492190214Srpaulo char str1[MAX_LINE_SIZE], str2[MAX_LINE_SIZE]; 493190214Srpaulo int s1_p1_len, s2_p1_len; 494190214Srpaulo int retval; 495190214Srpaulo 496190214Srpaulo if ((s1_p2 = strchr(s1, '_'))) { /* if an underscore is found... */ 497190214Srpaulo s1_p1_len = s1_p2 - s1; /* the prefix length is the difference in pointers */ 498190214Srpaulo s1_p2++; /* the suffix actually starts _after_ the underscore */ 499190214Srpaulo } else { /* otherwise... */ 500190214Srpaulo s1_p1_len = strlen(s1); /* the prefix length is the length of the string itself */ 501190214Srpaulo s1_p2 = 0; /* and there is no suffix */ 502190214Srpaulo } 503190214Srpaulo if ((s2_p2 = strchr(s2, '_'))) { /* now do the same for the second string */ 504190214Srpaulo s2_p1_len = s2_p2 - s2; 505190214Srpaulo s2_p2++; 506190214Srpaulo } else { 507190214Srpaulo s2_p1_len = strlen(s2); 508190214Srpaulo s2_p2 = 0; 509190214Srpaulo } 510190214Srpaulo strncpy(str1, s1, (s1_p1_len > sizeof(str1)) ? s1_p1_len : sizeof(str1)); *(str1 + s1_p1_len) = 0; 511190214Srpaulo strncpy(str2, s2, (s2_p1_len > sizeof(str2)) ? s2_p1_len : sizeof(str2)); *(str2 + s2_p1_len) = 0; 512190214Srpaulo retval = strcmp(str1, str2); 513190214Srpaulo if (retval != 0) return retval; /* if they are not identical, then we can quit now and return the indication */ 514190214Srpaulo return strcmp(s1_p2, s2_p2); /* otherwise we return the result of comparing the 2nd half of the string */ 515190214Srpaulo} 516190214Srpaulo 517190214Srpaulostatic void sort_if_table(void) { 518190214Srpaulo pcap_if_t *p1, *p2, *prev, *temp; 519190214Srpaulo int has_swapped; 520190214Srpaulo 521190214Srpaulo if (!acn_if_list) return; /* nothing to do if the list is empty */ 522190214Srpaulo 523190214Srpaulo while (1) { 524190214Srpaulo p1 = acn_if_list; /* start at the head of the list */ 525190214Srpaulo prev = 0; 526190214Srpaulo has_swapped = 0; 527190214Srpaulo while ((p2 = p1->next)) { 528190214Srpaulo if (if_sort(p1->name, p2->name) > 0) { 529190214Srpaulo if (prev) { /* we are swapping things that are _not_ at the head of the list */ 530190214Srpaulo temp = p2->next; 531190214Srpaulo prev->next = p2; 532190214Srpaulo p2->next = p1; 533190214Srpaulo p1->next = temp; 534190214Srpaulo } else { /* special treatment if we are swapping with the head of the list */ 535190214Srpaulo temp = p2->next; 536190214Srpaulo acn_if_list= p2; 537190214Srpaulo p2->next = p1; 538190214Srpaulo p1->next = temp; 539190214Srpaulo } 540190214Srpaulo p1 = p2; 541190214Srpaulo prev = p1; 542190214Srpaulo has_swapped = 1; 543190214Srpaulo } 544190214Srpaulo prev = p1; 545190214Srpaulo p1 = p1->next; 546190214Srpaulo } 547190214Srpaulo if (has_swapped == 0) 548190214Srpaulo return; 549190214Srpaulo } 550190214Srpaulo return; 551190214Srpaulo} 552190214Srpaulo 553190214Srpaulostatic int process_client_data (char *errbuf) { /* returns: -1 = error, 0 = OK */ 554190214Srpaulo int chassis, geoslot; 555190214Srpaulo unit_t *u; 556190214Srpaulo pcap_if_t *iff, *prev_iff; 557190214Srpaulo pcap_addr_t *addr, *prev_addr; 558190214Srpaulo char *ptr; 559190214Srpaulo int address_count; 560190214Srpaulo struct sockaddr_in *s; 561190214Srpaulo char *newname; 562190214Srpaulo bpf_u_int32 interfaceType; 563190214Srpaulo unsigned char flags; 564190214Srpaulo 565190214Srpaulo prev_iff = 0; 566190214Srpaulo for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { 567190214Srpaulo for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { /* now loop over all the devices */ 568190214Srpaulo u = &units[chassis][geoslot]; 569190214Srpaulo empty_unit_iface(u); 570190214Srpaulo ptr = u->imsg; /* point to the start of the msg for this IOP */ 571190214Srpaulo while (ptr < (u->imsg + u->len)) { 572190214Srpaulo if ((iff = malloc(sizeof(pcap_if_t))) == NULL) { 573190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 574190214Srpaulo return -1; 575190214Srpaulo } 576251129Sdelphij memset((char *)iff, 0, sizeof(pcap_if_t)); /* bzero() is deprecated, replaced with memset() */ 577190214Srpaulo if (acn_if_list == 0) acn_if_list = iff; /* remember the head of the list */ 578190214Srpaulo if (prev_iff) prev_iff->next = iff; /* insert a forward link */ 579190214Srpaulo 580190214Srpaulo if (*ptr) { /* if there is a count for the name */ 581190214Srpaulo if ((iff->name = malloc(*ptr + 1)) == NULL) { /* get that amount of space */ 582190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 583190214Srpaulo return -1; 584190214Srpaulo } 585190214Srpaulo memcpy(iff->name, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */ 586190214Srpaulo *(iff->name + *ptr) = 0; /* and null terminate the string */ 587190214Srpaulo ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */ 588190214Srpaulo } 589190214Srpaulo ptr++; 590190214Srpaulo 591190214Srpaulo if (*ptr) { /* if there is a count for the description */ 592190214Srpaulo if ((iff->description = malloc(*ptr + 1)) == NULL) { /* get that amount of space */ 593190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 594190214Srpaulo return -1; 595190214Srpaulo } 596190214Srpaulo memcpy(iff->description, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */ 597190214Srpaulo *(iff->description + *ptr) = 0; /* and null terminate the string */ 598190214Srpaulo ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */ 599190214Srpaulo } 600190214Srpaulo ptr++; 601190214Srpaulo 602190214Srpaulo interfaceType = ntohl(*(bpf_u_int32 *)ptr); 603190214Srpaulo ptr += 4; /* skip over the interface type */ 604190214Srpaulo 605190214Srpaulo flags = *ptr++; 606190214Srpaulo if (flags) iff->flags = PCAP_IF_LOOPBACK; /* if this is a loopback style interface, lets mark it as such */ 607190214Srpaulo 608190214Srpaulo address_count = *ptr++; 609190214Srpaulo 610190214Srpaulo prev_addr = 0; 611190214Srpaulo while (address_count--) { 612190214Srpaulo if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) { 613190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 614190214Srpaulo return -1; 615190214Srpaulo } 616251129Sdelphij+ memset((char *)addr, 0, sizeof(pcap_addr_t)); /* bzero() is deprecated, replaced with memset() */ 617190214Srpaulo if (iff->addresses == 0) iff->addresses = addr; 618190214Srpaulo if (prev_addr) prev_addr->next = addr; /* insert a forward link */ 619190214Srpaulo if (*ptr) { /* if there is a count for the address */ 620190214Srpaulo if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { /* get that amount of space */ 621190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 622190214Srpaulo return -1; 623190214Srpaulo } 624251129Sdelphij memset((char *)s, 0, sizeof(struct sockaddr_in)); /* bzero() is deprecated, replaced with memset() */ 625190214Srpaulo addr->addr = (struct sockaddr *)s; 626190214Srpaulo s->sin_family = AF_INET; 627190214Srpaulo s->sin_addr.s_addr = *(bpf_u_int32 *)(ptr + 1); /* copy the address in */ 628190214Srpaulo ptr += *ptr; /* now move the pointer forwards according to the specified length of the address */ 629190214Srpaulo } 630190214Srpaulo ptr++; /* then forwards one more for the 'length of the address' field */ 631190214Srpaulo if (*ptr) { /* process any netmask */ 632190214Srpaulo if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { 633190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 634190214Srpaulo return -1; 635190214Srpaulo } 636251129Sdelphij /* bzero() is deprecated, replaced with memset() */ 637251129Sdelphij memset((char *)s, 0, sizeof(struct sockaddr_in)); 638251129Sdelphij 639190214Srpaulo addr->netmask = (struct sockaddr *)s; 640190214Srpaulo s->sin_family = AF_INET; 641190214Srpaulo s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1); 642190214Srpaulo ptr += *ptr; 643190214Srpaulo } 644190214Srpaulo ptr++; 645190214Srpaulo if (*ptr) { /* process any broadcast address */ 646190214Srpaulo if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { 647190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 648190214Srpaulo return -1; 649190214Srpaulo } 650251129Sdelphij /* bzero() is deprecated, replaced with memset() */ 651251129Sdelphij memset((char *)s, 0, sizeof(struct sockaddr_in)); 652251129Sdelphij 653190214Srpaulo addr->broadaddr = (struct sockaddr *)s; 654190214Srpaulo s->sin_family = AF_INET; 655190214Srpaulo s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1); 656190214Srpaulo ptr += *ptr; 657190214Srpaulo } 658190214Srpaulo ptr++; 659190214Srpaulo if (*ptr) { /* process any destination address */ 660190214Srpaulo if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { 661190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 662190214Srpaulo return -1; 663190214Srpaulo } 664251129Sdelphij /* bzero() is deprecated, replaced with memset() */ 665251129Sdelphij memset((char *)s, 0, sizeof(struct sockaddr_in)); 666251129Sdelphij 667190214Srpaulo addr->dstaddr = (struct sockaddr *)s; 668190214Srpaulo s->sin_family = AF_INET; 669190214Srpaulo s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1); 670190214Srpaulo ptr += *ptr; 671190214Srpaulo } 672190214Srpaulo ptr++; 673190214Srpaulo prev_addr = addr; 674190214Srpaulo } 675190214Srpaulo prev_iff = iff; 676190214Srpaulo 677190214Srpaulo newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType); /* add a translation entry and get a point to the mangled name */ 678190214Srpaulo if ((iff->name = realloc(iff->name, strlen(newname) + 1)) == NULL) { /* we now re-write the name stored in the interface list */ 679190214Srpaulo snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno)); 680190214Srpaulo return -1; 681190214Srpaulo } 682190214Srpaulo strcpy(iff->name, newname); /* to this new name */ 683190214Srpaulo } 684190214Srpaulo } 685190214Srpaulo } 686190214Srpaulo return 0; 687190214Srpaulo} 688190214Srpaulo 689190214Srpaulostatic int read_client_data (int fd) { 690190214Srpaulo unsigned char buf[256]; 691190214Srpaulo int chassis, geoslot; 692190214Srpaulo unit_t *u; 693190214Srpaulo int len; 694190214Srpaulo 695190214Srpaulo find_unit_by_fd(fd, &chassis, &geoslot, &u); 696190214Srpaulo 697190214Srpaulo if ((len = recv(fd, buf, sizeof(buf), 0)) <= 0) return 0; /* read in whatever data was sent to us */ 698190214Srpaulo 699190214Srpaulo if ((u->imsg = realloc(u->imsg, (u->len + len))) == NULL) /* extend the buffer for the new data */ 700190214Srpaulo return 0; 701190214Srpaulo memcpy((u->imsg + u->len), buf, len); /* append the new data */ 702190214Srpaulo u->len += len; 703190214Srpaulo return 1; 704190214Srpaulo} 705190214Srpaulo 706190214Srpaulostatic void wait_for_all_answers(void) { 707190214Srpaulo int retval; 708190214Srpaulo struct timeval tv; 709190214Srpaulo int fd; 710190214Srpaulo int chassis, geoslot; 711190214Srpaulo 712190214Srpaulo tv.tv_sec = 2; 713190214Srpaulo tv.tv_usec = 0; 714190214Srpaulo 715190214Srpaulo while (1) { 716190214Srpaulo int flag = 0; 717190214Srpaulo for (fd = 0; fd <= max_fs; fd++) { /* scan the list of descriptors we may be listening to */ 718190214Srpaulo if (FD_ISSET(fd, &readfds)) flag = 1; /* and see if there are any still set */ 719190214Srpaulo } 720190214Srpaulo if (flag == 0) return; /* we are done, when they are all gone */ 721190214Srpaulo 722190214Srpaulo memcpy(&working_set, &readfds, sizeof(readfds)); /* otherwise, we still have to listen for more stuff, till we timeout */ 723190214Srpaulo retval = select(max_fs + 1, &working_set, NULL, NULL, &tv); 724190214Srpaulo if (retval == -1) { /* an error occured !!!!! */ 725190214Srpaulo return; 726190214Srpaulo } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */ 727190214Srpaulo printf("timeout\n"); 728190214Srpaulo return; 729190214Srpaulo } else { 730190214Srpaulo for (fd = 0; fd <= max_fs; fd++) { /* scan the list of things to do, and do them */ 731190214Srpaulo if (FD_ISSET(fd, &working_set)) { 732190214Srpaulo if (read_client_data(fd) == 0) { /* if the socket has closed */ 733190214Srpaulo FD_CLR(fd, &readfds); /* and descriptors we listen to for errors */ 734190214Srpaulo find_unit_by_fd(fd, &chassis, &geoslot, NULL); 735190214Srpaulo close_with_IOP(chassis, geoslot, FIND); /* and close out connection to him */ 736190214Srpaulo } 737190214Srpaulo } 738190214Srpaulo } 739190214Srpaulo } 740190214Srpaulo } 741190214Srpaulo} 742190214Srpaulo 743190214Srpaulostatic char *get_error_response(int fd, char *errbuf) { /* return a pointer on error, NULL on no error */ 744190214Srpaulo char byte; 745190214Srpaulo int len = 0; 746190214Srpaulo 747190214Srpaulo while (1) { 748190214Srpaulo recv(fd, &byte, 1, 0); /* read another byte in */ 749190214Srpaulo if (errbuf && (len++ < PCAP_ERRBUF_SIZE)) { /* and if there is still room in the buffer */ 750190214Srpaulo *errbuf++ = byte; /* stick it in */ 751190214Srpaulo *errbuf = '\0'; /* ensure the string is null terminated just in case we might exceed the buffer's size */ 752190214Srpaulo } 753190214Srpaulo if (byte == '\0') { 754190214Srpaulo if (len > 1) { return errbuf; } 755190214Srpaulo else { return NULL; } 756190214Srpaulo } 757190214Srpaulo } 758190214Srpaulo} 759190214Srpaulo 760190214Srpauloint acn_findalldevs(char *errbuf) { /* returns: -1 = error, 0 = OK */ 761190214Srpaulo int chassis, geoslot; 762190214Srpaulo unit_t *u; 763190214Srpaulo 764190214Srpaulo FD_ZERO(&readfds); 765190214Srpaulo max_fs = 0; 766190214Srpaulo for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { 767190214Srpaulo for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 768190214Srpaulo u = &units[chassis][geoslot]; 769190214Srpaulo if (u->ip && (open_with_IOP(u, FIND))) { /* connect to the remote IOP */ 770190214Srpaulo send_to_fd(u->find_fd, 1, (unsigned char *)"\0"); 771190214Srpaulo if (get_error_response(u->find_fd, errbuf)) 772190214Srpaulo close_with_IOP(chassis, geoslot, FIND); 773190214Srpaulo else { 774190214Srpaulo if (u->find_fd > max_fs) 775190214Srpaulo max_fs = u->find_fd; /* remember the highest number currently in use */ 776190214Srpaulo FD_SET(u->find_fd, &readfds); /* we are going to want to read this guy's response to */ 777190214Srpaulo u->len = 0; 778190214Srpaulo send_to_fd(u->find_fd, 1, (unsigned char *)"Q"); /* this interface query request */ 779190214Srpaulo } 780190214Srpaulo } 781190214Srpaulo } 782190214Srpaulo } 783190214Srpaulo wait_for_all_answers(); 784190214Srpaulo if (process_client_data(errbuf)) 785190214Srpaulo return -1; 786190214Srpaulo sort_if_table(); 787190214Srpaulo return 0; 788190214Srpaulo} 789190214Srpaulo 790190214Srpaulostatic int pcap_stats_acn(pcap_t *handle, struct pcap_stat *ps) { 791190214Srpaulo unsigned char buf[12]; 792190214Srpaulo 793190214Srpaulo send_to_fd(handle->fd, 1, (unsigned char *)"S"); /* send the get_stats command to the IOP */ 794190214Srpaulo 795190214Srpaulo if (read_client_nbytes(handle->fd, sizeof(buf), buf) == -1) return -1; /* try reading the required bytes */ 796190214Srpaulo 797190214Srpaulo ps->ps_recv = ntohl(*(uint32_t *)&buf[0]); /* break the buffer into its three 32 bit components */ 798190214Srpaulo ps->ps_drop = ntohl(*(uint32_t *)&buf[4]); 799190214Srpaulo ps->ps_ifdrop = ntohl(*(uint32_t *)&buf[8]); 800190214Srpaulo 801190214Srpaulo return 0; 802190214Srpaulo} 803190214Srpaulo 804190214Srpaulostatic int acn_open_live(const char *name, char *errbuf, int *linktype) { /* returns 0 on error, else returns the file descriptor */ 805190214Srpaulo int chassis, geoslot; 806190214Srpaulo unit_t *u; 807190214Srpaulo iface_t *p; 808190214Srpaulo pcap_if_t *alldevsp; 809190214Srpaulo 810251129Sdelphij pcap_findalldevs_interfaces(&alldevsp, errbuf); 811190214Srpaulo for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */ 812190214Srpaulo for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { 813190214Srpaulo u = &units[chassis][geoslot]; 814190214Srpaulo if (u->ip != NULL) { 815190214Srpaulo p = u->iface; 816190214Srpaulo while (p) { /* and all interfaces... */ 817190214Srpaulo if (p->IOPname && p->name && (strcmp(p->name, name) == 0)) { /* and if we found the interface we want... */ 818190214Srpaulo *linktype = p->iftype; 819190214Srpaulo open_with_IOP(u, LIVE); /* start a connection with that IOP */ 820190214Srpaulo send_to_fd(u->fd, strlen(p->IOPname)+1, (unsigned char *)p->IOPname); /* send the IOP's interface name, and a terminating null */ 821190214Srpaulo if (get_error_response(u->fd, errbuf)) { 822190214Srpaulo return -1; 823190214Srpaulo } 824190214Srpaulo return u->fd; /* and return that open descriptor */ 825190214Srpaulo } 826190214Srpaulo p = p->next; 827190214Srpaulo } 828190214Srpaulo } 829190214Srpaulo } 830190214Srpaulo } 831190214Srpaulo return -1; /* if the interface wasn't found, return an error */ 832190214Srpaulo} 833190214Srpaulo 834190214Srpaulostatic void acn_start_monitor(int fd, int snaplen, int timeout, int promiscuous, int direction) { 835190214Srpaulo unsigned char buf[8]; 836190214Srpaulo unit_t *u; 837190214Srpaulo 838190214Srpaulo //printf("acn_start_monitor()\n"); // fulko 839190214Srpaulo find_unit_by_fd(fd, NULL, NULL, &u); 840190214Srpaulo if (u->first_time == 0) { 841190214Srpaulo buf[0] = 'M'; 842190214Srpaulo *(uint32_t *)&buf[1] = htonl(snaplen); 843190214Srpaulo buf[5] = timeout; 844190214Srpaulo buf[6] = promiscuous; 845190214Srpaulo buf[7] = direction; 846190214Srpaulo //printf("acn_start_monitor() first time\n"); // fulko 847190214Srpaulo send_to_fd(fd, 8, buf); /* send the start monitor command with its parameters to the IOP */ 848190214Srpaulo u->first_time = 1; 849190214Srpaulo } 850190214Srpaulo //printf("acn_start_monitor() complete\n"); // fulko 851190214Srpaulo} 852190214Srpaulo 853190214Srpaulostatic int pcap_inject_acn(pcap_t *p, const void *buf _U_, size_t size _U_) { 854190214Srpaulo strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters", 855190214Srpaulo PCAP_ERRBUF_SIZE); 856190214Srpaulo return (-1); 857190214Srpaulo} 858190214Srpaulo 859190214Srpaulostatic int pcap_setfilter_acn(pcap_t *handle, struct bpf_program *bpf) { 860190214Srpaulo int fd = handle->fd; 861190214Srpaulo int count; 862190214Srpaulo struct bpf_insn *p; 863190214Srpaulo uint16_t shortInt; 864190214Srpaulo uint32_t longInt; 865190214Srpaulo 866190214Srpaulo send_to_fd(fd, 1, (unsigned char *)"F"); /* BPF filter follows command */ 867190214Srpaulo count = bpf->bf_len; 868190214Srpaulo longInt = htonl(count); 869190214Srpaulo send_to_fd(fd, 4, (unsigned char *)&longInt); /* send the instruction sequence count */ 870190214Srpaulo p = bpf->bf_insns; 871190214Srpaulo while (count--) { /* followed by the list of instructions */ 872190214Srpaulo shortInt = htons(p->code); 873190214Srpaulo longInt = htonl(p->k); 874190214Srpaulo send_to_fd(fd, 2, (unsigned char *)&shortInt); 875190214Srpaulo send_to_fd(fd, 1, (unsigned char *)&p->jt); 876190214Srpaulo send_to_fd(fd, 1, (unsigned char *)&p->jf); 877190214Srpaulo send_to_fd(fd, 4, (unsigned char *)&longInt); 878190214Srpaulo p++; 879190214Srpaulo } 880190214Srpaulo if (get_error_response(fd, NULL)) 881190214Srpaulo return -1; 882190214Srpaulo return 0; 883190214Srpaulo} 884190214Srpaulo 885190214Srpaulostatic int pcap_setdirection_acn(pcap_t *handle, pcap_direction_t d) { 886190214Srpaulo snprintf(handle->errbuf, sizeof(handle->errbuf), 887190214Srpaulo "Setting direction is not supported on ACN adapters"); 888190214Srpaulo return -1; 889190214Srpaulo} 890190214Srpaulo 891190214Srpaulostatic int acn_read_n_bytes_with_timeout(pcap_t *handle, int count) { 892190214Srpaulo struct timeval tv; 893190214Srpaulo int retval, fd; 894190214Srpaulo fd_set r_fds; 895190214Srpaulo fd_set w_fds; 896190214Srpaulo u_char *bp; 897190214Srpaulo int len = 0; 898190214Srpaulo int offset = 0; 899190214Srpaulo 900190214Srpaulo tv.tv_sec = 5; 901190214Srpaulo tv.tv_usec = 0; 902190214Srpaulo 903190214Srpaulo fd = handle->fd; 904190214Srpaulo FD_ZERO(&r_fds); 905190214Srpaulo FD_SET(fd, &r_fds); 906190214Srpaulo memcpy(&w_fds, &r_fds, sizeof(r_fds)); 907190214Srpaulo bp = handle->bp; 908190214Srpaulo while (count) { 909190214Srpaulo retval = select(fd + 1, &w_fds, NULL, NULL, &tv); 910190214Srpaulo if (retval == -1) { /* an error occured !!!!! */ 911190214Srpaulo// fprintf(stderr, "error during packet data read\n"); 912190214Srpaulo return -1; /* but we need to return a good indication to prevent unneccessary popups */ 913190214Srpaulo } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */ 914190214Srpaulo// fprintf(stderr, "timeout during packet data read\n"); 915190214Srpaulo return -1; 916190214Srpaulo } else { 917190214Srpaulo if ((len = recv(fd, (bp + offset), count, 0)) <= 0) { 918190214Srpaulo// fprintf(stderr, "premature exit during packet data rx\n"); 919190214Srpaulo return -1; 920190214Srpaulo } 921190214Srpaulo count -= len; 922190214Srpaulo offset += len; 923190214Srpaulo } 924190214Srpaulo } 925190214Srpaulo return 0; 926190214Srpaulo} 927190214Srpaulo 928190214Srpaulostatic int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { 929190214Srpaulo #define HEADER_SIZE (4 * 4) 930190214Srpaulo unsigned char packet_header[HEADER_SIZE]; 931190214Srpaulo struct pcap_pkthdr pcap_header; 932190214Srpaulo 933190214Srpaulo //printf("pcap_read_acn()\n"); // fulko 934190214Srpaulo acn_start_monitor(handle->fd, handle->snapshot, handle->md.timeout, handle->md.clear_promisc, handle->direction); /* maybe tell him to start monitoring */ 935190214Srpaulo //printf("pcap_read_acn() after start monitor\n"); // fulko 936190214Srpaulo 937190214Srpaulo handle->bp = packet_header; 938190214Srpaulo 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 */ 939190214Srpaulo 940190214Srpaulo pcap_header.ts.tv_sec = ntohl(*(uint32_t *)&packet_header[0]); /* tv_sec */ 941190214Srpaulo pcap_header.ts.tv_usec = ntohl(*(uint32_t *)&packet_header[4]); /* tv_usec */ 942190214Srpaulo pcap_header.caplen = ntohl(*(uint32_t *)&packet_header[8]); /* caplen */ 943190214Srpaulo pcap_header.len = ntohl(*(uint32_t *)&packet_header[12]); /* len */ 944190214Srpaulo 945190214Srpaulo handle->bp = handle->buffer + handle->offset; /* start off the receive pointer at the right spot */ 946190214Srpaulo if (acn_read_n_bytes_with_timeout(handle, pcap_header.caplen) == -1) return 0; /* then try to read in the rest of the data */ 947190214Srpaulo 948190214Srpaulo callback(user, &pcap_header, handle->bp); /* call the user supplied callback function */ 949190214Srpaulo return 1; 950190214Srpaulo} 951190214Srpaulo 952190214Srpaulostatic int pcap_activate_sita(pcap_t *handle) { 953190214Srpaulo int fd; 954190214Srpaulo 955190214Srpaulo if (handle->opt.rfmon) { 956190214Srpaulo /* 957190214Srpaulo * No monitor mode on SITA devices (they're not Wi-Fi 958190214Srpaulo * devices). 959190214Srpaulo */ 960190214Srpaulo return PCAP_ERROR_RFMON_NOTSUP; 961190214Srpaulo } 962190214Srpaulo 963190214Srpaulo /* Initialize some components of the pcap structure. */ 964190214Srpaulo 965190214Srpaulo handle->inject_op = pcap_inject_acn; 966190214Srpaulo handle->setfilter_op = pcap_setfilter_acn; 967190214Srpaulo handle->setdirection_op = pcap_setdirection_acn; 968190214Srpaulo handle->set_datalink_op = NULL; /* can't change data link type */ 969190214Srpaulo handle->getnonblock_op = pcap_getnonblock_fd; 970190214Srpaulo handle->setnonblock_op = pcap_setnonblock_fd; 971190214Srpaulo handle->cleanup_op = pcap_cleanup_acn; 972190214Srpaulo handle->read_op = pcap_read_acn; 973190214Srpaulo handle->stats_op = pcap_stats_acn; 974190214Srpaulo 975190214Srpaulo fd = acn_open_live(handle->opt.source, handle->errbuf, 976190214Srpaulo &handle->linktype); 977190214Srpaulo if (fd == -1) 978190214Srpaulo return PCAP_ERROR; 979190214Srpaulo handle->md.clear_promisc = handle->md.promisc; 980190214Srpaulo handle->fd = fd; 981190214Srpaulo handle->bufsize = handle->snapshot; 982190214Srpaulo 983190214Srpaulo /* Allocate the buffer */ 984190214Srpaulo 985190214Srpaulo handle->buffer = malloc(handle->bufsize + handle->offset); 986190214Srpaulo if (!handle->buffer) { 987190214Srpaulo snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 988190214Srpaulo "malloc: %s", pcap_strerror(errno)); 989190214Srpaulo pcap_cleanup_acn(handle); 990190214Srpaulo return PCAP_ERROR; 991190214Srpaulo } 992190214Srpaulo 993190214Srpaulo /* 994190214Srpaulo * "handle->fd" is a socket, so "select()" and "poll()" 995190214Srpaulo * should work on it. 996190214Srpaulo */ 997190214Srpaulo handle->selectable_fd = handle->fd; 998190214Srpaulo 999190214Srpaulo return 0; 1000190214Srpaulo} 1001190214Srpaulo 1002251129Sdelphijpcap_t *pcap_create_interface(const char *device, char *ebuf) { 1003190214Srpaulo pcap_t *p; 1004190214Srpaulo 1005190214Srpaulo p = pcap_create_common(device, ebuf); 1006190214Srpaulo if (p == NULL) 1007190214Srpaulo return (NULL); 1008190214Srpaulo 1009190214Srpaulo p->activate_op = pcap_activate_sita; 1010190214Srpaulo return (p); 1011190214Srpaulo} 1012