forked from Lainports/opnsense-ports
261 lines
8 KiB
C
261 lines
8 KiB
C
--- src/loopudp.c.orig 2010-05-28 00:03:25 UTC
|
|
+++ src/loopudp.c
|
|
@@ -21,17 +21,28 @@
|
|
void
|
|
loop_udp(int sockfd)
|
|
{
|
|
- int maxfdp1, nread, ntowrite, stdineof, clilen, servlen, flags;
|
|
+ int maxfdp1, nread, ntowrite, stdineof, clilen, flags;
|
|
+ socklen_t servlen;
|
|
fd_set rset;
|
|
- struct sockaddr_in cliaddr; /* for UDP server */
|
|
- struct sockaddr_in servaddr; /* for UDP client */
|
|
+ struct sockaddr_in cliaddr4; /* for IPv4 UDP server */
|
|
+ struct sockaddr_in6 cliaddr6; /* for IPv6 UDP server */
|
|
+ /*
|
|
+ * The original local variable servaddr, and later servaddr4 and
|
|
+ * servaddr6, were not initialized before use. Using the initialized
|
|
+ * global sockaddr structs allows the sendto() code, below, to work
|
|
+ * correctly. This was a problem with the original IPv4 code, and
|
|
+ * later the IPv6 code.
|
|
+ */
|
|
+ //struct sockaddr_in servaddr4; /* for IPv4 UDP client */
|
|
+ //struct sockaddr_in6 servaddr6; /* for IPv6 UDP client */
|
|
+ char inaddr_buf[INET6_ADDRSTRLEN];
|
|
|
|
- struct iovec iov[1];
|
|
- struct msghdr msg;
|
|
+ struct iovec iov[1];
|
|
+ struct msghdr msg;
|
|
#ifdef HAVE_MSGHDR_MSG_CONTROL
|
|
#ifdef IP_RECVDSTADDR /* 4.3BSD Reno and later */
|
|
static struct cmsghdr *cmptr = NULL; /* malloc'ed */
|
|
- struct in_addr dstinaddr; /* for UDP server */
|
|
+ struct in_addr dstinaddr; /* for UDP server */
|
|
#define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(struct in_addr))
|
|
#endif /* IP_RECVDSTADDR */
|
|
|
|
@@ -68,8 +79,10 @@ loop_udp(int sockfd)
|
|
err_sys("shutdown() error");
|
|
|
|
FD_CLR(STDIN_FILENO, &rset);
|
|
- stdineof = 1; /* don't read stdin anymore */
|
|
- continue; /* back to select() */
|
|
+ /* don't read stdin anymore */
|
|
+ stdineof = 1;
|
|
+ /* back to select() */
|
|
+ continue;
|
|
}
|
|
break; /* default: stdin EOF -> done */
|
|
}
|
|
@@ -77,23 +90,43 @@ loop_udp(int sockfd)
|
|
if (crlf) {
|
|
ntowrite = crlf_add(wbuf, writelen, rbuf, nread);
|
|
if (connectudp) {
|
|
- if (write(sockfd, wbuf, ntowrite) != ntowrite)
|
|
+ if (write(sockfd, wbuf, ntowrite) !=
|
|
+ ntowrite) {
|
|
err_sys("write error");
|
|
+ }
|
|
} else {
|
|
- if (sendto(sockfd, wbuf, ntowrite, 0,
|
|
- (struct sockaddr *) &servaddr, sizeof(servaddr))
|
|
- != ntowrite)
|
|
- err_sys("sendto error");
|
|
+ if (af_46 == AF_INET) {
|
|
+ if (sendto(sockfd, wbuf, ntowrite, 0,
|
|
+ (struct sockaddr *)&servaddr4,
|
|
+ sizeof(servaddr4)) != ntowrite) {
|
|
+ err_sys("sendto error");
|
|
+ }
|
|
+ } else {
|
|
+ if (sendto(sockfd, wbuf, ntowrite, 0,
|
|
+ (struct sockaddr *)&servaddr6,
|
|
+ sizeof(servaddr6)) != ntowrite) {
|
|
+ err_sys("sendto error");
|
|
+ }
|
|
+ }
|
|
}
|
|
} else {
|
|
if (connectudp) {
|
|
if (write(sockfd, rbuf, nread) != nread)
|
|
err_sys("write error");
|
|
} else {
|
|
- if (sendto(sockfd, rbuf, nread, 0,
|
|
- (struct sockaddr *) &servaddr, sizeof(servaddr))
|
|
- != nread)
|
|
- err_sys("sendto error");
|
|
+ if (af_46 == AF_INET) {
|
|
+ if (sendto(sockfd, rbuf, nread, 0,
|
|
+ (struct sockaddr *)&servaddr4,
|
|
+ sizeof(servaddr4)) != nread) {
|
|
+ err_sys("sendto error");
|
|
+ }
|
|
+ } else {
|
|
+ if (sendto(sockfd, rbuf, nread, 0,
|
|
+ (struct sockaddr *)&servaddr6,
|
|
+ sizeof(servaddr6)) != nread) {
|
|
+ err_sys("sendto error");
|
|
+ }
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -101,35 +134,54 @@ loop_udp(int sockfd)
|
|
if (FD_ISSET(sockfd, &rset)) {
|
|
/* data to read from socket */
|
|
if (server) {
|
|
- clilen = sizeof(cliaddr);
|
|
-#ifndef MSG_TRUNC /* vanilla BSD sockets */
|
|
+ if (af_46 == AF_INET) {
|
|
+ clilen = sizeof(cliaddr4);
|
|
+ } else {
|
|
+ clilen = sizeof(cliaddr6);
|
|
+ }
|
|
+
|
|
+#ifndef MSG_TRUNC /* vanilla BSD sockets */
|
|
+
|
|
+ /* Fixme: Not ported for IPv6 */
|
|
+ /* Not compiled in for FreeBSD 8.4 */
|
|
nread = recvfrom(sockfd, rbuf, readlen, 0,
|
|
- (struct sockaddr *) &cliaddr, &clilen);
|
|
-
|
|
+ (struct sockaddr *) &cliaddr4, &clilen);
|
|
+
|
|
#else /* 4.3BSD Reno and later; use recvmsg() to get at MSG_TRUNC flag */
|
|
- /* Also lets us get at control information (destination address) */
|
|
-
|
|
+ /* Also lets us get at control information (destination address) */
|
|
+
|
|
+ /* FreeBSD 8.4 */
|
|
iov[0].iov_base = rbuf;
|
|
iov[0].iov_len = readlen;
|
|
- msg.msg_iov = iov;
|
|
- msg.msg_iovlen = 1;
|
|
- msg.msg_name = (caddr_t) &cliaddr;
|
|
- msg.msg_namelen = clilen;
|
|
-
|
|
+ msg.msg_iov = iov;
|
|
+ msg.msg_iovlen = 1;
|
|
+ if (af_46 == AF_INET) {
|
|
+ msg.msg_name = (caddr_t) &cliaddr4;
|
|
+ } else {
|
|
+ msg.msg_name = (caddr_t) &cliaddr6;
|
|
+ }
|
|
+ msg.msg_namelen = clilen;
|
|
+
|
|
#ifdef HAVE_MSGHDR_MSG_CONTROL
|
|
#ifdef IP_RECVDSTADDR
|
|
+ /* FreeBSD 8.4 */
|
|
if (cmptr == NULL && (cmptr = malloc(CONTROLLEN)) == NULL)
|
|
err_sys("malloc error for control buffer");
|
|
|
|
- msg.msg_control = (caddr_t) cmptr; /* for dest address */
|
|
+ /* for dest address */
|
|
+ msg.msg_control = (caddr_t) cmptr;
|
|
msg.msg_controllen = CONTROLLEN;
|
|
#else
|
|
- msg.msg_control = (caddr_t) 0; /* no ancillary data */
|
|
+ /* Not used for FreeBSD 8.4 */
|
|
+ /* no ancillary data */
|
|
+ msg.msg_control = (caddr_t) 0;
|
|
msg.msg_controllen = 0;
|
|
#endif /* IP_RECVDSTADDR */
|
|
#endif
|
|
#ifdef HAVE_MSGHDR_MSG_FLAGS
|
|
- msg.msg_flags = 0; /* flags returned here */
|
|
+ /* FreeBSD 8.4 */
|
|
+ /* flags returned here */
|
|
+ msg.msg_flags = 0;
|
|
#endif
|
|
nread = recvmsg(sockfd, &msg, 0);
|
|
#endif /* MSG_TRUNC */
|
|
@@ -137,22 +189,39 @@ loop_udp(int sockfd)
|
|
err_sys("datagram receive error");
|
|
|
|
if (verbose) {
|
|
- printf("from %s", INET_NTOA(cliaddr.sin_addr));
|
|
+ if (af_46 == AF_INET) {
|
|
+ printf("from %s",
|
|
+ INET_NTOA(cliaddr4.sin_addr));
|
|
+ } else {
|
|
+ inet_ntop(AF_INET6,
|
|
+ &cliaddr6.sin6_addr.
|
|
+ __u6_addr.__u6_addr8,
|
|
+ inaddr_buf,
|
|
+ sizeof(inaddr_buf));
|
|
+ printf("from %s", inaddr_buf);
|
|
+ }
|
|
#ifdef HAVE_MSGHDR_MSG_CONTROL
|
|
#ifdef IP_RECVDSTADDR
|
|
+ /*
|
|
+ * Fixme: not ported for IPv6
|
|
+ * Fixme: recvdstaddr fails (earlier,
|
|
+ * in setsockopt()) for IPv6 under
|
|
+ * FreeBSD 8.4
|
|
+ */
|
|
if (recvdstaddr) {
|
|
if (cmptr->cmsg_len != CONTROLLEN)
|
|
err_quit("control length (%d) != %d",
|
|
- cmptr->cmsg_len, CONTROLLEN);
|
|
+ cmptr->cmsg_len, CONTROLLEN);
|
|
if (cmptr->cmsg_level != IPPROTO_IP)
|
|
err_quit("control level != IPPROTO_IP");
|
|
if (cmptr->cmsg_type != IP_RECVDSTADDR)
|
|
err_quit("control type != IP_RECVDSTADDR");
|
|
bcopy(CMSG_DATA(cmptr), &dstinaddr,
|
|
- sizeof(struct in_addr));
|
|
+ sizeof(struct in_addr));
|
|
bzero(cmptr, CONTROLLEN);
|
|
|
|
- printf(", to %s", INET_NTOA(dstinaddr));
|
|
+ printf(", to %s",
|
|
+ INET_NTOA(dstinaddr));
|
|
}
|
|
#endif /* IP_RECVDSTADDR */
|
|
#endif /* HAVE_MSGHDR_MSG_CONTROL */
|
|
@@ -178,15 +247,37 @@ loop_udp(int sockfd)
|
|
}
|
|
|
|
} else {
|
|
- /* Must use recvfrom() for unconnected UDP client */
|
|
- servlen = sizeof(servaddr);
|
|
- nread = recvfrom(sockfd, rbuf, readlen, 0,
|
|
- (struct sockaddr *) &servaddr, &servlen);
|
|
- if (nread < 0)
|
|
+ /*
|
|
+ * Must use recvfrom() for unconnected
|
|
+ * UDP client
|
|
+ */
|
|
+ /* Fixme: not tested on FreeBSD 8.4 */
|
|
+ if (af_46 == AF_INET) {
|
|
+ servlen = sizeof(servaddr4);
|
|
+ nread = recvfrom(sockfd, rbuf, readlen,
|
|
+ 0, (struct sockaddr *)&servaddr4,
|
|
+ &servlen);
|
|
+ } else {
|
|
+ servlen = sizeof(servaddr6);
|
|
+ nread = recvfrom(sockfd, rbuf, readlen,
|
|
+ 0, (struct sockaddr *)&servaddr6,
|
|
+ &servlen);
|
|
+ }
|
|
+ if (nread < 0) {
|
|
err_sys("datagram recvfrom() error");
|
|
-
|
|
+ }
|
|
if (verbose) {
|
|
- printf("from %s", INET_NTOA(servaddr.sin_addr));
|
|
+ if (af_46 == AF_INET) {
|
|
+ printf("from %s",
|
|
+ INET_NTOA(servaddr4.sin_addr));
|
|
+ } else {
|
|
+ inet_ntop(AF_INET6,
|
|
+ &servaddr6.sin6_addr.
|
|
+ __u6_addr.__u6_addr8,
|
|
+ inaddr_buf,
|
|
+ sizeof(inaddr_buf));
|
|
+ printf("from %s", inaddr_buf);
|
|
+ }
|
|
printf(": ");
|
|
fflush(stdout);
|
|
}
|