File: vde_plug_iplog.c

package info (click to toggle)
vdeplug4 4.0.1-5.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 464 kB
  • sloc: ansic: 4,280; makefile: 19
file content (138 lines) | stat: -rw-r--r-- 3,669 bytes parent folder | download | duplicates (3)
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* 
 * Copyright (C) 2002-2016  Renzo Davoli, University of Bologna
 * Modified by Ludovico Gardenghi 2005
 * 
 * iplog: log unique IP addresses seen on a line
 *
 * VDE 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.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; If not, see <http://www.gnu.org/licenses/>. 
 *
 */

#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <arpa/inet.h>
#include <vde_plug_log.h>
#define ETH_ALEN 6

struct header {
	unsigned char dest[ETH_ALEN];
	unsigned char src[ETH_ALEN];
	unsigned char proto[2];
};

union body {
	struct {
		unsigned char version;
		unsigned char filler[11];
		unsigned char ip4src[4];
		unsigned char ip4dst[4];
	} v4;
	struct {
		unsigned char version;
		unsigned char filler[7];
		unsigned char ip6src[16];
		unsigned char ip6dst[16];
	} v6;
	struct {
		unsigned char priovlan[2];
	} vlan;
};

struct addrelem {
	struct addrelem *next;
	unsigned int len;
	char addr[];
};

static unsigned long hash(unsigned int len, unsigned char *addr)
{
	unsigned long hash = 5381;
	int i;
	for (i = 0; i < len; i++)
		hash = ((hash << 5) + hash) + addr[i];
	return hash;
}

static int search_n_add(struct addrelem **scan, unsigned int len, unsigned char *addr) {
	struct addrelem *new;
	for (; *scan != NULL ; scan = &((*scan)->next)) 
		if ((*scan)->len == len && memcmp((*scan)->addr,addr,len) == 0)
			return 0;
	new = malloc(sizeof(struct addrelem) + len);
	if (new) {
		new->next = NULL;
		new->len = len;
		memcpy(new->addr, addr, len);
		*scan = new;
		return 1;
	} 
	return -1;
}

#define HASH_MASK 511

void hash_add_n_run(unsigned int len, unsigned char *addr, void *arg,
		void (*f)(unsigned int len, unsigned char *addr, void *arg)) {
	static struct addrelem **htable;
	unsigned long hashkey;

	if (__builtin_expect(htable == NULL, 0)) 
		htable = calloc(HASH_MASK + 1, sizeof(struct addrelem *));

	hashkey = hash(len, addr) % HASH_MASK;

	if (search_n_add(&(htable[hashkey]), len, addr) == 1) 
		f(len, addr, arg);
}

void printlogv4(unsigned int len, unsigned char *addr, void *arg) {
	char straddr[256];
	int *pvlan = arg;
	syslog(LOG_INFO, "user %s Real-IP %s has got VDE-IP4 %s on vlan %d",
			username, sshremotehost, inet_ntop(AF_INET, addr, straddr, 256), *pvlan);

}

void printlogv6(unsigned int len, unsigned char *addr, void *arg) {
	char straddr[256];
	int *pvlan = arg;
	syslog(LOG_INFO, "user %s Real-IP %s has got VDE-IP6 %s on vlan %d",
			username, sshremotehost, inet_ntop(AF_INET6, addr, straddr, 256), *pvlan);

}

void vde_ip_check(const unsigned char *buf, int rnx) 
{
	struct header *ph = (struct header *) buf;
	int vlan = 0;
	union body *pb;

	pb = (union body *)(ph+1);
	if (ph->proto[0] == 0x81 && ph->proto[1] == 0x00) { /*VLAN*/
		vlan = ((pb->vlan.priovlan[0] << 8) + pb->vlan.priovlan[1]) & 0xfff;
		pb = (union body *)(((char *)pb)+4);
	}
	if (ph->proto[0] == 0x08 && ph->proto[1] == 0x00 && 
			pb->v4.version == 0x45) {
		/*v4 */ 
		hash_add_n_run(4, pb->v4.ip4src, &vlan, printlogv4);
	}
	else if (ph->proto[0] == 0x86 && ph->proto[1] == 0xdd && 
			pb->v4.version == 0x60) {
		/* v6 */
		hash_add_n_run(16, pb->v6.ip6src, &vlan, printlogv6);
	}
}