eth_linux.c
author viric@mandarina
Mon, 28 Apr 2008 21:37:16 +0200
changeset 89 2692e4742267
parent 88 a7f546938313
permissions -rw-r--r--
Moving the utils from stdinmix to tm.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
     1
/* Copyright Coraid, Inc. 2006.  All rights reserved. */
53
07500c5c53cb Adding license and web html.
viric@llimona
parents: 44
diff changeset
     2
/* Modified the original with BSD license by Lluis Batlle */
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
     3
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
     4
#include <sys/types.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
     5
#include <sys/socket.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
     6
#include <stdio.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
     7
#include <string.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
     8
#include <stdlib.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
     9
#include <unistd.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    10
#include <sys/time.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    11
#include <features.h>    /* for the glibc version number */
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    12
#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    13
#include <netpacket/packet.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    14
#include <net/ethernet.h>     /* the L2 protocols */
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    15
#else
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    16
#include <asm/types.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    17
#include <linux/if_packet.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    18
#include <linux/if_ether.h>   /* The L2 protocols */
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    19
#endif
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    20
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    21
#include <sys/ioctl.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    22
#include <net/if.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    23
#include <netinet/in.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    24
#include <linux/fs.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    25
#include <sys/stat.h>
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    26
66
b2469563a1dc Reliable ethernet protocol. I still need pselect instead of select.
viric@mandarina
parents: 53
diff changeset
    27
#include "main.h"
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    28
#include "eth_linux.h"
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    29
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    30
enum {
87
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    31
    ETH_SERVER_PROTO = 0xCACA,
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    32
    ETH_CLIENT_PROTO = 0xCACC
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    33
};
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    34
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    35
static int fd;
87
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    36
static enum Eth_type eth_type;
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    37
static char srcaddr[6];
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    38
static int debug = 0;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    39
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    40
static void dump(unsigned char *buf, int len)
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    41
{
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    42
  int i;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    43
  for(i=0; i < len; ++i)
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    44
  {
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    45
    printf("%x ", (int) buf[i]);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    46
  }
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    47
  putchar('\n');
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    48
}
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    49
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    50
// return the index of device 'name'
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    51
static int getindx(int s, char *name)
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    52
{
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    53
    struct ifreq xx;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    54
    int n;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    55
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    56
    strncpy(xx.ifr_name, name, sizeof(xx.ifr_name));
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    57
    xx.ifr_name[sizeof(xx.ifr_name)-1] = 0;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    58
    n = ioctl(s, SIOCGIFINDEX, &xx);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    59
    if (n == -1)
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    60
        return -1;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    61
    return xx.ifr_ifindex;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    62
}
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    63
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    64
// get us a raw connection to an interface
87
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    65
int eth_open(char *eth, enum Eth_type type)
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    66
{
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    67
    int i, n;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    68
    struct sockaddr_ll sa;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    69
    struct ifreq xx;
87
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    70
    short int proto_num;
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    71
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    72
    if (type == ETH_SERVER)
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    73
    {
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    74
        dump_line("eth_open for server\n");
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    75
        proto_num = htons(ETH_SERVER_PROTO);
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    76
    }
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    77
    else if (type == ETH_CLIENT)
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    78
    {
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    79
        dump_line("eth_open for client\n");
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    80
        proto_num = htons(ETH_CLIENT_PROTO);
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    81
    }
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    82
    else
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    83
        return -1;
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    84
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    85
    /* Note the type server or client for this process */
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    86
    eth_type = type;
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    87
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    88
    memset(&sa, 0, sizeof sa);
87
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    89
    fd = socket(PF_PACKET, SOCK_DGRAM, proto_num);
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    90
    if (fd == -1) {
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    91
        perror("got bad socket");
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    92
        return -1;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    93
    }
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    94
    i = getindx(fd, eth);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    95
    sa.sll_family = AF_PACKET;
87
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
    96
    sa.sll_protocol = proto_num;
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    97
    sa.sll_ifindex = i;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    98
    n = bind(fd, (struct sockaddr *)&sa, sizeof sa);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
    99
    if (n == -1) {
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   100
        perror("bind funky");
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   101
        return -1;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   102
    }
44
41241a0f84bf Almost fixed eth transport.
viric@llimona
parents: 43
diff changeset
   103
    strncpy(xx.ifr_name, eth, sizeof(xx.ifr_name));
41241a0f84bf Almost fixed eth transport.
viric@llimona
parents: 43
diff changeset
   104
    xx.ifr_name[sizeof(xx.ifr_name)-1] = 0;
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   105
    n = ioctl(fd, SIOCGIFHWADDR, &xx);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   106
    if (n == -1) {
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   107
        perror("Can't get hw addr");
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   108
        return -1;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   109
    }
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   110
    memmove(srcaddr, xx.ifr_hwaddr.sa_data, 6);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   111
    return fd;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   112
}
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   113
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   114
int eth_recv(char *buf, int len, char *partner_mac)
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   115
{
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   116
    struct sockaddr_ll sa;
44
41241a0f84bf Almost fixed eth transport.
viric@llimona
parents: 43
diff changeset
   117
    int sa_len = sizeof(sa);
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   118
    int res;
66
b2469563a1dc Reliable ethernet protocol. I still need pselect instead of select.
viric@mandarina
parents: 53
diff changeset
   119
    dump_line("eth_recv\n");
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   120
    res = recvfrom(fd, buf, len, 0, (struct sockaddr *) &sa, &sa_len);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   121
    if (debug) {
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   122
        printf("read %d bytes\r\n", res);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   123
        dump(buf, res);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   124
    }
44
41241a0f84bf Almost fixed eth transport.
viric@llimona
parents: 43
diff changeset
   125
    /* Assume sa_len will be ok */
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   126
    if (partner_mac)
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   127
        memcpy(partner_mac, sa.sll_addr, sa.sll_halen);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   128
    return res;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   129
}
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   130
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   131
int eth_send(char *dev, char *mac, void *p, int len)
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   132
{
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   133
    struct sockaddr_ll sa;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   134
    int i;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   135
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   136
    i = getindx(fd, dev);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   137
    sa.sll_family = AF_PACKET;
87
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   138
    if (eth_type == ETH_SERVER)
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   139
    {
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   140
        dump_line("eth_send from server to client\n");
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   141
        sa.sll_protocol = htons(ETH_CLIENT_PROTO);
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   142
    }
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   143
    else if (eth_type == ETH_CLIENT)
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   144
    {
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   145
        dump_line("eth_send from client to server\n");
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   146
        sa.sll_protocol = htons(ETH_SERVER_PROTO);
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   147
    }
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   148
    else
be4ee314545c Making client and server use different ethernet protocols
viric@llimona
parents: 66
diff changeset
   149
        return -1;
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   150
    sa.sll_ifindex = i;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   151
    sa.sll_halen = 6;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   152
    memcpy(sa.sll_addr, mac, 6);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   153
    if (debug) {
88
a7f546938313 Adding port number on the ethernet protocol.
viric@llimona
parents: 87
diff changeset
   154
        printf("sending %d bytes to eth_protocol %hi\r\n", len, sa.sll_protocol);
43
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   155
        dump(p, len);
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   156
    }
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   157
    if (len > 1500)
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   158
        len = 1500;
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   159
    return sendto(fd, p, len, 0, (struct sockaddr*) &sa, sizeof(sa));
625794738afc Added first attempt for an ethernet protocol. Even not tried.
viric@llimona
parents:
diff changeset
   160
}