Add support for mdp clients to provide a link layer packet transport

This commit is contained in:
Jeremy Lakeman 2015-03-02 15:41:07 +10:30
parent 3ae0e95e0b
commit a9b9f51a9f
11 changed files with 460 additions and 139 deletions

View File

@ -760,6 +760,10 @@ int cf_opt_socket_type(short *typep, const char *text)
*typep = SOCK_FILE;
return CFOK;
}
if (strcasecmp(text, "external") == 0) {
*typep = SOCK_EXT;
return CFOK;
}
return CFINVALID;
}
@ -1018,7 +1022,7 @@ int vld_network_interface(const struct cf_om_node *parent, struct config_network
return result | CFINCOMPLETE;
}
} else {
if (nifp->socket_type != SOCK_DGRAM && !nifp->file[0]){
if (nifp->socket_type != SOCK_DGRAM && nifp->socket_type != SOCK_EXT && !nifp->file[0]){
cf_warn_missing_node(parent, "file");
return result | CFSUB(CFINCOMPATIBLE);
}

View File

@ -184,6 +184,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// force state packet interval
#define VOMP_CALL_STATUS_INTERVAL 1000
// mdp client interface
#define SOCK_EXT 0xFE
// dummy file interface
#define SOCK_FILE 0xFF
#define SOCK_UNSPECIFIED 0

View File

@ -24,12 +24,13 @@ import java.lang.StringBuilder;
public class Base64 {
public static final char[] SYMBOLS = {
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
'='
public static final char[] SYMBOLS;
public static final String charSet="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static{
char chars[] = new char[64];
for (int i=0;i<chars.length;i++)
chars[i]=charSet.charAt(i);
SYMBOLS=chars;
};
public static String encode(byte[] binary)
@ -38,20 +39,19 @@ public class Base64 {
int place = 0;
byte buf = 0;
for (byte b: binary) {
switch (place) {
int val = b&0xFF;
switch (place++) {
case 0:
sb.append(SYMBOLS[b >>> 2]);
buf = (byte)((b << 4) & 0x3f);
place = 1;
sb.append(SYMBOLS[val >>> 2]);
buf = (byte)((val << 4) & 0x3f);
break;
case 1:
sb.append(SYMBOLS[(b >>> 4) | buf]);
buf = (byte)((b << 2) & 0x3f);
place = 2;
sb.append(SYMBOLS[(val >>> 4) | buf]);
buf = (byte)((val << 2) & 0x3f);
break;
case 2:
sb.append(SYMBOLS[(b >>> 6) | buf]);
sb.append(SYMBOLS[b & 0x3f]);
sb.append(SYMBOLS[(val >>> 6) | buf]);
sb.append(SYMBOLS[val & 0x3f]);
place = 0;
break;
}
@ -60,11 +60,47 @@ public class Base64 {
sb.append(SYMBOLS[buf]);
switch (place) {
case 1:
sb.append(SYMBOLS[64]);
sb.append('=');
case 2:
sb.append(SYMBOLS[64]);
sb.append('=');
}
return sb.toString();
}
public static byte[] decode(String value)
{
int len = value.length()/4 * 3;
if (value.endsWith("=="))
len -=2;
else if(value.endsWith("="))
len --;
byte ret[] = new byte[len];
int pos=0;
for (int i=0;i<value.length();i++){
if (value.charAt(i)=='=')
break;
int val = charSet.indexOf(value.charAt(i));
if (val<0)
return null;
switch(i%4){
case 0:
ret[pos] = (byte) (val<<2);
break;
case 1:
ret[pos++] |= (byte) ((val>>4)&0x03);
if (pos>=ret.length) break;
ret[pos] = (byte) (val<<4);
break;
case 2:
ret[pos++] |= (byte) ((val>>2)&0x0F);
if (pos>=ret.length) break;
ret[pos] = (byte) (val<<6);
break;
case 3:
ret[pos++] |= (byte) (val & 0x3f);
break;
}
}
return ret;
}
}

View File

@ -0,0 +1,97 @@
package org.servalproject.servaldna;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
/**
* Created by jeremy on 8/05/14.
*/
public abstract class AbstractExternalInterface extends ChannelSelector.Handler {
private final ChannelSelector selector;
protected final MdpSocket socket;
public AbstractExternalInterface(ChannelSelector selector, int loopbackMdpPort) throws IOException {
this.socket = new MdpSocket(loopbackMdpPort);
this.selector = selector;
selector.register(this);
}
public void close(){
try {
selector.unregister(this);
} catch (IOException e) {
e.printStackTrace();
}
socket.close();
}
private static final int MDP_INTERFACE=4;
private static final int MDP_INTERFACE_UP=0;
private static final int MDP_INTERFACE_DOWN=1;
private static final int MDP_INTERFACE_RECV=2;
public void up(String config) throws IOException {
MdpPacket packet = new MdpPacket();
packet.setRemotePort(MDP_INTERFACE);
packet.payload.put((byte) MDP_INTERFACE_UP);
packet.payload.put(config.getBytes());
packet.payload.flip();
packet.send((DatagramChannel)socket.getChannel());
}
public void down() throws IOException {
MdpPacket packet = new MdpPacket();
packet.setRemotePort(MDP_INTERFACE);
packet.payload.put((byte) MDP_INTERFACE_DOWN);
packet.payload.flip();
packet.send((DatagramChannel) socket.getChannel());
}
public void receivedPacket(byte recvaddr[], byte recvbytes[]) throws IOException {
receivedPacket(recvaddr, recvbytes, 0, recvbytes==null?0:recvbytes.length);
}
public void receivedPacket(byte recvaddr[], byte recvbytes[], int offset, int len) throws IOException {
MdpPacket packet = new MdpPacket();
packet.setRemotePort(MDP_INTERFACE);
packet.payload.put((byte) MDP_INTERFACE_RECV);
packet.payload.put((byte) recvaddr.length);
packet.payload.put(recvaddr);
if (len>0)
packet.payload.put(recvbytes, offset, len);
packet.payload.flip();
packet.send((DatagramChannel) socket.getChannel());
}
protected abstract void sendPacket(byte addr[], ByteBuffer payload);
@Override
public void read() {
try {
MdpPacket response = new MdpPacket();
socket.receive(response);
int addrlen = response.payload.get() & 0xFF;
byte addr[]=null;
if (addrlen>0) {
addr = new byte[addrlen];
response.payload.get(addr);
}
sendPacket(addr, response.payload);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public SelectableChannel getChannel() throws IOException {
return socket.getChannel();
}
@Override
public int getInterest() {
return SelectionKey.OP_READ;
}
}

View File

@ -89,6 +89,17 @@ struct mdp_identity_request {
*/
#define MDP_SYNC_CONFIG 3
/* External interface implementation
*
* Messages used for talking to a client application that implements a network
* interface that isn't based on simple file descriptors
* eg android bluetooth & wifi-direct
*/
#define MDP_INTERFACE 4
#define MDP_INTERFACE_UP 0
#define MDP_INTERFACE_DOWN 1
#define MDP_INTERFACE_RECV 2
struct overlay_route_record{
sid_t sid;
char interface_name[256];

View File

@ -59,22 +59,27 @@ struct profile_total sock_any_stats;
static void overlay_interface_poll(struct sched_ent *alarm);
static void
overlay_interface_close(overlay_interface *interface){
void overlay_interface_close(overlay_interface *interface)
{
if (interface->alarm.poll.fd>=0){
if (interface->address.addr.sa_family == AF_UNIX)
unlink(interface->address.local.sun_path);
if (is_watching(&interface->alarm))
unwatch(&interface->alarm);
close(interface->alarm.poll.fd);
interface->alarm.poll.fd=-1;
}
unschedule(&interface->alarm);
if (interface->radio_link_state)
radio_link_free(interface);
interface->state=INTERFACE_STATE_DOWN;
monitor_tell_formatted(MONITOR_INTERFACE, "\nINTERFACE:%s:DOWN\n", interface->name);
INFOF("Interface %s addr %s is down",
interface->name, alloca_socket_address(&interface->address));
if (interface->address.addr.sa_family == AF_UNIX)
unlink(interface->address.local.sun_path);
link_interface_down(interface);
unschedule(&interface->alarm);
if (is_watching(&interface->alarm))
unwatch(&interface->alarm);
close(interface->alarm.poll.fd);
if (interface->radio_link_state)
radio_link_free(interface);
interface->alarm.poll.fd=-1;
interface->state=INTERFACE_STATE_DOWN;
}
void overlay_interface_close_all()
@ -134,6 +139,12 @@ void interface_state_html(struct strbuf *b, struct overlay_interface *interface)
case SOCK_FILE:
strbuf_puts(b, "Socket: File<br>");
break;
case SOCK_EXT:
{
strbuf_puts(b, "Socket: External<br>");
strbuf_sprintf(b, "Client: %s<br>", alloca_socket_address(&interface->address));
}
break;
}
strbuf_sprintf(b, "TX: %d<br>", interface->tx_count);
strbuf_sprintf(b, "RX: %d<br>", interface->recv_count);
@ -268,6 +279,22 @@ overlay_interface * overlay_interface_find_name(const char *name){
return NULL;
}
// find an interface by name and address
overlay_interface * overlay_interface_find_name_addr(const char *name, struct socket_address *addr){
int i;
for(i = 0; i < OVERLAY_MAX_INTERFACES; i++){
if (overlay_interfaces[i].state==INTERFACE_STATE_DOWN)
continue;
if (cmp_sockaddr(addr, &overlay_interfaces[i].address)==0
&& (!name || strcasecmp(overlay_interfaces[i].name, name)==0)){
return &overlay_interfaces[i];
}
}
return NULL;
}
static int interface_type_priority(int type)
{
switch(type){
@ -405,61 +432,28 @@ overlay_interface_init_socket(overlay_interface *interface)
return 0;
}
/* Returns 0 if interface is successfully added.
* Returns 1 if interface is not added (eg, dummy file does not exist).
* Returns -1 in case of error (misconfiguration or system error).
*/
static int
overlay_interface_init(const char *name, struct socket_address *addr,
struct socket_address *netmask,
struct socket_address *broadcast,
const struct config_network_interface *ifconfig)
int overlay_interface_configure(struct overlay_interface *interface, const struct config_network_interface *ifconfig)
{
int cleanup_ret = -1;
int interface_id=-1;
int i;
for (i=0; i<OVERLAY_MAX_INTERFACES; i++){
if (overlay_interfaces[i].state==INTERFACE_STATE_DOWN){
interface_id=i;
break;
}
}
if (interface_id==-1)
return WHY("Too many interfaces -- Increase OVERLAY_MAX_INTERFACES");
overlay_interface *const interface = &overlay_interfaces[interface_id];
bzero(interface, sizeof(overlay_interface));
interface->state=INTERFACE_STATE_DOWN;
strncpy(interface->name, name, sizeof interface->name);
// copy ifconfig values
interface->drop_broadcasts = ifconfig->drop_broadcasts;
interface->drop_unicasts = ifconfig->drop_unicasts;
interface->drop_packets = ifconfig->drop_packets;
interface->port = ifconfig->port;
interface->type = ifconfig->type;
interface->send_broadcasts = ifconfig->send_broadcasts;
interface->dont_route = ifconfig->dont_route;
interface->prefer_unicast = ifconfig->prefer_unicast;
interface->default_route = ifconfig->default_route;
interface->destination->encapsulation = ifconfig->encapsulation;
interface->port = ifconfig->port;
interface->socket_type = ifconfig->socket_type;
interface->uartbps = ifconfig->uartbps;
interface->ctsrts = ifconfig->ctsrts;
set_destination_ref(&interface->destination, NULL);
interface->destination = new_destination(interface, ifconfig->encapsulation);
interface->point_to_point = ifconfig->point_to_point;
interface->debug = ifconfig->debug;
/* Pick a reasonable default MTU.
This will ultimately get tuned by the bandwidth and other properties of the interface */
interface->mtu = 1200;
interface->point_to_point = ifconfig->point_to_point;
interface->alarm.poll.fd=0;
interface->debug = ifconfig->debug;
interface->tx_count=0;
interface->recv_count=0;
// How often do we announce ourselves on this interface?
int tick_ms=-1;
int packet_interval=-1;
@ -505,72 +499,125 @@ overlay_interface_init(const char *name, struct socket_address *addr,
reachable_timeout_ms = ifconfig->mdp.reachable_timeout_ms;
if (packet_interval<0)
return WHYF("Invalid packet interval %d specified for interface %s", packet_interval, name);
return WHYF("Invalid packet interval %d specified for interface %s", packet_interval, interface->name);
if (packet_interval==0){
INFOF("Interface %s is not sending any traffic!", name);
INFOF("Interface %s is not sending any traffic!", interface->name);
tick_ms=0;
}else if (!interface->send_broadcasts){
INFOF("Interface %s is not sending any broadcast traffic!", name);
INFOF("Interface %s is not sending any broadcast traffic!", interface->name);
}else if (tick_ms==0)
INFOF("Interface %s is running tickless", name);
INFOF("Interface %s is running tickless", interface->name);
if (tick_ms<0)
return WHYF("No tick interval specified for interface %s", name);
return WHYF("No tick interval specified for interface %s", interface->name);
interface->destination->tick_ms = tick_ms;
interface->destination->reachable_timeout_ms = reachable_timeout_ms >= 0 ? reachable_timeout_ms : tick_ms > 0 ? tick_ms * 5 : 2500;
limit_init(&interface->destination->transfer_limit, packet_interval);
return 0;
}
/* Returns 0 if interface is successfully added.
* Returns 1 if interface is not added (eg, dummy file does not exist).
* Returns -1 in case of error (misconfiguration or system error).
*/
int
overlay_interface_init(const char *name, struct socket_address *addr,
struct socket_address *netmask,
struct socket_address *broadcast,
const struct config_network_interface *ifconfig)
{
int cleanup_ret = -1;
int interface_id=-1;
int i;
for (i=0; i<OVERLAY_MAX_INTERFACES; i++){
if (overlay_interfaces[i].state==INTERFACE_STATE_DOWN){
interface_id=i;
break;
}
}
if (interface_id==-1)
return WHY("Too many interfaces -- Increase OVERLAY_MAX_INTERFACES");
overlay_interface *const interface = &overlay_interfaces[interface_id];
bzero(interface, sizeof(overlay_interface));
interface->state=INTERFACE_STATE_DOWN;
strncpy(interface->name, name, sizeof interface->name);
set_destination_ref(&interface->destination, NULL);
interface->destination = new_destination(interface);
if (overlay_interface_configure(interface, ifconfig)==-1)
return -1;
interface->alarm.poll.fd=0;
interface->tx_count=0;
interface->recv_count=0;
if (addr)
interface->address = *addr;
if (broadcast)
interface->destination->address = *broadcast;
interface->alarm.function = overlay_interface_poll;
interface_poll_stats.name="overlay_interface_poll";
interface->alarm.stats=&interface_poll_stats;
if (ifconfig->socket_type == SOCK_DGRAM){
if (ifconfig->drop_broadcasts || ifconfig->drop_unicasts || ifconfig->drop_packets)
FATALF("Invalid interface definition. We only support dropping packets on dummy file interfaces");
if (netmask)
interface->netmask = netmask->inet.sin_addr;
else
interface->netmask = ifconfig->dummy_netmask;
interface->local_echo = 1;
if (overlay_interface_init_socket(interface))
return WHY("overlay_interface_init_socket() failed");
}else{
char read_file[1024];
interface->local_echo = interface->point_to_point?0:1;
if (!FORMF_SERVAL_TMP_PATH(read_file, "%s/%s", config.server.interface_path, ifconfig->file))
return -1;
if ((interface->alarm.poll.fd = open(read_file, O_APPEND|O_RDWR)) == -1) {
if (errno == ENOENT && ifconfig->socket_type == SOCK_FILE) {
cleanup_ret = 1;
WARNF("dummy interface not enabled: %s does not exist", alloca_str_toprint(read_file));
} else {
cleanup_ret = WHYF_perror("file interface not enabled: open(%s, O_APPEND|O_RDWR)", alloca_str_toprint(read_file));
}
goto cleanup;
}
if (ifconfig->type==OVERLAY_INTERFACE_PACKETRADIO)
overlay_packetradio_setup_port(interface);
switch (ifconfig->socket_type) {
switch(ifconfig->socket_type){
case SOCK_DGRAM:
if (ifconfig->drop_broadcasts || ifconfig->drop_unicasts || ifconfig->drop_packets)
FATALF("Invalid interface definition. We only support dropping packets on dummy file interfaces");
if (netmask)
interface->netmask = netmask->inet.sin_addr;
else
interface->netmask = ifconfig->dummy_netmask;
interface->local_echo = 1;
if (overlay_interface_init_socket(interface))
return WHY("overlay_interface_init_socket() failed");
break;
case SOCK_EXT:
interface->local_echo = 0;
interface->alarm.poll.fd = -1;
break;
case SOCK_STREAM:
radio_link_init(interface);
interface->alarm.poll.events=POLLIN|POLLOUT;
watch(&interface->alarm);
break;
case SOCK_FILE:
/* Seek to end of file as initial reading point */
interface->recv_offset = lseek(interface->alarm.poll.fd,0,SEEK_END);
break;
{
char read_file[1024];
interface->local_echo = interface->point_to_point?0:1;
if (!FORMF_SERVAL_TMP_PATH(read_file, "%s/%s", config.server.interface_path, ifconfig->file))
return -1;
if ((interface->alarm.poll.fd = open(read_file, O_APPEND|O_RDWR)) == -1) {
if (errno == ENOENT && ifconfig->socket_type == SOCK_FILE) {
cleanup_ret = 1;
WARNF("dummy interface not enabled: %s does not exist", alloca_str_toprint(read_file));
} else {
cleanup_ret = WHYF_perror("file interface not enabled: open(%s, O_APPEND|O_RDWR)", alloca_str_toprint(read_file));
}
goto cleanup;
}
if (ifconfig->type==OVERLAY_INTERFACE_PACKETRADIO)
overlay_packetradio_setup_port(interface);
switch (ifconfig->socket_type) {
case SOCK_STREAM:
radio_link_init(interface);
interface->alarm.poll.events=POLLIN|POLLOUT;
watch(&interface->alarm);
break;
case SOCK_FILE:
/* Seek to end of file as initial reading point */
interface->recv_offset = lseek(interface->alarm.poll.fd,0,SEEK_END);
break;
}
}
}
@ -786,6 +833,7 @@ static void overlay_interface_poll(struct sched_ent *alarm)
radio_link_tx(interface);
return;
case SOCK_DGRAM:
case SOCK_EXT:
break;
case SOCK_FILE:
interface_read_file(interface);
@ -808,6 +856,7 @@ static void overlay_interface_poll(struct sched_ent *alarm)
case SOCK_STREAM:
radio_link_tx(interface);
return;
case SOCK_EXT:
case SOCK_DGRAM:
case SOCK_FILE:
//XXX error? fatal?
@ -831,6 +880,8 @@ static void overlay_interface_poll(struct sched_ent *alarm)
case SOCK_FILE:
interface_read_file(interface);
break;
case SOCK_EXT:
break;
}
}
@ -903,9 +954,11 @@ int overlay_broadcast_ensemble(struct network_destination *destination, struct o
return WHYF("Cannot send to interface %s as it is down", interface->name);
}
if (interface->debug)
DEBUGF("Sending on %s, len %zu: %s", interface->name, len, alloca_tohex(bytes, len>64?64:len));
if (config.debug.overlayinterfaces || interface->debug)
DEBUGF("Sending %zu byte overlay frame on %s to %s [%s]",
(size_t)len, interface->name, alloca_socket_address(&destination->address),
alloca_tohex(bytes, len>64?64:len));
interface->tx_count++;
switch(interface->socket_type){
@ -960,13 +1013,14 @@ int overlay_broadcast_ensemble(struct network_destination *destination, struct o
return WHYF("only wrote %d of %d bytes", (int)nwrite, (int)sizeof(packet));
return 0;
}
case SOCK_EXT:
{
mdp_send_external_packet(interface, &destination->address, bytes, (size_t)len);
ob_free(buffer);
return 0;
}
case SOCK_DGRAM:
{
if (config.debug.overlayinterfaces)
DEBUGF("Sending %zu byte overlay frame on %s to %s",
(size_t)len, interface->name, alloca_socket_address(&destination->address));
set_nonblock(interface->alarm.poll.fd);
if (destination->address.addr.sa_family == AF_UNIX
&& !destination->unicast){
@ -1051,20 +1105,12 @@ overlay_interface_register(char *name,
DEBUGF("%s broadcast address: %s", name, alloca_socket_address(broadcast));
}
/* Search in the exist list of interfaces */
for(i = 0; i < OVERLAY_MAX_INTERFACES; i++){
if (overlay_interfaces[i].state==INTERFACE_STATE_DOWN)
continue;
if (strcasecmp(overlay_interfaces[i].name, name)==0
&& cmp_sockaddr(addr, &overlay_interfaces[i].address)==0){
// mark this interface as still alive
if (overlay_interfaces[i].state==INTERFACE_STATE_DETECTING)
overlay_interfaces[i].state=INTERFACE_STATE_UP;
return 0;
}
struct overlay_interface *interface = overlay_interface_find_name_addr(name, addr);
if (interface){
// mark this interface as still alive
if (interface->state == INTERFACE_STATE_DETECTING)
interface->state = INTERFACE_STATE_UP;
return 0;
}
/* New interface, so register it */
@ -1135,6 +1181,9 @@ void overlay_interface_discover(struct sched_ent *alarm)
case SOCK_STREAM:
overlay_interface_init(ifconfig->file, &addr, NULL, &broadcast, ifconfig);
break;
case SOCK_EXT:
// FAIL?
break;
case SOCK_DGRAM:
{
// use a local dgram socket

View File

@ -143,7 +143,7 @@ typedef struct overlay_interface {
*/
extern overlay_interface overlay_interfaces[OVERLAY_MAX_INTERFACES];
struct network_destination * new_destination(struct overlay_interface *interface, char encapsulation);
struct network_destination * new_destination(struct overlay_interface *interface);
struct network_destination * create_unicast_destination(struct socket_address *addr, struct overlay_interface *interface);
struct network_destination * add_destination_ref(struct network_destination *ref);
void release_destination_ref(struct network_destination *ref);
@ -151,6 +151,15 @@ int set_destination_ref(struct network_destination **ptr, struct network_destina
DECLARE_ALARM(overlay_interface_discover);
struct config_network_interface;
int overlay_interface_configure(struct overlay_interface *interface, const struct config_network_interface *ifconfig);
int
overlay_interface_init(const char *name, struct socket_address *addr,
struct socket_address *netmask,
struct socket_address *broadcast,
const struct config_network_interface *ifconfig);
void overlay_interface_close(overlay_interface *interface);
int overlay_interface_register(char *name,
struct socket_address *addr,
struct socket_address *netmask,
@ -159,6 +168,7 @@ void overlay_interface_close_all();
overlay_interface * overlay_interface_get_default();
overlay_interface * overlay_interface_find(struct in_addr addr, int return_default);
overlay_interface * overlay_interface_find_name(const char *name);
overlay_interface * overlay_interface_find_name_addr(const char *name, struct socket_address *addr);
int overlay_interface_compare(overlay_interface *one, overlay_interface *two);
int overlay_broadcast_ensemble(struct network_destination *destination, struct overlay_buffer *buffer);
void interface_state_html(struct strbuf *b, struct overlay_interface *interface);

View File

@ -1110,7 +1110,7 @@ static int search_subscribers(struct subscriber *subscriber, void *context){
return 0;
}
int overlay_mdp_address_list(struct overlay_mdp_addrlist *request, struct overlay_mdp_addrlist *response)
static int overlay_mdp_address_list(struct overlay_mdp_addrlist *request, struct overlay_mdp_addrlist *response)
{
if (config.debug.mdprequests)
DEBUGF("MDP_GETADDRS first_sid=%u mode=%d", request->first_sid, request->mode);
@ -1340,6 +1340,110 @@ static int mdp_search_identities(struct socket_address *client, struct mdp_heade
return 0;
}
const char *external_name="ext"; // TODO?
int mdp_send_external_packet(struct overlay_interface *interface, struct socket_address *address, const uint8_t *payload, size_t len)
{
struct mdp_header header;
bzero(&header, sizeof header);
header.remote.port = MDP_INTERFACE;
uint8_t addrlen = address->addrlen;
struct iovec iov[]={
{
.iov_base = (void *)&header,
.iov_len = sizeof(struct mdp_header)
},
{
.iov_base = (void *)&addrlen,
.iov_len = sizeof addrlen
},
{
.iov_base = (void *)&address->raw,
.iov_len = addrlen
},
{
.iov_base = (void *)payload,
.iov_len = len
}
};
struct msghdr hdr={
.msg_name=&interface->address.addr,
.msg_namelen=interface->address.addrlen,
.msg_iov=iov,
.msg_iovlen=4,
};
int fd=-1;
switch(interface->address.addr.sa_family){
case AF_UNIX:
fd = mdp_sock2.poll.fd;
break;
case AF_INET:
fd = mdp_sock2_inet.poll.fd;
break;
}
if (fd==-1)
return WHYF("Unhandled client family %d", interface->address.addr.sa_family);
if (sendmsg(fd, &hdr, 0)<0)
return WHY_perror("sendmsg");
return 0;
}
static void mdp_interface_packet(struct socket_address *client, struct mdp_header *UNUSED(header),
struct overlay_buffer *payload){
int msg_type = ob_get(payload);
switch (msg_type){
case MDP_INTERFACE_UP:{
struct config_network_interface ifconfig;
cf_dfl_config_network_interface(&ifconfig);
struct cf_om_node *conf_node = NULL;
int result = cf_om_parse(external_name, (char*)ob_current_ptr(payload), ob_remaining(payload), &conf_node);
if (result == CFOK || result == CFEMPTY){
result = conf_node ? cf_opt_config_network_interface(&ifconfig, conf_node) : CFEMPTY;
}
if (result == CFOK || result == CFEMPTY){
if (ifconfig.socket_type != SOCK_EXT){
// TODO log nice warning, pick right result code
result |= CFSUB(CFUNSUPPORTED);
}
}
if (result == CFOK || result == CFEMPTY){
struct overlay_interface *interface=overlay_interface_find_name_addr(external_name, client);
if (!interface){
overlay_interface_init(external_name, client, NULL, NULL, &ifconfig);
}else{
if (overlay_interface_configure(interface, &ifconfig)==-1)
overlay_interface_close(interface);
}
}
}break;
case MDP_INTERFACE_DOWN:{
struct overlay_interface *interface=overlay_interface_find_name_addr(external_name, client);
if (interface)
overlay_interface_close(interface);
}break;
case MDP_INTERFACE_RECV:{
struct overlay_interface *interface=overlay_interface_find_name_addr(external_name, client);
if (interface){
struct socket_address addr;
addr.addrlen = ob_get(payload);
if (addr.addrlen > sizeof(addr))
break; // TODO errors
bcopy(ob_get_bytes_ptr(payload, addr.addrlen), addr.raw, addr.addrlen);
packetOkOverlay(interface, ob_current_ptr(payload), ob_remaining(payload), &addr);
}
break;
}
}
}
static void mdp_process_packet(struct socket_address *client, struct mdp_header *header,
struct overlay_buffer *payload)
{
@ -1485,6 +1589,11 @@ static void mdp_process_packet(struct socket_address *client, struct mdp_header
server_config_reload(NULL);
mdp_reply_ok(client, header);
break;
case MDP_INTERFACE:
if (config.debug.mdprequests)
DEBUGF("Processing MDP_INTERFACE from %s", alloca_socket_address(client));
mdp_interface_packet(client, header, payload);
break;
default:
WHYF("Unknown command port %d", header->remote.port);
mdp_reply_error(client, header);

View File

@ -172,12 +172,11 @@ static int neighbour_find_best_link(struct neighbour *n);
struct neighbour *neighbours=NULL;
int route_version=0;
struct network_destination * new_destination(struct overlay_interface *interface, char encapsulation){
struct network_destination * new_destination(struct overlay_interface *interface){
assert(interface);
struct network_destination *ret = emalloc_zero(sizeof(struct network_destination));
if (ret){
ret->_ref_count=1;
ret->encapsulation = encapsulation;
ret->interface = interface;
ret->resend_delay = 1000;
ret->last_tx = TIME_MS_NEVER_HAS;
@ -201,8 +200,9 @@ struct network_destination * create_unicast_destination(struct socket_address *a
if (addr->addr.sa_family == AF_INET && (addr->inet.sin_addr.s_addr==0 || addr->inet.sin_port==0))
return NULL;
struct network_destination *ret = new_destination(interface, ENCAP_OVERLAY);
struct network_destination *ret = new_destination(interface);
if (ret){
ret->encapsulation = ENCAP_OVERLAY;
ret->address = *addr;
ret->unicast = 1;
ret->tick_ms = interface->destination->tick_ms;

View File

@ -174,6 +174,7 @@ struct overlay_frame;
struct broadcast;
void overlay_mdp_clean_socket_files();
int mdp_send_external_packet(struct overlay_interface *interface, struct socket_address *address, const uint8_t *payload, size_t len);
int overlay_forward_payload(struct overlay_frame *f);
int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, size_t len,

View File

@ -41,6 +41,7 @@ struct socket_address{
struct sockaddr_un local; // name "unix" is a predefined macro
struct sockaddr_in inet;
struct sockaddr_storage store;
uint8_t raw[255];
};
};