summaryrefslogtreecommitdiffstats
path: root/src/channel_udp.c
blob: 1c15b47ac291f78a36f042effb2c846613acf62c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 * (C) 2009 by Pablo Neira Ayuso <pablo@netfilter.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <stdlib.h>
#include <libnfnetlink/libnfnetlink.h>

#include "channel.h"
#include "udp.h"

static void
*channel_udp_open(void *conf)
{
	struct udp_channel *m;
	struct udp_conf *c = conf;

	m = calloc(sizeof(struct udp_channel), 1);
	if (m == NULL)
		return NULL;

	m->client = udp_client_create(c);
	if (m->client == NULL) {
		free(m);
		return NULL;
	}

	m->server = udp_server_create(c);
	if (m->server == NULL) {
		udp_client_destroy(m->client);
		free(m);
		return NULL;
	}
	return m;
}

static int
channel_udp_send(void *channel, const void *data, int len)
{
	struct udp_channel *m = channel;
	return udp_send(m->client, data, len);
}

static int
channel_udp_recv(void *channel, char *buf, int size)
{
	struct udp_channel *m = channel;
	return udp_recv(m->server, buf, size);
}

static void
channel_udp_close(void *channel)
{
	struct udp_channel *m = channel;
	udp_client_destroy(m->client);
	udp_server_destroy(m->server);
	free(m);
}

static int
channel_udp_get_fd(void *channel)
{
	struct udp_channel *m = channel;
	return udp_get_fd(m->server);
}

static void
channel_udp_stats(struct channel *c, int fd)
{
	struct udp_channel *m = c->data;
	char ifname[IFNAMSIZ], buf[512];
	int size;

	if_indextoname(c->channel_ifindex, ifname);
	size = udp_snprintf_stats(buf, sizeof(buf), ifname,
				    &m->client->stats, &m->server->stats);
	send(fd, buf, size, 0);
}

static void
channel_udp_stats_extended(struct channel *c, int active,
			     struct nlif_handle *h, int fd)
{
	struct udp_channel *m = c->data;
	char ifname[IFNAMSIZ], buf[512];
	const char *status;
	unsigned int flags;
	int size;

	if_indextoname(c->channel_ifindex, ifname);
	nlif_get_ifflags(h, c->channel_ifindex, &flags);
	/* 
	 * IFF_UP shows administrative status
	 * IFF_RUNNING shows carrier status
	 */
	if (flags & IFF_UP) {
		if (!(flags & IFF_RUNNING))
			status = "NO-CARRIER";
		else
			status = "RUNNING";
	} else {
		status = "DOWN";
	}
	size = udp_snprintf_stats2(buf, sizeof(buf),
				     ifname, status, active,
				     &m->client->stats,
				     &m->server->stats);
	send(fd, buf, size, 0);
}

struct channel_ops channel_udp = {
	.open		= channel_udp_open,
	.close		= channel_udp_close,
	.send		= channel_udp_send,
	.recv		= channel_udp_recv,
	.get_fd		= channel_udp_get_fd,
	.stats		= channel_udp_stats,
	.stats_extended = channel_udp_stats_extended,
};