linux/tools/testing/selftests/net/psock_lib.h
<<
>>
Prefs
   1/*
   2 * Copyright 2013 Google Inc.
   3 * Author: Willem de Bruijn <willemb@google.com>
   4 *         Daniel Borkmann <dborkman@redhat.com>
   5 *
   6 * License (GPLv2):
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms and conditions of the GNU General Public License,
  10 * version 2, as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope it will be useful, but WITHOUT
  13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14 * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
  15 * more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along with
  18 * this program; if not, write to the Free Software Foundation, Inc.,
  19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  20 */
  21
  22#ifndef PSOCK_LIB_H
  23#define PSOCK_LIB_H
  24
  25#include <sys/types.h>
  26#include <sys/socket.h>
  27#include <string.h>
  28#include <arpa/inet.h>
  29#include <unistd.h>
  30
  31#define DATA_LEN                        100
  32#define DATA_CHAR                       'a'
  33#define DATA_CHAR_1                     'b'
  34
  35#define PORT_BASE                       8000
  36
  37#ifndef __maybe_unused
  38# define __maybe_unused         __attribute__ ((__unused__))
  39#endif
  40
  41static __maybe_unused void sock_setfilter(int fd, int lvl, int optnum)
  42{
  43        struct sock_filter bpf_filter[] = {
  44                { 0x80, 0, 0, 0x00000000 },  /* LD  pktlen                    */
  45                { 0x35, 0, 4, DATA_LEN   },  /* JGE DATA_LEN  [f goto nomatch]*/
  46                { 0x30, 0, 0, 0x00000050 },  /* LD  ip[80]                    */
  47                { 0x15, 1, 0, DATA_CHAR  },  /* JEQ DATA_CHAR   [t goto match]*/
  48                { 0x15, 0, 1, DATA_CHAR_1},  /* JEQ DATA_CHAR_1 [t goto match]*/
  49                { 0x06, 0, 0, 0x00000060 },  /* RET match                     */
  50                { 0x06, 0, 0, 0x00000000 },  /* RET no match                  */
  51        };
  52        struct sock_fprog bpf_prog;
  53
  54        if (lvl == SOL_PACKET && optnum == PACKET_FANOUT_DATA)
  55                bpf_filter[5].code = 0x16;   /* RET A                         */
  56
  57        bpf_prog.filter = bpf_filter;
  58        bpf_prog.len = sizeof(bpf_filter) / sizeof(struct sock_filter);
  59        if (setsockopt(fd, lvl, optnum, &bpf_prog,
  60                       sizeof(bpf_prog))) {
  61                perror("setsockopt SO_ATTACH_FILTER");
  62                exit(1);
  63        }
  64}
  65
  66static __maybe_unused void pair_udp_setfilter(int fd)
  67{
  68        sock_setfilter(fd, SOL_SOCKET, SO_ATTACH_FILTER);
  69}
  70
  71static __maybe_unused void pair_udp_open(int fds[], uint16_t port)
  72{
  73        struct sockaddr_in saddr, daddr;
  74
  75        fds[0] = socket(PF_INET, SOCK_DGRAM, 0);
  76        fds[1] = socket(PF_INET, SOCK_DGRAM, 0);
  77        if (fds[0] == -1 || fds[1] == -1) {
  78                fprintf(stderr, "ERROR: socket dgram\n");
  79                exit(1);
  80        }
  81
  82        memset(&saddr, 0, sizeof(saddr));
  83        saddr.sin_family = AF_INET;
  84        saddr.sin_port = htons(port);
  85        saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  86
  87        memset(&daddr, 0, sizeof(daddr));
  88        daddr.sin_family = AF_INET;
  89        daddr.sin_port = htons(port + 1);
  90        daddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  91
  92        /* must bind both to get consistent hash result */
  93        if (bind(fds[1], (void *) &daddr, sizeof(daddr))) {
  94                perror("bind");
  95                exit(1);
  96        }
  97        if (bind(fds[0], (void *) &saddr, sizeof(saddr))) {
  98                perror("bind");
  99                exit(1);
 100        }
 101        if (connect(fds[0], (void *) &daddr, sizeof(daddr))) {
 102                perror("connect");
 103                exit(1);
 104        }
 105}
 106
 107static __maybe_unused void pair_udp_send_char(int fds[], int num, char payload)
 108{
 109        char buf[DATA_LEN], rbuf[DATA_LEN];
 110
 111        memset(buf, payload, sizeof(buf));
 112        while (num--) {
 113                /* Should really handle EINTR and EAGAIN */
 114                if (write(fds[0], buf, sizeof(buf)) != sizeof(buf)) {
 115                        fprintf(stderr, "ERROR: send failed left=%d\n", num);
 116                        exit(1);
 117                }
 118                if (read(fds[1], rbuf, sizeof(rbuf)) != sizeof(rbuf)) {
 119                        fprintf(stderr, "ERROR: recv failed left=%d\n", num);
 120                        exit(1);
 121                }
 122                if (memcmp(buf, rbuf, sizeof(buf))) {
 123                        fprintf(stderr, "ERROR: data failed left=%d\n", num);
 124                        exit(1);
 125                }
 126        }
 127}
 128
 129static __maybe_unused void pair_udp_send(int fds[], int num)
 130{
 131        return pair_udp_send_char(fds, num, DATA_CHAR);
 132}
 133
 134static __maybe_unused void pair_udp_close(int fds[])
 135{
 136        close(fds[0]);
 137        close(fds[1]);
 138}
 139
 140#endif /* PSOCK_LIB_H */
 141