socket.c

back


/* Helpers for our socket operations
 *
 */

#include <sys/types.h>
#include <sys/socket.h>

#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <net/if.h>

#include <string.h>

#include <unistd.h>

#include <data_util.h>
#include <ip.h>
#include <link.h>
#include <socket.h>

/* Get and setup unix-styled socket for us
 *
 */
int raw_socket(const char *iface) {
    int sock = socket(AF_PACKET, SOCK_RAW, htons(3));
    if (sock == -1) {
        return sock;
    }
    int stat = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface));
    if (stat == -1) {
        close(sock);
        return stat;
    }
    return sock;
}

/* Send up to size_t bytes of data
 *
 * @param net_socket *sock -- Pointer to socket we're working with
 * @param const void *data -- Pointer to data to transmit
 * @param size_t len       -- Amount of bytes to send
 * @return amount of bytes written on success or -1 on error.
 *         set errno on error.
 */
size_t transmit(net_socket *sock, const void *data, size_t len) {
    struct sockaddr_ll saddr;
    link_options *link = (link_options *)sock->link_options;

    memcpy(saddr.sll_addr, link->proto.eth_header->mac_src, 6);
    saddr.sll_family   = AF_PACKET;
    saddr.sll_protocol = htons(ETH_P_ALL);
    saddr.sll_ifindex  = if_nametoindex(sock->iface);
    saddr.sll_hatype   = 1;
    saddr.sll_pkttype  = PACKET_OTHERHOST;
    saddr.sll_halen    = ETH_ALEN;

    return sendto(sock->raw_sockfd, data, len, 0, 
            (const struct sockaddr *)&saddr, sizeof(struct sockaddr_ll));
}