138451Smsmith/* $NetBSD: net.c,v 1.20 1997/12/26 22:41:30 scottr Exp $ */ 238451Smsmith 338451Smsmith/* 438451Smsmith * Copyright (c) 1992 Regents of the University of California. 538451Smsmith * All rights reserved. 638451Smsmith * 738451Smsmith * This software was developed by the Computer Systems Engineering group 838451Smsmith * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 938451Smsmith * contributed to Berkeley. 1038451Smsmith * 1138451Smsmith * Redistribution and use in source and binary forms, with or without 1238451Smsmith * modification, are permitted provided that the following conditions 1338451Smsmith * are met: 1438451Smsmith * 1. Redistributions of source code must retain the above copyright 1538451Smsmith * notice, this list of conditions and the following disclaimer. 1638451Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1738451Smsmith * notice, this list of conditions and the following disclaimer in the 1838451Smsmith * documentation and/or other materials provided with the distribution. 1938451Smsmith * 4. Neither the name of the University nor the names of its contributors 2038451Smsmith * may be used to endorse or promote products derived from this software 2138451Smsmith * without specific prior written permission. 2238451Smsmith * 2338451Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2438451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2538451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2638451Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2738451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2838451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2938451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3038451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3138451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3238451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3338451Smsmith * SUCH DAMAGE. 3438451Smsmith * 3538451Smsmith * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) 3638451Smsmith */ 3738451Smsmith 3884221Sdillon#include <sys/cdefs.h> 3984221Sdillon__FBSDID("$FreeBSD$"); 4084221Sdillon 4138451Smsmith#include <sys/param.h> 4238451Smsmith#include <sys/socket.h> 4338451Smsmith 4438451Smsmith#include <string.h> 4538451Smsmith 4638451Smsmith#include <net/if.h> 4738451Smsmith#include <netinet/in.h> 4838451Smsmith#include <netinet/if_ether.h> 4938451Smsmith#include <netinet/in_systm.h> 5038451Smsmith 51221364Srodrigc#include <netinet/in_pcb.h> 5238451Smsmith#include <netinet/ip.h> 5338451Smsmith#include <netinet/ip_var.h> 5438451Smsmith#include <netinet/udp.h> 5538451Smsmith#include <netinet/udp_var.h> 5638451Smsmith 5738451Smsmith#include "stand.h" 5838451Smsmith#include "net.h" 5938451Smsmith 6038451Smsmith/* 6138451Smsmith * Send a packet and wait for a reply, with exponential backoff. 6238451Smsmith * 6338451Smsmith * The send routine must return the actual number of bytes written, 6438451Smsmith * or -1 on error. 6538451Smsmith * 6638451Smsmith * The receive routine can indicate success by returning the number of 6738451Smsmith * bytes read; it can return 0 to indicate EOF; it can return -1 with a 6838451Smsmith * non-zero errno to indicate failure; finally, it can return -1 with a 6938451Smsmith * zero errno to indicate it isn't done yet. 7038451Smsmith */ 7138451Smsmithssize_t 72197178Semastesendrecv(struct iodesc *d, 73197178Semaste ssize_t (*sproc)(struct iodesc *, void *, size_t), 74197178Semaste void *sbuf, size_t ssize, 75197178Semaste ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t), 76197178Semaste void *rbuf, size_t rsize) 7738451Smsmith{ 7892913Sobrien ssize_t cc; 7992913Sobrien time_t t, tmo, tlast; 8038451Smsmith long tleft; 8138451Smsmith 8238451Smsmith#ifdef NET_DEBUG 8338451Smsmith if (debug) 8438451Smsmith printf("sendrecv: called\n"); 8538451Smsmith#endif 8638451Smsmith 8738451Smsmith tmo = MINTMO; 88197178Semaste tlast = 0; 89197178Semaste tleft = 0; 9038451Smsmith t = getsecs(); 9138451Smsmith for (;;) { 9238451Smsmith if (tleft <= 0) { 9338451Smsmith if (tmo >= MAXTMO) { 9438451Smsmith errno = ETIMEDOUT; 9538451Smsmith return -1; 9638451Smsmith } 9738451Smsmith cc = (*sproc)(d, sbuf, ssize); 9838451Smsmith if (cc != -1 && cc < ssize) 99146835Sjhb panic("sendrecv: short write! (%zd < %zd)", 10038451Smsmith cc, ssize); 10138451Smsmith 10238451Smsmith tleft = tmo; 103223121Srodrigc tmo += MINTMO; 10438451Smsmith if (tmo > MAXTMO) 10538451Smsmith tmo = MAXTMO; 10638451Smsmith 10738451Smsmith if (cc == -1) { 10838451Smsmith /* Error on transmit; wait before retrying */ 109197178Semaste while ((getsecs() - t) < tmo) 110197178Semaste ; 11138451Smsmith tleft = 0; 11238451Smsmith continue; 11338451Smsmith } 11438451Smsmith 11538451Smsmith tlast = t; 11638451Smsmith } 11738451Smsmith 11838451Smsmith /* Try to get a packet and process it. */ 11938451Smsmith cc = (*rproc)(d, rbuf, rsize, tleft); 12038451Smsmith /* Return on data, EOF or real error. */ 12138451Smsmith if (cc != -1 || errno != 0) 12238451Smsmith return (cc); 12338451Smsmith 12438451Smsmith /* Timed out or didn't get the packet we're waiting for */ 12538451Smsmith t = getsecs(); 12638451Smsmith tleft -= t - tlast; 12738451Smsmith tlast = t; 12838451Smsmith } 12938451Smsmith} 13038451Smsmith 13138451Smsmith/* 13238451Smsmith * Like inet_addr() in the C library, but we only accept base-10. 13338451Smsmith * Return values are in network order. 13438451Smsmith */ 13538451Smsmithn_long 136197178Semasteinet_addr(char *cp) 13738451Smsmith{ 13892913Sobrien u_long val; 13992913Sobrien int n; 14092913Sobrien char c; 14138451Smsmith u_int parts[4]; 14292913Sobrien u_int *pp = parts; 14338451Smsmith 14438451Smsmith for (;;) { 14538451Smsmith /* 14638451Smsmith * Collect number up to ``.''. 14738451Smsmith * Values are specified as for C: 14838451Smsmith * 0x=hex, 0=octal, other=decimal. 14938451Smsmith */ 15038451Smsmith val = 0; 15138451Smsmith while ((c = *cp) != '\0') { 15238451Smsmith if (c >= '0' && c <= '9') { 15338451Smsmith val = (val * 10) + (c - '0'); 15438451Smsmith cp++; 15538451Smsmith continue; 15638451Smsmith } 15738451Smsmith break; 15838451Smsmith } 15938451Smsmith if (*cp == '.') { 16038451Smsmith /* 16138451Smsmith * Internet format: 16238451Smsmith * a.b.c.d 16338451Smsmith * a.b.c (with c treated as 16-bits) 16438451Smsmith * a.b (with b treated as 24 bits) 16538451Smsmith */ 16638451Smsmith if (pp >= parts + 3 || val > 0xff) 16738451Smsmith goto bad; 16838451Smsmith *pp++ = val, cp++; 16938451Smsmith } else 17038451Smsmith break; 17138451Smsmith } 17238451Smsmith /* 17338451Smsmith * Check for trailing characters. 17438451Smsmith */ 17538451Smsmith if (*cp != '\0') 17638451Smsmith goto bad; 17738451Smsmith 17838451Smsmith /* 17938451Smsmith * Concoct the address according to 18038451Smsmith * the number of parts specified. 18138451Smsmith */ 18238451Smsmith n = pp - parts + 1; 18338451Smsmith switch (n) { 18438451Smsmith 18538451Smsmith case 1: /* a -- 32 bits */ 18638451Smsmith break; 18738451Smsmith 18838451Smsmith case 2: /* a.b -- 8.24 bits */ 18938451Smsmith if (val > 0xffffff) 19038451Smsmith goto bad; 19138451Smsmith val |= parts[0] << 24; 19238451Smsmith break; 19338451Smsmith 19438451Smsmith case 3: /* a.b.c -- 8.8.16 bits */ 19538451Smsmith if (val > 0xffff) 19638451Smsmith goto bad; 19738451Smsmith val |= (parts[0] << 24) | (parts[1] << 16); 19838451Smsmith break; 19938451Smsmith 20038451Smsmith case 4: /* a.b.c.d -- 8.8.8.8 bits */ 20138451Smsmith if (val > 0xff) 20238451Smsmith goto bad; 20338451Smsmith val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 20438451Smsmith break; 20538451Smsmith } 20638451Smsmith 20738451Smsmith return (htonl(val)); 20838451Smsmith bad: 20938451Smsmith return (htonl(INADDR_NONE)); 21038451Smsmith} 21138451Smsmith 21238451Smsmithchar * 213197178Semasteinet_ntoa(struct in_addr ia) 21438451Smsmith{ 21538451Smsmith return (intoa(ia.s_addr)); 21638451Smsmith} 21738451Smsmith 21838451Smsmith/* Similar to inet_ntoa() */ 21938451Smsmithchar * 220197178Semasteintoa(n_long addr) 22138451Smsmith{ 22292913Sobrien char *cp; 22392913Sobrien u_int byte; 22492913Sobrien int n; 22538451Smsmith static char buf[17]; /* strlen(".255.255.255.255") + 1 */ 22638451Smsmith 22790868Smike addr = ntohl(addr); 22838451Smsmith cp = &buf[sizeof buf]; 22938451Smsmith *--cp = '\0'; 23038451Smsmith 23138451Smsmith n = 4; 23238451Smsmith do { 23338451Smsmith byte = addr & 0xff; 23438451Smsmith *--cp = byte % 10 + '0'; 23538451Smsmith byte /= 10; 23638451Smsmith if (byte > 0) { 23738451Smsmith *--cp = byte % 10 + '0'; 23838451Smsmith byte /= 10; 23938451Smsmith if (byte > 0) 24038451Smsmith *--cp = byte + '0'; 24138451Smsmith } 24238451Smsmith *--cp = '.'; 24338451Smsmith addr >>= 8; 24438451Smsmith } while (--n > 0); 24538451Smsmith 24638451Smsmith return (cp+1); 24738451Smsmith} 24838451Smsmith 24938451Smsmithstatic char * 250197178Semastenumber(char *s, int *n) 25138451Smsmith{ 25238451Smsmith for (*n = 0; isdigit(*s); s++) 25338451Smsmith *n = (*n * 10) + *s - '0'; 25438451Smsmith return s; 25538451Smsmith} 25638451Smsmith 25738451Smsmithn_long 258197178Semasteip_convertaddr(char *p) 25938451Smsmith{ 26038451Smsmith#define IP_ANYADDR 0 26138451Smsmith n_long addr = 0, n; 26238451Smsmith 26338451Smsmith if (p == (char *)0 || *p == '\0') 26438451Smsmith return IP_ANYADDR; 26538451Smsmith p = number(p, &n); 26638451Smsmith addr |= (n << 24) & 0xff000000; 26738451Smsmith if (*p == '\0' || *p++ != '.') 26838451Smsmith return IP_ANYADDR; 26938451Smsmith p = number(p, &n); 27038451Smsmith addr |= (n << 16) & 0xff0000; 27138451Smsmith if (*p == '\0' || *p++ != '.') 27238451Smsmith return IP_ANYADDR; 27338451Smsmith p = number(p, &n); 27438451Smsmith addr |= (n << 8) & 0xff00; 27538451Smsmith if (*p == '\0' || *p++ != '.') 27638451Smsmith return IP_ANYADDR; 27738451Smsmith p = number(p, &n); 27838451Smsmith addr |= n & 0xff; 27938451Smsmith if (*p != '\0') 28038451Smsmith return IP_ANYADDR; 28138451Smsmith 28238451Smsmith return htonl(addr); 28338451Smsmith} 284