~ubuntu-branches/ubuntu/dapper/sup/dapper

« back to all changes in this revision

Viewing changes to scm.c

  • Committer: Bazaar Package Importer
  • Author(s): Jochen Friedrich
  • Date: 2003-12-30 22:02:24 UTC
  • Revision ID: james.westby@ubuntu.com-20031230220224-g6rzexudlhhtk3nv
Tags: 1.8-10
* Bumped standards version to 3.6.1 (no changes required).
* Fixed errno handling (Thanks to Thorsten Sauter <tsauter@debian.org>
  for the patch) (Closes: #223422).
* Corrected debian/copyright.
* Documented IPv6 options in man page.

Show diffs side-by-side

added added

removed removed

Lines of Context:
175
175
 */
176
176
 
177
177
#include <libc.h>
 
178
#include <stdlib.h>
178
179
#include <errno.h>
179
180
#include <sys/param.h>
180
181
#include <sys/types.h>
190
191
#else
191
192
#include <varargs.h>
192
193
#endif
 
194
#include <ifaddrs.h>
193
195
#include "sup.h"
194
196
 
195
197
#ifndef INADDR_NONE
227
229
int netfile = -1;                       /* network file descriptor */
228
230
 
229
231
static int sock = -1;                   /* socket used to make connection */
230
 
static struct in_addr remoteaddr;       /* remote host address */
 
232
static struct sockaddr_storage remoteaddr; /* remote host address */
231
233
static char *remotename = NULL;         /* remote host name */
232
234
static int swapmode;                    /* byte-swapping needed on server? */
233
235
 
236
238
 ***    F O R   S E R V E R                      ***
237
239
 ***************************************************/
238
240
 
239
 
servicesetup (server)           /* listen for clients */
 
241
servicesetup (server, af)               /* listen for clients */
240
242
char *server;
 
243
int af;
241
244
{
242
 
        struct sockaddr_in sin;
243
 
        struct servent *sp;
244
 
        short port;
 
245
        struct addrinfo hints, *res0, *res;
 
246
        char port[NI_MAXSERV];
 
247
        int error;
 
248
        const char *cause = "unknown";
245
249
        int one = 1;
246
250
 
247
 
        if (myhost () == NULL)
248
 
                return (scmerr (-1,"Local hostname not known"));
249
 
        if ((sp = getservbyname(server,"tcp")) == 0) {
 
251
        memset(&hints, 0, sizeof(hints));
 
252
        hints.ai_family = af;
 
253
        hints.ai_socktype = SOCK_STREAM;
 
254
        hints.ai_socktype = AI_PASSIVE;
 
255
        error = getaddrinfo(NULL, server, &hints, &res0);
 
256
        if (error) {
 
257
                /* retry with precompiled knowledge */
250
258
                if (strcmp(server, FILEPORT) == 0)
251
 
                        port = htons((u_short)FILEPORTNUM);
 
259
                        snprintf(port, sizeof(port), "%u", FILEPORTNUM);
252
260
                else if (strcmp(server, DEBUGFPORT) == 0)
253
 
                        port = htons((u_short)DEBUGFPORTNUM);
 
261
                        snprintf(port, sizeof(port), "%u", DEBUGFPORTNUM);
254
262
                else
255
 
                        return (scmerr (-1,"Can't find %s server description",server));
256
 
                (void) scmerr (-1,"%s/tcp: unknown service: using port %d",
257
 
                                        server,port);
258
 
        } else
259
 
                port = sp->s_port;
260
 
        endservent ();
261
 
        sock = socket (AF_INET,SOCK_STREAM,0);
262
 
        if (sock < 0)
263
 
                return (scmerr (errno,"Can't create socket for connections"));
264
 
        if (setsockopt (sock,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0)
265
 
                (void) scmerr (errno,"Can't set SO_REUSEADDR socket option");
266
 
        (void) bzero ((char *)&sin,sizeof(sin));
267
 
        sin.sin_family = AF_INET;
268
 
        sin.sin_port = port;
269
 
        if (bind (sock,(struct sockaddr *)&sin,sizeof(sin)) < 0)
270
 
                return (scmerr (errno,"Can't bind socket for connections"));
271
 
        if (listen (sock,NCONNECTS) < 0)
272
 
                return (scmerr (errno,"Can't listen on socket"));
273
 
        return (SCMOK);
 
263
                        port[0] = '\0';
 
264
                if (port[0])
 
265
                        error = getaddrinfo(NULL, port, &hints, &res0);
 
266
                if (error)
 
267
                        return (scmerr (-1, "%s: %s", server,
 
268
                            gai_strerror(error)));
 
269
        }
 
270
        for (res = res0; res; res = res->ai_next) {
 
271
                sock = socket(res->ai_family, res->ai_socktype,
 
272
                    res->ai_protocol);
 
273
                if (sock < 0) {
 
274
                        cause = "socket";
 
275
                        continue;
 
276
                }
 
277
                if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
 
278
                    (char *)&one, sizeof(int)) < 0) {
 
279
                        cause = "setsockopt(SO_REUSEADDR)";
 
280
                        close(sock);
 
281
                        continue;
 
282
                }
 
283
                if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
 
284
                        cause = "bind";
 
285
                        close(sock);
 
286
                        continue;
 
287
                }
 
288
                if (listen(sock, NCONNECTS) < 0) {
 
289
                        cause = "listen";
 
290
                        close(sock);
 
291
                        continue;
 
292
                }
 
293
 
 
294
                freeaddrinfo(res0);
 
295
                return SCMOK;
 
296
        }
 
297
 
 
298
        freeaddrinfo(res0);
 
299
        return (scmerr (errno, "%s", cause));
274
300
}
275
301
 
276
302
service ()
277
303
{
278
 
        struct sockaddr_in from;
 
304
        struct sockaddr_storage from;
279
305
        int x,len;
280
306
 
281
307
        remotename = NULL;
285
311
        } while (netfile < 0 && errno == EINTR);
286
312
        if (netfile < 0)
287
313
                return (scmerr (errno,"Can't accept connections"));
288
 
        remoteaddr = from.sin_addr;
 
314
        if (len > sizeof(remoteaddr)) {
 
315
                close(netfile);
 
316
                return (scmerr (errno,"Can't accept connections"));
 
317
        }
 
318
        memcpy(&remoteaddr, &from, len);
289
319
        if (read(netfile,(char *)&x,sizeof(int)) != sizeof(int))
290
320
                return (scmerr (errno,"Can't transmit data on connection"));
291
321
        if (x == 0x01020304)
364
394
char *hostname;
365
395
int *retry;
366
396
{
367
 
        int x, backoff;
368
 
        struct hostent *h;
369
 
        struct servent *sp;
370
 
        struct sockaddr_in sin, tin;
371
 
        short port;
 
397
        struct addrinfo hints, *res, *res0;
 
398
        int error;
 
399
        char port[NI_MAXSERV];
 
400
        int backoff;
 
401
        int x;
372
402
 
373
 
        if ((sp = getservbyname(server,"tcp")) == 0) {
 
403
        memset(&hints, 0, sizeof(hints));
 
404
        hints.ai_family = PF_UNSPEC;
 
405
        hints.ai_socktype = SOCK_STREAM;
 
406
        error = getaddrinfo(hostname, server, &hints, &res0);
 
407
        if (error) {
 
408
                /* retry with precompiled knowledge */
374
409
                if (strcmp(server, FILEPORT) == 0)
375
 
                        port = htons((u_short)FILEPORTNUM);
 
410
                        snprintf(port, sizeof(port), "%u", FILEPORTNUM);
376
411
                else if (strcmp(server, DEBUGFPORT) == 0)
377
 
                        port = htons((u_short)DEBUGFPORTNUM);
 
412
                        snprintf(port, sizeof(port), "%u", DEBUGFPORTNUM);
378
413
                else
379
 
                        return (scmerr (-1,"Can't find %s server description",
380
 
                                        server));
381
 
                (void) scmerr (-1,"%s/tcp: unknown service: using port %d",
382
 
                                        server,port);
383
 
        } else
384
 
                port = sp->s_port;
385
 
        (void) bzero ((char *)&sin,sizeof(sin));
386
 
        sin.sin_family = AF_INET;
387
 
        sin.sin_addr.s_addr = inet_addr (hostname);
388
 
        if (sin.sin_addr.s_addr == (u_long) INADDR_NONE) {
389
 
                if ((h = gethostbyname (hostname)) == NULL)
390
 
                        return (scmerr (-1,"Can't find host entry for %s",
391
 
                                        hostname));
392
 
                hostname = h->h_name;
393
 
                (void) bcopy (h->h_addr,(char *)&sin.sin_addr,h->h_length);
 
414
                        port[0] = '\0';
 
415
                if (port[0])
 
416
                        error = getaddrinfo(hostname, port, &hints, &res0);
 
417
                if (error)
 
418
                        return (scmerr (-1, "%s: %s", server,
 
419
                            gai_strerror(error)));
394
420
        }
395
 
        sin.sin_port = port;
396
421
        backoff = 1;
397
 
        for (;;) {
398
 
                netfile = socket (AF_INET,SOCK_STREAM,0);
399
 
                if (netfile < 0)
400
 
                        return (scmerr (errno,"Can't create socket"));
401
 
                tin = sin;
402
 
                if (connect(netfile,(struct sockaddr *)&tin,sizeof(tin)) >= 0)
403
 
                        break;
404
 
                (void) scmerr (errno,"Can't connect to server for %s",server);
405
 
                (void) close(netfile);
406
 
                if (!dobackoff (retry,&backoff))
407
 
                        return (SCMERR);
 
422
        while (1) {
 
423
                netfile = -1;
 
424
                for (res = res0; res; res = res->ai_next) {
 
425
                        if (res->ai_addrlen > sizeof(remoteaddr))
 
426
                                continue;
 
427
                        netfile = socket(res->ai_family, res->ai_socktype,
 
428
                            res->ai_protocol);
 
429
                        if (netfile < 0)
 
430
                                continue;
 
431
                        if (connect(netfile, res->ai_addr, res->ai_addrlen) < 0) {
 
432
                                close(netfile);
 
433
                                netfile = -1;
 
434
                                continue;
 
435
                        }
 
436
 
 
437
                        break;
 
438
                }
 
439
 
 
440
                if (netfile < 0) {
 
441
                        if (!dobackoff (retry, &backoff)) {
 
442
                                freeaddrinfo(res0);
 
443
                                return (SCMERR);
 
444
                        }
 
445
                        continue;
 
446
                } else
 
447
                        break;
408
448
        }
409
 
        remoteaddr = sin.sin_addr;
 
449
 
 
450
        memcpy(&remoteaddr, res->ai_addr, res->ai_addrlen);
410
451
        remotename = salloc(hostname);
411
452
        x = 0x01020304;
412
453
        (void) write (netfile,(char *)&x,sizeof(int));
413
454
        swapmode = 0;           /* swap only on server, not client */
 
455
        freeaddrinfo(res0);
414
456
        return (SCMOK);
415
457
}
416
458
 
451
493
 
452
494
char *remotehost ()     /* remote host name (if known) */
453
495
{
454
 
        register struct hostent *h;
 
496
        char h1[NI_MAXHOST];
455
497
 
456
498
        if (remotename == NULL) {
457
 
                h = gethostbyaddr ((char *)&remoteaddr,sizeof(remoteaddr),
458
 
                                    AF_INET);
459
 
                remotename = salloc (h ? h->h_name : inet_ntoa(remoteaddr));
 
499
                if (getnameinfo((struct sockaddr *)&remoteaddr,
 
500
                    sizeof(remoteaddr), h1, sizeof(h1), NULL, 0, 0))
 
501
                        return("UNKNOWN");
 
502
                remotename = salloc (h1);
460
503
                if (remotename == NULL)
461
504
                        return("UNKNOWN");
462
505
        }
478
521
 
479
522
int samehost ()         /* is remote host same as local host? */
480
523
{
481
 
        static struct in_addr *intp;
482
 
        static int nint = 0;
483
 
        struct in_addr *ifp;
484
 
        int n;
485
 
 
486
 
        if (nint <= 0) {
487
 
                int s;
488
 
                char buf[BUFSIZ];
489
 
                struct ifconf ifc;
490
 
                struct ifreq *ifr;
491
 
                struct sockaddr_in sin;
492
 
 
493
 
                if ((s = socket (AF_INET,SOCK_DGRAM,0)) < 0)
494
 
                        logquit (1,"Can't create socket for SIOCGIFCONF");
495
 
                ifc.ifc_len = sizeof(buf);
496
 
                ifc.ifc_buf = buf;
497
 
                if (ioctl (s,SIOCGIFCONF,(char *)&ifc) < 0)
498
 
                        logquit (1,"SIOCGIFCONF failed");
499
 
                (void) close(s);
500
 
                if ((nint = ifc.ifc_len/sizeof(struct ifreq)) <= 0)
501
 
                        return (0);
502
 
                intp = (struct in_addr *)
503
 
                        malloc ((unsigned) nint*sizeof(struct in_addr));
504
 
                if ((ifp = intp) == 0)
505
 
                        logquit (1,"no space for interfaces");
506
 
                for (ifr = ifc.ifc_req, n = nint; n > 0; --n, ifr++) {
507
 
                        (void) bcopy ((char *)&ifr->ifr_addr,(char *)&sin,sizeof(sin));
508
 
                        *ifp++ = sin.sin_addr;
 
524
        struct ifaddrs *ifap, *ifa;
 
525
        char h1[NI_MAXHOST], h2[NI_MAXHOST];
 
526
        int len;
 
527
#ifdef NI_WITHSCOPEID
 
528
        const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
 
529
#else
 
530
        const int niflags = NI_NUMERICHOST;
 
531
#endif
 
532
 
 
533
        if (getnameinfo((struct sockaddr *)&remoteaddr, sizeof(remoteaddr),
 
534
            h1, sizeof(h1), NULL, 0, niflags))
 
535
                return (0);
 
536
        if (getifaddrs(&ifap) < 0)
 
537
                return (0);
 
538
        for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
 
539
                if (remoteaddr.ss_family != ifa->ifa_addr->sa_family)
 
540
                        continue;
 
541
                if (ifa->ifa_addr->sa_family == AF_INET)
 
542
                        len = sizeof(struct sockaddr_in);
 
543
                else if (ifa->ifa_addr->sa_family == AF_INET6)
 
544
                        len = sizeof(struct sockaddr_in6);
 
545
                else
 
546
                        continue;
 
547
                if (getnameinfo(ifa->ifa_addr, len,
 
548
                    h2, sizeof(h2), NULL, 0, niflags))
 
549
                        continue;
 
550
                if (strcmp(h1, h2) == 0) {
 
551
                        freeifaddrs(ifap);
 
552
                        return (1);
509
553
                }
510
554
        }
511
 
        if (remoteaddr.s_addr == htonl(INADDR_LOOPBACK))
512
 
                return (1);
513
 
        for (ifp = intp, n = nint; n > 0; --n, ifp++)
514
 
                if (remoteaddr.s_addr == ifp->s_addr)
515
 
                        return (1);
 
555
        freeifaddrs(ifap);
516
556
        return (0);
517
557
}
518
558
 
519
559
int matchhost (name)    /* is this name of remote host? */
520
560
char *name;
521
561
{
522
 
        struct hostent *h;
523
 
        struct in_addr addr;
524
 
        char **ap;
525
 
        if ((addr.s_addr = inet_addr(name)) != (u_long) INADDR_NONE)
526
 
                return (addr.s_addr == remoteaddr.s_addr);
527
 
        if ((h = gethostbyname (name)) == 0)
528
 
                return (0);
529
 
        if (h->h_addrtype != AF_INET || h->h_length != sizeof(struct in_addr))
530
 
                return (0);
531
 
        for (ap = h->h_addr_list; *ap; ap++)
532
 
                if (bcmp ((char *)&remoteaddr,*ap,h->h_length) == 0)
 
562
        char h1[NI_MAXHOST], h2[NI_MAXHOST];
 
563
#ifdef NI_WITHSCOPEID
 
564
        const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
 
565
#else
 
566
        const int niflags = NI_NUMERICHOST;
 
567
#endif
 
568
        struct addrinfo hints, *res0, *res;
 
569
 
 
570
        if (getnameinfo((struct sockaddr *)&remoteaddr, sizeof(remoteaddr),
 
571
            h1, sizeof(h1), NULL, 0, niflags))
 
572
                return (0);
 
573
        memset(&hints, 0, sizeof(hints));
 
574
        hints.ai_family = PF_UNSPEC;
 
575
        hints.ai_socktype = SOCK_DGRAM; /*dummy*/
 
576
        hints.ai_flags = AI_NUMERICHOST;
 
577
        if (getaddrinfo(name, "0", &hints, &res0) != 0)
 
578
                return (0);
 
579
        for (res = res0; res; res = res->ai_next) {
 
580
                if (remoteaddr.ss_family != res->ai_family)
 
581
                        continue;
 
582
                if (getnameinfo(res->ai_addr, res->ai_addrlen,
 
583
                    h2, sizeof(h2), NULL, 0, niflags))
 
584
                        continue;
 
585
                if (strcmp(h1, h2) == 0) {
 
586
                        freeaddrinfo(res0);
533
587
                        return (1);
 
588
                }
 
589
        }
 
590
        freeaddrinfo(res0);
534
591
        return (0);
535
592
}
536
593
 
537
594
#if __STDC__
538
 
int scmerr (int errno,char *fmt,...)
 
595
int scmerr (int erno,char *fmt,...)
539
596
#else
540
597
/*VARARGS*//*ARGSUSED*/
541
598
int scmerr (va_alist)
543
600
#endif
544
601
{
545
602
#if !__STDC__
546
 
        int errno;
 
603
        int erno;
547
604
        char *fmt;
548
605
#endif
549
606
        va_list ap;
557
614
        va_start(ap,fmt);
558
615
#else
559
616
        va_start(ap);
560
 
        errno = va_arg(ap,int);
 
617
        erno = va_arg(ap,int);
561
618
        fmt = va_arg(ap,char *);
562
619
#endif
563
620
        vfprintf(stderr, fmt, ap);
564
621
        va_end(ap);
565
 
        if (errno >= 0)
566
 
                fprintf (stderr,": %s\n",errmsg(errno));
 
622
        if (erno >= 0)
 
623
                fprintf (stderr,": %s\n",errmsg(erno));
567
624
        else
568
625
                fprintf (stderr,"\n");
569
626
        (void) fflush (stderr);