Deleted Added
full compact
commands.c (49861) commands.c (56668)
1/*
2 * Copyright (c) 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 15 unchanged lines hidden (view full) ---

24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
1/*
2 * Copyright (c) 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 15 unchanged lines hidden (view full) ---

24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $FreeBSD: head/contrib/telnet/telnet/commands.c 56668 2000-01-27 09:28:38Z shin $
32 */
33
34#ifndef lint
35static const char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
36#endif /* not lint */
37
38#if defined(unix)
39#include <sys/param.h>

--- 38 unchanged lines hidden (view full) ---

78
79#if !defined(CRAY) && !defined(sysV88)
80#include <netinet/in_systm.h>
81# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
82# include <machine/endian.h>
83# endif /* vax */
84#endif /* !defined(CRAY) && !defined(sysV88) */
85#include <netinet/ip.h>
34 */
35
36#ifndef lint
37static const char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
38#endif /* not lint */
39
40#if defined(unix)
41#include <sys/param.h>

--- 38 unchanged lines hidden (view full) ---

80
81#if !defined(CRAY) && !defined(sysV88)
82#include <netinet/in_systm.h>
83# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
84# include <machine/endian.h>
85# endif /* vax */
86#endif /* !defined(CRAY) && !defined(sysV88) */
87#include <netinet/ip.h>
88#include <netinet/ip6.h>
86
87
88#ifndef MAXHOSTNAMELEN
89#define MAXHOSTNAMELEN 64
90#endif MAXHOSTNAMELEN
91
92#if defined(IPPROTO_IP) && defined(IP_TOS)
93int tos = -1;

--- 2171 unchanged lines hidden (view full) ---

2265 */
2266 void
2267ayt_status()
2268{
2269 (void) call(status, "status", "notmuch", 0);
2270}
2271#endif
2272
89
90
91#ifndef MAXHOSTNAMELEN
92#define MAXHOSTNAMELEN 64
93#endif MAXHOSTNAMELEN
94
95#if defined(IPPROTO_IP) && defined(IP_TOS)
96int tos = -1;

--- 2171 unchanged lines hidden (view full) ---

2268 */
2269 void
2270ayt_status()
2271{
2272 (void) call(status, "status", "notmuch", 0);
2273}
2274#endif
2275
2273unsigned long inet_addr();
2276static const char *
2277sockaddr_ntop(sa)
2278 struct sockaddr *sa;
2279{
2280 void *addr;
2281 static char addrbuf[INET6_ADDRSTRLEN];
2274
2282
2283 switch (sa->sa_family) {
2284 case AF_INET:
2285 addr = &((struct sockaddr_in *)sa)->sin_addr;
2286 break;
2287#ifdef INET6
2288 case AF_INET6:
2289 addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
2290 break;
2291#endif
2292 default:
2293 return NULL;
2294 }
2295 inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf));
2296 return addrbuf;
2297}
2298
2299#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
2300static int
2301setpolicy(net, res, policy)
2302 int net;
2303 struct addrinfo *res;
2304 char *policy;
2305{
2306 char *buf;
2307 int level;
2308 int optname;
2309
2310 if (policy == NULL)
2311 return 0;
2312
2313 buf = ipsec_set_policy(policy, strlen(policy));
2314 if (buf == NULL) {
2315 printf("%s\n", ipsec_strerror());
2316 return -1;
2317 }
2318 level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
2319 optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY;
2320 if (setsockopt(net, level, optname, buf, ipsec_get_policylen(buf)) < 0){
2321 perror("setsockopt");
2322 return -1;
2323 }
2324
2325 free(buf);
2326}
2327#endif
2328
2275 int
2276tn(argc, argv)
2277 int argc;
2278 char *argv[];
2279{
2329 int
2330tn(argc, argv)
2331 int argc;
2332 char *argv[];
2333{
2280 register struct hostent *host = 0;
2281 struct sockaddr_in sin, src_sin;
2282 struct servent *sp = 0;
2283 unsigned long temp;
2284 extern char *inet_ntoa();
2285#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2334 struct sockaddr_storage ss, src_ss;
2286 char *srp = 0, *strrchr();
2335 char *srp = 0, *strrchr();
2287 unsigned long sourceroute(), srlen;
2288#endif
2336 int proto, opt;
2337 int sourceroute(), srlen;
2338 int srcroute = 0, result;
2289 char *cmd, *hostp = 0, *portp = 0, *user = 0;
2290 char *src_addr = NULL;
2339 char *cmd, *hostp = 0, *portp = 0, *user = 0;
2340 char *src_addr = NULL;
2341 struct addrinfo hints, *res;
2342 int error = 0;
2291
2292 /* clear the socket address prior to use */
2343
2344 /* clear the socket address prior to use */
2293 memset((char *)&sin, 0, sizeof(sin));
2345 memset((char *)&ss, 0, sizeof(ss));
2294
2295 if (connected) {
2296 printf("?Already connected to %s\n", hostname);
2297 setuid(getuid());
2298 return 0;
2299 }
2300 if (argc < 2) {
2301 (void) strcpy(line, "open ");

--- 43 unchanged lines hidden (view full) ---

2345 printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd);
2346 setuid(getuid());
2347 return 0;
2348 }
2349 if (hostp == 0)
2350 goto usage;
2351
2352 if (src_addr != NULL) {
2346
2347 if (connected) {
2348 printf("?Already connected to %s\n", hostname);
2349 setuid(getuid());
2350 return 0;
2351 }
2352 if (argc < 2) {
2353 (void) strcpy(line, "open ");

--- 43 unchanged lines hidden (view full) ---

2397 printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd);
2398 setuid(getuid());
2399 return 0;
2400 }
2401 if (hostp == 0)
2402 goto usage;
2403
2404 if (src_addr != NULL) {
2353 bzero((char *)&src_sin, sizeof(src_sin));
2354 src_sin.sin_family = AF_INET;
2355 if (!inet_aton(src_addr, &src_sin.sin_addr)) {
2356 host = gethostbyname2(src_addr, AF_INET);
2357 if (host == NULL) {
2358 herror(src_addr);
2405 memset(&hints, 0, sizeof(hints));
2406 hints.ai_flags = AI_NUMERICHOST;
2407 hints.ai_family = family;
2408 hints.ai_socktype = SOCK_STREAM;
2409 error = getaddrinfo(src_addr, 0, &hints, &res);
2410 if (error == EAI_NONAME) {
2411 hints.ai_flags = 0;
2412 error = getaddrinfo(src_addr, 0, &hints, &res);
2413 }
2414 if (error != 0) {
2415 fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error));
2416 if (error == EAI_SYSTEM)
2417 fprintf(stderr, "%s: %s\n", src_addr, strerror(errno));
2359 return 0;
2418 return 0;
2360 }
2361 if (host->h_length != sizeof(src_sin.sin_addr)) {
2362 fprintf(stderr, "telnet: gethostbyname2: invalid address\n");
2363 return 0;
2364 }
2365 memcpy((void *)&src_sin.sin_addr, (void *)host->h_addr_list[0],
2366 sizeof(src_sin.sin_addr));
2367 }
2419 }
2420 memcpy((void *)&src_ss, (void *)res->ai_addr, res->ai_addrlen);
2421 freeaddrinfo(res);
2368 }
2422 }
2369
2370#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2371 if (hostp[0] == '@' || hostp[0] == '!') {
2423 if (hostp[0] == '@' || hostp[0] == '!') {
2372 if ((hostname = strrchr(hostp, ':')) == NULL)
2424 if (
2425#ifdef INET6
2426 family == AF_INET6 ||
2427#endif
2428 (hostname = strrchr(hostp, ':')) == NULL)
2373 hostname = strrchr(hostp, '@');
2374 hostname++;
2429 hostname = strrchr(hostp, '@');
2430 hostname++;
2431 srcroute = 1;
2432 } else
2433 hostname = hostp;
2434 if (!portp) {
2435 telnetport = 1;
2436 portp = "telnet";
2437 } else if (*portp == '-') {
2438 portp++;
2439 telnetport = 1;
2440 } else
2441 telnetport = 0;
2442
2443 memset(&hints, 0, sizeof(hints));
2444 hints.ai_flags = AI_NUMERICHOST;
2445 hints.ai_family = family;
2446 hints.ai_socktype = SOCK_STREAM;
2447 error = getaddrinfo(hostname, portp, &hints, &res);
2448 if (error == 0) {
2449 int gni_err = 1;
2450
2451 if (doaddrlookup)
2452 gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len,
2453 _hostname, sizeof(_hostname) - 1, NULL, 0,
2454 0);
2455 if (gni_err != 0)
2456 (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1);
2457 _hostname[sizeof(_hostname)-1] = '\0';
2458 hostname = _hostname;
2459 } else if (error == EAI_NONAME) {
2460 hints.ai_flags = AI_CANONNAME;
2461 error = getaddrinfo(hostname, portp, &hints, &res);
2462 if (error != 0) {
2463 fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error));
2464 if (error == EAI_SYSTEM)
2465 fprintf(stderr, "%s: %s\n", hostname, strerror(errno));
2466 setuid(getuid());
2467 return 0;
2468 }
2469 memcpy((void *)&ss, (void *)res->ai_addr, res->ai_addrlen);
2470 if (srcroute != 0)
2471 (void) strncpy(_hostname, hostname, sizeof(_hostname) - 1);
2472 else if (res->ai_canonname != NULL)
2473 strcpy(_hostname, res->ai_canonname);
2474 else
2475 (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1);
2476 _hostname[sizeof(_hostname)-1] = '\0';
2477 hostname = _hostname;
2478 }
2479 if (srcroute != 0) {
2375 srp = 0;
2480 srp = 0;
2376 temp = sourceroute(hostp, &srp, &srlen);
2377 if (temp == 0) {
2378 herror(srp);
2481 result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt);
2482 if (result == 0) {
2379 setuid(getuid());
2483 setuid(getuid());
2484 freeaddrinfo(res);
2380 return 0;
2485 return 0;
2381 } else if (temp == -1) {
2486 } else if (result == -1) {
2382 printf("Bad source route option: %s\n", hostp);
2383 setuid(getuid());
2487 printf("Bad source route option: %s\n", hostp);
2488 setuid(getuid());
2489 freeaddrinfo(res);
2384 return 0;
2490 return 0;
2385 } else {
2386 sin.sin_addr.s_addr = temp;
2387 sin.sin_family = AF_INET;
2388 }
2491 }
2389 } else {
2390#endif
2391 temp = inet_addr(hostp);
2392 if (temp != INADDR_NONE) {
2393 sin.sin_addr.s_addr = temp;
2394 sin.sin_family = AF_INET;
2395 if (doaddrlookup)
2396 host = gethostbyaddr((char *)&temp, sizeof(temp), AF_INET);
2397 if (host)
2398 (void) strncpy(_hostname, host->h_name, sizeof(_hostname));
2399 else
2400 (void) strncpy(_hostname, hostp, sizeof(_hostname));
2401 _hostname[sizeof(_hostname)-1] = '\0';
2402 hostname = _hostname;
2403 } else {
2404 host = gethostbyname(hostp);
2405 if (host) {
2406 sin.sin_family = host->h_addrtype;
2407#if defined(h_addr) /* In 4.3, this is a #define */
2408 memmove((caddr_t)&sin.sin_addr,
2409 host->h_addr_list[0], host->h_length);
2410#else /* defined(h_addr) */
2411 memmove((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
2412#endif /* defined(h_addr) */
2413 strncpy(_hostname, host->h_name, sizeof(_hostname));
2414 _hostname[sizeof(_hostname)-1] = '\0';
2415 hostname = _hostname;
2416 } else {
2417 herror(hostp);
2418 setuid(getuid());
2419 return 0;
2420 }
2421 }
2422#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2423 }
2492 }
2424#endif
2425 if (portp) {
2426 if (*portp == '-') {
2427 portp++;
2428 telnetport = 1;
2429 } else
2430 telnetport = 0;
2431 sin.sin_port = atoi(portp);
2432 if (sin.sin_port == 0) {
2433 sp = getservbyname(portp, "tcp");
2434 if (sp)
2435 sin.sin_port = sp->s_port;
2436 else {
2437 printf("%s: bad port number\n", portp);
2438 setuid(getuid());
2439 return 0;
2440 }
2441 } else {
2442#if !defined(htons)
2443 u_short htons P((unsigned short));
2444#endif /* !defined(htons) */
2445 sin.sin_port = htons(sin.sin_port);
2446 }
2447 } else {
2448 if (sp == 0) {
2449 sp = getservbyname("telnet", "tcp");
2450 if (sp == 0) {
2451 fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
2452 setuid(getuid());
2453 return 0;
2454 }
2455 sin.sin_port = sp->s_port;
2456 }
2457 telnetport = 1;
2458 }
2459 printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
2493 printf("Trying %s...\n", sockaddr_ntop(res->ai_addr));
2460 do {
2494 do {
2461 net = socket(AF_INET, SOCK_STREAM, 0);
2495 net = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
2462 setuid(getuid());
2463 if (net < 0) {
2464 perror("telnet: socket");
2465 return 0;
2466 }
2496 setuid(getuid());
2497 if (net < 0) {
2498 perror("telnet: socket");
2499 return 0;
2500 }
2467#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2468 if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
2469 perror("setsockopt (IP_OPTIONS)");
2470#endif
2501 if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0)
2502 perror("setsockopt (source route)");
2471#if defined(IPPROTO_IP) && defined(IP_TOS)
2503#if defined(IPPROTO_IP) && defined(IP_TOS)
2472 {
2504 if (res->ai_family == PF_INET) {
2473# if defined(HAS_GETTOS)
2474 struct tosent *tp;
2475 if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
2476 tos = tp->t_tos;
2477# endif
2478 if (tos < 0)
2479 tos = 020; /* Low Delay bit */
2480 if (tos

--- 4 unchanged lines hidden (view full) ---

2485 }
2486#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
2487
2488 if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
2489 perror("setsockopt (SO_DEBUG)");
2490 }
2491
2492 if (src_addr != NULL) {
2505# if defined(HAS_GETTOS)
2506 struct tosent *tp;
2507 if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
2508 tos = tp->t_tos;
2509# endif
2510 if (tos < 0)
2511 tos = 020; /* Low Delay bit */
2512 if (tos

--- 4 unchanged lines hidden (view full) ---

2517 }
2518#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
2519
2520 if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
2521 perror("setsockopt (SO_DEBUG)");
2522 }
2523
2524 if (src_addr != NULL) {
2493 if (bind(net, (struct sockaddr *)&src_sin, sizeof(src_sin)) == -1) {
2525 if (bind(net, (struct sockaddr *)&src_ss,
2526 ((struct sockaddr *)&src_ss)->sa_len) == -1) {
2494 perror("bind");
2495 return 0;
2496 }
2497 }
2527 perror("bind");
2528 return 0;
2529 }
2530 }
2531#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
2532 if (setpolicy(net, res, ipsec_policy_in) < 0)
2533 return 0;
2534 if (setpolicy(net, res, ipsec_policy_out) < 0)
2535 return 0;
2536#endif
2498
2537
2499 if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
2500#if defined(h_addr) /* In 4.3, this is a #define */
2501 if (host && host->h_addr_list[1]) {
2538 if (connect(net, res->ai_addr, res->ai_addrlen) < 0) {
2539 if (res->ai_next) {
2502 int oerrno = errno;
2503
2504 fprintf(stderr, "telnet: connect to address %s: ",
2540 int oerrno = errno;
2541
2542 fprintf(stderr, "telnet: connect to address %s: ",
2505 inet_ntoa(sin.sin_addr));
2543 sockaddr_ntop(res->ai_addr));
2506 errno = oerrno;
2507 perror((char *)0);
2544 errno = oerrno;
2545 perror((char *)0);
2508 host->h_addr_list++;
2509 memmove((caddr_t)&sin.sin_addr,
2510 host->h_addr_list[0], host->h_length);
2546 res = res->ai_next;
2511 (void) NetClose(net);
2512 continue;
2513 }
2547 (void) NetClose(net);
2548 continue;
2549 }
2514#endif /* defined(h_addr) */
2515 perror("telnet: Unable to connect to remote host");
2516 return 0;
2517 }
2518 connected++;
2519#if defined(AUTHENTICATION) || defined(ENCRYPTION)
2520 auth_encrypt_connect(connected);
2521#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
2522 } while (connected == 0);
2550 perror("telnet: Unable to connect to remote host");
2551 return 0;
2552 }
2553 connected++;
2554#if defined(AUTHENTICATION) || defined(ENCRYPTION)
2555 auth_encrypt_connect(connected);
2556#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
2557 } while (connected == 0);
2558 freeaddrinfo(res);
2523 cmdrc(hostp, hostname);
2524 if (autologin && user == NULL) {
2525 struct passwd *pw;
2526
2527 user = getenv("USER");
2528 if (user == NULL ||
2529 ((pw = getpwnam(user)) && pw->pw_uid != getuid())) {
2530 if ((pw = getpwuid(getuid())))

--- 325 unchanged lines hidden (view full) ---

2856 printf("?Need to be connected first for %s.\n", margv[0]);
2857 continue;
2858 }
2859 (*c->handler)(margc, margv);
2860 }
2861 fclose(rcfile);
2862}
2863
2559 cmdrc(hostp, hostname);
2560 if (autologin && user == NULL) {
2561 struct passwd *pw;
2562
2563 user = getenv("USER");
2564 if (user == NULL ||
2565 ((pw = getpwnam(user)) && pw->pw_uid != getuid())) {
2566 if ((pw = getpwuid(getuid())))

--- 325 unchanged lines hidden (view full) ---

2892 printf("?Need to be connected first for %s.\n", margv[0]);
2893 continue;
2894 }
2895 (*c->handler)(margc, margv);
2896 }
2897 fclose(rcfile);
2898}
2899
2864#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2865
2866/*
2867 * Source route is handed in as
2868 * [!]@hop1@hop2...[@|:]dst
2869 * If the leading ! is present, it is a
2870 * strict source route, otherwise it is
2871 * assmed to be a loose source route.
2872 *
2873 * We fill in the source route option as
2874 * hop1,hop2,hop3...dest
2875 * and return a pointer to hop1, which will
2876 * be the address to connect() to.
2877 *
2878 * Arguments:
2900/*
2901 * Source route is handed in as
2902 * [!]@hop1@hop2...[@|:]dst
2903 * If the leading ! is present, it is a
2904 * strict source route, otherwise it is
2905 * assmed to be a loose source route.
2906 *
2907 * We fill in the source route option as
2908 * hop1,hop2,hop3...dest
2909 * and return a pointer to hop1, which will
2910 * be the address to connect() to.
2911 *
2912 * Arguments:
2913 *
2914 * res: ponter to addrinfo structure which contains sockaddr to
2915 * the host to connect to.
2916 *
2879 * arg: pointer to route list to decipher
2880 *
2881 * cpp: If *cpp is not equal to NULL, this is a
2882 * pointer to a pointer to a character array
2883 * that should be filled in with the option.
2884 *
2885 * lenp: pointer to an integer that contains the
2886 * length of *cpp if *cpp != NULL.
2887 *
2917 * arg: pointer to route list to decipher
2918 *
2919 * cpp: If *cpp is not equal to NULL, this is a
2920 * pointer to a pointer to a character array
2921 * that should be filled in with the option.
2922 *
2923 * lenp: pointer to an integer that contains the
2924 * length of *cpp if *cpp != NULL.
2925 *
2926 * protop: pointer to an integer that should be filled in with
2927 * appropriate protocol for setsockopt, as socket
2928 * protocol family.
2929 *
2930 * optp: pointer to an integer that should be filled in with
2931 * appropriate option for setsockopt, as socket protocol
2932 * family.
2933 *
2888 * Return values:
2889 *
2934 * Return values:
2935 *
2890 * Returns the address of the host to connect to. If the
2936 * If the return value is 1, then all operations are
2937 * successful. If the
2891 * return value is -1, there was a syntax error in the
2892 * option, either unknown characters, or too many hosts.
2893 * If the return value is 0, one of the hostnames in the
2894 * path is unknown, and *cpp is set to point to the bad
2895 * hostname.
2896 *
2897 * *cpp: If *cpp was equal to NULL, it will be filled
2898 * in with a pointer to our static area that has
2899 * the option filled in. This will be 32bit aligned.
2900 *
2901 * *lenp: This will be filled in with how long the option
2902 * pointed to by *cpp is.
2903 *
2938 * return value is -1, there was a syntax error in the
2939 * option, either unknown characters, or too many hosts.
2940 * If the return value is 0, one of the hostnames in the
2941 * path is unknown, and *cpp is set to point to the bad
2942 * hostname.
2943 *
2944 * *cpp: If *cpp was equal to NULL, it will be filled
2945 * in with a pointer to our static area that has
2946 * the option filled in. This will be 32bit aligned.
2947 *
2948 * *lenp: This will be filled in with how long the option
2949 * pointed to by *cpp is.
2950 *
2951 * *protop: This will be filled in with appropriate protocol for
2952 * setsockopt, as socket protocol family.
2953 *
2954 * *optp: This will be filled in with appropriate option for
2955 * setsockopt, as socket protocol family.
2904 */
2956 */
2905 unsigned long
2906sourceroute(arg, cpp, lenp)
2957int
2958sourceroute(ai, arg, cpp, lenp, protop, optp)
2959 struct addrinfo *ai;
2907 char *arg;
2908 char **cpp;
2909 int *lenp;
2960 char *arg;
2961 char **cpp;
2962 int *lenp;
2963 int *protop;
2964 int *optp;
2910{
2965{
2911 static char lsr[44];
2966 static char buf[1024]; /*XXX*/
2967 struct cmsghdr *cmsg;
2912#ifdef sysV88
2913 static IOPTN ipopt;
2914#endif
2968#ifdef sysV88
2969 static IOPTN ipopt;
2970#endif
2915 char *cp, *cp2, *lsrp, *lsrep;
2971 char *cp, *cp2, *lsrp, *ep;
2916 register int tmp;
2972 register int tmp;
2917 struct in_addr sin_addr;
2918 register struct hostent *host = 0;
2973 struct sockaddr_in *sin;
2974 struct sockaddr_in6 *sin6;
2975 struct addrinfo hints, *res;
2976 int error;
2919 register char c;
2920
2921 /*
2922 * Verify the arguments, and make sure we have
2923 * at least 7 bytes for the option.
2924 */
2925 if (cpp == NULL || lenp == NULL)
2926 return((unsigned long)-1);
2977 register char c;
2978
2979 /*
2980 * Verify the arguments, and make sure we have
2981 * at least 7 bytes for the option.
2982 */
2983 if (cpp == NULL || lenp == NULL)
2984 return((unsigned long)-1);
2927 if (*cpp != NULL && *lenp < 7)
2928 return((unsigned long)-1);
2985 if (*cpp != NULL) {
2986 switch (res->ai_family) {
2987 case AF_INET:
2988 if (*lenp < 7)
2989 return((unsigned long)-1);
2990 break;
2991#ifdef INET6
2992 case AF_INET6:
2993 if (*lenp < (sizeof(struct cmsghdr) +
2994 sizeof(struct ip6_rthdr) +
2995 sizeof(struct in6_addr)))
2996 return((unsigned long)-1);
2997 break;
2998#endif
2999 }
3000 }
2929 /*
2930 * Decide whether we have a buffer passed to us,
2931 * or if we need to use our own static buffer.
2932 */
2933 if (*cpp) {
2934 lsrp = *cpp;
3001 /*
3002 * Decide whether we have a buffer passed to us,
3003 * or if we need to use our own static buffer.
3004 */
3005 if (*cpp) {
3006 lsrp = *cpp;
2935 lsrep = lsrp + *lenp;
3007 ep = lsrp + *lenp;
2936 } else {
3008 } else {
2937 *cpp = lsrp = lsr;
2938 lsrep = lsrp + 44;
3009 *cpp = lsrp = buf;
3010 ep = lsrp + 1024;
2939 }
2940
2941 cp = arg;
2942
3011 }
3012
3013 cp = arg;
3014
3015#ifdef INET6
3016 if (ai->ai_family == AF_INET6) {
3017 cmsg = inet6_rthdr_init(*cpp, IPV6_RTHDR_TYPE_0);
3018 if (*cp != '@')
3019 return -1;
3020 *protop = IPPROTO_IPV6;
3021 *optp = IPV6_PKTOPTIONS;
3022 } else
3023#endif
3024 {
2943 /*
2944 * Next, decide whether we have a loose source
2945 * route or a strict source route, and fill in
2946 * the begining of the option.
2947 */
2948#ifndef sysV88
2949 if (*cp == '!') {
2950 cp++;

--- 10 unchanged lines hidden (view full) ---

2961
2962 if (*cp != '@')
2963 return((unsigned long)-1);
2964
2965#ifndef sysV88
2966 lsrp++; /* skip over length, we'll fill it in later */
2967 *lsrp++ = 4;
2968#endif
3025 /*
3026 * Next, decide whether we have a loose source
3027 * route or a strict source route, and fill in
3028 * the begining of the option.
3029 */
3030#ifndef sysV88
3031 if (*cp == '!') {
3032 cp++;

--- 10 unchanged lines hidden (view full) ---

3043
3044 if (*cp != '@')
3045 return((unsigned long)-1);
3046
3047#ifndef sysV88
3048 lsrp++; /* skip over length, we'll fill it in later */
3049 *lsrp++ = 4;
3050#endif
3051 *protop = IPPROTO_IP;
3052 *optp = IP_OPTIONS;
3053 }
2969
2970 cp++;
3054
3055 cp++;
2971
2972 sin_addr.s_addr = 0;
2973
3056 memset(&hints, 0, sizeof(hints));
3057 hints.ai_family = ai->ai_family;
3058 hints.ai_socktype = SOCK_STREAM;
2974 for (c = 0;;) {
3059 for (c = 0;;) {
2975 if (c == ':')
3060 if (
3061#ifdef INET6
3062 ai->ai_family != AF_INET6 &&
3063#endif
3064 c == ':')
2976 cp2 = 0;
2977 else for (cp2 = cp; (c = *cp2); cp2++) {
2978 if (c == ',') {
2979 *cp2++ = '\0';
2980 if (*cp2 == '@')
2981 cp2++;
2982 } else if (c == '@') {
2983 *cp2++ = '\0';
3065 cp2 = 0;
3066 else for (cp2 = cp; (c = *cp2); cp2++) {
3067 if (c == ',') {
3068 *cp2++ = '\0';
3069 if (*cp2 == '@')
3070 cp2++;
3071 } else if (c == '@') {
3072 *cp2++ = '\0';
2984 } else if (c == ':') {
3073 } else if (
3074#ifdef INET6
3075 ai->ai_family != AF_INET6 &&
3076#endif
3077 c == ':') {
2985 *cp2++ = '\0';
2986 } else
2987 continue;
2988 break;
2989 }
2990 if (!c)
2991 cp2 = 0;
2992
3078 *cp2++ = '\0';
3079 } else
3080 continue;
3081 break;
3082 }
3083 if (!c)
3084 cp2 = 0;
3085
2993 if ((tmp = inet_addr(cp)) != -1) {
2994 sin_addr.s_addr = tmp;
2995 } else if ((host = gethostbyname(cp))) {
2996#if defined(h_addr)
2997 memmove((caddr_t)&sin_addr,
2998 host->h_addr_list[0], host->h_length);
2999#else
3000 memmove((caddr_t)&sin_addr, host->h_addr, host->h_length);
3001#endif
3002 } else {
3086 hints.ai_flags = AI_NUMERICHOST;
3087 error = getaddrinfo(cp, NULL, &hints, &res);
3088 if (error == EAI_NONAME) {
3089 hints.ai_flags = 0;
3090 error = getaddrinfo(cp, NULL, &hints, &res);
3091 }
3092 if (error != 0) {
3093 fprintf(stderr, "%s: %s\n", cp, gai_strerror(error));
3094 if (error == EAI_SYSTEM)
3095 fprintf(stderr, "%s: %s\n", cp,
3096 strerror(errno));
3003 *cpp = cp;
3004 return(0);
3005 }
3097 *cpp = cp;
3098 return(0);
3099 }
3006 memmove(lsrp, (char *)&sin_addr, 4);
3100#ifdef INET6
3101 if (res->ai_family == AF_INET6) {
3102 sin6 = (struct sockaddr_in6 *)res->ai_addr;
3103 inet6_rthdr_add(cmsg, &sin6->sin6_addr,
3104 IPV6_RTHDR_LOOSE);
3105 } else
3106#endif
3107 {
3108 sin = (struct sockaddr_in *)res->ai_addr;
3109 memcpy(lsrp, (char *)&sin->sin_addr, 4);
3007 lsrp += 4;
3110 lsrp += 4;
3111 }
3008 if (cp2)
3009 cp = cp2;
3010 else
3011 break;
3012 /*
3013 * Check to make sure there is space for next address
3014 */
3112 if (cp2)
3113 cp = cp2;
3114 else
3115 break;
3116 /*
3117 * Check to make sure there is space for next address
3118 */
3015 if (lsrp + 4 > lsrep)
3119#ifdef INET6
3120 if (res->ai_family == AF_INET6) {
3121 if (((char *)cmsg +
3122 sizeof(struct cmsghdr) +
3123 sizeof(struct ip6_rthdr) +
3124 ((inet6_rthdr_segments(cmsg) + 1) *
3125 sizeof(struct in6_addr))) > ep)
3016 return((unsigned long)-1);
3126 return((unsigned long)-1);
3127 } else
3128#endif
3129 if (lsrp + 4 > ep)
3130 return((unsigned long)-1);
3131 freeaddrinfo(res);
3017 }
3132 }
3133#ifdef INET6
3134 if (res->ai_family == AF_INET6) {
3135 inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
3136 *lenp = cmsg->cmsg_len;
3137 } else
3138#endif
3139 {
3018#ifndef sysV88
3019 if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
3020 *cpp = 0;
3021 *lenp = 0;
3022 return((unsigned long)-1);
3023 }
3024 *lsrp++ = IPOPT_NOP; /* 32 bit word align it */
3025 *lenp = lsrp - *cpp;
3026#else
3027 ipopt.io_len = lsrp - *cpp;
3028 if (ipopt.io_len <= 5) { /* Is 3 better ? */
3029 *cpp = 0;
3030 *lenp = 0;
3031 return((unsigned long)-1);
3032 }
3033 *lenp = sizeof(ipopt);
3034 *cpp = (char *) &ipopt;
3035#endif
3140#ifndef sysV88
3141 if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
3142 *cpp = 0;
3143 *lenp = 0;
3144 return((unsigned long)-1);
3145 }
3146 *lsrp++ = IPOPT_NOP; /* 32 bit word align it */
3147 *lenp = lsrp - *cpp;
3148#else
3149 ipopt.io_len = lsrp - *cpp;
3150 if (ipopt.io_len <= 5) { /* Is 3 better ? */
3151 *cpp = 0;
3152 *lenp = 0;
3153 return((unsigned long)-1);
3154 }
3155 *lenp = sizeof(ipopt);
3156 *cpp = (char *) &ipopt;
3157#endif
3036 return(sin_addr.s_addr);
3158 }
3159 freeaddrinfo(res);
3160 return 1;
3037}
3161}
3038#endif
3162
3163
3164