net.c revision 221364
11590Srgrimes/* $NetBSD: net.c,v 1.20 1997/12/26 22:41:30 scottr Exp $ */ 21590Srgrimes 31590Srgrimes/* 41590Srgrimes * Copyright (c) 1992 Regents of the University of California. 51590Srgrimes * All rights reserved. 61590Srgrimes * 71590Srgrimes * This software was developed by the Computer Systems Engineering group 81590Srgrimes * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 91590Srgrimes * contributed to Berkeley. 101590Srgrimes * 111590Srgrimes * Redistribution and use in source and binary forms, with or without 121590Srgrimes * modification, are permitted provided that the following conditions 131590Srgrimes * are met: 141590Srgrimes * 1. Redistributions of source code must retain the above copyright 151590Srgrimes * notice, this list of conditions and the following disclaimer. 161590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 171590Srgrimes * notice, this list of conditions and the following disclaimer in the 181590Srgrimes * documentation and/or other materials provided with the distribution. 191590Srgrimes * 4. Neither the name of the University nor the names of its contributors 201590Srgrimes * may be used to endorse or promote products derived from this software 211590Srgrimes * without specific prior written permission. 221590Srgrimes * 231590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 241590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 251590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 261590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 271590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 281590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 291590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 301590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 311590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 321590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 331590Srgrimes * SUCH DAMAGE. 3487710Smarkm * 3587710Smarkm * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) 3687710Smarkm */ 3787710Smarkm 381590Srgrimes#include <sys/cdefs.h> 3987710Smarkm__FBSDID("$FreeBSD: head/lib/libstand/net.c 221364 2011-05-03 07:39:54Z rodrigc $"); 4032503Scharnier 411590Srgrimes#include <sys/param.h> 421590Srgrimes#include <sys/socket.h> 431590Srgrimes 441590Srgrimes#include <string.h> 451590Srgrimes 461590Srgrimes#include <net/if.h> 4787710Smarkm#include <netinet/in.h> 4887710Smarkm#include <netinet/if_ether.h> 4932503Scharnier#include <netinet/in_systm.h> 5032503Scharnier 5178733Sdd#include <netinet/in_pcb.h> 525297Sache#include <netinet/ip.h> 5350636Speter#include <netinet/ip_var.h> 5487710Smarkm#include <netinet/udp.h> 551590Srgrimes#include <netinet/udp_var.h> 561590Srgrimes 578874Srgrimes#include "stand.h" 585297Sache#include "net.h" 595297Sache 6014443Sjoerg/* 6114443Sjoerg * Send a packet and wait for a reply, with exponential backoff. 625297Sache * 635297Sache * The send routine must return the actual number of bytes written, 645297Sache * or -1 on error. 655297Sache * 665297Sache * The receive routine can indicate success by returning the number of 675297Sache * bytes read; it can return 0 to indicate EOF; it can return -1 with a 685297Sache * non-zero errno to indicate failure; finally, it can return -1 with a 695297Sache * zero errno to indicate it isn't done yet. 705297Sache */ 715297Sachessize_t 725297Sachesendrecv(struct iodesc *d, 735297Sache ssize_t (*sproc)(struct iodesc *, void *, size_t), 748874Srgrimes void *sbuf, size_t ssize, 751590Srgrimes ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t), 761590Srgrimes void *rbuf, size_t rsize) 771590Srgrimes{ 7814443Sjoerg ssize_t cc; 791590Srgrimes time_t t, tmo, tlast; 801590Srgrimes long tleft; 8117676Speter 821590Srgrimes#ifdef NET_DEBUG 831590Srgrimes if (debug) 841590Srgrimes printf("sendrecv: called\n"); 8517676Speter#endif 8617676Speter 8717676Speter tmo = MINTMO; 881590Srgrimes tlast = 0; 891590Srgrimes tleft = 0; 901590Srgrimes t = getsecs(); 911590Srgrimes for (;;) { 921590Srgrimes if (tleft <= 0) { 931590Srgrimes if (tmo >= MAXTMO) { 941590Srgrimes errno = ETIMEDOUT; 951590Srgrimes return -1; 961590Srgrimes } 971590Srgrimes cc = (*sproc)(d, sbuf, ssize); 981590Srgrimes if (cc != -1 && cc < ssize) 9920988Speter panic("sendrecv: short write! (%zd < %zd)", 1002929Sache cc, ssize); 1011590Srgrimes 1021590Srgrimes tleft = tmo; 1031590Srgrimes tmo <<= 1; 1041590Srgrimes if (tmo > MAXTMO) 1051590Srgrimes tmo = MAXTMO; 1061590Srgrimes 10720988Speter if (cc == -1) { 1082929Sache /* Error on transmit; wait before retrying */ 1091590Srgrimes while ((getsecs() - t) < tmo) 1101590Srgrimes ; 1111590Srgrimes tleft = 0; 11217698Speter continue; 11317698Speter } 11417698Speter 11517698Speter tlast = t; 11617698Speter } 1171590Srgrimes 1181590Srgrimes /* Try to get a packet and process it. */ 1191590Srgrimes cc = (*rproc)(d, rbuf, rsize, tleft); 1201590Srgrimes /* Return on data, EOF or real error. */ 1211590Srgrimes if (cc != -1 || errno != 0) 1221590Srgrimes return (cc); 1231590Srgrimes 1241590Srgrimes /* Timed out or didn't get the packet we're waiting for */ 1251590Srgrimes t = getsecs(); 1261590Srgrimes tleft -= t - tlast; 12714443Sjoerg tlast = t; 1281590Srgrimes } 1291590Srgrimes} 1301590Srgrimes 1311590Srgrimes/* 13217676Speter * Like inet_addr() in the C library, but we only accept base-10. 1338874Srgrimes * Return values are in network order. 13417676Speter */ 13517676Spetern_long 13617676Speterinet_addr(char *cp) 13717676Speter{ 13817676Speter u_long val; 13917676Speter int n; 14017676Speter char c; 14117676Speter u_int parts[4]; 14217676Speter u_int *pp = parts; 14317676Speter 1441590Srgrimes for (;;) { 1451590Srgrimes /* 1461590Srgrimes * Collect number up to ``.''. 1471590Srgrimes * Values are specified as for C: 1481590Srgrimes * 0x=hex, 0=octal, other=decimal. 1491590Srgrimes */ 1501590Srgrimes val = 0; 1511590Srgrimes while ((c = *cp) != '\0') { 1521590Srgrimes if (c >= '0' && c <= '9') { 1531590Srgrimes val = (val * 10) + (c - '0'); 1541590Srgrimes cp++; 1551590Srgrimes continue; 1561590Srgrimes } 1571590Srgrimes break; 15814443Sjoerg } 1591590Srgrimes if (*cp == '.') { 16014443Sjoerg /* 16187710Smarkm * Internet format: 1621590Srgrimes * a.b.c.d 1631590Srgrimes * a.b.c (with c treated as 16-bits) 1641590Srgrimes * a.b (with b treated as 24 bits) 1651590Srgrimes */ 1661590Srgrimes if (pp >= parts + 3 || val > 0xff) 1671590Srgrimes goto bad; 1681590Srgrimes *pp++ = val, cp++; 1691590Srgrimes } else 1701590Srgrimes break; 17114443Sjoerg } 1721590Srgrimes /* 1731590Srgrimes * Check for trailing characters. 1741590Srgrimes */ 1751590Srgrimes if (*cp != '\0') 1761590Srgrimes goto bad; 1771590Srgrimes 1781590Srgrimes /* 1791590Srgrimes * Concoct the address according to 1801590Srgrimes * the number of parts specified. 1811590Srgrimes */ 1821590Srgrimes n = pp - parts + 1; 1831590Srgrimes switch (n) { 1841590Srgrimes 185 case 1: /* a -- 32 bits */ 186 break; 187 188 case 2: /* a.b -- 8.24 bits */ 189 if (val > 0xffffff) 190 goto bad; 191 val |= parts[0] << 24; 192 break; 193 194 case 3: /* a.b.c -- 8.8.16 bits */ 195 if (val > 0xffff) 196 goto bad; 197 val |= (parts[0] << 24) | (parts[1] << 16); 198 break; 199 200 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 201 if (val > 0xff) 202 goto bad; 203 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 204 break; 205 } 206 207 return (htonl(val)); 208 bad: 209 return (htonl(INADDR_NONE)); 210} 211 212char * 213inet_ntoa(struct in_addr ia) 214{ 215 return (intoa(ia.s_addr)); 216} 217 218/* Similar to inet_ntoa() */ 219char * 220intoa(n_long addr) 221{ 222 char *cp; 223 u_int byte; 224 int n; 225 static char buf[17]; /* strlen(".255.255.255.255") + 1 */ 226 227 addr = ntohl(addr); 228 cp = &buf[sizeof buf]; 229 *--cp = '\0'; 230 231 n = 4; 232 do { 233 byte = addr & 0xff; 234 *--cp = byte % 10 + '0'; 235 byte /= 10; 236 if (byte > 0) { 237 *--cp = byte % 10 + '0'; 238 byte /= 10; 239 if (byte > 0) 240 *--cp = byte + '0'; 241 } 242 *--cp = '.'; 243 addr >>= 8; 244 } while (--n > 0); 245 246 return (cp+1); 247} 248 249static char * 250number(char *s, int *n) 251{ 252 for (*n = 0; isdigit(*s); s++) 253 *n = (*n * 10) + *s - '0'; 254 return s; 255} 256 257n_long 258ip_convertaddr(char *p) 259{ 260#define IP_ANYADDR 0 261 n_long addr = 0, n; 262 263 if (p == (char *)0 || *p == '\0') 264 return IP_ANYADDR; 265 p = number(p, &n); 266 addr |= (n << 24) & 0xff000000; 267 if (*p == '\0' || *p++ != '.') 268 return IP_ANYADDR; 269 p = number(p, &n); 270 addr |= (n << 16) & 0xff0000; 271 if (*p == '\0' || *p++ != '.') 272 return IP_ANYADDR; 273 p = number(p, &n); 274 addr |= (n << 8) & 0xff00; 275 if (*p == '\0' || *p++ != '.') 276 return IP_ANYADDR; 277 p = number(p, &n); 278 addr |= n & 0xff; 279 if (*p != '\0') 280 return IP_ANYADDR; 281 282 return htonl(addr); 283} 284