Revision: 454 http://vde.svn.sourceforge.net/vde/?rev=454&view=rev Author: rd235 Date: 2010-11-29 19:14:21 +0000 (Mon, 29 Nov 2010)
Log Message: ----------- iplog: loggin plugin for ipv4/ipv6 addresses Modified Paths: -------------- trunk/vde-2/include/vdeplugin.h trunk/vde-2/src/vde_switch/plugins/Makefile.am trunk/vde-2/src/vde_switch/port.c Added Paths: ----------- trunk/vde-2/src/vde_switch/plugins/iplog.c Modified: trunk/vde-2/include/vdeplugin.h =================================================================== --- trunk/vde-2/include/vdeplugin.h 2010-11-29 12:20:11 UTC (rev 453) +++ trunk/vde-2/include/vdeplugin.h 2010-11-29 19:14:21 UTC (rev 454) @@ -2,6 +2,7 @@ #define _VDEPLUGIN_H #include <stdarg.h> #include <stdio.h> +#include <time.h> /* command type constants */ /* doit signature: @@ -112,7 +113,13 @@ #endif void printoutc(FILE *f, const char *format, ...); +void printlog(int priority, const char *format, ...); uid_t port_user(int port); +time_t qtime(); // returns global time (faster than time()) +void qtime_csenter(); +void qtime_csexit(); +unsigned int qtimer_add(time_t period,int times,void (*call)(),void *arg); +void qtimer_del(unsigned int n); #endif Modified: trunk/vde-2/src/vde_switch/plugins/Makefile.am =================================================================== --- trunk/vde-2/src/vde_switch/plugins/Makefile.am 2010-11-29 12:20:11 UTC (rev 453) +++ trunk/vde-2/src/vde_switch/plugins/Makefile.am 2010-11-29 19:14:21 UTC (rev 454) @@ -13,11 +13,14 @@ # cd "$(DESTDIR)/$(moddir)" && rm -f $(mod_LTLIBRARIES) -mod_LTLIBRARIES = dump.la +mod_LTLIBRARIES = dump.la iplog.la dump_la_SOURCES = dump.c dump_la_LIBADD = $(top_builddir)/src/common/libvdecommon.la +iplog_la_SOURCES = iplog.c +iplog_la_LIBADD = $(top_builddir)/src/common/libvdecommon.la + if ENABLE_PCAP mod_LTLIBRARIES += pdump.la pdump_la_SOURCES = pdump.c Added: trunk/vde-2/src/vde_switch/plugins/iplog.c =================================================================== --- trunk/vde-2/src/vde_switch/plugins/iplog.c (rev 0) +++ trunk/vde-2/src/vde_switch/plugins/iplog.c 2010-11-29 19:14:21 UTC (rev 454) @@ -0,0 +1,711 @@ +/* This is part of VDE Virtual Distributed Internet + * + * iplog: ip logging plugin for vde_switch + * + * Copyright 2010 Renzo Davoli University of Bologna - Italy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* XXX missing: + search ip + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdint.h> + +#include <config.h> +#include <vde.h> +#include <syslog.h> +#include <errno.h> +#include <limits.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> +#include <stdio.h> +#include <string.h> +#include <netinet/in.h> +#include <sys/uio.h> +#include <pwd.h> +#include <ctype.h> + +#include <vdecommon.h> + +#include <vdeplugin.h> + +static char *logfile; +static int logfilefd=-1; + +#define D_LOGIP 0300 +static struct dbgcl dl[]= { + {"iplog/newip","show new ip addresses",D_LOGIP|D_PLUS}, +}; +#define D_LOGIP_NEWIP (dl) + +struct ip4logaddr { + struct ip4logaddr *next; + uint32_t addr; + uint32_t mask; +}; + +struct ip6logaddr { + struct ip6logaddr *next; + uint32_t addr[4]; + uint32_t mask[4]; +}; + +struct ip4logaddr *ip4loghead; +struct ip6logaddr *ip6loghead; + +#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 plugin vde_plugin_data={ + .name="iplog", + .help="log ip/port/user assignment", +}; + +#define IP_HASH_SIZE 1024 + +struct ip_hash_entry { + struct ip_hash_entry *next; + struct ip_hash_entry **prev; + time_t last_seen; + int port; + short vlan; + short len; + unsigned char ipaddr[4]; +}; + +static struct ip_hash_entry **iph; + +static inline int ip_hash(int len,unsigned char *addr) +{ + if (len == 4) + return((addr[0]+2*addr[1]+3*addr[2]+5*addr[3]) % IP_HASH_SIZE); + else + return((addr[0]+2*addr[1]+3*addr[2]+5*addr[3]+ + 7*addr[4]+11*addr[5]+13*addr[6]+17*addr[7]+ + 19*addr[8]+23*addr[9]+29*addr[10]+31*addr[11]+ + 37*addr[12]+41*addr[13]+43*addr[14]+47*addr[15]) % IP_HASH_SIZE); +} + +static inline int ip42string(uint32_t *addr, char *hostname, unsigned int len) +{ + struct sockaddr_in ip4addr; + ip4addr.sin_family=AF_INET; + ip4addr.sin_port=0; + ip4addr.sin_addr.s_addr = *addr; + return getnameinfo((struct sockaddr *)&ip4addr,sizeof(ip4addr), + hostname,len,NULL,0,NI_NUMERICHOST); +} + +static inline int ip62string(uint32_t *addr, char *hostname, unsigned int len) +{ + struct sockaddr_in6 ip6addr; + ip6addr.sin6_family=AF_INET6; + ip6addr.sin6_port=0; + ip6addr.sin6_flowinfo=0; + ip6addr.sin6_scope_id=0; + memcpy(&ip6addr.sin6_addr.s6_addr,addr,16); + return getnameinfo((struct sockaddr *)&ip6addr,sizeof(ip6addr), + hostname,len,NULL,0,NI_NUMERICHOST); +} + +static void ip_find_in_hash_update(int len,unsigned char *addr,int vlan,int port) +{ + struct ip_hash_entry *e; + int k = ip_hash(len, addr); + time_t now; + for(e = iph[k]; e && memcmp(e->ipaddr, addr, len) && e->len == len && + e->vlan == vlan; e = e->next) + ; + if(e == NULL) { + e = (struct ip_hash_entry *) malloc(sizeof(*e)+(len-4)); + if(e == NULL){ + printlog(LOG_WARNING,"Failed to malloc ip_hash entry %s",strerror(errno)); + return; + } + memcpy(e->ipaddr, addr, len); + if(iph[k] != NULL) iph[k]->prev = &(e->next); + e->next = iph[k]; + e->prev = &(iph[k]); + e->vlan = vlan; + e->len = len; + e->port = -1; + iph[k] = e; + } + now=qtime(); + e->last_seen = now; + if(e->port != port) { + e->port=port; + char hostname[100]; + char msg[256]; + char lf[]="\n"; + struct iovec iov[]={{msg,0},{lf,1}}; + + if ((len==4 && ip42string((uint32_t *)addr,hostname,sizeof(hostname))==0) || + (len==16 && ip62string((uint32_t *)addr,hostname,sizeof(hostname))==0)) { + struct passwd *pwd; + char *username; + if ((pwd=getpwuid(port_user(port))) == NULL) + username="(none)"; + else + username=pwd->pw_name; + iov[0].iov_len=snprintf(msg,sizeof(msg),"ipv%d %s port=%d user=%s", + (len==4)?4:6, hostname, port, username); + if (logfilefd >= 0) + writev(logfilefd,iov,2); + else if (logfilefd != -1) + syslog(LOG_INFO, msg); + DBGOUT(D_LOGIP_NEWIP,"%s",msg); + } + } +} + +static void ip_for_all_hash(void (*f)(struct ip_hash_entry *, void *), void *arg) +{ + int i; + struct ip_hash_entry *e, *next; + + for(i = 0; i < IP_HASH_SIZE; i++){ + for(e = iph[i]; e; e = next){ + next = e->next; + (*f)(e, arg); + } + } +} + +static inline void delete_hash_entry(struct ip_hash_entry *old) +{ + *((old)->prev)=(old)->next; + if((old)->next != NULL) (old)->next->prev = (old)->prev; + free((old)); +} + + +#define IP_GC_INTERVAL 10 +#define IP_GC_EXPIRE 360 +static int ip_gc_interval=IP_GC_INTERVAL; +static int ip_gc_expire=IP_GC_EXPIRE; +static unsigned int ip_gc_timerno; + +/* clean from the hash table entries older than IP_GC_EXPIRE seconds, given that + * 'now' points to a time_t structure describing the current time */ +static void ip_gc(struct ip_hash_entry *e, void *expiretime) +{ + if(e->last_seen <= *((time_t *)expiretime)) + delete_hash_entry(e); +} + +/* clean old entries in the hash table 'h', and prepare the timer to be called + * again between GC_INTERVAL seconds */ +static void ip_hash_gc(void *arg) +{ + time_t t = qtime() - ip_gc_expire; + ip_for_all_hash(ip_gc, &t); +} + +static void port_gc(struct ip_hash_entry *e, void *arg) +{ + int *port=arg; + if(*port == e->port) + delete_hash_entry(e); +} + +#define UINT32(X) (((uint32_t *)&(X))) +static int iplog_pktin(struct dbgcl *event,void *arg,va_list v) +{ + int vlan=0; + int port=va_arg(v,int); + unsigned char *buf=va_arg(v,unsigned char *); + //int len=va_arg(v,int); + struct header *ph=(struct header *) buf; + union body *pb=(union body *)(ph+1); + //fprintf(stderr,"packet from port %d len %d\n",port,len); + if (ph->proto[0]==0x81 && ph->proto[1]==0x00) { /*VLAN*/ + vlan=((pb->vlan.priovlan[0] << 8) + pb->vlan.priovlan[1]) & 0xfff; + ph=(struct header *)(((char *)ph)+4); + pb=(union body *)(((char *)pb)+4); + } + if (ph->proto[0]==0x08 && ph->proto[1]==0x00 && + pb->v4.version == 0x45) { + /*v4 */ + struct ip4logaddr *ip4scan; + for (ip4scan=ip4loghead; ip4scan!=NULL; ip4scan=ip4scan->next) { + /*printf("%x %x %x\n",UINT32(pb->v4.ip4src[0]) , ip4scan->mask , + ip4scan->addr);*/ + uint32_t *addr=UINT32(pb->v4.ip4src[0]); + if ((addr[0] & ip4scan->mask) == + ip4scan->addr) { + ip_find_in_hash_update(4,pb->v4.ip4src,vlan,port); + break; + } + } + } + else if (ph->proto[0]==0x86 && ph->proto[1]==0xdd && + pb->v4.version == 0x60) { + /*v6 */ + struct ip6logaddr *ip6scan; + for (ip6scan=ip6loghead; ip6scan!=NULL; ip6scan=ip6scan->next) { + /*printf("%x %x %x:",UINT32(pb->v6.ip6src[0]) , ip6scan->mask[0] , ip6scan->addr[0]); + printf("%x %x %x:",UINT32(pb->v6.ip6src[4]) , ip6scan->mask[1] , ip6scan->addr[1]); + printf("%x %x %x:",UINT32(pb->v6.ip6src[8]) , ip6scan->mask[2] , ip6scan->addr[2]); + printf("%x %x %x:",UINT32(pb->v6.ip6src[12]) , ip6scan->mask[3] , ip6scan->addr[3]); + printf("\n");*/ + uint32_t *addr=UINT32(pb->v6.ip6src[0]); + if ( + ((addr[0] & ip6scan->mask[0]) == ip6scan->addr[0]) && + ((addr[1] & ip6scan->mask[1]) == ip6scan->addr[1]) && + ((addr[2] & ip6scan->mask[2]) == ip6scan->addr[2]) && + ((addr[3] & ip6scan->mask[3]) == ip6scan->addr[3]) + ) + { + ip_find_in_hash_update(16,pb->v6.ip6src,vlan,port); + break; + } + } + } + return 0; +} + +static int iplog_port_minus(struct dbgcl *event,void *arg,va_list v) +{ + int port=va_arg(v,int); + ip_for_all_hash(&port_gc, &port); + return 0; +} + +static int ipshowinfo(FILE *fd) +{ + printoutc(fd,"iplog: ip/port/user loggin plugin"); + if (logfilefd<0) { + if (logfilefd == -1) + printoutc(fd,"log disabled"); + else + printoutc(fd,"log on syslog"); + } else + printoutc(fd,"log on file %s",logfile); + return 0; +} + +static void closelogfile(void) +{ + if (logfilefd >= 0) + close(logfilefd); + if (logfile != NULL) + free(logfile); +} + +static int iplogfile(char *arg) +{ + if (*arg) { + if (strcmp(arg,"-")==0) { + closelogfile(); + logfilefd=-2; + return 0; + } else { + int fd; + fd=open(arg,O_CREAT|O_WRONLY|O_APPEND,0600); + if (fd>=0) { + char abspath[PATH_MAX]; + closelogfile(); + logfilefd=fd; + vde_realpath(arg,abspath); + logfile=strdup(abspath); + return 0; + } else + return ENOENT; + } + } else + return EINVAL; +} + +static int iplog4radd(struct ip4logaddr **ph, uint32_t addr, uint32_t mask) +{ + if (*ph == NULL) { + *ph=malloc(sizeof(struct ip4logaddr)); + if (*ph==NULL) + return ENOMEM; + else { + (*ph)->next=NULL; + (*ph)->addr=addr; + (*ph)->mask=mask; + return 0; + } + } else { + if ((*ph)->addr==addr && (*ph)->mask==mask) + return EEXIST; + else + return iplog4radd(&((*ph)->next),addr,mask); + } +} + +static int iplog6radd(struct ip6logaddr **ph, uint32_t addr[4], uint32_t mask[4]) +{ + if (*ph == NULL) { + *ph=malloc(sizeof(struct ip6logaddr)); + if (*ph==NULL) + return ENOMEM; + else { + (*ph)->next=NULL; + memcpy((void *)((*ph)->addr),addr,16); + memcpy((void *)((*ph)->mask),mask,16); + return 0; + } + } else { + if (memcmp(&((*ph)->addr),addr,16) == 0 && + memcmp(&((*ph)->mask),mask,16) == 0) + return EEXIST; + else + return iplog6radd(&((*ph)->next),addr,mask); + } +} + +static int iplog4rdel(struct ip4logaddr **ph, uint32_t addr, uint32_t mask) +{ + if (*ph == NULL) { + return ENOENT; + } else { + if ((*ph)->addr==addr && (*ph)->mask==mask) { + struct ip4logaddr *this=*ph; + *ph=(*ph)->next; + free(this); + return 0; + } else + return iplog4rdel(&((*ph)->next),addr,mask); + } +} + +static int iplog6rdel(struct ip6logaddr **ph, uint32_t addr[4], uint32_t mask[4]) +{ + if (*ph == NULL) { + return ENOENT; + } else { + if (memcmp(&((*ph)->addr),addr,16) == 0 && + memcmp(&((*ph)->mask),mask,16) == 0) { + struct ip6logaddr *this=*ph; + *ph=(*ph)->next; + free(this); + return 0; + } else + return iplog6rdel(&((*ph)->next),addr,mask); + } +} + +static void n2mask(int len,int n, uint32_t *out) +{ + char m[len]; + int i; + for (i=0;i<len;i++,n-=8) { + if (n>=8) + m[i]=0xff; + else if (n>0) + m[i]=~((1<<(8-n))-1); + else + m[i]=0; + } + len=(len+sizeof(uint32_t)-1)/sizeof(uint32_t); + for (i=0;i<len;i++) + out[i]=*(((uint32_t *)m)+i); +} + +static int mask2n(int len, void *addr) +{ + char *m=addr; + int n=0; + int i,sm; + for (i=0;i<len;i++) { + for (sm=0x80;sm!=0;sm>>=1) { + if (m[i] & sm) + n++; + else + return n; + } + } + return n; +} + +static int char2addr_mask(char *arg, uint32_t *addr, uint32_t *mask) +{ + struct addrinfo *ai; + char *smask=strrchr(arg,'/'); + int len; + if (smask != NULL) { + *smask=0; + smask++; + } + if (getaddrinfo(arg,NULL,NULL,&ai) != 0) + return -1; + else { + if (ai->ai_family == AF_INET) { + struct sockaddr_in *ip4addr=(struct sockaddr_in *) ai->ai_addr; + len=4; + if (smask != NULL) + n2mask(len,atoi(smask),mask); + else + n2mask(len,32,mask); + addr[0]=ip4addr->sin_addr.s_addr & mask[0]; + } else if (ai->ai_family == AF_INET6) { + int i; + struct sockaddr_in6 *ip6addr=(struct sockaddr_in6 *) ai->ai_addr; + len=16; + if (smask != NULL) + n2mask(len,atoi(smask),mask); + else + n2mask(len,128,mask); + for (i=0;i<4;i++) + addr[i]=*(((uint32_t *)ip6addr->sin6_addr.s6_addr)+i) & mask[i]; + } else + len=-1; + freeaddrinfo(ai); + return len; + } +} + +static int iplogadd(char *arg) +{ + uint32_t addr[4],mask[4]; + int len=char2addr_mask(arg,addr,mask); + if (len == 4) + return iplog4radd(&ip4loghead,addr[0],mask[0]); + else if (len == 16) + return iplog6radd(&ip6loghead,addr,mask); + else + return EINVAL; +} + +static int iplogdel(char *arg) +{ + uint32_t addr[4],mask[4]; + int len=char2addr_mask(arg,addr,mask); + if (len == 4) + return iplog4rdel(&ip4loghead,addr[0],mask[0]); + else if (len == 16) + return iplog6rdel(&ip6loghead,addr,mask); + else + return EINVAL; +} + +static void iplog4rlist(struct ip4logaddr *ph, FILE *fd) +{ + if (ph != NULL) { + char hostname[20]; + if (ip42string(&ph->addr,hostname,sizeof(hostname)) == 0) + printoutc(fd," ipv4: %s/%d",hostname,mask2n(4,&ph->mask)); + iplog4rlist(ph->next,fd); + } +} + +static void iplog6rlist(struct ip6logaddr *ph, FILE *fd) +{ + if (ph != NULL) { + char hostname[100]; + if (ip62string(ph->addr,hostname,sizeof(hostname)) == 0) + printoutc(fd," ipv6: %s/%d",hostname,mask2n(16,&ph->mask)); + iplog6rlist(ph->next,fd); + } +} + +static int iploglist(FILE *fd) +{ + iplog4rlist(ip4loghead,fd); + iplog6rlist(ip6loghead,fd); + return 0; +} + +int iplog_set_gc_interval(int p) +{ + qtimer_del(ip_gc_timerno); + ip_gc_interval=p; + ip_gc_timerno=qtimer_add(ip_gc_interval,0,ip_hash_gc,NULL); + return 0; +} + +int iplog_set_gc_expire(int e) +{ + ip_gc_expire=e; + return 0; +} + +static void iplog_iplist_item(struct ip_hash_entry *e, void *arg) +{ + FILE *fd=arg; + char hostname[100]; + if ((e->len==4 && ip42string((uint32_t *)e->ipaddr,hostname,sizeof(hostname))==0) || + (e->len==16 && ip62string((uint32_t *)e->ipaddr,hostname,sizeof(hostname))==0)) { + struct passwd *pwd; + char *username; + if ((pwd=getpwuid(port_user(e->port))) == NULL) + username="(none)"; + else + username=pwd->pw_name; + printoutc(fd,"ipv%d %s port=%d user=%s", (e->len==4)?4:6, hostname, e->port, username); + } +} + +static int iplog_iplist(FILE *fd) +{ + ip_for_all_hash(iplog_iplist_item, fd); + return 0; +} + +struct ipport_data { + FILE *fd; + int port; +}; + +static void iplog_ipport_item(struct ip_hash_entry *e, void *arg) +{ + struct ipport_data *pipd=arg; + if (e->port == pipd->port) + iplog_iplist_item(e,pipd->fd); +} + +static int iplog_ipport(FILE *fd,int port) +{ + struct ipport_data ipd={fd, port}; + ip_for_all_hash(iplog_ipport_item, &ipd); + return 0; +} + +struct ipuser_data { + FILE *fd; + uid_t user; +}; + +static void iplog_ipuser_item(struct ip_hash_entry *e, void *arg) +{ + struct ipuser_data *piud=arg; + if (port_user(e->port) == piud->user) + iplog_iplist_item(e,piud->fd); +} + +static int iplog_ipuser(FILE *fd,char *user) +{ + struct passwd *pwd; + struct ipuser_data iud={.fd=fd}; + if (user==NULL || *user==0) + return EINVAL; + if (isdigit(*user)) + pwd=getpwuid(atoi(user)); + else + pwd=getpwnam(user); + if (pwd == NULL) + return EINVAL; + iud.user=pwd->pw_uid; + ip_for_all_hash(iplog_ipuser_item, &iud); + return 0; +} + +static void iplog_ipsearch_item(int len,unsigned char *addr, FILE *fd) +{ + struct ip_hash_entry *e; + int k = ip_hash(len, addr); + for(e = iph[k]; e && memcmp(e->ipaddr, addr, len) && e->len == len; e = e->next) + ; + if(e != NULL) + iplog_iplist_item(e,fd); +} + +static int iplog_ipsearch(FILE *fd,char *addr) +{ + struct addrinfo *ai; + int rv=0; + if (addr==NULL || *addr==0) + return EINVAL; + if (getaddrinfo(addr,NULL,NULL,&ai) != 0) + return EINVAL; + if (ai->ai_family == AF_INET) { + struct sockaddr_in *ip4addr=(struct sockaddr_in *) ai->ai_addr; + iplog_ipsearch_item(4, (unsigned char *) &ip4addr->sin_addr.s_addr, fd); + } else if (ai->ai_family == AF_INET6) { + struct sockaddr_in6 *ip6addr=(struct sockaddr_in6 *) ai->ai_addr; + iplog_ipsearch_item(16, ip6addr->sin6_addr.s6_addr , fd); + } else + return rv=EINVAL; + freeaddrinfo(ai); + return rv; +} + +static struct comlist cl[]={ + {"iplog","============","IP/Mac/User Logging",NULL,NOARG}, + {"iplog/showinfo","","Show info on logging",ipshowinfo,NOARG|WITHFILE}, + {"iplog/logfile","pathname","Set the logfile",iplogfile,STRARG}, + {"iplog/ipadd","ipaddr/mask","add an ipv4/v6 range",iplogadd,STRARG}, + {"iplog/ipdel","ipaddr/mask","del an ipv6/v6 range",iplogdel,STRARG}, + {"iplog/list","","list ip ranges",iploglist,NOARG|WITHFILE}, + {"iplog/setgcint","N","change garbage collector interval",iplog_set_gc_interval,INTARG}, + {"iplog/setexpire","N","change iplog entries expire time",iplog_set_gc_expire,INTARG}, + {"iplog/iplist","","list active IP",iplog_iplist,NOARG|WITHFILE}, + {"iplog/ipport","port","list active IP on a port",iplog_ipport,INTARG|WITHFILE}, + {"iplog/ipuser","user","list active IP of a user",iplog_ipuser,STRARG|WITHFILE}, + {"iplog/ipsearch","ipaddr","search an IP address",iplog_ipsearch,STRARG|WITHFILE}, +}; + + static void + __attribute__ ((constructor)) +init (void) +{ + fprintf(stderr,"iplog init\n"); + iph=calloc(IP_HASH_SIZE,sizeof(struct ip_hash_entry *)); + ADDCL(cl); + ADDDBGCL(dl); + ip_gc_timerno=qtimer_add(ip_gc_interval,0,ip_hash_gc,NULL); + eventadd(iplog_pktin, "packet/in", NULL); + eventadd(iplog_port_minus, "port/-", NULL); + /* XXX add event port/minux */ +} + + static void + __attribute__ ((destructor)) +fini (void) +{ + time_t t = qtime(); + fprintf(stderr,"iplog fini\n"); + eventdel(iplog_pktin, "packet/in", NULL); + qtimer_del(ip_gc_timerno); + DELCL(cl); + DELDBGCL(dl); + ip_for_all_hash(ip_gc, &t); + free(iph); +} Modified: trunk/vde-2/src/vde_switch/port.c =================================================================== --- trunk/vde-2/src/vde_switch/port.c 2010-11-29 12:20:11 UTC (rev 453) +++ trunk/vde-2/src/vde_switch/port.c 2010-11-29 19:14:21 UTC (rev 454) @@ -1200,7 +1200,7 @@ if (port<0 || port>=numports) return -1; else - return portv[port]->user; + return portv[port]->curuser; } static struct comlist cl[]={ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Increase Visibility of Your 3D Game App & Earn a Chance To Win $500! Tap into the largest installed PC base & get more eyes on your game by optimizing for Intel(R) Graphics Technology. Get started today with the Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs. http://p.sf.net/sfu/intelisp-dev2dev _______________________________________________ vde-users mailing list vde-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/vde-users