1: /* client.c - connect to a server */ 2: 3: #ifdef BSD42 4: #include "../h/strings.h" 5: #include <stdio.h> 6: #include "mts.h" 7: #include <errno.h> 8: #include <sys/types.h> 9: #include <sys/socket.h> 10: #include <netinet/in.h> 11: #include <netdb.h> 12: #include <arpa/inet.h> 13: 14: 15: #define NOTOK (-1) 16: #define OK 0 17: #define DONE 1 18: 19: #define TRUE 1 20: #define FALSE 0 21: 22: #define OOPS1 (-2) 23: #define OOPS2 (-3) 24: 25: #define MAXARGS 1000 26: #define MAXNETS 5 27: #define MAXHOSTS 25 28: 29: /* */ 30: 31: extern int errno; 32: extern int sys_nerr; 33: extern char *sys_errlist[]; 34: 35: 36: struct addrent { 37: int a_addrtype; /* assumes AF_INET for inet_netof () */ 38: 39: union { 40: int un_net; 41: char un_addr[14]; 42: } un; 43: #define a_net un.un_net 44: #define a_addr un.un_addr 45: }; 46: 47: static struct addrent *ne, *nz; 48: static struct addrent nets[MAXNETS]; 49: 50: static struct addrent *he, *hz; 51: static struct addrent hosts[MAXHOSTS]; 52: 53: 54: char *getcpy (), **brkstring (), **copyip (); 55: 56: /* */ 57: 58: int client (args, protocol, service, rproto, response) 59: char *args, 60: *protocol, 61: *service, 62: *response; 63: int rproto; 64: { 65: int sd; 66: register char **ap; 67: char *arguments[MAXARGS]; 68: register struct hostent *hp; 69: #ifndef BIND 70: register struct netent *np; 71: #endif BIND 72: register struct servent *sp; 73: 74: if ((sp = getservbyname (service, protocol)) == NULL) { 75: (void) sprintf (response, "%s/%s: unknown service", protocol, service); 76: return NOTOK; 77: } 78: 79: ap = arguments; 80: if (args != NULL && *args != NULL) 81: ap = copyip (brkstring (getcpy (args), " ", "\n"), ap); 82: else 83: if (servers != NULL && *servers != NULL) 84: ap = copyip (brkstring (getcpy (servers), " ", "\n"), ap); 85: if (ap == arguments) { 86: *ap++ = getcpy ("localhost"); 87: *ap = NULL; 88: } 89: 90: nz = (ne = nets) + sizeof nets / sizeof nets[0]; 91: hz = (he = hosts) + sizeof hosts / sizeof hosts[0]; 92: 93: for (ap = arguments; *ap; ap++) { 94: if (**ap == '\01') { 95: #ifndef BIND 96: if (np = getnetbyname (*ap + 1)) { 97: sethostent (1); 98: while (hp = gethostent ()) 99: if (np -> n_addrtype == hp -> h_addrtype 100: && inet (hp, np -> n_net)) { 101: switch (sd = rcaux (sp, hp, rproto, response)) { 102: case NOTOK: 103: continue; 104: case OOPS1: 105: break; 106: case OOPS2: 107: return NOTOK; 108: 109: default: 110: return sd; 111: } 112: break; 113: } 114: } 115: #endif not BIND 116: continue; 117: } 118: 119: if (hp = gethostbyname (*ap)) { 120: switch (sd = rcaux (sp, hp, rproto, response)) { 121: case NOTOK: 122: case OOPS1: 123: break; 124: case OOPS2: 125: return NOTOK; 126: 127: default: 128: return sd; 129: } 130: continue; 131: } 132: } 133: 134: (void) strcpy (response, "no servers available"); 135: return NOTOK; 136: } 137: 138: /* */ 139: 140: static int rcaux (sp, hp, rproto, response) 141: register struct servent *sp; 142: register struct hostent *hp; 143: int rproto; 144: register char *response; 145: { 146: int sd; 147: struct in_addr in; 148: register struct addrent *ap; 149: struct sockaddr_in in_socket; 150: register struct sockaddr_in *isock = &in_socket; 151: 152: for (ap = nets; ap < ne; ap++) 153: if (ap -> a_addrtype == hp -> h_addrtype && inet (hp, ap -> a_net)) 154: return NOTOK; 155: 156: for (ap = hosts; ap < he; ap++) 157: if (ap -> a_addrtype == hp -> h_addrtype 158: && bcmp (ap -> a_addr, hp -> h_addr, hp -> h_length) == 0) 159: return NOTOK; 160: 161: if ((sd = getport (rproto, hp -> h_addrtype, response)) == NOTOK) 162: return OOPS2; 163: 164: bzero ((char *) isock, sizeof *isock); 165: isock -> sin_family = hp -> h_addrtype; 166: isock -> sin_port = sp -> s_port; 167: bcopy (hp -> h_addr, (char *) &isock -> sin_addr, hp -> h_length); 168: 169: if (connect (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK) 170: switch (errno) { 171: case ENETDOWN: 172: case ENETUNREACH: 173: (void) close (sd); 174: if (ne < nz) { 175: ne -> a_addrtype = hp -> h_addrtype; 176: bcopy (hp -> h_addr, (char *) &in, sizeof in); 177: ne -> a_net = inet_netof (in); 178: ne++; 179: } 180: return OOPS1; 181: 182: case ETIMEDOUT: 183: case ECONNREFUSED: 184: default: 185: (void) close (sd); 186: if (he < hz) { 187: he -> a_addrtype = hp -> h_addrtype; 188: bcopy (hp -> h_addr, he -> a_addr, hp -> h_length); 189: he++; 190: } 191: return NOTOK; 192: } 193: 194: return sd; 195: } 196: 197: /* */ 198: 199: static int getport (rproto, addrtype, response) 200: int rproto, 201: addrtype; 202: register char *response; 203: { 204: int sd, 205: port; 206: struct sockaddr_in in_socket, 207: *isock = &in_socket; 208: 209: if (rproto && addrtype != AF_INET) { 210: (void) sprintf (response, "reserved ports not supported for af=%d", 211: addrtype); 212: errno = ENOPROTOOPT; 213: return NOTOK; 214: } 215: 216: if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) { 217: (void) sprintf (response, "unable to create socket: %s", 218: errno > 0 && errno < sys_nerr ? sys_errlist[errno] 219: : "unknown error"); 220: return NOTOK; 221: } 222: if (!rproto) 223: return sd; 224: 225: bzero ((char *) isock, sizeof *isock); 226: isock -> sin_family = addrtype; 227: for (port = IPPORT_RESERVED - 1;;) { 228: isock -> sin_port = htons ((u_short) port); 229: if (bind (sd, (struct sockaddr *) isock, sizeof *isock) != NOTOK) 230: return sd; 231: 232: switch (errno) { 233: case EADDRINUSE: 234: case EADDRNOTAVAIL: 235: if (--port <= IPPORT_RESERVED / 2) { 236: (void) strcpy (response, "ports available"); 237: return NOTOK; 238: } 239: break; 240: 241: default: 242: (void) sprintf (response, "unable to bind socket: %s", 243: errno > 0 && errno < sys_nerr ? sys_errlist[errno] 244: : "unknown error"); 245: return NOTOK; 246: } 247: } 248: } 249: 250: /* */ 251: 252: static int inet (hp, net) 253: register struct hostent *hp; 254: int net; 255: { 256: struct in_addr in; 257: 258: bcopy (hp -> h_addr, (char *) &in, sizeof in); 259: return (inet_netof (in) == net); 260: } 261: 262: /* */ 263: 264: /* static copies of three MH subroutines... (sigh) */ 265: 266: char *malloc (); 267: 268: 269: static char *broken[MAXARGS + 1]; 270: 271: 272: static char **brkstring (strg, brksep, brkterm) 273: register char *strg; 274: register char *brksep, 275: *brkterm; 276: { 277: register int bi; 278: register char c, 279: *sp; 280: 281: sp = strg; 282: 283: for (bi = 0; bi < MAXARGS; bi++) { 284: while (brkany (c = *sp, brksep)) 285: *sp++ = 0; 286: if (!c || brkany (c, brkterm)) { 287: *sp = 0; 288: broken[bi] = 0; 289: return broken; 290: } 291: 292: broken[bi] = sp; 293: while ((c = *++sp) && !brkany (c, brksep) && !brkany (c, brkterm)) 294: continue; 295: } 296: broken[MAXARGS] = 0; 297: 298: return broken; 299: } 300: 301: 302: static brkany (chr, strg) 303: register char chr, 304: *strg; 305: { 306: register char *sp; 307: 308: if (strg) 309: for (sp = strg; *sp; sp++) 310: if (chr == *sp) 311: return 1; 312: return 0; 313: } 314: 315: 316: static char **copyip (p, q) 317: register char **p, 318: **q; 319: { 320: while (*p) 321: *q++ = *p++; 322: *q = 0; 323: 324: return q; 325: } 326: 327: 328: static char *getcpy (str) 329: register char *str; 330: { 331: register char *cp; 332: 333: if ((cp = malloc ((unsigned) (strlen (str) + 1))) == NULL) 334: return NULL; 335: 336: (void) strcpy (cp, str); 337: return cp; 338: } 339: #endif BSD42