summaryrefslogtreecommitdiffstats
path: root/debian/pilot-link/pilot-link-0.12.5-dfsg/src/pilot-csd.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/pilot-link/pilot-link-0.12.5-dfsg/src/pilot-csd.c')
-rw-r--r--debian/pilot-link/pilot-link-0.12.5-dfsg/src/pilot-csd.c432
1 files changed, 432 insertions, 0 deletions
diff --git a/debian/pilot-link/pilot-link-0.12.5-dfsg/src/pilot-csd.c b/debian/pilot-link/pilot-link-0.12.5-dfsg/src/pilot-csd.c
new file mode 100644
index 00000000..e8e92094
--- /dev/null
+++ b/debian/pilot-link/pilot-link-0.12.5-dfsg/src/pilot-csd.c
@@ -0,0 +1,432 @@
+/*
+ * $Id: pilot-csd.c,v 1.44 2009/06/04 13:32:31 desrod Exp $
+ *
+ * pilot-csd.c: Connection Service Daemon, required for accepting logons via
+ * NetSync(tm)
+ *
+ * Copyright (c) 1997, Kenneth Albanowski
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "pi-source.h"
+#include "pi-dlp.h"
+#include "pi-serial.h"
+#include "pi-slp.h"
+#include "pi-header.h"
+#include "pi-userland.h"
+#include "pi-debug.h"
+
+static char hostname_[130]; /* buffer fetch_host() can write to. */
+static char *hostname = hostname_; /* pointer poptGetNextOpt() can change. */
+struct in_addr address, netmask;
+
+#ifdef HAVE_SA_LEN
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#define ifreq_size(i) max(sizeof(struct ifreq),\
+ sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
+#else
+#define ifreq_size(i) sizeof(struct ifreq)
+#endif /* HAVE_SA_LEN */
+
+/* What, me worry? */
+#ifndef IFF_POINTOPOINT
+# ifdef IFF_POINTTOPOINT
+# define IFF_POINTOPOINT IFF_POINTTOPOINT
+# endif
+#endif
+
+
+/***********************************************************************
+ *
+ * Function: fetch_host
+ *
+ * Summary: Retrieve the networking information from the host
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static void
+fetch_host(char *hostname, size_t hostlen, struct in_addr *address,
+ struct in_addr *mask)
+{
+ int i,
+ n,
+ s;
+
+ struct ifconf ifc;
+ struct ifreq *ifr, ifreqaddr, ifreqmask;
+ struct hostent *hent;
+
+#ifdef HAVE_GETHOSTNAME
+ /* Get host name the easy way */
+ gethostname(hostname, hostlen);
+#else
+#ifdef HAVE_UNAME
+ struct utsname uts;
+
+ if (uname(&uts) == 0) {
+ strncpy(hostname, uts.nodename, hostlen - 1);
+ hostname[hostlen - 1] = '\0';
+ }
+#endif /* def HAVE_UNAME */
+#endif /* def HAVE_GETHOSTNAME */
+
+ /* Get host address through DNS */
+ hent = gethostbyname(hostname);
+
+ if (hent) {
+ while (*hent->h_addr_list) {
+ struct in_addr haddr;
+
+ memcpy(&haddr, *(hent->h_addr_list++),
+ sizeof(haddr));
+ if (haddr.s_addr != inet_addr("127.0.0.1"))
+ memcpy(address, &haddr, sizeof(haddr));
+ }
+ }
+#if defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (s < 0)
+ return;
+
+ ifc.ifc_buf = calloc(1024, 1);
+ ifc.ifc_len = 1024;
+
+ if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0)
+ goto done;
+
+ n = ifc.ifc_len;
+ for (i = 0; i < n; i += ifreq_size(*ifr)) {
+ struct sockaddr_in *a;
+ struct sockaddr_in *b;
+
+ ifr = (struct ifreq *) ((caddr_t) ifc.ifc_buf + i);
+ a = (struct sockaddr_in *) &ifr->ifr_addr;
+
+ strncpy(ifreqaddr.ifr_name, ifr->ifr_name,
+ sizeof(ifreqaddr.ifr_name));
+
+ strncpy(ifreqmask.ifr_name, ifr->ifr_name,
+ sizeof(ifreqmask.ifr_name));
+
+ if (ioctl(s, SIOCGIFFLAGS, (char *) &ifreqaddr) < 0)
+ continue;
+
+ /* Reject loopback device */
+#ifdef IFF_LOOPBACK
+ if (ifreqaddr.ifr_flags & IFF_LOOPBACK)
+ continue;
+#endif /* def IFF_LOOPBACK */
+
+#ifdef IFF_UP
+ /* Reject down devices */
+ if (!(ifreqaddr.ifr_flags & IFF_UP))
+ continue;
+#endif /* def IFF_UP */
+
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+
+ /* If it is a point-to-point device, use the dest address */
+#if defined(IFF_POINTOPOINT) && defined(SIOCGIFDSTADDR)
+ if (ifreqaddr.ifr_flags & IFF_POINTOPOINT) {
+ if (ioctl(s, SIOCGIFDSTADDR, (char *) &ifreqaddr) <
+ 0)
+ break;
+
+ a = (struct sockaddr_in *) &ifreqaddr.ifr_dstaddr;
+
+ if (address->s_addr == 0) {
+ memcpy(address, &a->sin_addr,
+ sizeof(struct in_addr));
+ }
+ } else
+#endif /* defined(IFF_POINTOPOINT) && defined(SIOCGIFDSTADDR) */
+ /* If it isn't a point-to-point device, use the address */
+#ifdef SIOCGIFADDR
+ {
+ if (ioctl(s, SIOCGIFADDR, (char *) &ifreqaddr) < 0)
+ break;
+
+ a = (struct sockaddr_in *) &ifreqaddr.ifr_addr;
+
+ if (address->s_addr == 0) {
+ memcpy(address, &a->sin_addr,
+ sizeof(struct in_addr));
+ }
+ }
+#endif /* def SIOCGIFADDR */
+ /* OK, we've got an address */
+
+ /* Compare netmask against the current address and see if it
+ seems to match. */
+#ifdef SIOCGIFNETMASK
+ if (ioctl(s, SIOCGIFNETMASK, (char *) &ifreqmask) < 0)
+ break;
+
+/* Is there any system where we need to use ifr_netmask? */
+#if 1
+ b = (struct sockaddr_in *) &ifreqmask.ifr_addr;
+#else
+ b = (struct sockaddr_in *) &ifreqmask.ifr_netmask;
+#endif
+
+ if ((mask->s_addr == 0) && (address->s_addr != 0)) {
+ if ((b->sin_addr.s_addr & a->sin_addr.s_addr) ==
+ (b->sin_addr.s_addr & address->s_addr)) {
+ memcpy(mask, &b->sin_addr,
+ sizeof(struct in_addr));
+
+ /* OK, we've got a netmask */
+
+ break;
+ }
+ }
+#endif /* def SIOCGIFNETMASK */
+
+ }
+
+ done:
+ free(ifc.ifc_buf);
+ close(s);
+#endif /* defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS) */
+}
+
+int main(int argc, const char *argv[])
+{
+ const char *progname = "pi-csd";
+
+ int c, /* switch */
+ n,
+ sockfd;
+ int quiet = 0;
+
+ struct hostent *hent;
+ struct in_addr raddress;
+ struct sockaddr_in serv_addr, cli_addr;
+
+ char *addrarg = NULL,
+ *nmarg = NULL;
+
+ fd_set rset;
+ unsigned char mesg[1026];
+ unsigned int clilen;
+
+
+ poptContext po;
+
+ struct poptOption options[] = {
+ /* Don't use USERLAND_RESERVED_OPTIONS, because this thing doesn't
+ connect to the Palm at all. */
+ { "version", 0 , POPT_ARG_NONE, NULL, 'v', "Display version information", NULL},
+ { "quiet", 'q', POPT_ARG_NONE, &quiet, 0 , "Suppress messages", NULL},
+ {"hostname", 'H', POPT_ARG_STRING, &hostname, 0, "The hostname used for verification"},
+ {"address", 'a', POPT_ARG_STRING, &addrarg, 0, "IP address of the host","name-or-IP"},
+ {"netmask", 'n', POPT_ARG_STRING, &nmarg, 0, "The subnet mask of the address","dotted-quad"},
+ POPT_AUTOHELP
+ POPT_TABLEEND
+ };
+
+ memset(&address, 0, sizeof(address));
+ memset(&netmask, 0, sizeof(netmask));
+ hostname[0] = 0;
+ fetch_host(hostname, 128, &address, &netmask);
+
+ po = poptGetContext(progname, argc, argv, options, 0);
+ poptSetOtherOptionHelp(po,"\n\n"
+ " Connection Service Daemon for Palm Devices\n\n"
+ " Example arguments:\n"
+ " -H \"localhost\" -a 127.0.0.1 -n 255.255.255.0\n\n");
+
+ if (argc < 2) {
+ poptPrintUsage(po,stderr,0);
+ return 1;
+ }
+
+ while ((c = poptGetNextOpt(po)) >= 0) {
+ switch (c) {
+ case 'v':
+ print_splash(progname);
+ return 0;
+ default:
+ fprintf(stderr," ERROR: Unhandled option %d.\n",c);
+ return 1;
+ }
+ }
+
+ if (!addrarg) {
+ fprintf(stderr," ERROR: Must give an address with -a.\n");
+ return 1;
+ }
+
+ if (!inet_pton(AF_INET, addrarg, &address)) {
+ if ((hent = gethostbyname(addrarg))) {
+ memcpy(&address.s_addr,
+ hent->h_addr,
+ sizeof(address));
+ } else {
+ fprintf(stderr," ERROR: Invalid address '%s'\n\n",addrarg);
+ return 1;
+ }
+ }
+
+
+ if (nmarg) {
+ if (!inet_pton(AF_INET, nmarg, &netmask)) {
+ fprintf(stderr," ERROR: Invalid netmask '%s'\n\n",nmarg);
+ return 1;
+ }
+ }
+
+ /* cannot execute without address and hostname */
+ if ((address.s_addr == 0) || (strlen(hostname) == 0)) {
+ fprintf(stderr," ERROR: Must give an address and a hostname.\n");
+ return -1;
+ }
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0) {
+ fprintf(stderr," ERROR: Unable to get socket: %s\n",strerror(errno));
+ return 1;
+ }
+
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ serv_addr.sin_port = htons(14237);
+
+ if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
+ < 0) {
+ fprintf(stderr," ERROR: Unable to bind socket: %s\n",strerror(errno));
+ return 1;
+ }
+
+ if (!quiet) {
+ fprintf(stdout,
+ "%s(%d): Connection Service Daemon for Palm Computing(tm) device active.\n",
+ progname, getpid());
+ fprintf(stdout,
+ "%s(%d): Accepting connection requests for '%s' at %s",
+ progname, getpid(), hostname, inet_ntoa(address));
+ fprintf(stdout, " with mask %s.\n", inet_ntoa(netmask));
+ }
+ for (;;) {
+ fflush(stdout);
+ clilen = sizeof(cli_addr);
+ FD_ZERO(&rset);
+ FD_SET(sockfd, &rset);
+ if (select(sockfd + 1, &rset, 0, 0, 0) < 0) {
+ fprintf(stderr," ERROR: Select failure: %s\n",strerror(errno));
+ close(sockfd);
+ return 1;
+ }
+ n = recvfrom(sockfd, mesg, 1024, 0,
+ (struct sockaddr *) &cli_addr, &clilen);
+
+ if (n < 0) {
+ continue;
+ }
+
+ mesg[n] = 0;
+
+ if (!quiet) {
+ hent =
+ gethostbyaddr((char *) &cli_addr.sin_addr.
+ s_addr, 4, AF_INET);
+ memcpy(&raddress, &cli_addr.sin_addr.s_addr, 4);
+
+ fprintf(stdout, "%s(%d): Connection from %s[%s], ",
+ progname,
+ getpid(), hent ? hent->h_name : "",
+ inet_ntoa(raddress));
+ }
+
+ if (get_short(mesg) != 0xFADE)
+ goto invalid;
+
+ if ((get_byte(mesg + 2) == 0x01) && (n > 12)) {
+ struct in_addr ip, mask;
+ char *name = mesg + 12;
+
+ memcpy(&ip, mesg + 4, 4);
+ memcpy(&mask, mesg + 8, 4);
+
+ if (!quiet) {
+ fprintf(stdout, "req '%s', %s", name,
+ inet_ntoa(ip));
+ fprintf(stdout, ", %s", inet_ntoa(mask));
+ }
+
+ if (strcmp(hostname, name) == 0) {
+ if (!quiet)
+ fprintf(stdout, " = accept.\n");
+
+ set_byte(mesg + 2, 0x02);
+ memcpy(mesg + 4, &address, 4); /* address is already in Motorola byte order */
+ n = sendto(sockfd, mesg, n, 0,
+ (struct sockaddr *) &cli_addr,
+ clilen);
+ if (n < 0) {
+ fprintf(stderr," ERROR: sendto() error: %s\n",
+ strerror(errno));
+ }
+ continue;
+ }
+ if (!quiet) {
+ fprintf(stdout, " = reject.\n");
+ }
+ continue;
+ }
+
+ invalid:
+ if (!quiet)
+ fprintf(stdout, "invalid packet of %d bytes:\n", n);
+ pi_dumpdata(mesg, n);
+ }
+
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* ex: set tabstop=4 expandtab: */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */