示例#1
0
/*
 * Receive a packet.
 */
int artnet_net_recv(node n, artnet_packet p, int delay) {
    ssize_t len;
    struct sockaddr_in cliAddr;
    socklen_t cliLen = sizeof(cliAddr);
    fd_set rset;
    struct timeval tv;
    int maxfdp1 = n->sd + 1;
    
    FD_ZERO(&rset);
    FD_SET((unsigned int) n->sd, &rset);
    
    tv.tv_usec = 0;
    tv.tv_sec = delay;
    p->length = 0;
    
    switch (select(maxfdp1, &rset, NULL, NULL, &tv)) {
        case 0:
            // timeout
            return RECV_NO_DATA;
            break;
        case -1:
            if ( errno != EINTR) {
                artnet_error("Select error %s", artnet_net_last_error());
                return ARTNET_ENET;
            }
            return ARTNET_EOK;
            break;
        default:
            break;
    }
    
    // need a check here for the amount of data read
    // should prob allow an extra byte after data, and pass the size as sizeof(Data) +1
    // then check the size read and if equal to size(data)+1 we have an error
    len = recvfrom(n->sd,
                   (char*) &(p->data), // char* for win32
                   sizeof(p->data),
                   0,
                   (SA*) &cliAddr,
                   &cliLen);
    if (len < 0) {
        artnet_error("Recvfrom error %s", artnet_net_last_error());
        return ARTNET_ENET;
    }
    
    if (cliAddr.sin_addr.s_addr == n->state.ip_addr.s_addr ||
        ntohl(cliAddr.sin_addr.s_addr) == LOOPBACK_IP) {
        p->length = 0;
        return ARTNET_EOK;
    }
    
    p->length = len;
    memcpy(&(p->from), &cliAddr.sin_addr, sizeof(struct in_addr));
    // should set to in here if we need it
    return ARTNET_EOK;
}
示例#2
0
/*
 * Convert a string to an in_addr
 */
int artnet_net_inet_aton(const char *ip_address, struct in_addr *address) {
#ifdef HAVE_INET_ATON
    if (!inet_aton(ip_address, address)) {
#else
        in_addr_t *addr = (in_addr_t*) address;
        if ((*addr = inet_addr(ip_address)) == INADDR_NONE) {
#endif
            artnet_error("IP conversion from %s failed", ip_address);
            return ARTNET_EARG;
        }
        return ARTNET_EOK;
    }
    
    
    /*
     *
     */
    const char *artnet_net_last_error() {
#ifdef WIN32
        static char error_str[10];
        int error = WSAGetLastError();
        snprintf(error_str, sizeof(error_str), "%d", error);
        return error_str;
#else
        return strerror(errno);
#endif
    }
示例#3
0
/*
 * Set if_head to point to a list of iface_t structures which represent the
 * interfaces on this machine
 * @param ift_head the address of the pointer to the head of the list
 */
static int get_ifaces(iface_t **if_head) {
    struct ifaddrs *ifa_list, *ifa_iter;
    iface_t *if_tail, *if_iter;
    //    struct sockaddr_in *sin;
    char *if_name, *cptr;
    *if_head = if_tail = NULL;
    //    struct sockaddr_dl *dl;
    if (getifaddrs(&ifa_list) != 0) {
        artnet_error("Error getting interfaces: %s", strerror(errno));
        return ARTNET_ENET;
    }
    //    //    for (ifa_iter = ifa_list; ifa_iter; ifa_iter = ifa_iter->ifa_next)
    //    iface = new_iface(if_head, &if_tail);
    
    for (ifa_iter = ifa_list; ifa_iter; ifa_iter = ifa_iter->ifa_next)
        add_iface_if_needed(if_head, &if_tail, ifa_iter);
    
    // Match up the interfaces with the corrosponding AF_PACKET interface
    // to fetch the hw addresses
    //
    // TODO: Will probably not work on OS X, it should
    //      return AF_LINK -type sockaddr
    for (if_iter = *if_head; if_iter; if_iter = if_iter->next) {
        if_name = strdup(if_iter->if_name);
        
        // if this is an alias, get mac of real interface
        if ((cptr = strchr(if_name, ':')))
            *cptr = 0;
        
        // Find corresponding iface_t structure
        for (ifa_iter = ifa_list; ifa_iter; ifa_iter = ifa_iter->ifa_next) {
            if ((!ifa_iter->ifa_addr) || ifa_iter->ifa_addr->sa_family != AF_INET)
                continue;
            
            //            if (strncmp(if_name, ifa_iter->ifa_name, IFNAME_SIZE) == 0) {
            //                // Found matching hw-address
            ////                sll = (struct sockaddr_ll*) ifa_iter->ifa_addr;
            ////                memcpy(if_iter->hw_addr, sll->sll_addr, ARTNET_MAC_SIZE);
            //                break;
            //            }
        }
        //        // Find corresponding iface_t structure
        //        for (ifa_iter = ifa_list; ifa_iter; ifa_iter = ifa_iter->ifa_next) {
        //            if ((!ifa_iter->ifa_addr) || ifa_iter->ifa_addr->sa_family != AF_INET)
        //                continue;
        //
        //            //            if (strncmp(if_name, ifa_iter->ifa_name, IFNAME_SIZE) == 0) {
        //            // Found matching hw-address
        //            dl = (struct sockaddr_dl*)ifa_iter->ifa_addr;
        //            sin = (struct sockaddr_in *) ifa_iter->ifa_addr;
        //            iface->ip_addr.sin_addr = sin->sin_addr;
        //            sin = (struct sockaddr_in *) ifa_iter->ifa_dstaddr;
        //            iface->bcast_addr.sin_addr = sin->sin_addr;
        //        }
        free(if_name);
    }
    
    freeifaddrs(ifa_list);
    return 0;
}
示例#4
0
/*
 * Set if_head to point to a list of iface_t structures which represent the
 * interfaces on this machine
 * @param ift_head the address of the pointer to the head of the list
 */
static int get_ifaces(iface_t **if_head) {
    iface_t *if_tail, *iface;
    PIP_ADAPTER_INFO pAdapter = NULL;
    PIP_ADAPTER_INFO pAdapterInfo;
    IP_ADDR_STRING *ipAddress;
    DWORD status;
    ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
    unsigned long net, mask;
    if_tail = NULL;
    
    while (1) {
        pAdapterInfo = (IP_ADAPTER_INFO*) malloc(ulOutBufLen);
        if (!pAdapterInfo) {
            artnet_error("Error allocating memory needed for GetAdaptersinfo");
            return ARTNET_EMEM;
        }
        
        status= GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
        if (status == NO_ERROR)
            break;
        
        free(pAdapterInfo);
        if (status != ERROR_BUFFER_OVERFLOW) {
            printf("GetAdaptersInfo failed with error: %d\n", (int) status);
            return ARTNET_ENET;
        }
    }
    
    for (pAdapter = pAdapterInfo;
         pAdapter && pAdapter < pAdapterInfo + ulOutBufLen;
         pAdapter = pAdapter->Next) {
        
        if(pAdapter->Type != MIB_IF_TYPE_ETHERNET)
            continue;
        
        for (ipAddress = &pAdapter->IpAddressList; ipAddress;
             ipAddress = ipAddress->Next) {
            
            net = inet_addr(ipAddress->IpAddress.String);
            if (net) {
                // Windows doesn't seem to have the notion of an interface being 'up'
                // so we check if this interface has an address assigned.
                iface = new_iface(if_head, &if_tail);
                if (!iface)
                    continue;
                
                mask = inet_addr(ipAddress->IpMask.String);
                strncpy(iface->if_name, pAdapter->AdapterName, IFNAME_SIZE);
                memcpy(iface->hw_addr, pAdapter->Address, ARTNET_MAC_SIZE);
                iface->ip_addr.sin_addr.s_addr = net;
                iface->bcast_addr.sin_addr.s_addr = (
                                                     (net & mask) | (0xFFFFFFFF ^ mask));
            }
        }
    }
    
    free(pAdapterInfo);
    return (ARTNET_EOK);
}
示例#5
0
/*
 * Send a packet.
 */
int artnet_net_send(node n, artnet_packet p) {
    struct sockaddr_in addr;
    int ret;
    
    if (n->state.mode != ARTNET_ON)
        return ARTNET_EACTION;
    
    addr.sin_family = AF_INET;
    addr.sin_port = htons(ARTNET_PORT);
    addr.sin_addr = p->to;
    p->from = n->state.ip_addr;
    
    if (n->state.verbose) {
        //printf("sending to %s\n" , inet_ntoa(addr.sin_addr));
    }
    
    ret = sendto(n->sd,
                 (char*) &p->data, // char* required for win32
                 p->length,
                 0,
                 (SA*) &addr,
                 sizeof(addr));
    if (ret == -1) {
        artnet_error("Sendto failed: %s", artnet_net_last_error());
        n->state.report_code = ARTNET_RCUDPFAIL;
        return ARTNET_ENET;
        
    } else if (p->length != ret) {
        artnet_error("failed to send full datagram");
        n->state.report_code = ARTNET_RCSOCKETWR1;
        return ARTNET_ENET;
    }
    
    if (n->callbacks.send.fh) {
        get_type(p);
        n->callbacks.send.fh(n, p, n->callbacks.send.data);
    }
    return ARTNET_EOK;
}
示例#6
0
/*
 * Close a socket
 */
int artnet_net_close(int sock) {
#ifdef WIN32
    shutdown(sock, SD_BOTH);
    closesocket(sock);
    //WSACancelBlockingCall();
    WSACleanup();
#else
    if (close(sock)) {
        artnet_error(artnet_net_last_error());
        return ARTNET_ENET;
    }
#endif
    return ARTNET_EOK;
}
示例#7
0
/*
 * Add a new interface to an interface list
 * @param head pointer to the head of the list
 * @param tail pointer to the end of the list
 * @return a new iface_t or void
 */
static iface_t *new_iface(iface_t **head, iface_t **tail) {
    iface_t *iface = (iface_t*) calloc(1, sizeof(iface_t));
    
    if (!iface) {
        artnet_error("%s: calloc error %s" , __FUNCTION__, strerror(errno));
        return NULL;
    }
    memset(iface, 0, sizeof(iface_t));
    
    if (!*head) {
        *head = *tail = iface;
    } else {
        (*tail)->next = iface;
        *tail = iface;
    }
    return iface;
}
示例#8
0
/*
 * Start listening on the socket
 */
int artnet_net_start(node n) {
    int sock;
    struct sockaddr_in servAddr;
    int true_flag = TRUE;
    node tmp;
    
    // only attempt to bind if we are the group master
    if (n->peering.master == TRUE) {
        
#ifdef WIN32
        // check winsock version
        WSADATA wsaData;
        u_long _true = 1;
        WORD wVersionRequested = MAKEWORD(2, 2);
        if (WSAStartup(wVersionRequested, &wsaData) != 0)
            return (-1);
        if (wsaData.wVersion != wVersionRequested)
            return (-2);
#endif
        
        // create socket
        sock = socket(PF_INET, SOCK_DGRAM, 0);
        
        if (sock < 0) {
            artnet_error("Could not create socket %s", artnet_net_last_error());
            return ARTNET_ENET;
        }
        
        memset(&servAddr, 0x00, sizeof(servAddr));
        servAddr.sin_family = AF_INET;
        servAddr.sin_port = htons(ARTNET_PORT);
        servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        
        if (n->state.verbose)
            printf("Binding to %s \n", inet_ntoa(servAddr.sin_addr));
        
        // bind sockets
        if (bind(sock, (SA *) &servAddr, sizeof(servAddr)) == -1) {
            artnet_error("Failed to bind to socket %s", artnet_net_last_error());
            artnet_net_close(sock);
            return ARTNET_ENET;
        }
        
        // allow bcasting
        if (setsockopt(sock,
                       SOL_SOCKET,
                       SO_BROADCAST,
                       (char*) &true_flag, // char* for win32
                       sizeof(int)) == -1) {
            artnet_error("Failed to bind to socket %s", artnet_net_last_error());
            artnet_net_close(sock);
            return ARTNET_ENET;
        }
        
#ifdef WIN32
        // ### LH - 22.08.2008
        // make it possible to reuse port, if SO_REUSEADDR
        // exists on operating system
        
        // NEVER USE SO_EXCLUSIVEADDRUSE, as that freezes the application
        // on WinXP, if port is in use !
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &true_flag,
                       sizeof(true_flag)) < 0) {
            
            artnet_error("Set reuse failed", artnet_net_last_error());
            artnet_net_close(sock);
            return ARTNET_ENET;
        }
        
        if (SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &_true)) {
            
            artnet_error("ioctlsocket", artnet_net_last_error());
            artnet_net_close(sock);
            return ARTNET_ENET;
        }
#endif
        
        n->sd = sock;
        // Propagate the socket to all our peers
        for (tmp = n->peering.peer; tmp && tmp != n; tmp = tmp->peering.peer)
            tmp->sd = sock;
    }
    return ARTNET_EOK;
}
示例#9
0
/*
 * Scan for interfaces, and work out which one the user wanted to use.
 */
int artnet_net_init(node n, const char *preferred_ip) {
    iface_t *ift, *ift_head = NULL;
    struct in_addr wanted_ip;
    
    int found = FALSE;
    int i;
    int ret = ARTNET_EOK;
    
    if ((ret = get_ifaces(&ift_head)))
        goto e_return;
    
    if (n->state.verbose) {
        printf("#### INTERFACES FOUND ####\n");
        for (ift = ift_head; ift != NULL; ift = ift->next) {
            printf("IP: %s\n", inet_ntoa(ift->ip_addr.sin_addr));
            printf("  bcast: %s\n" , inet_ntoa(ift->bcast_addr.sin_addr));
            printf("  hwaddr: ");
            for (i = 0; i < ARTNET_MAC_SIZE; i++) {
                if (i)
                    printf(":");
                printf("%02x", (uint8_t) ift->hw_addr[i]);
            }
            printf("\n");
        }
        printf("#########################\n");
    }
    
    if (preferred_ip) {
        // search through list of interfaces for one with the correct address
        ret = artnet_net_inet_aton(preferred_ip, &wanted_ip);
        if (ret)
            goto e_cleanup;
        
        for (ift = ift_head; ift != NULL; ift = ift->next) {
            if (ift->ip_addr.sin_addr.s_addr == wanted_ip.s_addr) {
                found = TRUE;
                n->state.ip_addr = ift->ip_addr.sin_addr;
                n->state.bcast_addr = ift->bcast_addr.sin_addr;
                memcpy(&n->state.hw_addr, &ift->hw_addr, ARTNET_MAC_SIZE);
                break;
            }
        }
        if (!found) {
            artnet_error("Cannot find interface by ip %s", preferred_ip);
            ret = ARTNET_ENET;
            goto e_cleanup;
        }
    } else {
        if (ift_head) {
            // pick first address
            // copy ip address, bcast address and hardware address
            n->state.ip_addr = ift_head->ip_addr.sin_addr;
            n->state.bcast_addr = ift_head->bcast_addr.sin_addr;
            memcpy(&n->state.hw_addr, &ift_head->hw_addr, ARTNET_MAC_SIZE);
        } else {
            artnet_error("No interfaces found!");
            ret = ARTNET_ENET;
        }
    }
    
e_cleanup:
    free_ifaces(ift_head);
    e_return :
    return ret;
}
示例#10
0
/*
 * Set if_head to point to a list of iface_t structures which represent the
 * interfaces on this machine
 * @param ift_head the address of the pointer to the head of the list
 */
static int get_ifaces(iface_t **if_head) {
  struct ifconf ifc;
  struct ifreq *ifr, ifrcopy;
  struct sockaddr_in *sin;
  int len, lastlen, flags;
  char *buf, *ptr;
  iface_t *if_tail, *iface;
  int ret = ARTNET_EOK;
  int sd;

  *if_head = if_tail = NULL;

  // create socket to get iface config
  sd = socket(PF_INET, SOCK_DGRAM, 0);

  if (sd < 0) {
    artnet_error("%s : Could not create socket %s", __FUNCTION__, strerror(errno));
    ret = ARTNET_ENET;
    goto e_return;
  }

  // first use ioctl to get a listing of interfaces
  lastlen = 0;
  len = INITIAL_IFACE_COUNT * sizeof(struct ifreq);

  for (;;) {
    buf = malloc(len);

    if (buf == NULL) {
      artnet_error_malloc();
      ret = ARTNET_EMEM;
      goto e_free;
    }

    ifc.ifc_len = len;
    ifc.ifc_buf = buf;
    if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) {
      if (errno != EINVAL || lastlen != 0) {
        artnet_error("%s : ioctl error %s", __FUNCTION__, strerror(errno));
        ret = ARTNET_ENET;
        goto e_free;
      }
    } else {
      if (ifc.ifc_len == lastlen)
        break;
      lastlen = ifc.ifc_len;
    }
    len += IFACE_COUNT_INC * sizeof(struct ifreq);
    free(buf);
  }

  // loop through each iface
  for (ptr = buf; ptr < buf + ifc.ifc_len;) {
    ifr = (struct ifreq*) ptr;

    // work out length here
#ifdef HAVE_SOCKADDR_SA_LEN
    len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);
#else
    switch (ifr->ifr_addr.sa_family) {
#ifdef  IPV6
      case AF_INET6:
        len = sizeof(struct sockaddr_in6);
        break;
#endif
      case AF_INET:
      default:
        len = sizeof(SA);
        break;
    }
#endif

    ptr += sizeof(ifr->ifr_name) + len;

    // look for AF_INET interfaces
    if (ifr->ifr_addr.sa_family == AF_INET) {
      ifrcopy = *ifr;
      if (ioctl(sd, SIOCGIFFLAGS, &ifrcopy) < 0) {
        artnet_error("%s : ioctl error %s" , __FUNCTION__, strerror(errno));
        ret = ARTNET_ENET;
        goto e_free_list;
      }

      flags = ifrcopy.ifr_flags;
      if ((flags & IFF_UP) == 0)
        continue; //skip down interfaces

      if ((flags & IFF_LOOPBACK))
        continue; //skip lookback

      iface = new_iface(if_head, &if_tail);
      if (!iface)
        goto e_free_list;

      sin = (struct sockaddr_in *) &ifr->ifr_addr;
      iface->ip_addr.sin_addr = sin->sin_addr;

      // fetch bcast address
#ifdef SIOCGIFBRDADDR
      if (flags & IFF_BROADCAST) {
        if (ioctl(sd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
          artnet_error("%s : ioctl error %s" , __FUNCTION__, strerror(errno));
          ret = ARTNET_ENET;
          goto e_free_list;
        }

        sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
        iface->bcast_addr.sin_addr = sin->sin_addr;
      }
#endif
      // fetch hardware address
#ifdef SIOCGIFHWADDR
      if (flags & SIOCGIFHWADDR) {
        if (ioctl(sd, SIOCGIFHWADDR, &ifrcopy) < 0) {
          artnet_error("%s : ioctl error %s", __FUNCTION__, strerror(errno));
          ret = ARTNET_ENET;
          goto e_free_list;
        }
        memcpy(&iface->hw_addr, ifrcopy.ifr_hwaddr.sa_data, ARTNET_MAC_SIZE);
      }
#endif

    /* ok, if that all failed we should prob try and use sysctl to work out the bcast
     * and hware addresses
     * i'll leave that for another day
     */
    }
  }
  free(buf);
  return ARTNET_EOK;

e_free_list:
  free_ifaces(*if_head);
e_free:
  free(buf);
  close(sd);
e_return:
  return ret;
}