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 |