16815097bSBrian Somers /*- 26815097bSBrian Somers * Copyright (c) 1999 Brian Somers <brian@Awfulhak.org> 36815097bSBrian Somers * All rights reserved. 46815097bSBrian Somers * 56815097bSBrian Somers * Redistribution and use in source and binary forms, with or without 66815097bSBrian Somers * modification, are permitted provided that the following conditions 76815097bSBrian Somers * are met: 86815097bSBrian Somers * 1. Redistributions of source code must retain the above copyright 96815097bSBrian Somers * notice, this list of conditions and the following disclaimer. 106815097bSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 116815097bSBrian Somers * notice, this list of conditions and the following disclaimer in the 126815097bSBrian Somers * documentation and/or other materials provided with the distribution. 136815097bSBrian Somers * 146815097bSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 156815097bSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 166815097bSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 176815097bSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 186815097bSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 196815097bSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 206815097bSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 216815097bSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 226815097bSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 236815097bSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 246815097bSBrian Somers * SUCH DAMAGE. 256815097bSBrian Somers * 266815097bSBrian Somers * $Id: tcp.c,v 1.1 1999/05/08 11:07:45 brian Exp $ 276815097bSBrian Somers */ 286815097bSBrian Somers 296815097bSBrian Somers #include <sys/types.h> 306815097bSBrian Somers #include <sys/socket.h> 316815097bSBrian Somers #include <netinet/in.h> 326815097bSBrian Somers #include <arpa/inet.h> 336815097bSBrian Somers #include <netdb.h> 346815097bSBrian Somers 356815097bSBrian Somers #include <errno.h> 366815097bSBrian Somers #include <stdio.h> 376815097bSBrian Somers #include <stdlib.h> 386815097bSBrian Somers #include <string.h> 396815097bSBrian Somers #include <sys/uio.h> 406815097bSBrian Somers #include <termios.h> 416815097bSBrian Somers #include <unistd.h> 426815097bSBrian Somers 436815097bSBrian Somers #include "layer.h" 446815097bSBrian Somers #include "defs.h" 456815097bSBrian Somers #include "mbuf.h" 466815097bSBrian Somers #include "log.h" 476815097bSBrian Somers #include "sync.h" 486815097bSBrian Somers #include "timer.h" 496815097bSBrian Somers #include "lqr.h" 506815097bSBrian Somers #include "hdlc.h" 516815097bSBrian Somers #include "throughput.h" 526815097bSBrian Somers #include "fsm.h" 536815097bSBrian Somers #include "lcp.h" 546815097bSBrian Somers #include "ccp.h" 556815097bSBrian Somers #include "link.h" 566815097bSBrian Somers #include "async.h" 576815097bSBrian Somers #include "descriptor.h" 586815097bSBrian Somers #include "physical.h" 596815097bSBrian Somers #include "udp.h" 606815097bSBrian Somers 616815097bSBrian Somers struct udpdevice { 626815097bSBrian Somers struct device dev; /* What struct physical knows about */ 636815097bSBrian Somers struct sockaddr_in sock; /* peer address */ 646815097bSBrian Somers unsigned connected : 1; /* Have we connect()d ? */ 656815097bSBrian Somers }; 666815097bSBrian Somers 676815097bSBrian Somers #define device2udp(d) ((d)->type == UDP_DEVICE ? (struct udpdevice *)d : NULL) 686815097bSBrian Somers 696815097bSBrian Somers static ssize_t 706815097bSBrian Somers udp_Sendto(struct physical *p, const void *v, size_t n) 716815097bSBrian Somers { 726815097bSBrian Somers struct udpdevice *dev = device2udp(p->handler); 736815097bSBrian Somers 746815097bSBrian Somers if (dev->connected) 756815097bSBrian Somers return write(p->fd, v, n); 766815097bSBrian Somers 776815097bSBrian Somers return sendto(p->fd, v, n, 0, (struct sockaddr *)&dev->sock, 786815097bSBrian Somers sizeof dev->sock); 796815097bSBrian Somers } 806815097bSBrian Somers 816815097bSBrian Somers static ssize_t 826815097bSBrian Somers udp_Recvfrom(struct physical *p, void *v, size_t n) 836815097bSBrian Somers { 846815097bSBrian Somers struct udpdevice *dev = device2udp(p->handler); 856815097bSBrian Somers int sz, ret; 866815097bSBrian Somers 876815097bSBrian Somers if (dev->connected) 886815097bSBrian Somers return read(p->fd, v, n); 896815097bSBrian Somers 906815097bSBrian Somers sz = sizeof dev->sock; 916815097bSBrian Somers ret = recvfrom(p->fd, v, n, 0, (struct sockaddr *)&dev->sock, &sz); 926815097bSBrian Somers 936815097bSBrian Somers if (*p->name.full == '\0') { 946815097bSBrian Somers snprintf(p->name.full, sizeof p->name.full, "%s:%d/udp", 956815097bSBrian Somers inet_ntoa(dev->sock.sin_addr), ntohs(dev->sock.sin_port)); 966815097bSBrian Somers p->name.base = p->name.full; 976815097bSBrian Somers } 986815097bSBrian Somers 996815097bSBrian Somers return ret; 1006815097bSBrian Somers } 1016815097bSBrian Somers 1026815097bSBrian Somers static void 1036815097bSBrian Somers udp_Free(struct physical *p) 1046815097bSBrian Somers { 1056815097bSBrian Somers struct udpdevice *dev = device2udp(p->handler); 1066815097bSBrian Somers 1076815097bSBrian Somers free(dev); 1086815097bSBrian Somers } 1096815097bSBrian Somers 1106815097bSBrian Somers static void 1116815097bSBrian Somers udp_device2iov(struct physical *p, struct iovec *iov, int *niov, 1126815097bSBrian Somers int maxiov, pid_t newpid) 1136815097bSBrian Somers { 1146815097bSBrian Somers iov[*niov].iov_base = p ? p->handler : malloc(sizeof(struct udpdevice)); 1156815097bSBrian Somers iov[*niov].iov_len = sizeof(struct udpdevice); 1166815097bSBrian Somers (*niov)++; 1176815097bSBrian Somers } 1186815097bSBrian Somers 1196815097bSBrian Somers static const struct device baseudpdevice = { 1206815097bSBrian Somers UDP_DEVICE, 1216815097bSBrian Somers "udp", 1226815097bSBrian Somers NULL, 1236815097bSBrian Somers NULL, 1246815097bSBrian Somers NULL, 1256815097bSBrian Somers NULL, 1266815097bSBrian Somers udp_Free, 1276815097bSBrian Somers udp_Recvfrom, 1286815097bSBrian Somers udp_Sendto, 1296815097bSBrian Somers udp_device2iov, 1306815097bSBrian Somers NULL, 1316815097bSBrian Somers NULL 1326815097bSBrian Somers }; 1336815097bSBrian Somers 1346815097bSBrian Somers struct device * 1356815097bSBrian Somers udp_iov2device(int type, struct physical *p, struct iovec *iov, int *niov, 1366815097bSBrian Somers int maxiov) 1376815097bSBrian Somers { 1386815097bSBrian Somers struct device *dev; 1396815097bSBrian Somers 1406815097bSBrian Somers if (type == UDP_DEVICE) { 1416815097bSBrian Somers /* It's one of ours ! Let's create the device */ 1426815097bSBrian Somers 1436815097bSBrian Somers dev = (struct device *)iov[(*niov)++].iov_base; 1446815097bSBrian Somers /* Refresh function pointers etc */ 1456815097bSBrian Somers memcpy(dev, &baseudpdevice, sizeof *dev); 1466815097bSBrian Somers /* Remember, there's really more than (sizeof *dev) there */ 1476815097bSBrian Somers 1486815097bSBrian Somers physical_SetupStack(p, PHYSICAL_FORCE_SYNC); 1496815097bSBrian Somers } else 1506815097bSBrian Somers dev = NULL; 1516815097bSBrian Somers 1526815097bSBrian Somers return dev; 1536815097bSBrian Somers } 1546815097bSBrian Somers 1556815097bSBrian Somers static struct udpdevice * 1566815097bSBrian Somers udp_CreateDevice(struct physical *p, char *host, char *port) 1576815097bSBrian Somers { 1586815097bSBrian Somers struct udpdevice *dev; 1596815097bSBrian Somers struct servent *sp; 1606815097bSBrian Somers 1616815097bSBrian Somers if ((dev = malloc(sizeof *dev)) == NULL) { 1626815097bSBrian Somers log_Printf(LogWARN, "%s: Cannot allocate a udp device: %s\n", 1636815097bSBrian Somers p->link.name, strerror(errno)); 1646815097bSBrian Somers return NULL; 1656815097bSBrian Somers } 1666815097bSBrian Somers 1676815097bSBrian Somers dev->sock.sin_family = AF_INET; 1686815097bSBrian Somers dev->sock.sin_addr.s_addr = inet_addr(host); 1696815097bSBrian Somers dev->sock.sin_addr = GetIpAddr(host); 1706815097bSBrian Somers if (dev->sock.sin_addr.s_addr == INADDR_NONE) { 1716815097bSBrian Somers log_Printf(LogWARN, "%s: %s: unknown host\n", p->link.name, host); 1726815097bSBrian Somers free(dev); 1736815097bSBrian Somers return NULL; 1746815097bSBrian Somers } 1756815097bSBrian Somers dev->sock.sin_port = htons(atoi(port)); 1766815097bSBrian Somers if (dev->sock.sin_port == 0) { 1776815097bSBrian Somers sp = getservbyname(port, "udp"); 1786815097bSBrian Somers if (sp) 1796815097bSBrian Somers dev->sock.sin_port = sp->s_port; 1806815097bSBrian Somers else { 1816815097bSBrian Somers log_Printf(LogWARN, "%s: %s: unknown service\n", p->link.name, port); 1826815097bSBrian Somers free(dev); 1836815097bSBrian Somers return NULL; 1846815097bSBrian Somers } 1856815097bSBrian Somers } 1866815097bSBrian Somers 1876815097bSBrian Somers log_Printf(LogPHASE, "%s: Connecting to %s:%s/udp\n", p->link.name, 1886815097bSBrian Somers host, port); 1896815097bSBrian Somers 1906815097bSBrian Somers p->fd = socket(PF_INET, SOCK_DGRAM, 0); 1916815097bSBrian Somers if (p->fd >= 0) { 1926815097bSBrian Somers log_Printf(LogDEBUG, "%s: Opened udp socket %s\n", p->link.name, 1936815097bSBrian Somers p->name.full); 1946815097bSBrian Somers if (connect(p->fd, (struct sockaddr *)&dev->sock, sizeof dev->sock) == 0) { 1956815097bSBrian Somers dev->connected = 1; 1966815097bSBrian Somers return dev; 1976815097bSBrian Somers } else 1986815097bSBrian Somers log_Printf(LogWARN, "%s: connect: %s\n", p->name.full, strerror(errno)); 1996815097bSBrian Somers } else 2006815097bSBrian Somers log_Printf(LogWARN, "%s: socket: %s\n", p->name.full, strerror(errno)); 2016815097bSBrian Somers 2026815097bSBrian Somers close(p->fd); 2036815097bSBrian Somers p->fd = -1; 2046815097bSBrian Somers free(dev); 2056815097bSBrian Somers 2066815097bSBrian Somers return NULL; 2076815097bSBrian Somers } 2086815097bSBrian Somers 2096815097bSBrian Somers struct device * 2106815097bSBrian Somers udp_Create(struct physical *p) 2116815097bSBrian Somers { 2126815097bSBrian Somers char *cp, *host, *port, *svc; 2136815097bSBrian Somers struct udpdevice *dev; 2146815097bSBrian Somers 2156815097bSBrian Somers dev = NULL; 2166815097bSBrian Somers if (p->fd < 0) { 2176815097bSBrian Somers if ((cp = strchr(p->name.full, ':')) != NULL) { 2186815097bSBrian Somers *cp = '\0'; 2196815097bSBrian Somers host = p->name.full; 2206815097bSBrian Somers port = cp + 1; 2216815097bSBrian Somers svc = strchr(port, '/'); 2226815097bSBrian Somers if (svc && strcasecmp(svc, "/udp")) { 2236815097bSBrian Somers *cp = ':'; 2246815097bSBrian Somers return NULL; 2256815097bSBrian Somers } 2266815097bSBrian Somers if (svc) 2276815097bSBrian Somers *svc = '\0'; 2286815097bSBrian Somers 2296815097bSBrian Somers if (*host && *port) 2306815097bSBrian Somers dev = udp_CreateDevice(p, host, port); 2316815097bSBrian Somers 2326815097bSBrian Somers *cp = ':'; 2336815097bSBrian Somers if (svc) 2346815097bSBrian Somers *svc = '/'; 2356815097bSBrian Somers } 2366815097bSBrian Somers } else { 2376815097bSBrian Somers /* See if we're a connected udp socket */ 2386815097bSBrian Somers int type, sz, err; 2396815097bSBrian Somers 2406815097bSBrian Somers sz = sizeof type; 2416815097bSBrian Somers if ((err = getsockopt(p->fd, SOL_SOCKET, SO_TYPE, &type, &sz)) == 0 && 2426815097bSBrian Somers sz == sizeof type && type == SOCK_DGRAM) { 2436815097bSBrian Somers if ((dev = malloc(sizeof *dev)) == NULL) { 2446815097bSBrian Somers log_Printf(LogWARN, "%s: Cannot allocate a udp device: %s\n", 2456815097bSBrian Somers p->link.name, strerror(errno)); 2466815097bSBrian Somers return NULL; 2476815097bSBrian Somers } 2486815097bSBrian Somers 2496815097bSBrian Somers /* We can't getpeername().... hence we stay un-connect()ed */ 2506815097bSBrian Somers dev->connected = 0; 2516815097bSBrian Somers 2526815097bSBrian Somers log_Printf(LogPHASE, "%s: Link is a udp socket\n", p->link.name); 2536815097bSBrian Somers 2546815097bSBrian Somers if (p->link.lcp.cfg.openmode != OPEN_PASSIVE) { 2556815097bSBrian Somers log_Printf(LogPHASE, "%s: Changing openmode to PASSIVE\n", 2566815097bSBrian Somers p->link.name); 2576815097bSBrian Somers p->link.lcp.cfg.openmode = OPEN_PASSIVE; 2586815097bSBrian Somers } 2596815097bSBrian Somers } 2606815097bSBrian Somers } 2616815097bSBrian Somers 2626815097bSBrian Somers if (dev) { 2636815097bSBrian Somers memcpy(&dev->dev, &baseudpdevice, sizeof dev->dev); 2646815097bSBrian Somers physical_SetupStack(p, PHYSICAL_FORCE_SYNC); 2656815097bSBrian Somers return &dev->dev; 2666815097bSBrian Somers } 2676815097bSBrian Somers 2686815097bSBrian Somers return NULL; 2696815097bSBrian Somers } 270