1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) B.A.T.M.A.N. contributors:
*
* Simon Wunderlich
*
* License-Filename: LICENSES/preferred/GPL-2.0
*/
#include <netinet/ether.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "alfred.h"
int time_diff(struct timespec *tv1, struct timespec *tv2,
struct timespec *tvdiff) {
tvdiff->tv_sec = tv1->tv_sec - tv2->tv_sec;
if (tv1->tv_nsec < tv2->tv_nsec) {
tvdiff->tv_nsec = 1000000000 + tv1->tv_nsec - tv2->tv_nsec;
tvdiff->tv_sec -= 1;
} else {
tvdiff->tv_nsec = tv1->tv_nsec - tv2->tv_nsec;
}
return (tvdiff->tv_sec >= 0);
}
void time_random_seed(void)
{
struct timespec now;
uint8_t *c = (uint8_t *)&now;
size_t i;
unsigned int s = 0;
clock_gettime(CLOCK_REALTIME, &now);
for (i = 0; i < sizeof(now); i++) {
s *= 127u;
s += c[i];
}
srand(s);
}
uint16_t get_random_id(void)
{
return random();
}
bool is_valid_ether_addr(uint8_t addr[ETH_ALEN])
{
/* multicast address */
if (addr[0] & 0x01)
return false;
/* 00:00:00:00:00:00 */
if ((addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]) == 0)
return false;
return true;
}
bool is_iface_disabled(char *iface)
{
if (!iface)
return false;
if (strcmp(iface, "none") != 0)
return false;
return true;
}
static void ipv4_request_mac_resolve(const alfred_addr *addr)
{
const struct sockaddr *sockaddr;
struct sockaddr_in inet4;
size_t sockaddr_len;
int sock;
char t = 0;
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0)
return;
memset(&inet4, 0, sizeof(inet4));
inet4.sin_family = AF_INET;
inet4.sin_port = htons(9);
inet4.sin_addr.s_addr = addr->ipv4.s_addr;
sockaddr = (const struct sockaddr *)&inet4;
sockaddr_len = sizeof(inet4);
sendto(sock, &t, sizeof(t), 0, sockaddr, sockaddr_len);
close(sock);
}
int ipv4_arp_request(struct interface *interface, const alfred_addr *addr,
struct ether_addr *mac)
{
struct arpreq arpreq;
struct sockaddr_in *sin;
int retries = 1;
memset(&arpreq, 0, sizeof(arpreq));
memset(mac, 0, ETH_ALEN);
sin = (struct sockaddr_in *)&arpreq.arp_pa;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = addr->ipv4.s_addr;
strncpy(arpreq.arp_dev, interface->interface, sizeof(arpreq.arp_dev));
arpreq.arp_dev[sizeof(arpreq.arp_dev) - 1] = '\0';
while ((ioctl(interface->netsock, SIOCGARP, &arpreq) < 0) || !(arpreq.arp_flags & ATF_COM)) {
ipv4_request_mac_resolve(addr);
usleep(200000);
if (retries-- == 0)
break;
}
if (arpreq.arp_flags & ATF_COM) {
memcpy(mac, arpreq.arp_ha.sa_data, sizeof(*mac));
} else {
perror("arp: incomplete");
return -1;
}
return 0;
}
|