Revision: 494 http://vde.svn.sourceforge.net/vde/?rev=494&view=rev Author: rd235 Date: 2011-04-29 16:42:39 +0000 (Fri, 29 Apr 2011)
Log Message: ----------- libvdeplug: added UDP connection Modified Paths: -------------- branches/rd235/vde-2/src/lib/libvdeplug.c Modified: branches/rd235/vde-2/src/lib/libvdeplug.c =================================================================== --- branches/rd235/vde-2/src/lib/libvdeplug.c 2011-04-23 14:25:39 UTC (rev 493) +++ branches/rd235/vde-2/src/lib/libvdeplug.c 2011-04-29 16:42:39 UTC (rev 494) @@ -2,6 +2,7 @@ * libvdeplug - A library to connect to a VDE Switch. * Copyright (C) 2006 Renzo Davoli, University of Bologna * (c) 2010 Renzo Davoli - stream + point2point + * (c) 2011 Renzo Davoli - udpconnect * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by @@ -32,6 +33,8 @@ #include <sys/uio.h> #include <unistd.h> #include <string.h> +#include <netdb.h> +#include <netinet/in.h> #include <config.h> #include <vde.h> @@ -95,13 +98,16 @@ struct vdeconn { int fdctl; int fddata; - struct sockaddr_un inpath; - struct sockaddr_un *outpath; + char *inpath; + size_t outlen; + struct sockaddr *outsock; }; #define SWITCH_MAGIC 0xfeedface #define MAXDESCR 128 #define VDEFLAG_P2P_SOCKET 1 +#define VDEFLAG_UDP_SOCKET 2 +#define VDEFLAG_P2P (VDEFLAG_P2P_SOCKET | VDEFLAG_UDP_SOCKET) enum request_type { REQ_NEW_CONTROL, REQ_NEW_PORT0 }; @@ -118,10 +124,8 @@ { struct vdeconn *conn=NULL; struct passwd *callerpwd; - struct request_v3 *req=NULL; + struct request_v3 req; int pid = getpid(); - struct sockaddr_un *sockun=NULL; - struct sockaddr_un *dataout=NULL; int port=0; char *group=NULL; mode_t mode=0700; @@ -148,18 +152,7 @@ } } - if ((req=(struct request_v3 *)calloc(1, sizeof(struct request_v3)))==NULL) { - errno=ENOMEM; - goto abort; - } - if ((sockun=(struct sockaddr_un *)calloc(1, sizeof(struct sockaddr_un)))==NULL) { - errno=ENOMEM; - goto abort; - } - if ((dataout=(struct sockaddr_un *)calloc(1, sizeof(struct sockaddr_un)))==NULL) { - errno=ENOMEM; - goto abort; - } + memset(&req, 0, sizeof(req)); if ((std_sockname=(char *)calloc(PATH_MAX,sizeof(char)))==NULL) { errno=ENOMEM; goto abort; @@ -177,7 +170,7 @@ conn->fdctl=conn->fddata=-1; //get the login name callerpwd=getpwuid(getuid()); - req->type = REQ_NEW_CONTROL; + req.type = REQ_NEW_CONTROL; if (given_sockname == NULL || *given_sockname == '\0') { char *homedir = getenv("HOME"); given_sockname = NULL; @@ -189,14 +182,17 @@ } } else { char *split; - if(given_sockname[strlen(given_sockname)-1] == ']' && (split=rindex(given_sockname,'[')) != NULL) { + if((split = strstr(given_sockname,"->")) != NULL && rindex(split,':') != NULL) + flags |= VDEFLAG_UDP_SOCKET; + else if(given_sockname[strlen(given_sockname)-1] == ']' + && (split=rindex(given_sockname,'[')) != NULL) { *split=0; split++; port=atoi(split); if (*split==']') flags |= VDEFLAG_P2P_SOCKET; else if (port == 0) - req->type = REQ_NEW_PORT0; + req.type = REQ_NEW_PORT0; if (*given_sockname==0) given_sockname = NULL; } @@ -206,7 +202,7 @@ * switch (we don't know its cwd) for the data socket. Appending * given_sockname to getcwd() would be enough, but we could end up with a * name longer than PATH_MAX that couldn't be used as sun_path. */ - if (given_sockname && !(flags & VDEFLAG_P2P_SOCKET) && + if (given_sockname && !(flags & VDEFLAG_P2P) && vde_realpath(given_sockname, real_sockname) == NULL) goto abort; @@ -220,17 +216,19 @@ sockun.sun_family = AF_IPN; } #endif - if((flags & VDEFLAG_P2P_SOCKET) == 0 && + if((flags & VDEFLAG_P2P) == 0 && (conn->fddata = socket(AF_IPN_STOLEN,SOCK_RAW,IPN_ANY)) >= 0) { + struct sockaddr_un sockun; + memset(&sockun, 0, sizeof(sockun)); /* IPN_STOLEN service exists */ - sockun->sun_family = AF_IPN_STOLEN; - if (port != 0 || req->type == REQ_NEW_PORT0) + sockun.sun_family = AF_IPN_STOLEN; + if (port != 0 || req.type == REQ_NEW_PORT0) setsockopt(conn->fddata,0,IPN_SO_PORT,&port,sizeof(port)); /* If we're given a sockname, just try it */ if (given_sockname) { - snprintf(sockun->sun_path, sizeof(sockun->sun_path), "%s", sockname); - res = connect(conn->fddata, (struct sockaddr *) sockun, sizeof(*sockun)); + snprintf(sockun.sun_path, sizeof(sockun.sun_path), "%s", sockname); + res = connect(conn->fddata, (struct sockaddr *) &sockun, sizeof(sockun)); } /* Else try all the fallback socknames, one by one */ else @@ -238,36 +236,106 @@ int i; for (i = 0, res = -1; fallback_sockname[i] && (res != 0); i++) { - snprintf(sockun->sun_path, sizeof(sockun->sun_path), "%s", fallback_sockname[i]); - res = connect(conn->fddata, (struct sockaddr *) sockun, sizeof(*sockun)); + snprintf(sockun.sun_path, sizeof(sockun.sun_path), "%s", fallback_sockname[i]); + res = connect(conn->fddata, (struct sockaddr *) &sockun, sizeof(sockun)); } } /* If one of the connect succeeded, we're done */ if (res == 0) { - int descrlen=snprintf(req->description,MAXDESCR,"%s user=%s PID=%d", + int descrlen=snprintf(req.description,MAXDESCR,"%s user=%s PID=%d", descr,(callerpwd != NULL)?callerpwd->pw_name:"??", pid); if (ssh_client) { char *endofip=strchr(ssh_client,' '); if (endofip) *endofip=0; - snprintf(req->description+descrlen,MAXDESCR-descrlen, + snprintf(req.description+descrlen,MAXDESCR-descrlen, " SSH=%s", ssh_client); if (endofip) *endofip=' '; } - setsockopt(conn->fddata,0,IPN_SO_DESCR,req->description, - strlen(req->description+1)); - *(conn->inpath.sun_path)=0; /*null string, do not delete "return path"*/ + setsockopt(conn->fddata,0,IPN_SO_DESCR,req.description, + strlen(req.description+1)); conn->fdctl=-1; goto cleanup; } else close(conn->fddata); } #endif + /* UDP connection */ + if (flags & VDEFLAG_UDP_SOCKET) { + struct addrinfo hints; + struct addrinfo *result,*rp; + int s; + char *dst=strstr(given_sockname,"->"); + char *src=given_sockname; + char *srcport; + char *dstport; + memset(&hints,0,sizeof(hints)); + hints.ai_socktype=SOCK_DGRAM; + *dst=0; + dst+=2; + dstport=rindex(dst,':'); + if (dstport==NULL) { + errno=EINVAL; + goto abort; + } + *dstport=0; + dstport++; + srcport=rindex(src,':'); + if (srcport==NULL) { + srcport=src; + src=NULL; + } + //fprintf(stderr,"UDP!%s:%s -> %s:%s \n",src,srcport,dst,dstport); + hints.ai_flags = AI_PASSIVE; + s = getaddrinfo(src, srcport, &hints, &result); + + if (s != 0) { + errno=ECONNABORTED; + goto abort; + } + + for (rp = result; rp != NULL; rp = rp->ai_next) { + conn->fddata = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (conn->fddata == -1) + continue; + + if (bind(conn->fddata, rp->ai_addr, rp->ai_addrlen) == 0) + break; /* Success */ + + close(conn->fddata); + } + + if (rp == NULL) { + errno=ECONNABORTED; + goto abort; + } + + freeaddrinfo(result); + hints.ai_flags = 0; + + s = getaddrinfo(dst, dstport, &hints, &result); + + if (s != 0) { + errno=ECONNABORTED; + goto abort; + } + /* for now it takes the first */ + conn->outlen = result->ai_addrlen; + conn->outsock = malloc(result->ai_addrlen); + memcpy(conn->outsock, result->ai_addr, result->ai_addrlen); + + freeaddrinfo(result); + + goto cleanup; + } /* define a female socket for point2point connection */ if (flags & VDEFLAG_P2P_SOCKET) { struct stat sockstat; + struct sockaddr_un sockun; + struct sockaddr_un *sockout; + memset(&sockun, 0, sizeof(sockun)); if(given_sockname == NULL) { errno = EINVAL; goto abort; @@ -275,33 +343,32 @@ strcpy(sockname,given_sockname); /* XXX canonicalize should be better */ if((conn->fddata = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) goto abort; - sockun->sun_family = AF_UNIX; - memset(sockun->sun_path,0,sizeof(sockun->sun_path)); - snprintf(sockun->sun_path, sizeof(sockun->sun_path)-1, "%s", sockname); + sockun.sun_family = AF_UNIX; + memset(sockun.sun_path,0,sizeof(sockun.sun_path)); + snprintf(sockun.sun_path, sizeof(sockun.sun_path)-1, "%s", sockname); /* the socket already exists */ - if(stat(sockun->sun_path,&sockstat) == 0) { + if(stat(sockun.sun_path,&sockstat) == 0) { if (S_ISSOCK(sockstat.st_mode)) { /* the socket is already in use */ - res = connect(conn->fddata, (struct sockaddr *) sockun, sizeof(*sockun)); + res = connect(conn->fddata, (struct sockaddr *) &sockun, sizeof(sockun)); if (res >= 0) { errno = EADDRINUSE; goto abort; } if (errno == ECONNREFUSED) - unlink(sockun->sun_path); + unlink(sockun.sun_path); } } - res = bind(conn->fddata, (struct sockaddr *) sockun, sizeof(*sockun)); + res = bind(conn->fddata, (struct sockaddr *) &sockun, sizeof(sockun)); if (res < 0) goto abort; - memcpy(&(conn->inpath),sockun,sizeof(conn->inpath)); - conn->outpath = calloc(1,sizeof(struct sockaddr_un)); - if (conn->outpath==NULL) + conn->inpath=strdup(sockun.sun_path); + conn->outlen = sizeof(struct sockaddr_un); + conn->outsock = (struct sockaddr *) (sockout = calloc(1,sizeof(struct sockaddr_un))); + if (conn->outsock ==NULL) goto abort; - conn->outpath->sun_family = AF_UNIX; - snprintf(conn->outpath->sun_path, sizeof(sockun->sun_path), "%s+", sockname); - if (!conn->outpath) - goto abort; + sockout->sun_family = AF_UNIX; + snprintf(sockout->sun_path, sizeof(sockun.sun_path), "%s+", sockname); if (group) { struct group *gs; gid_t gid; @@ -309,182 +376,190 @@ gid=atoi(group); else gid=gs->gr_gid; - chown(conn->inpath.sun_path,-1,gid); + chown(sockun.sun_path,-1,gid); } - chmod(conn->inpath.sun_path,mode); + chmod(sockun.sun_path,mode); goto cleanup; - } - if((conn->fdctl = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - goto abort; - if((conn->fddata = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) - goto abort; - sockun->sun_family = AF_UNIX; + } else { + struct sockaddr_un sockun; + struct sockaddr_un dataout; + memset(&sockun, 0, sizeof(sockun)); + memset(&dataout, 0, sizeof(dataout)); - /* If we're given a sockname, just try it (remember: sockname is the - * canonicalized version of given_sockname - though we don't strictly need - * the canonicalized versiono here). sockname should be the name of a - * *directory* which contains the control socket, named ctl. Older - * versions of VDE used a socket instead of a directory (so an additional - * attempt with %s instead of %s/ctl could be made), but they should - * really not be used anymore. */ - if (given_sockname) - { - snprintf(sockun->sun_path, sizeof(sockun->sun_path), "%s/ctl", sockname); - res = connect(conn->fdctl, (struct sockaddr *) sockun, sizeof(*sockun)); - } - /* Else try all the fallback socknames, one by one */ - else - { - int i; - for (i = 0, res = -1; fallback_sockname[i] && (res != 0); i++) + /* connection to a vde_switch */ + if((conn->fdctl = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + goto abort; + if((conn->fddata = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) + goto abort; + sockun.sun_family = AF_UNIX; + + /* If we're given a sockname, just try it (remember: sockname is the + * canonicalized version of given_sockname - though we don't strictly need + * the canonicalized versiono here). sockname should be the name of a + * *directory* which contains the control socket, named ctl. Older + * versions of VDE used a socket instead of a directory (so an additional + * attempt with %s instead of %s/ctl could be made), but they should + * really not be used anymore. */ + if (given_sockname) { - /* Remember sockname for the data socket directory */ - sockname = fallback_sockname[i]; - snprintf(sockun->sun_path, sizeof(sockun->sun_path), "%s", sockname); - res = connect(conn->fdctl, (struct sockaddr *) sockun, sizeof(*sockun)); + snprintf(sockun.sun_path, sizeof(sockun.sun_path), "%s/ctl", sockname); + res = connect(conn->fdctl, (struct sockaddr *) &sockun, sizeof(sockun)); } - } + /* Else try all the fallback socknames, one by one */ + else + { + int i; + for (i = 0, res = -1; fallback_sockname[i] && (res != 0); i++) + { + /* Remember sockname for the data socket directory */ + sockname = fallback_sockname[i]; + snprintf(sockun.sun_path, sizeof(sockun.sun_path), "%s", sockname); + res = connect(conn->fdctl, (struct sockaddr *) &sockun, sizeof(sockun)); + } + } - if (res != 0) { - struct stat sockstat; - /* define a male plug for point2point connection */ - if (!given_sockname) - goto abort; - snprintf(sockun->sun_path, sizeof(sockun->sun_path), "%s", sockname); - res = connect(conn->fddata, (struct sockaddr *) sockun, sizeof(*sockun)); + if (res != 0) { + struct stat sockstat; + /* define a male plug for point2point connection */ + if (!given_sockname) + goto abort; + snprintf(sockun.sun_path, sizeof(sockun.sun_path), "%s", sockname); + res = connect(conn->fddata, (struct sockaddr *) &sockun, sizeof(sockun)); + if (res < 0) + goto abort; + snprintf(sockun.sun_path, sizeof(sockun.sun_path), "%s+", sockname); + if(stat(sockun.sun_path,&sockstat) == 0) { + if (S_ISSOCK(sockstat.st_mode)) { + /* the socket is already in use */ + res = connect(conn->fddata, (struct sockaddr *) &sockun, sizeof(sockun)); + if (res >= 0) { + errno = EADDRINUSE; + goto abort; + } + if (errno == ECONNREFUSED) + unlink(sockun.sun_path); + } + } + res = bind(conn->fddata, (struct sockaddr *) &sockun, sizeof(sockun)); + if (res < 0) + goto abort; + conn->inpath=strdup(sockun.sun_path); + if (group) { + struct group *gs; + gid_t gid; + if ((gs=getgrnam(group)) == NULL) + gid=atoi(group); + else + gid=gs->gr_gid; + chown(sockun.sun_path,-1,gid); + } + chmod(sockun.sun_path,mode); + close(conn->fdctl); + conn->fdctl=-1; + goto cleanup; + } + + req.magic=SWITCH_MAGIC; + req.version=3; + req.type=req.type+(port << 8); + req.sock.sun_family=AF_UNIX; + + /* First choice, store the return socket from the switch in the control + * dir. We assume that given_sockname (hence sockname) is a directory. + * Should be a safe assumption unless someone modifies the previous group + * of connect() attempts (see the comments above for more information). */ + memset(req.sock.sun_path, 0, sizeof(req.sock.sun_path)); + do + { + /* Here sockname is the last successful one in the previous step. */ + sprintf(req.sock.sun_path, "%s/.%05d-%05d", sockname, pid, sockno++); + res=bind(conn->fddata, (struct sockaddr *) &req.sock, sizeof (req.sock)); + } + while (res < 0 && errno == EADDRINUSE); + + /* It didn't work. So we cycle on the fallback directories until we find a + * suitable one (or the list ends). */ if (res < 0) - goto abort; - snprintf(sockun->sun_path, sizeof(sockun->sun_path), "%s+", sockname); - if(stat(sockun->sun_path,&sockstat) == 0) { - if (S_ISSOCK(sockstat.st_mode)) { - /* the socket is already in use */ - res = connect(conn->fddata, (struct sockaddr *) sockun, sizeof(*sockun)); - if (res >= 0) { - errno = EADDRINUSE; - goto abort; + { + int i; + for (i = 0, res = -1; fallback_dirname[i] && (res != 0); i++) + { + memset(req.sock.sun_path, 0, sizeof(req.sock.sun_path)); + do + { + sprintf(req.sock.sun_path, "%s/vde.%05d-%05d", fallback_dirname[i], pid, sockno++); + res = bind(conn->fddata, (struct sockaddr *) &req.sock, sizeof (req.sock)); } - if (errno == ECONNREFUSED) - unlink(sockun->sun_path); + while (res < 0 && errno == EADDRINUSE); } } - res = bind(conn->fddata, (struct sockaddr *) sockun, sizeof(*sockun)); + + /* Nothing worked, so cleanup and return with an error. */ if (res < 0) goto abort; - memcpy(&(conn->inpath),sockun,sizeof(conn->inpath)); - if (group) { + + conn->inpath=strdup(req.sock.sun_path); + + if (group) { struct group *gs; gid_t gid; if ((gs=getgrnam(group)) == NULL) gid=atoi(group); else gid=gs->gr_gid; - chown(conn->inpath.sun_path,-1,gid); - } - chmod(conn->inpath.sun_path,mode); - close(conn->fdctl); - conn->fdctl=-1; - goto cleanup; - } - - req->magic=SWITCH_MAGIC; - req->version=3; - req->type=req->type+(port << 8); - req->sock.sun_family=AF_UNIX; - - /* First choice, store the return socket from the switch in the control - * dir. We assume that given_sockname (hence sockname) is a directory. - * Should be a safe assumption unless someone modifies the previous group - * of connect() attempts (see the comments above for more information). */ - memset(req->sock.sun_path, 0, sizeof(req->sock.sun_path)); - do - { - /* Here sockname is the last successful one in the previous step. */ - sprintf(req->sock.sun_path, "%s/.%05d-%05d", sockname, pid, sockno++); - res=bind(conn->fddata, (struct sockaddr *) &req->sock, sizeof (req->sock)); - } - while (res < 0 && errno == EADDRINUSE); - - /* It didn't work. So we cycle on the fallback directories until we find a - * suitable one (or the list ends). */ - if (res < 0) - { - int i; - for (i = 0, res = -1; fallback_dirname[i] && (res != 0); i++) - { - memset(req->sock.sun_path, 0, sizeof(req->sock.sun_path)); - do - { - sprintf(req->sock.sun_path, "%s/vde.%05d-%05d", fallback_dirname[i], pid, sockno++); - res = bind(conn->fddata, (struct sockaddr *) &req->sock, sizeof (req->sock)); - } - while (res < 0 && errno == EADDRINUSE); - } - } - - /* Nothing worked, so cleanup and return with an error. */ - if (res < 0) - goto abort; - - memcpy(&(conn->inpath),&req->sock,sizeof(req->sock)); - if (group) { - struct group *gs; - gid_t gid; - if ((gs=getgrnam(group)) == NULL) - gid=atoi(group); - else - gid=gs->gr_gid; - chown(conn->inpath.sun_path,-1,gid); - } else { - /* when group is not defined, set permission for the reverse channel */ - struct stat ctlstat; - /* if no permission gets "voluntarily" granted to the socket */ - if ((mode & 077) == 0) { - if (stat(sockun->sun_path, &ctlstat) == 0) { - /* if the switch is owned by root or by the same user it should - work 0700 */ - if (ctlstat.st_uid != 0 && ctlstat.st_uid != geteuid()) { - /* try to change the group ownership to the same of the switch */ - /* this call succeeds if the vde user and the owner of the switch - belong to the group */ - if (chown(conn->inpath.sun_path,-1,ctlstat.st_gid) == 0) - mode |= 070; - else - mode |= 077; + chown(req.sock.sun_path,-1,gid); + } else { + /* when group is not defined, set permission for the reverse channel */ + struct stat ctlstat; + /* if no permission gets "voluntarily" granted to the socket */ + if ((mode & 077) == 0) { + if (stat(sockun.sun_path, &ctlstat) == 0) { + /* if the switch is owned by root or by the same user it should + work 0700 */ + if (ctlstat.st_uid != 0 && ctlstat.st_uid != geteuid()) { + /* try to change the group ownership to the same of the switch */ + /* this call succeeds if the vde user and the owner of the switch + belong to the group */ + if (chown(req.sock.sun_path,-1,ctlstat.st_gid) == 0) + mode |= 070; + else + mode |= 077; + } } } } - } - chmod(conn->inpath.sun_path,mode); + chmod(req.sock.sun_path,mode); #ifdef DESCR_INCLUDE_SOCK - descrlen=snprintf(req->description,MAXDESCR,"%s user=%s PID=%d SOCK=%s", - descr,(callerpwd != NULL)?callerpwd->pw_name:"??", - pid,req->sock.sun_path); + descrlen=snprintf(req.description,MAXDESCR,"%s user=%s PID=%d SOCK=%s", + descr,(callerpwd != NULL)?callerpwd->pw_name:"??", + pid,req.sock.sun_path); #else - descrlen=snprintf(req->description,MAXDESCR,"%s user=%s PID=%d", - descr,(callerpwd != NULL)?callerpwd->pw_name:"??", pid); + descrlen=snprintf(req.description,MAXDESCR,"%s user=%s PID=%d", + descr,(callerpwd != NULL)?callerpwd->pw_name:"??", pid); #endif - if (ssh_client) { - char *endofip=strchr(ssh_client,' '); - if (endofip) *endofip=0; - snprintf(req->description+descrlen,MAXDESCR-descrlen," SSH=%s", ssh_client); - if (endofip) *endofip=' '; - } + if (ssh_client) { + char *endofip=strchr(ssh_client,' '); + if (endofip) *endofip=0; + snprintf(req.description+descrlen,MAXDESCR-descrlen," SSH=%s", ssh_client); + if (endofip) *endofip=' '; + } - if (send(conn->fdctl,req,sizeof(*req)-MAXDESCR+strlen(req->description),0)<0) - goto abort; + if (send(conn->fdctl,&req,sizeof(req)-MAXDESCR+strlen(req.description),0)<0) + goto abort; - if (recv(conn->fdctl,dataout,sizeof(struct sockaddr_un),0)<0) - goto abort; + if (recv(conn->fdctl,&dataout,sizeof(struct sockaddr_un),0)<0) + goto abort; - if (connect(conn->fddata,(struct sockaddr *)dataout,sizeof(struct sockaddr_un))<0) - goto abort; + if (connect(conn->fddata,(struct sockaddr *)&dataout,sizeof(struct sockaddr_un))<0) + goto abort; - chmod(dataout->sun_path,mode); + chmod(dataout.sun_path,mode); - goto cleanup; + goto cleanup; + } abort: { @@ -494,19 +569,16 @@ close(conn->fdctl); if (conn->fddata >= 0) close(conn->fddata); - if (*(conn->inpath.sun_path)) - unlink(conn->inpath.sun_path); - if (conn->outpath != NULL) - free(conn->outpath); + if (conn->inpath != NULL) + unlink(conn->inpath); + if (conn->outsock != NULL) + free(conn->outsock); free(conn); } conn = NULL; errno=err; } cleanup: - if (req) free(req); - if (sockun) free(sockun); - if (dataout) free(dataout); if (std_sockname) free(std_sockname); if (real_sockname) free(real_sockname); return conn; @@ -520,7 +592,7 @@ if (__builtin_expect(((retval=recv(conn->fddata,buf,len,0)) > 0), 1)) return retval; else { - if (retval == 0 && conn->outpath != NULL) { + if (retval == 0 && conn->outsock != NULL) { static struct sockaddr unspec={AF_UNSPEC}; connect(conn->fddata,&unspec,sizeof(unspec)); } @@ -546,12 +618,12 @@ #ifdef CONNECTED_P2P if (__builtin_expect(conn!=0,1)) { ssize_t retval; - if (__builtin_expect(((retval=send(conn->fddata,buf,len,0)) >= 0),1)) + if (__builtin_expect(((retval=send(conn->fddata,buf,len,0)) >= 0),1)) return retval; else { - if (__builtin_expect(errno == ENOTCONN,0)) { - if (__builtin_expect(conn->outpath != NULL,1)) { - connect(conn->fddata, (struct sockaddr *)conn->outpath,sizeof(conn->inpath)); + if (__builtin_expect(errno == ENOTCONN || errno == EDESTADDRREQ,0)) { + if (__builtin_expect(conn->outsock != NULL,1)) { + connect(conn->fddata, conn->outsock,conn->outlen); return send(conn->fddata,buf,len,0); } else return retval; @@ -564,11 +636,11 @@ } #else if (__builtin_expect(conn!=0,1)) { - if (__builtin_expect(conn->outpath == NULL,1)) + if (__builtin_expect(conn->outsock == NULL,1)) return send(conn->fddata,buf,len,0); else return sendto(conn->fddata,buf,len,0, - (struct sockaddr *)conn->outpath,sizeof(conn->inpath)); + conn->outsock,conn->outlen); } else { errno=EBADF; return -1; @@ -602,10 +674,10 @@ #ifdef CONNECTED_P2P send(conn->fddata,NULL,0,0); #endif - if (*(conn->inpath.sun_path)) - unlink(conn->inpath.sun_path); - if (conn->outpath != NULL) - free(conn->outpath); + if (conn->inpath != NULL) + unlink(conn->inpath); + if (conn->outsock != NULL) + free(conn->outsock); close(conn->fddata); close(conn->fdctl); free(conn); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ WhatsUp Gold - Download Free Network Management Software The most intuitive, comprehensive, and cost-effective network management toolset available today. Delivers lowest initial acquisition cost and overall TCO of any competing solution. http://p.sf.net/sfu/whatsupgold-sd _______________________________________________ vde-users mailing list vde-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/vde-users