dhcp: merge branch 'systemd-dhcp' into master

Conflicts:
	src/dhcp-manager/systemd-dhcp/src/shared/util.c
This commit is contained in:
Thomas Haller 2015-03-23 21:00:10 +01:00
commit 99df201a0c
11 changed files with 176 additions and 91 deletions

View file

@ -1471,7 +1471,7 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
_cleanup_free_ DHCPMessage *message = NULL;
int buflen = 0, len, r;
const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
const struct ether_addr *expected_chaddr = NULL;
bool expect_chaddr;
uint8_t expected_hlen = 0;
assert(s);
@ -1516,11 +1516,11 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
if (client->arp_type == ARPHRD_ETHER) {
expected_hlen = ETH_ALEN;
expected_chaddr = (const struct ether_addr *) &client->mac_addr;
expect_chaddr = true;
} else {
/* Non-ethernet links expect zero chaddr */
expected_hlen = 0;
expected_chaddr = &zero_mac;
expect_chaddr = false;
}
if (message->hlen != expected_hlen) {
@ -1528,7 +1528,10 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
return 0;
}
if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
if (memcmp(&message->chaddr[0], expect_chaddr ?
(void *)&client->mac_addr :
(void *)&zero_mac,
ETH_ALEN)) {
log_dhcp_client(client, "received chaddr does not match "
"expected: ignoring");
return 0;

View file

@ -112,9 +112,9 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
static thread_local bool saved_machine_id_valid = false;
_cleanup_close_ int fd = -1;
char buf[33];
ssize_t k;
unsigned j;
sd_id128_t t;
int r;
assert_return(ret, -EINVAL);
@ -127,13 +127,9 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
if (fd < 0)
return -errno;
k = loop_read(fd, buf, 33, false);
if (k < 0)
return (int) k;
if (k != 33)
return -EIO;
r = loop_read_exact(fd, buf, 33, false);
if (r < 0)
return r;
if (buf[32] !='\n')
return -EIO;
@ -162,10 +158,10 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) {
static thread_local bool saved_boot_id_valid = false;
_cleanup_close_ int fd = -1;
char buf[36];
ssize_t k;
unsigned j;
sd_id128_t t;
char *p;
int r;
assert_return(ret, -EINVAL);
@ -178,22 +174,19 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) {
if (fd < 0)
return -errno;
k = loop_read(fd, buf, 36, false);
if (k < 0)
return (int) k;
if (k != 36)
return -EIO;
r = loop_read_exact(fd, buf, 36, false);
if (r < 0)
return r;
for (j = 0, p = buf; j < 16; j++) {
int a, b;
if (p >= buf + k - 1)
if (p >= buf + 35)
return -EIO;
if (*p == '-') {
p++;
if (p >= buf + k - 1)
if (p >= buf + 35)
return -EIO;
}

View file

@ -25,6 +25,7 @@
#include <stdbool.h>
#include <stdarg.h>
#include <stdlib.h>
#include <syslog.h>
#include <sys/signalfd.h>
#include <errno.h>

View file

@ -407,12 +407,18 @@ char* path_startswith(const char *path, const char *prefix) {
}
}
bool path_equal(const char *a, const char *b) {
int path_compare(const char *a, const char *b) {
int d;
assert(a);
assert(b);
if ((a[0] == '/') != (b[0] == '/'))
return false;
/* A relative path and an abolute path must not compare as equal.
* Which one is sorted before the other does not really matter.
* Here a relative path is ordered before an absolute path. */
d = (a[0] == '/') - (b[0] == '/');
if (d)
return d;
for (;;) {
size_t j, k;
@ -421,25 +427,36 @@ bool path_equal(const char *a, const char *b) {
b += strspn(b, "/");
if (*a == 0 && *b == 0)
return true;
return 0;
if (*a == 0 || *b == 0)
return false;
/* Order prefixes first: "/foo" before "/foo/bar" */
if (*a == 0)
return -1;
if (*b == 0)
return 1;
j = strcspn(a, "/");
k = strcspn(b, "/");
if (j != k)
return false;
/* Alphabetical sort: "/foo/aaa" before "/foo/b" */
d = memcmp(a, b, MIN(j, k));
if (d)
return (d > 0) - (d < 0); /* sign of d */
if (memcmp(a, b, j) != 0)
return false;
/* Sort "/foo/a" before "/foo/aaa" */
d = (j > k) - (j < k); /* sign of (j - k) */
if (d)
return d;
a += j;
b += k;
}
}
bool path_equal(const char *a, const char *b) {
return path_compare(a, b) == 0;
}
bool path_equal_or_files_same(const char *a, const char *b) {
return path_equal(a, b) || files_same(a, b) > 0;
}
@ -464,9 +481,9 @@ int path_is_mount_point(const char *t, bool allow_symlink) {
union file_handle_union h = FILE_HANDLE_INIT;
int mount_id = -1, mount_id_parent = -1;
_cleanup_free_ char *parent = NULL;
struct stat a, b;
int r;
_cleanup_close_ int fd = -1;
bool nosupp = false;
/* We are not actually interested in the file handles, but
@ -476,7 +493,15 @@ int path_is_mount_point(const char *t, bool allow_symlink) {
if (path_equal(t, "/"))
return 1;
r = name_to_handle_at(AT_FDCWD, t, &h.handle, &mount_id, allow_symlink ? AT_SYMLINK_FOLLOW : 0);
fd = openat(AT_FDCWD, t, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|(allow_symlink ? 0 : O_PATH));
if (fd < 0) {
if (errno == ENOENT)
return 0;
return -errno;
}
r = name_to_handle_at(fd, "", &h.handle, &mount_id, AT_EMPTY_PATH);
if (r < 0) {
if (errno == ENOSYS)
/* This kernel does not support name_to_handle_at()
@ -493,12 +518,9 @@ int path_is_mount_point(const char *t, bool allow_symlink) {
return -errno;
}
r = path_get_parent(t, &parent);
if (r < 0)
return r;
h.handle.handle_bytes = MAX_HANDLE_SZ;
r = name_to_handle_at(AT_FDCWD, parent, &h.handle, &mount_id_parent, AT_SYMLINK_FOLLOW);
r = name_to_handle_at(fd, "..", &h.handle, &mount_id_parent, 0);
if (r < 0)
if (errno == EOPNOTSUPP)
if (nosupp)
@ -517,10 +539,7 @@ int path_is_mount_point(const char *t, bool allow_symlink) {
return mount_id != mount_id_parent;
fallback:
if (allow_symlink)
r = stat(t, &a);
else
r = lstat(t, &a);
r = fstatat(fd, "", &a, AT_EMPTY_PATH);
if (r < 0) {
if (errno == ENOENT)
@ -529,14 +548,8 @@ fallback:
return -errno;
}
free(parent);
parent = NULL;
r = path_get_parent(t, &parent);
if (r < 0)
return r;
r = stat(parent, &b);
r = fstatat(fd, "..", &b, 0);
if (r < 0)
return -errno;

View file

@ -46,6 +46,7 @@ char* path_make_absolute_cwd(const char *p);
int path_make_relative(const char *from_dir, const char *to_path, char **_r);
char* path_kill_slashes(char *path);
char* path_startswith(const char *path, const char *prefix) _pure_;
int path_compare(const char *a, const char *b) _pure_;
bool path_equal(const char *a, const char *b) _pure_;
bool path_equal_or_files_same(const char *a, const char *b);
char* path_join(const char *root, const char *path, const char *rest);

View file

@ -99,7 +99,9 @@ const char* socket_address_get_path(const SocketAddress *a);
bool socket_ipv6_is_supported(void);
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, char **ret);
int sockaddr_port(const struct sockaddr *_sa) _pure_;
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
int getpeername_pretty(int fd, char **ret);
int getsockname_pretty(int fd, char **ret);

View file

@ -82,9 +82,10 @@ void strv_clear(char **l) {
*l = NULL;
}
void strv_free(char **l) {
char **strv_free(char **l) {
strv_clear(l);
free(l);
return NULL;
}
char **strv_copy(char * const *l) {

View file

@ -33,7 +33,7 @@ char *strv_find(char **l, const char *name) _pure_;
char *strv_find_prefix(char **l, const char *name) _pure_;
char *strv_find_startswith(char **l, const char *name) _pure_;
void strv_free(char **l);
char **strv_free(char **l);
DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free);
#define _cleanup_strv_free_ _cleanup_(strv_freep)

View file

@ -100,6 +100,9 @@
#include "sparse-endian.h"
#endif /* NM_IGNORED */
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
#if 0 /* NM_IGNORED */
int saved_argc = 0;
char **saved_argv = NULL;
@ -2350,6 +2353,17 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
return n;
}
int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
ssize_t n;
n = loop_read(fd, buf, nbytes, do_poll);
if (n < 0)
return n;
if ((size_t) n != nbytes)
return -EIO;
return 0;
}
#if 0 /* NM_IGNORED */
int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
const uint8_t *p = buf;
@ -2607,8 +2621,9 @@ char* dirname_malloc(const char *path) {
int dev_urandom(void *p, size_t n) {
#if 0 /* NM_IGNORED */
static int have_syscall = -1;
int r, fd;
ssize_t k;
_cleanup_close_ int fd = -1;
int r;
/* Gathers some randomness from the kernel. This call will
* never block, and will always return some data from the
@ -2643,26 +2658,17 @@ int dev_urandom(void *p, size_t n) {
return -errno;
} else
/* too short read? */
return -EIO;
return -ENODATA;
}
#else /* NM IGNORED */
int fd;
ssize_t k;
_cleanup_close_ int fd = -1;
#endif /* NM_IGNORED */
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return errno == ENOENT ? -ENOSYS : -errno;
k = loop_read(fd, p, n, true);
safe_close(fd);
if (k < 0)
return (int) k;
if ((size_t) k != n)
return -EIO;
return 0;
return loop_read_exact(fd, p, n, true);
}
void initialize_srand(void) {
@ -2951,31 +2957,30 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
/* This is an ugly hack */
if (major(devnr) == 136) {
asprintf(&b, "pts/%u", minor(devnr));
goto finish;
if (asprintf(&b, "pts/%u", minor(devnr)) < 0)
return -ENOMEM;
} else {
/* Probably something like the ptys which have no
* symlink in /dev/char. Let's return something
* vaguely useful. */
b = strdup(fn + 5);
if (!b)
return -ENOMEM;
}
} else {
if (startswith(s, "/dev/"))
p = s + 5;
else if (startswith(s, "../"))
p = s + 3;
else
p = s;
/* Probably something like the ptys which have no
* symlink in /dev/char. Let's return something
* vaguely useful. */
b = strdup(fn + 5);
goto finish;
b = strdup(p);
if (!b)
return -ENOMEM;
}
if (startswith(s, "/dev/"))
p = s + 5;
else if (startswith(s, "../"))
p = s + 3;
else
p = s;
b = strdup(p);
finish:
if (!b)
return -ENOMEM;
*r = b;
if (_devnr)
*_devnr = devnr;
@ -4147,8 +4152,7 @@ static int do_execute(char **directories, usec_t timeout, char *argv[]) {
if (null_or_empty_path(path)) {
log_debug("%s is empty (a mask).", path);
continue;
} else
log_debug("%s will be executed.", path);
}
pid = fork();
if (pid < 0) {
@ -6710,7 +6714,7 @@ int getpeersec(int fd, char **ret) {
if (isempty(s)) {
free(s);
return -ENOTSUP;
return -EOPNOTSUPP;
}
*ret = s;
@ -7890,6 +7894,28 @@ int chattr_path(const char *p, bool b, unsigned mask) {
return chattr_fd(fd, b, mask);
}
int change_attr_fd(int fd, unsigned value, unsigned mask) {
unsigned old_attr, new_attr;
assert(fd >= 0);
if (mask == 0)
return 0;
if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
return -errno;
new_attr = (old_attr & ~mask) |(value & mask);
if (new_attr == old_attr)
return 0;
if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
return -errno;
return 0;
}
int read_attr_fd(int fd, unsigned *ret) {
assert(fd >= 0);
@ -8172,4 +8198,45 @@ void cmsg_close_all(struct msghdr *mh) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
}
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
struct stat buf;
int ret;
ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
if (ret >= 0)
return 0;
/* Even though renameat2() exists since Linux 3.15, btrfs added
* support for it later. If it is not implemented, fallback to another
* method. */
if (errno != EINVAL)
return -errno;
/* The link()/unlink() fallback does not work on directories. But
* renameat() without RENAME_NOREPLACE gives the same semantics on
* directories, except when newpath is an *empty* directory. This is
* good enough. */
ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
if (ret >= 0 && S_ISDIR(buf.st_mode)) {
ret = renameat(olddirfd, oldpath, newdirfd, newpath);
return ret >= 0 ? 0 : -errno;
}
/* If it is not a directory, use the link()/unlink() fallback. */
ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
if (ret < 0)
return -errno;
ret = unlinkat(olddirfd, oldpath, 0);
if (ret < 0) {
/* backup errno before the following unlinkat() alters it */
ret = errno;
(void) unlinkat(newdirfd, newpath, 0);
errno = ret;
return -errno;
}
return 0;
}
#endif /* NM_IGNORED */

View file

@ -438,6 +438,7 @@ int sigaction_many(const struct sigaction *sa, ...);
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll);
int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll);
int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll);
bool is_device_path(const char *path);
@ -1062,6 +1063,7 @@ int same_fd(int a, int b);
int chattr_fd(int fd, bool b, unsigned mask);
int chattr_path(const char *p, bool b, unsigned mask);
int change_attr_fd(int fd, unsigned value, unsigned mask);
int read_attr_fd(int fd, unsigned *ret);
int read_attr_path(const char *p, unsigned *ret);
@ -1090,3 +1092,5 @@ void sigkill_wait(pid_t *pid);
int syslog_parse_priority(const char **p, int *priority, bool with_facility);
void cmsg_close_all(struct msghdr *mh);
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);

View file

@ -53,8 +53,8 @@ enum {
};
enum {
SD_EVENT_PASSIVE,
SD_EVENT_PREPARED,
SD_EVENT_INITIAL,
SD_EVENT_ARMED,
SD_EVENT_PENDING,
SD_EVENT_RUNNING,
SD_EVENT_EXITING,