1: /*
   2: ** Routines to open a TCP connection
   3: **
   4: ** New version that supports the old (pre 4.2 BSD) socket calls,
   5: ** and systems with the old (pre 4.2 BSD) hostname lookup stuff.
   6: ** Compile-time options are:
   7: **
   8: **	USG		- you're on System III/V (you have my sympathies)
   9: **	NONETDB		- old hostname lookup with rhost()
  10: **	OLDSOCKET	- different args for socket() and connect()
  11: **
  12: ** Erik E. Fair <fair@ucbarpa.berkeley.edu>
  13: **
  14: */
  15: 
  16: #include <sys/types.h>
  17: #include <sys/socket.h>
  18: #include <netinet/in.h>
  19: #include <ctype.h>
  20: #include <stdio.h>
  21: #include "get_tcp_conn.h"
  22: #ifndef NONETDB
  23: #include <netdb.h>
  24: #endif	NONETDB
  25: 
  26: extern  int errno;
  27: extern  char    *Pname;
  28: extern  char    *errmsg();
  29: #ifndef htons
  30: extern  u_short htons();
  31: #endif	htons
  32: #ifndef NONETDB
  33: extern  char    *inet_ntoa();
  34: extern  u_long  inet_addr();
  35: #else
  36: /*
  37:  * inet_addr for EXCELAN (which does not have it!)
  38:  *
  39:  */
  40: u_long
  41: inet_addr(cp)
  42: register char   *cp;
  43: {
  44:     u_long val, base, n;
  45:     register char c;
  46:     u_long octet[4], *octetptr = octet;
  47: #ifndef htonl
  48:     extern  u_long  htonl();
  49: #endif	htonl
  50: again:
  51:     /*
  52: 	 * Collect number up to ``.''.
  53: 	 * Values are specified as for C:
  54: 	 * 0x=hex, 0=octal, other=decimal.
  55: 	 */
  56:     val = 0; base = 10;
  57:     if (*cp == '0')
  58:         base = 8, cp++;
  59:     if (*cp == 'x' || *cp == 'X')
  60:         base = 16, cp++;
  61:     while (c = *cp) {
  62:         if (isdigit(c)) {
  63:             val = (val * base) + (c - '0');
  64:             cp++;
  65:             continue;
  66:         }
  67:         if (base == 16 && isxdigit(c)) {
  68:             val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
  69:             cp++;
  70:             continue;
  71:         }
  72:         break;
  73:     }
  74:     if (*cp == '.') {
  75:         /*
  76: 		 * Internet format:
  77: 		 *	a.b.c.d
  78: 		 *	a.b.c	(with c treated as 16-bits)
  79: 		 *	a.b	(with b treated as 24 bits)
  80: 		 */
  81:         if (octetptr >= octet + 4)
  82:             return (-1);
  83:         *octetptr++ = val, cp++;
  84:         goto again;
  85:     }
  86:     /*
  87: 	 * Check for trailing characters.
  88: 	 */
  89:     if (*cp && !isspace(*cp))
  90:         return (-1);
  91:     *octetptr++ = val;
  92:     /*
  93: 	 * Concoct the address according to
  94: 	 * the number of octet specified.
  95: 	 */
  96:     n = octetptr - octet;
  97:     switch (n) {
  98: 
  99:     case 1:             /* a -- 32 bits */
 100:         val = octet[0];
 101:         break;
 102: 
 103:     case 2:             /* a.b -- 8.24 bits */
 104:         val = (octet[0] << 24) | (octet[1] & 0xffffff);
 105:         break;
 106: 
 107:     case 3:             /* a.b.c -- 8.8.16 bits */
 108:         val = (octet[0] << 24) | ((octet[1] & 0xff) << 16) |
 109:             (octet[2] & 0xffff);
 110:         break;
 111: 
 112:     case 4:             /* a.b.c.d -- 8.8.8.8 bits */
 113:         val = (octet[0] << 24) | ((octet[1] & 0xff) << 16) |
 114:               ((octet[2] & 0xff) << 8) | (octet[3] & 0xff);
 115:         break;
 116: 
 117:     default:
 118:         return (-1);
 119:     }
 120:     val = htonl(val);
 121:     return (val);
 122: }
 123: 
 124: char *
 125: inet_ntoa(in)
 126: struct in_addr in;
 127: {
 128:     static char address[20];
 129: 
 130:     sprintf(address, "%u.%u.%u.%u",
 131:              (in.s_addr>>24)&0xff,
 132:              (in.s_addr>>16)&0xff,
 133:              (in.s_addr>>8 )&0xff,
 134:              (in.s_addr    )&0xff);
 135:     return(address);
 136: }
 137: #endif	NONETDB
 138: 
 139: #ifdef  USG
 140: void
 141: bcopy(s, d, l)
 142: register caddr_t s, d;
 143: register int l;
 144: {
 145:     while (l-- > 0) *d++ = *s++;
 146: }
 147: #endif	USG
 148: 
 149: /*
 150: ** Take the name of an internet host in ASCII (this may either be its
 151: ** official host name or internet number (with or without enclosing
 152: ** backets [])), and return a list of internet addresses.
 153: **
 154: ** returns NULL for failure to find the host name in the local database,
 155: ** or for a bad internet address spec.
 156: */
 157: u_long **
 158: name_to_address(host)
 159: char    *host;
 160: {
 161:     static  u_long  *host_addresses[2];
 162:     static  u_long  haddr;
 163: 
 164:     if (host == (char *)NULL) {
 165:         return((u_long **)NULL);
 166:     }
 167: 
 168:     host_addresses[0] = &haddr;
 169:     host_addresses[1] = (u_long *)NULL;
 170: 
 171:     /*
 172: 	** Is this an ASCII internet address? (either of [10.0.0.78] or
 173: 	** 10.0.0.78). We get away with the second test because hostnames
 174: 	** and domain labels are not allowed to begin in numbers.
 175: 	** (cf. RFC952, RFC882).
 176: 	*/
 177:     if (*host == '[' || isdigit(*host)) {
 178:         char    namebuf[128];
 179:         register char   *cp = namebuf;
 180: 
 181:         /*
 182: 		** strip brackets [] or anything else we don't want.
 183: 		*/
 184:         while(*host != '\0' && cp < &namebuf[sizeof(namebuf)]) {
 185:             if (isdigit(*host) || *host == '.')
 186:                 *cp++ = *host++;    /* copy */
 187:             else
 188:                 host++;         /* skip */
 189:         }
 190:         *cp = '\0';
 191:         haddr = inet_addr(namebuf);
 192:         return(&host_addresses[0]);
 193:     } else {
 194: #ifdef  NONETDB
 195:         extern  u_long  rhost();
 196: 
 197:         /* lint is gonna bitch about this (comparing an unsigned?!) */
 198:         if ((haddr = rhost(&host)) == FAIL)
 199:             return((u_long **)NULL);    /* no such host */
 200:         return(&host_addresses[0]);
 201: #else
 202:         struct hostent  *hstp = gethostbyname(host);
 203: 
 204:         if (hstp == NULL) {
 205:             return((u_long **)NULL);    /* no such host */
 206:         }
 207: 
 208:         if (hstp->h_length != sizeof(u_long))
 209:             abort();    /* this is fundamental */
 210: #ifndef h_addr
 211:         /* alignment problems (isn't dbm wonderful?) */
 212:         bcopy((caddr_t)hstp->h_addr, (caddr_t)&haddr, sizeof(haddr));
 213:         return(&host_addresses[0]);
 214: #else
 215:         return((u_long **)hstp->h_addr_list);
 216: #endif	h_addr
 217: #endif	NONETDB
 218:     }
 219: }
 220: 
 221: /*
 222: ** Get a service port number from a service name (or ASCII number)
 223: **
 224: ** Return zero if something is wrong (that's a reserved port)
 225: */
 226: #ifdef  NONETDB
 227: static struct Services {
 228:     char    *name;
 229:     u_short port;
 230: } Services[] = {
 231:     {"nntp",    IPPORT_NNTP},       /* RFC977 */
 232:     {"smtp",    IPPORT_SMTP},       /* RFC821 */
 233:     {"name",    IPPORT_NAMESERVER}, /* RFC881, RFC882, RFC883 */
 234:     {"time",    IPPORT_TIMESERVER}, /* RFC868 */
 235:     {"echo",    IPPORT_ECHO},       /* RFC862 */
 236:     {"discard", IPPORT_DISCARD},    /* RFC863 */
 237:     {"daytime", IPPORT_DAYTIME},    /* RFC867 */
 238:     {"login",   IPPORT_LOGINSERVER},    /* N/A - 4BSD specific */
 239: };
 240: #endif	NONETDB
 241: 
 242: u_short
 243: gservice(serv, proto)
 244: char    *serv, *proto;
 245: {
 246:     if (serv == (char *)NULL || proto == (char *)NULL)
 247:         return((u_short)0);
 248: 
 249:     if (isdigit(*serv)) {
 250:         return(htons((u_short)(atoi(serv))));
 251:     } else {
 252: #ifdef  NONETDB
 253:         register int    i;
 254: 
 255:         for(i = 0; i < (sizeof(Services) / sizeof(struct Services)); i++) {
 256:             if (strcmp(serv, Services[i].name) == 0)
 257:                 return(htons(Services[i].port));
 258:         }
 259:         return((u_short)0);
 260: #else
 261:         struct servent  *srvp = getservbyname(serv, proto);
 262: 
 263:         if (srvp == (struct servent *)NULL)
 264:             return((u_short)0);
 265:         return((u_short)srvp->s_port);
 266: #endif	NONETDB
 267:     }
 268: }
 269: 
 270: /*
 271: ** given a host name (either name or internet address) and service name
 272: ** (or port number) (both in ASCII), give us a TCP connection to the
 273: ** requested service at the requested host (or give us FAIL).
 274: */
 275: get_tcp_conn(host, serv)
 276: char    *host, *serv;
 277: {
 278:     register int    sock;
 279:     u_long  **addrlist;
 280:     struct sockaddr_in  sadr;
 281: #ifdef  OLDSOCKET
 282:     struct sockproto    sp;
 283: 
 284:     sp.sp_family    = (u_short)AF_INET;
 285:     sp.sp_protocol  = (u_short)IPPROTO_TCP;
 286: #endif	OLDSOCKET
 287: 
 288:     if ((addrlist = name_to_address(host)) == (u_long **)NULL) {
 289:         return(NOHOST);
 290:     }
 291: 
 292:     sadr.sin_family = (u_short)AF_INET; /* Only internet for now */
 293:     if ((sadr.sin_port = gservice(serv, "tcp")) == 0)
 294:         return(NOSERVICE);
 295: 
 296:     for(; *addrlist != (u_long *)NULL; addrlist++) {
 297:         bcopy((caddr_t)*addrlist, (caddr_t)&sadr.sin_addr,
 298:             sizeof(sadr.sin_addr));
 299: 
 300: #ifdef  OLDSOCKET
 301:         if ((sock = socket(SOCK_STREAM, &sp, (struct sockaddr *)NULL, 0)) < 0)
 302:             return(FAIL);
 303: 
 304:         if (connect(sock, (struct sockaddr *)&sadr) < 0) {
 305: #else
 306:         if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
 307:             return(FAIL);
 308: 
 309:         if (connect(sock, (struct sockaddr *)&sadr, sizeof(sadr)) < 0) {
 310: #endif	OLDSOCKET
 311:             int e_save = errno;
 312: 
 313:             fprintf(stderr, "%s: %s [%s]: %s\n", Pname, host,
 314:                 inet_ntoa(sadr.sin_addr), errmsg(errno));
 315:             (void) close(sock); /* dump descriptor */
 316:             errno = e_save;
 317:         } else
 318:             return(sock);
 319:     }
 320:     return(FAIL);
 321: }

Defined functions

bcopy defined in line 140; used 3 times
get_tcp_conn defined in line 275; used 1 times
gservice defined in line 242; used 1 times
inet_addr defined in line 40; used 2 times
inet_ntoa defined in line 124; used 2 times
name_to_address defined in line 157; used 1 times

Defined variables

Services defined in line 230; used 3 times

Defined struct's

Services defined in line 227; used 2 times
  • in line 255(2)
Last modified: 1987-11-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3942
Valid CSS Valid XHTML 1.0 Strict