1 /* vi:ai:et:ts=8 sw=2
2  */
3 /*
4  * wzdftpd - a modular and cool ftp server
5  * Copyright (C) 2002-2006  Pierre Chifflier
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * As a special exemption, Pierre Chifflier
22  * and other respective copyright holders give permission to link this program
23  * with OpenSSL, and distribute the resulting executable, without including
24  * the source code for OpenSSL in the source distribution.
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 
31 #ifdef USE_BONJOUR
32 
33 #include "libwzd_bonjour.h"
34 
35 DNSServiceRef publish_session = NULL;
36 
37 #ifdef WIN32
38 static void DNSSD_API
39 #else
40 static void
41 #endif
publish_reply(DNSServiceRef sdRef,const DNSServiceFlags flags,DNSServiceErrorType errorCode,const char * name,const char * regtype,const char * domain,void * context)42 publish_reply (DNSServiceRef sdRef,
43          const DNSServiceFlags flags,
44          DNSServiceErrorType errorCode,
45          const char *name,
46          const char *regtype,
47          const char *domain,
48          void *context)
49 {
50 }
51 
bo_zeroconf_setup(unsigned long port,const char * name,const char * username,const char * password,const char * path)52 void* bo_zeroconf_setup(unsigned long port,
53                         const char *name,
54                         const char *username,
55                         const char *password,
56                         const char *path) {
57   DNSServiceErrorType err;
58 #ifdef HAVE_OSX_TIGER
59   TXTRecordRef txtRecord;
60 #endif
61   char service[256] = "WZDFTP Server on ";
62 
63   /* Prepare service name */
64   if (!name) {
65     out_log(LEVEL_INFO, "Assigning default service name.\n");
66     gethostname(service+17, sizeof(service)-18);
67     service[sizeof(service)-1] = 0;
68 
69     name = strdup(service);
70   }
71 
72   if (!name) return NULL;
73   if (!port) return NULL;
74 
75 #ifdef HAVE_OSX_TIGER
76   /* prepare text records */
77   TXTRecordCreate(&txtRecord, 0, 0);
78 
79   /* assign TXT keys if any */
80   if (username) {
81     if (TXTRecordSetValue(&text_record,
82                           "u",
83                           8,
84                           username) != kDNSServiceErr_NoError) {
85       out_log(LEVEL_CRITICAL, "Adding TXT record %s=%s failed\n", "u", username);
86 
87       TXTRecordDeallocate(&txt_record);
88       bo_zeroconf_unregister();
89     }
90     else {
91       txt_rec_len++;
92     }
93   }
94   if (password) {
95     if (TXTRecordSetValue(&text_record,
96                           "p",
97                           8,
98                           password) != kDNSServiceErr_NoError) {
99       out_log(LEVEL_CRITICAL, "Adding TXT record %s=%s failed\n", "p", password);
100 
101       TXTRecordDeallocate(&txt_record);
102       bo_zeroconf_unregister();
103     }
104     else {
105       txt_rec_len++;
106     }
107   }
108   if (path) {
109     if (TXTRecordSetValue(&text_record
110                           "path",
111                           4,
112                           path) != kDNSServiceErr_NoError) {
113       out_log(LEVEL_CRITICAL, "Adding TXT record %s=%s failed\n", "path", path);
114 
115       TXTRecordDeallocate(&txt_record);
116       bo_zeroconf_unregister();
117     }
118     else {
119       txt_rec_len++;
120     }
121   }
122 #else
123   out_log(LEVEL_INFO,
124           "You did provide certain TXT keys.\n"
125           "Unfortunatly this particular OSX version is not able to publish TXT keys.\n");
126 #endif
127 
128   err = DNSServiceRegister (&publish_session,
129                             0,                          /* flags */
130                             0,                          /* interface; 0 for all */
131                             name,                       /* name */
132                             FTP_DNS_SERVICE_TYPE,       /* type */
133                             NULL,                       /* domain */
134                             NULL,                       /* hostname */
135                             htons (port),               /* port in network byte order */
136 #ifdef HAVE_OSX_TIGER
137                             TXTRecordGetLength(&txt),   /* text record length */
138                             TXTRecordGetBytesPtr(&txt), /* text record */
139 #else
140                             0,
141                             NULL,
142 #endif
143                             publish_reply,              /* callback */
144                             NULL);                      /* context */
145 
146 #ifdef HAVE_OSX_TIGER
147   TXTRecordDeallocate(&txt_record);
148 #endif
149 
150   if (err == kDNSServiceErr_NoError) {
151     out_log(LEVEL_INFO, "Adding service '%s'\n", name);
152   } else {
153     out_log(LEVEL_CRITICAL, "Adding service '%s' failed\n", name);
154     bo_zeroconf_unregister();
155   }
156 }
157 
bo_zeroconf_run(void)158 int bo_zeroconf_run(void) {
159   fd_set set;
160   int fd;
161   struct timeval timeout;
162 
163   /* Initialize the file descriptor set. */
164   FD_ZERO (&set);
165   FD_SET (fd, &set);
166 
167   /* Initialize the timeout data structure. */
168   /* TODO: Should the value for sec be configurable? */
169   timeout.tv_sec = 10;
170   timeout.tv_usec = 0;
171 
172   if (publish_session != NULL) {
173     fd = DNSServiceRefSockFD(publish_session);
174 
175     if (select(FD_SETSIZE,
176                   &set, NULL, NULL,
177                   &timeout) > 0) {
178       DNSServiceProcessResult(publish_session);
179     }
180   }
181 
182   return 0;
183 }
184 
bo_zeroconf_unregister(void)185 int bo_zeroconf_unregister(void) {
186   if (publish_session != NULL) {
187     DNSServiceRefDeallocate(publish_session);
188     publish_session = NULL;
189   }
190 
191   return 0;
192 }
193 
194 #endif /* USE_BONJOUR */
195