sd-ipv4ll.c revision 25d6213b4331e9cbf355f4e851fc5b4ee2ae4c0f
/***
This file is part of systemd.
Copyright (C) 2014 Axis Communications AB. All rights reserved.
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include "util.h"
#include "siphash24.h"
#include "list.h"
#include "random-util.h"
#include "arp-util.h"
#include "sd-ipv4ll.h"
/* Constants from the RFC */
#define PROBE_WAIT 1
#define PROBE_NUM 3
#define PROBE_MIN 1
#define PROBE_MAX 2
#define ANNOUNCE_WAIT 2
#define ANNOUNCE_NUM 2
#define ANNOUNCE_INTERVAL 2
#define MAX_CONFLICTS 10
#define RATE_LIMIT_INTERVAL 60
#define DEFEND_INTERVAL 10
#define IPV4LL_NETWORK 0xA9FE0000L
#define IPV4LL_NETMASK 0xFFFF0000L
#define log_ipv4ll(ll, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "IPv4LL: " fmt, ##__VA_ARGS__)
typedef enum IPv4LLState {
} IPv4LLState;
struct sd_ipv4ll {
unsigned n_ref;
int index;
int fd;
int iteration;
int conflict;
int next_wakeup_valid;
struct random_data *random_data;
char *random_data_state;
/* External */
struct ether_addr mac_addr;
int event_priority;
void* userdata;
};
} else {
}
}
}
return ll;
}
if (ll) {
ll->claimed_address = 0;
}
return ll;
}
int r;
do {
if (r < 0)
return r;
return 0;
}
usec_t next_timeout = 0;
assert(random_sec >= 0);
if (random_sec)
}
return true;
return false;
}
return true;
return true;
return false;
}
int r = 0;
/* Send a probe */
if (r < 0) {
goto out;
}
/* Send the last probe */
if (r < 0) {
goto out;
}
/* Send announcement packet */
if (r < 0) {
goto out;
}
goto out;
}
ll->next_wakeup_valid = 0;
}
if (ll->next_wakeup_valid) {
if (r < 0)
goto out;
if (r < 0)
goto out;
if (r < 0)
goto out;
}
out:
if (r < 0 && ll)
ipv4ll_stop(ll, r);
return 1;
}
int r;
return 0;
ll->claimed_address = 0;
/* Pick a new address */
if (r < 0)
return r;
if (r < 0)
return r;
ll->defend_window = 0;
} else
return 0;
}
int r;
if (r < (int) sizeof(struct ether_arp))
goto out;
case IPV4LL_STATE_ANNOUNCING:
case IPV4LL_STATE_RUNNING:
/* Defend address */
if (r < 0) {
goto out;
}
} else {
r = ipv4ll_on_conflict(ll);
if (r < 0)
goto out;
}
}
break;
case IPV4LL_STATE_PROBING:
r = ipv4ll_on_conflict(ll);
if (r < 0)
goto out;
}
break;
default:
assert_not_reached("Invalid state.");
}
out:
if (r < 0 && ll)
ipv4ll_stop(ll, r);
return 1;
}
return 0;
}
bool need_restart = false;
return 0;
"client, restarting");
need_restart = true;
}
if (!ll)
return 0;
if (need_restart)
return 0;
}
return 0;
}
int r;
if (event)
else {
if (r < 0) {
return r;
}
}
return 0;
}
return 0;
}
if (ll->claimed_address == 0)
return -ENOENT;
return 0;
}
unsigned int entropy;
int r;
r = -ENOMEM;
goto error;
}
if (r < 0)
goto error;
if (r < 0){
}
return r;
}
assert_return(ll, false);
}
int r;
ll->defend_window = 0;
ll->claimed_address = 0;
if (!ll->random_data) {
/* Fallback to mac */
if (r < 0)
goto out;
}
if (r < 0)
goto out;
}
if (r < 0)
goto out;
if (r < 0)
goto out;
if (r < 0)
goto out;
if (r < 0)
goto out;
now(clock_boottime_or_monotonic()), 0,
if (r < 0)
goto out;
if (r < 0)
goto out;
out:
if (r < 0)
return 0;
}
if (ll)
return 0;
}
if (!ll)
return NULL;
return ll;
}
if (!ll)
return NULL;
return ll;
return NULL;
}
if (!ll)
return -ENOMEM;
return 0;
}