/*
- * $Id: vip6-autod.c,v 1.2 2007/07/26 19:00:23 dhozac Exp $
+ * $Id: vip6-autod.c,v 1.4 2007/07/30 14:59:11 dhozac Exp $
* Copyright (c) 2007 The Trustees of Princeton University
* Author: Daniel Hokka Zakrisson <daniel@hozac.com>
*
* version 2 or later.
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
+#include <syslog.h>
#include <asm/types.h>
/* not defined for gcc -ansi */
#include <netlink/netlink.h>
#include <netlink/route/addr.h>
-typedef unsigned int nid_t;
-typedef unsigned int xid_t;
#include <vserver.h>
+#include "pathconfig.h"
#define HAS_ADDRESS 0x01
#define HAS_PREFIX 0x02
return err;
}
-static int add_nid_to_list(struct prefix_list *i, nid_t nid)
+static int add_nid_to_list(struct nid_list **l, nid_t nid)
{
struct nid_list *n;
+ for (n = *l; n; n = n->next) {
+ if (n->nid == nid)
+ return 0;
+ }
n = calloc(1, sizeof(struct nid_list));
if (!n)
return -1;
n->nid = nid;
- n->next = i->nids;
- i->nids = n;
- return 0;
+ n->next = *l;
+ *l = n;
+ return 1;
}
static void cleanup_prefix(struct prefix_list *i)
{
- struct nid_list *n;
+ struct nid_list *n, *p = NULL;
for (n = i->nids; n; n = n->next) {
struct rtnl_addr *rta;
struct nl_addr *nl;
struct in6_addr a;
+ if (p)
+ free(p);
memcpy(&a, &i->address.addr, sizeof(a));
rta = rtnl_addr_alloc();
nl = nl_addr_build(AF_INET6, &a, sizeof(a));
nl_addr_destroy(nl);
rtnl_addr_free(rta);
+
+ p = n;
}
+ if (p)
+ free(p);
}
static void do_slices_autoconf(struct prefix_list *head)
nid_t nid;
struct vc_net_nx addr;
struct prefix_list *i;
+ struct nid_list *current = NULL, *n;
if ((dp = opendir("/proc/virtnet")) == NULL)
return;
addr.type = vcNET_IPV6A;
addr.count = 0;
if (vc_net_remove(nid, &addr) == -1) {
- perror("vc_net_remove");
+ syslog(LOG_ERR, "vc_net_remove(%u): %s", nid, strerror(errno));
continue;
}
+ add_nid_to_list(¤t, nid);
+
for (i = head->next; i;) {
/* expired */
if (i->mask & HAS_PREFIX && i->prefix.valid_until < time(NULL)) {
char buf[64];
inet_ntop(AF_INET6, &i->address.addr, buf, sizeof(buf));
- printf("Address %s timed out.\n", buf);
+ syslog(LOG_NOTICE, "Address %s timed out", buf);
if (i->next)
i->next->prev = i->prev;
if (i->mask != (HAS_ADDRESS|HAS_PREFIX))
goto next;
+ addr.type = vcNET_IPV6;
addr.count = 1;
addr.mask[0] = i->prefix.prefix_len;
memcpy(addr.ip, &i->address.addr, sizeof(struct in6_addr));
- addr.ip[2] = htonl((ntohl(addr.ip[2]) & 0xffffff00) | ((nid & 0x7f00) >> 7));
- addr.ip[3] = htonl((ntohl(addr.ip[3]) & 0x00ffffff) | ((nid & 0xff) << 25));
+ addr.ip[2] = htonl((ntohl(addr.ip[2]) & 0xffffff00) | ((nid & 0x7f80) >> 7));
+ addr.ip[3] = htonl((ntohl(addr.ip[3]) & 0x00ffffff) | ((nid & 0x7f) << 25));
if (vc_net_add(nid, &addr) == -1) {
- perror("vc_net_add");
- exit(1);
+ syslog(LOG_ERR, "vc_net_add(%u): %s", nid, strerror(errno));
+ goto next;
}
if (add_address_to_interface(i->ifindex, (struct in6_addr *) addr.ip, i->prefix.prefix_len) == -1) {
- perror("add_address_to_interface");
- exit(1);
+ syslog(LOG_ERR, "add_address_to_interface: %s", strerror(errno));
+ goto next;
}
- if (add_nid_to_list(i, nid) == -1) {
- perror("add_nid_to_list");
- exit(1);
+ if (add_nid_to_list(&i->nids, nid) == -1) {
+ syslog(LOG_ERR, "add_nid_to_list: %s", strerror(errno));
+ goto next;
}
next:
i = i->next;
struct nlattr *tb[PREFIX_MAX+1];
if (nlmsg_parse(nlh, sizeof(struct prefixmsg), tb, PREFIX_MAX, prefix_policy) < 0) {
- printf("Failed to parse prefixmsg.\n");
+ syslog(LOG_ERR, "Failed to parse prefixmsg");
return -1;
}
struct nlattr *tb[IFA_MAX+1];
if (nlmsg_parse(nlh, sizeof(struct ifaddrmsg), tb, IFA_MAX, addr_policy) < 0) {
- printf("Failed to parse ifaddrmsg.\n");
+ syslog(LOG_ERR, "Failed to parse ifaddrmsg");
return -1;
}
int handle_error_msg(struct sockaddr_nl *source, struct nlmsgerr *err,
void *arg)
{
- perror("Got an error");
+ syslog(LOG_ERR, "%s", strerror(err->error));
return 0;
}
}
}
+static int write_pidfile(const char *filename)
+{
+ FILE *fp;
+ fp = fopen(filename, "w");
+ if (!fp)
+ return -1;
+ fprintf(fp, "%d\n", getpid());
+ fclose(fp);
+ return 0;
+}
+
int main(int argc, char *argv[])
{
struct nl_cb *cbs;
-
head.prev = head.next = NULL;
- signal(SIGUSR1, signal_handler);
+
+ openlog("vip6-autod", LOG_PERROR, LOG_DAEMON);
handle = nl_handle_alloc_nondefault(NL_CB_VERBOSE);
cbs = nl_handle_get_cb(handle);
nl_join_groups(handle, RTMGRP_IPV6_PREFIX|RTMGRP_IPV6_IFADDR);
if (nl_connect(handle, NETLINK_ROUTE) == -1) {
- perror("nl_connect");
+ syslog(LOG_CRIT, "nl_connect: %s", strerror(errno));
exit(1);
}
+ if (daemon(0, 0) == -1)
+ return -1;
+
+ /* XXX .. here is a hack */
+ write_pidfile(DEFAULT_PKGSTATEDIR "/../vip6-autod.pid");
+
+ signal(SIGUSR1, signal_handler);
+
while (nl_recvmsgs(handle, cbs) > 0);
nl_close(handle);
+ closelog();
return 0;
}