diff options
author | Mark Bryars <mark@darkskiez.co.uk> | 2012-05-04 22:19:13 +0100 |
---|---|---|
committer | Mark Bryars <mark@darkskiez.co.uk> | 2012-05-04 22:19:13 +0100 |
commit | e756c7948078bd5109c5b8a0f252851efc4532d6 (patch) | |
tree | 39c4c6d660d7c377989e1adc1492ec198cdaa084 /nhrp/nhrp_interface.c | |
download | vyos-opennhrp-e756c7948078bd5109c5b8a0f252851efc4532d6.tar.gz vyos-opennhrp-e756c7948078bd5109c5b8a0f252851efc4532d6.zip |
Imported Upstream version 0.13
Diffstat (limited to 'nhrp/nhrp_interface.c')
-rw-r--r-- | nhrp/nhrp_interface.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/nhrp/nhrp_interface.c b/nhrp/nhrp_interface.c new file mode 100644 index 0000000..32c2383 --- /dev/null +++ b/nhrp/nhrp_interface.c @@ -0,0 +1,188 @@ +/* nhrp_interface.c - NHRP configuration per interface + * + * Copyright (C) 2007 Timo Teräs <timo.teras@iki.fi> + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 or later as + * published by the Free Software Foundation. + * + * See http://www.gnu.org/ for details. + */ + +#include <stdio.h> +#include <stddef.h> +#include <string.h> +#include <malloc.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/socket.h> +#include <linux/rtnetlink.h> +#include "nhrp_common.h" +#include "nhrp_interface.h" +#include "nhrp_address.h" + +#define NHRP_INDEX_HASH_SIZE (1 << 6) + +static struct list_head name_list = LIST_INITIALIZER(name_list); +static struct hlist_head index_hash[NHRP_INDEX_HASH_SIZE]; + +static char *env(const char *key, const char *value) +{ + char *buf; + buf = malloc(strlen(key)+strlen(value)+2); + if (buf == NULL) + return NULL; + sprintf(buf, "%s=%s", key, value); + return buf; +} + +static char *envu32(const char *key, uint32_t value) +{ + char *buf; + buf = malloc(strlen(key)+16); + if (buf == NULL) + return NULL; + sprintf(buf, "%s=%u", key, value); + return buf; +} + +void nhrp_interface_cleanup(void) +{ + struct nhrp_interface *iface, *n; + + list_for_each_entry_safe(iface, n, &name_list, name_list_entry) { + list_del(&iface->name_list_entry); + hlist_del(&iface->index_list_entry); + free(iface); + } +} + +void nhrp_interface_hash(struct nhrp_interface *iface) +{ + int iidx = iface->index & (NHRP_INDEX_HASH_SIZE - 1); + + list_del(&iface->name_list_entry); + list_add(&iface->name_list_entry, &name_list); + + hlist_del(&iface->index_list_entry); + hlist_add_head(&iface->index_list_entry, &index_hash[iidx]); +} + +int nhrp_interface_foreach(nhrp_interface_enumerator enumerator, void *ctx) +{ + struct nhrp_interface *iface; + int rc; + + list_for_each_entry(iface, &name_list, name_list_entry) { + rc = enumerator(ctx, iface); + if (rc != 0) + return rc; + } + return 0; +} + +struct nhrp_interface *nhrp_interface_get_by_name(const char *name, int create) +{ + struct nhrp_interface *iface; + + list_for_each_entry(iface, &name_list, name_list_entry) { + if (strcmp(iface->name, name) == 0) + return iface; + } + + if (!create) + return NULL; + + iface = calloc(1, sizeof(struct nhrp_interface)); + iface->holding_time = NHRP_DEFAULT_HOLDING_TIME; + iface->route_table = RT_TABLE_MAIN; + strncpy(iface->name, name, sizeof(iface->name)); + + list_init(&iface->peer_list); + list_init(&iface->mcast_list); + list_add(&iface->name_list_entry, &name_list); + hlist_add_head(&iface->index_list_entry, &index_hash[0]); + + return iface; +} + +struct nhrp_interface *nhrp_interface_get_by_index(unsigned int index, int create) +{ + struct nhrp_interface *iface; + struct hlist_node *n; + int iidx = index & (NHRP_INDEX_HASH_SIZE - 1); + + hlist_for_each_entry(iface, n, &index_hash[iidx], index_list_entry) { + if (iface->index == index) + return iface; + } + + return NULL; +} + +struct nhrp_interface *nhrp_interface_get_by_nbma(struct nhrp_address *addr) +{ + struct nhrp_interface *iface; + + list_for_each_entry(iface, &name_list, name_list_entry) { + if (!(iface->flags & NHRP_INTERFACE_FLAG_CONFIGURED)) + continue; + + if (nhrp_address_cmp(addr, &iface->nbma_address) == 0) + return iface; + + if (iface->nbma_address.type == PF_UNSPEC && !iface->link_index) + return iface; + } + + return NULL; +} + +struct nhrp_interface *nhrp_interface_get_by_protocol(struct nhrp_address *addr) +{ + struct nhrp_interface *iface; + + list_for_each_entry(iface, &name_list, name_list_entry) { + if (nhrp_address_cmp(addr, &iface->protocol_address) == 0) + return iface; + } + + return NULL; +} + +int nhrp_interface_run_script(struct nhrp_interface *iface, char *action) +{ + const char *argv[] = { nhrp_script_file, action, NULL }; + char *envp[6]; + pid_t pid; + int i = 0; + + pid = fork(); + if (pid == -1) + return FALSE; + if (pid > 0) + return TRUE; + + envp[i++] = "NHRP_TYPE=INTERFACE"; + envp[i++] = env("NHRP_INTERFACE", iface->name); + envp[i++] = envu32("NHRP_GRE_KEY", iface->gre_key); + envp[i++] = NULL; + + execve(nhrp_script_file, (char **) argv, envp); + exit(1); +} + +struct nhrp_peer *nhrp_interface_find_peer(struct nhrp_interface *iface, + const struct nhrp_address *nbma) +{ + unsigned int key = nhrp_address_hash(nbma) % NHRP_INTERFACE_NBMA_HASH_SIZE; + struct nhrp_peer *peer; + struct hlist_node *n; + + hlist_for_each_entry(peer, n, &iface->nbma_hash[key], nbma_hash_entry) { + if (nhrp_address_cmp(nbma, &peer->next_hop_address) == 0) + return peer; + } + return NULL; +} |