ipv4 = NULL;
for(ifr = conf.ifc_ifcu.ifcu_req; (void *)ifr < bufend; ifr++)
{
- if(strcmp(ifr->ifrname, pif))
+ if(strcmp(ifr->ifr_name, pif))
continue;
memset(&req, 0, sizeof(req));
memcpy(req.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
new->inbuf.d.f = new->inbuf.d.l = NULL;
break;
}
- new->conncb = NULL;
- new->errcb = NULL;
- new->readcb = NULL;
- new->writecb = NULL;
- new->acceptcb = NULL;
+ CBCHAININIT(new, socket_conn);
+ CBCHAININIT(new, socket_err);
+ CBCHAININIT(new, socket_read);
+ CBCHAININIT(new, socket_write);
+ CBCHAININIT(new, socket_accept);
new->next = sockets;
new->prev = NULL;
if(sockets != NULL)
if(--(sk->refcount) == 0)
{
+ CBCHAINFREE(sk, socket_conn);
+ CBCHAINFREE(sk, socket_err);
+ CBCHAINFREE(sk, socket_read);
+ CBCHAINFREE(sk, socket_write);
+ CBCHAINFREE(sk, socket_accept);
switch(sk->type)
{
case SOCK_STREAM:
{
sk->outbuf.d.f = buf->next;
free(buf->data);
+ free(buf->addr);
free(buf);
}
while((buf = sk->inbuf.d.f) != NULL)
{
sk->inbuf.d.f = buf->next;
free(buf->data);
+ free(buf->addr);
free(buf);
}
break;
{
if((errno == EINTR) || (errno == EAGAIN))
return;
- if(sk->errcb != NULL)
- sk->errcb(sk, errno, sk->data);
+ CBCHAINDOCB(sk, socket_err, sk, errno);
closesock(sk);
return;
}
if(ret == 0)
{
- if(sk->errcb != NULL)
- sk->errcb(sk, 0, sk->data);
+ CBCHAINDOCB(sk, socket_err, sk, 0);
closesock(sk);
return;
}
sk->inbuf.s.datasize += ret;
- if(sk->readcb != NULL)
- sk->readcb(sk, sk->data);
+ CBCHAINDOCB(sk, socket_read, sk);
break;
case SOCK_DGRAM:
if(ioctl(sk->fd, SIOCINQ, &inq))
free(dbuf);
if((errno == EINTR) || (errno == EAGAIN))
return;
- if(sk->errcb != NULL)
- sk->errcb(sk, errno, sk->data);
+ CBCHAINDOCB(sk, socket_err, sk, errno);
closesock(sk);
return;
}
free(dbuf);
if(!((sk->family == AF_INET) || (sk->family == AF_INET6)))
{
- if(sk->errcb != NULL)
- sk->errcb(sk, 0, sk->data);
+ CBCHAINDOCB(sk, socket_err, sk, 0);
closesock(sk);
}
return;
else
sk->inbuf.d.f = dbuf;
sk->inbuf.d.l = dbuf;
- if(sk->readcb != NULL)
- sk->readcb(sk, sk->data);
+ CBCHAINDOCB(sk, socket_read, sk);
break;
}
}
if(ret > 0)
{
memmove(sk->outbuf.s.buf, ((char *)sk->outbuf.s.buf) + ret, sk->outbuf.s.datasize -= ret);
- if(sk->writecb != NULL)
- sk->writecb(sk, sk->data);
+ CBCHAINDOCB(sk, socket_write, sk);
}
break;
case SOCK_DGRAM:
free(dbuf->data);
free(dbuf->addr);
free(dbuf);
- if(sk->writecb != NULL)
- sk->writecb(sk, sk->data);
+ CBCHAINDOCB(sk, socket_write, sk);
break;
}
}
* netcslisten() instead.
*/
-struct socket *netcslistenlocal(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct socket *, struct socket *, void *), void *data)
+struct socket *netcslistenlocal(int type, struct sockaddr *name, socklen_t namelen, int (*func)(struct socket *, struct socket *, void *), void *data)
{
struct socket *sk;
int intbuf;
putsock(sk);
return(NULL);
}
- sk->acceptcb = func;
- sk->data = data;
+ if(func != NULL)
+ CBREG(sk, socket_accept, func, NULL, data);
return(sk);
}
-struct socket *netcslisten(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct socket *, struct socket *, void *), void *data)
+struct socket *netcslisten(int type, struct sockaddr *name, socklen_t namelen, int (*func)(struct socket *, struct socket *, void *), void *data)
{
if(confgetint("net", "mode") == 1)
{
return(NULL);
}
-struct socket *netcstcplisten(int port, int local, void (*func)(struct socket *, struct socket *, void *), void *data)
+struct socket *netcstcplisten(int port, int local, int (*func)(struct socket *, struct socket *, void *), void *data)
{
struct sockaddr_in addr;
#ifdef HAVE_IPV6
struct sockaddr_in6 addr6;
#endif
- struct socket *(*csfunc)(int, struct sockaddr *, socklen_t, void (*)(struct socket *, struct socket *, void *), void *);
+ struct socket *(*csfunc)(int, struct sockaddr *, socklen_t, int (*)(struct socket *, struct socket *, void *), void *);
struct socket *ret;
if(local)
sk->ignread = 1;
}
-struct socket *netcsconn(struct sockaddr *addr, socklen_t addrlen, void (*func)(struct socket *, int, void *), void *data)
+struct socket *netcsconn(struct sockaddr *addr, socklen_t addrlen, int (*func)(struct socket *, int, void *), void *data)
{
struct socket *sk;
int mode;
if(errno == EINPROGRESS)
{
sk->state = SOCK_SYN;
- sk->conncb = func;
- sk->data = data;
+ if(func != NULL)
+ CBREG(sk, socket_conn, func, NULL, data);
return(sk);
}
putsock(sk);
int pollsocks(int timeout)
{
- int i, num, ret, retlen;
+ int i, num, ret;
+ socklen_t retlen;
int newfd;
struct pollfd *pfds;
struct socket *sk, *next, *newsk;
{
sslen = sizeof(ss);
if((newfd = accept(sk->fd, (struct sockaddr *)&ss, &sslen)) < 0)
- {
- if(sk->errcb != NULL)
- sk->errcb(sk, errno, sk->data);
- }
+ CBCHAINDOCB(sk, socket_err, sk, errno);
newsk = newsock(sk->type);
newsk->fd = newfd;
newsk->family = sk->family;
memcpy(newsk->remote = smalloc(sslen), &ss, sslen);
newsk->remotelen = sslen;
putsock(newsk);
- if(sk->acceptcb != NULL)
- sk->acceptcb(sk, newsk, sk->data);
+ CBCHAINDOCB(sk, socket_accept, sk, newsk);
}
if(pfds[i].revents & POLLERR)
{
retlen = sizeof(ret);
getsockopt(sk->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
- if(sk->errcb != NULL)
- sk->errcb(sk, ret, sk->data);
+ CBCHAINDOCB(sk, socket_err, sk, ret);
continue;
}
break;
{
retlen = sizeof(ret);
getsockopt(sk->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
- if(sk->conncb != NULL)
- sk->conncb(sk, ret, sk->data);
+ CBCHAINDOCB(sk, socket_conn, sk, ret);
closesock(sk);
continue;
}
if(pfds[i].revents & (POLLIN | POLLOUT))
{
sk->state = SOCK_EST;
- if(sk->conncb != NULL)
- sk->conncb(sk, 0, sk->data);
+ CBCHAINDOCB(sk, socket_conn, sk, 0);
}
break;
case SOCK_EST:
{
retlen = sizeof(ret);
getsockopt(sk->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
- if(sk->errcb != NULL)
- sk->errcb(sk, ret, sk->data);
+ CBCHAINDOCB(sk, socket_err, sk, ret);
closesock(sk);
continue;
}
}
if(pfds[i].revents & POLLHUP)
{
- if(sk->errcb != NULL)
- sk->errcb(sk, 0, sk->data);
+ CBCHAINDOCB(sk, socket_err, sk, 0);
closesock(sk);
unlinksock(sk);
continue;
return(0);
}
-int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
+static void sethostaddr(struct sockaddr *dst, struct sockaddr *src)
+{
+ if(dst->sa_family != src->sa_family)
+ {
+ flog(LOG_ERR, "BUG: non-matching socket families in sethostaddr (%i -> %i)", src->sa_family, dst->sa_family);
+ return;
+ }
+ switch(src->sa_family)
+ {
+ case AF_INET:
+ ((struct sockaddr_in *)dst)->sin_addr = ((struct sockaddr_in *)src)->sin_addr;
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)dst)->sin6_addr = ((struct sockaddr_in6 *)src)->sin6_addr;
+ break;
+ default:
+ flog(LOG_WARNING, "sethostaddr unimplemented for family %i", src->sa_family);
+ break;
+ }
+}
+
+static int makepublic(struct sockaddr *addr)
{
int ret;
+ socklen_t plen;
+ struct sockaddr *pname;
+
+ if((ret = getpublicaddr(addr->sa_family, &pname, &plen)) < 0)
+ {
+ flog(LOG_ERR, "could not get public address: %s", strerror(errno));
+ return(-1);
+ }
+ if(ret)
+ return(0);
+ sethostaddr(addr, pname);
+ free(pname);
+ return(0);
+}
+
+int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
+{
socklen_t len;
struct sockaddr *name;
case 0:
*namebuf = NULL;
if((sk->state == SOCK_STL) || (sk->fd < 0))
- return(-1);
- if((ret = getpublicaddr(sk->family, &name, &len)) < 0)
{
- flog(LOG_ERR, "could not get public address: %s", strerror(errno));
+ errno = EBADF;
return(-1);
}
- if(ret == 0)
- {
- *namebuf = name;
- *lenbuf = len;
- return(0);
- }
if(!sockgetlocalname(sk, &name, &len))
{
*namebuf = name;
*lenbuf = len;
+ makepublic(name);
return(0);
}
flog(LOG_ERR, "could not get remotely accessible name by any means");
}
}
+int sockgetremotename2(struct socket *sk, struct socket *sk2, struct sockaddr **namebuf, socklen_t *lenbuf)
+{
+ struct sockaddr *name1, *name2;
+ socklen_t len1, len2;
+
+ if(sk->family != sk2->family)
+ {
+ flog(LOG_ERR, "using sockgetremotename2 with sockets of differing family: %i %i", sk->family, sk2->family);
+ return(-1);
+ }
+ if(sockgetremotename(sk, &name1, &len1))
+ return(-1);
+ if(sockgetremotename(sk2, &name2, &len2)) {
+ free(name1);
+ return(-1);
+ }
+ sethostaddr(name1, name2);
+ free(name2);
+ *namebuf = name1;
+ *lenbuf = len1;
+ return(0);
+}
+
int addreq(struct sockaddr *x, struct sockaddr *y)
{
struct sockaddr_un *u1, *u2;
if(n1->sin_addr.s_addr != n2->sin_addr.s_addr)
return(0);
break;
+#ifdef HAVE_IPV6
case AF_INET6:
s1 = (struct sockaddr_in6 *)x; s2 = (struct sockaddr_in6 *)y;
if(s1->sin6_port != s2->sin6_port)
if(memcmp(s1->sin6_addr.s6_addr, s2->sin6_addr.s6_addr, sizeof(s1->sin6_addr.s6_addr)))
return(0);
break;
+#endif
}
return(1);
}