pmlag

Poor man's link aggregation
git clone git://git.finwo.net/app/pmlag
Log | Files | Refs | README | LICENSE

socket.c (3775B)


      1 #include <fcntl.h>
      2 #include <linux/if_arp.h>
      3 #include <linux/if_packet.h>
      4 #include <linux/if_tun.h>
      5 #include <linux/if.h>
      6 #include <netinet/in.h>
      7 #include <string.h>
      8 #include <strings.h>
      9 #include <sys/ioctl.h>
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <sys/socket.h>
     13 #include <unistd.h>
     14 
     15 #include "socket.h"
     16 
     17 unsigned char * iface_mac(char * ifname) {
     18   unsigned char *mac = calloc(1, ETH_ALEN);
     19   struct ifreq ifr;
     20   int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
     21   ifr.ifr_addr.sa_family = AF_INET;
     22   strncpy(ifr.ifr_name , ifname , IFNAMSIZ-1);
     23   ioctl(sockfd, SIOCGIFHWADDR, &ifr);
     24   close(sockfd);
     25   memcpy(mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
     26   return mac;
     27 }
     28 
     29 int iface_idx(int sockfd, char * ifname) {
     30   struct ifreq ifr;
     31   bzero(&ifr, sizeof(ifr));
     32 
     33   // Get interface index
     34   strncpy((char *)ifr.ifr_name, ifname, IFNAMSIZ);
     35   if ((ioctl(sockfd, SIOCGIFINDEX, &ifr)) == -1) {
     36     fprintf(stderr, "Error getting interface index for %s\n", ifname);
     37     perror("Error getting interface index");
     38     close(sockfd);
     39     return -1;
     40   }
     41 
     42   return ifr.ifr_ifindex;
     43 }
     44 
     45 int if_ioctl(int cmd, struct ifreq* req) {
     46   int ret, sock;
     47   sock = socket(AF_INET, SOCK_PACKET, 0);
     48   if (sock < 0) {
     49     return -1;
     50   }
     51   ret = ioctl(sock, cmd, req);
     52   close(sock);
     53   return ret;
     54 }
     55 
     56 int sockraw_open(char * ifname) {
     57   struct ifreq ifr;
     58 
     59   // Open socket (P_ALL, due to custom ethertype field)
     60   int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
     61   if (sockfd < 0) {
     62     perror("Error opening socket");
     63     close(sockfd);
     64     return -1;
     65   }
     66 
     67   // Old bind to socket
     68   struct sockaddr_ll sll;
     69   bzero(&sll, sizeof(sll));
     70   sll.sll_family   = AF_PACKET;
     71   sll.sll_ifindex  = iface_idx(sockfd, ifname);
     72   sll.sll_protocol = htons(ETH_P_ALL);
     73   if (sll.sll_ifindex < 0) {
     74     // Error already printed, not reprinting
     75     return -1;
     76   }
     77   if((bind(sockfd, (struct sockaddr *)&sll, sizeof(sll))) == -1) {
     78     perror("Error binding raw socket to interface");
     79     close(sockfd);
     80     return -1;
     81   }
     82 
     83   // Get current iface configuration
     84   memset(&ifr, 0, sizeof(ifr));
     85   strcpy(ifr.ifr_name, ifname);
     86   if (if_ioctl(SIOCGIFFLAGS, &ifr) < 0) {
     87     perror("Get interface flags");
     88   }
     89 
     90   // Set iface to promiscuous mode
     91   ifr.ifr_flags |= IFF_PROMISC;
     92   if (if_ioctl(SIOCSIFFLAGS, &ifr) < 0) {
     93     perror("Configure interface promiscuous mode");
     94   }
     95 
     96   // Return the prepared socket
     97   return sockfd;
     98 }
     99 
    100 int tap_alloc(char * ifname, unsigned char * mac) {
    101   struct ifreq ifr;
    102   int fd, err;
    103 
    104   if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
    105     perror("Open tun");
    106     return -1;
    107   }
    108 
    109   // Bring up the interface
    110   memset(&ifr, 0, sizeof(ifr));
    111   ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
    112   if( *ifname ) {
    113     strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
    114   }
    115   if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
    116     perror("Open tun");
    117     close(fd);
    118     return err;
    119   }
    120   strcpy(ifname, ifr.ifr_name);
    121 
    122   // Set the interface's mac address
    123   if ( mac ) {
    124     // TODO: random, copied or specific mac address pulled from ini
    125     memset(&ifr, 0, sizeof(ifr));
    126     strcpy(ifr.ifr_name, ifname);
    127     ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
    128     memcpy(ifr.ifr_hwaddr.sa_data, mac, ETH_ALEN);
    129     if ((err = if_ioctl(SIOCSIFHWADDR, &ifr)) < 0) {
    130       perror("Set if hwaddr");
    131       close(fd);
    132       return err;
    133     }
    134   }
    135 
    136   // Fetch the current flags
    137   memset(&ifr, 0, sizeof(ifr));
    138   strcpy(ifr.ifr_name, ifname);
    139   if (if_ioctl(SIOCGIFFLAGS, &ifr) < 0) {
    140     perror("failed to get the interface flags");
    141     close(fd);
    142     return err;
    143   }
    144 
    145   // Bring up the interface
    146   if (!(ifr.ifr_flags & IFF_UP)) {
    147     ifr.ifr_flags |= IFF_UP;
    148     if (if_ioctl(SIOCSIFFLAGS, &ifr) < 0) {
    149       perror("failed to get the interface flags");
    150       close(fd);
    151       return err;
    152     }
    153   }
    154 
    155   return fd;
    156 }