summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ppp/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/ppp/udp.c')
-rw-r--r--usr.sbin/ppp/udp.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/usr.sbin/ppp/udp.c b/usr.sbin/ppp/udp.c
index 9260003..7334f59 100644
--- a/usr.sbin/ppp/udp.c
+++ b/usr.sbin/ppp/udp.c
@@ -59,10 +59,15 @@
#include "main.h"
#include "udp.h"
+
+#define UDP_CONNECTED 1
+#define UDP_UNCONNECTED 2
+#define UDP_MAYBEUNCONNECTED 3
+
struct udpdevice {
struct device dev; /* What struct physical knows about */
struct sockaddr_in sock; /* peer address */
- unsigned connected : 1; /* Have we connect()d ? */
+ unsigned connected : 2; /* Have we connect()d ? */
};
#define device2udp(d) ((d)->type == UDP_DEVICE ? (struct udpdevice *)d : NULL)
@@ -77,12 +82,28 @@ static ssize_t
udp_Sendto(struct physical *p, const void *v, size_t n)
{
struct udpdevice *dev = device2udp(p->handler);
+ int ret;
+
+ switch (dev->connected) {
+ case UDP_CONNECTED:
+ ret = write(p->fd, v, n);
+ break;
+
+ case UDP_UNCONNECTED:
+ default:
+ ret = sendto(p->fd, v, n, 0, (struct sockaddr *)&dev->sock,
+ sizeof dev->sock);
+ break;
+ }
+ if (dev->connected == UDP_MAYBEUNCONNECTED) {
+ if (ret == -1 && errno == EISCONN) {
+ dev->connected = UDP_CONNECTED;
+ ret = write(p->fd, v, n);
+ } else
+ dev->connected = UDP_UNCONNECTED;
+ }
- if (dev->connected)
- return write(p->fd, v, n);
-
- return sendto(p->fd, v, n, 0, (struct sockaddr *)&dev->sock,
- sizeof dev->sock);
+ return ret;
}
static ssize_t
@@ -91,7 +112,7 @@ udp_Recvfrom(struct physical *p, void *v, size_t n)
struct udpdevice *dev = device2udp(p->handler);
int sz, ret;
- if (dev->connected)
+ if (dev->connected == UDP_CONNECTED)
return read(p->fd, v, n);
sz = sizeof dev->sock;
@@ -211,7 +232,7 @@ udp_CreateDevice(struct physical *p, char *host, char *port)
log_Printf(LogDEBUG, "%s: Opened udp socket %s\n", p->link.name,
p->name.full);
if (connect(p->fd, (struct sockaddr *)&dev->sock, sizeof dev->sock) == 0) {
- dev->connected = 1;
+ dev->connected = UDP_CONNECTED;
return dev;
} else
log_Printf(LogWARN, "%s: connect: %s\n", p->name.full, strerror(errno));
@@ -267,8 +288,8 @@ udp_Create(struct physical *p)
return NULL;
}
- /* We can't getpeername().... hence we stay un-connect()ed */
- dev->connected = 0;
+ /* We can't getpeername().... */
+ dev->connected = UDP_MAYBEUNCONNECTED;
log_Printf(LogPHASE, "%s: Link is a udp socket\n", p->link.name);
OpenPOWER on IntegriCloud