Kaarsemaker.net


atftp.patch
10.55 KB

288 lines

Download

zonediff.py
booking_beta.js

Preview

 1 diff -urN atftp-0.7.dfsg/atftpd.8 atftp-0.7.dfsg.patched/atftpd.8
 2 --- atftp-0.7.dfsg/atftpd.8	2004-02-13 05:03:12.000000000 +0100
 3 +++ atftp-0.7.dfsg.patched/atftpd.8	2009-04-16 19:30:15.000000000 +0200
 4 @@ -161,6 +161,15 @@
 5  printout the substitution.
 6  
 7  .TP
 8 +.B \-\-content\-generator <path>
 9 +Execute <path> to generate content for nonexisting files. If a
10 +requested file does not exist, the program will be called as <path> 
11 +--file <requested file>. The generated contents must be written to
12 +file descriptor 3,  which will be opened by atftpd using tmpfile(). 
13 +If the contents need to be stored as well, the program itself is 
14 +responsible for doing so, atftpd will not store the contents.
15 +
  1 diff -urN atftp-0.7.dfsg/atftpd.8 atftp-0.7.dfsg.patched/atftpd.8
  2 --- atftp-0.7.dfsg/atftpd.8	2004-02-13 05:03:12.000000000 +0100
  3 +++ atftp-0.7.dfsg.patched/atftpd.8	2009-04-16 19:30:15.000000000 +0200
  4 @@ -161,6 +161,15 @@
  5  printout the substitution.
  6  
  7  .TP
  8 +.B \-\-content\-generator <path>
  9 +Execute <path> to generate content for nonexisting files. If a
 10 +requested file does not exist, the program will be called as <path> 
 11 +--file <requested file>. The generated contents must be written to
 12 +file descriptor 3,  which will be opened by atftpd using tmpfile(). 
 13 +If the contents need to be stored as well, the program itself is 
 14 +responsible for doing so, atftpd will not store the contents.
 15 +
 16 +.TP
 17  .B \-\-mtftp <file>
 18  This will start a mtftp server thread for each valid entry in the
 19  supplied file. See PXE specification for detail about mtftp. An
 20 diff -urN atftp-0.7.dfsg/configure.ac atftp-0.7.dfsg.patched/configure.ac
 21 --- atftp-0.7.dfsg/configure.ac	2004-03-16 02:51:40.000000000 +0100
 22 +++ atftp-0.7.dfsg.patched/configure.ac	2009-04-13 22:36:36.000000000 +0200
 23 @@ -45,6 +45,12 @@
 24  		yes) libpcre=true ;;
 25  		no) libpcre=flase ;;
 26  	  esac], [libpcre=true])
 27 +AC_ARG_ENABLE(generated_content,
 28 +        [  --enable-generated-content enable support for generated content in the server],
 29 +	[ case "${enableval}" in
 30 +		yes) generated_content=true ;;
 31 +		no) generated_content=false ;;
 32 +	  esac], [generated_content=false])
 33  
 34  AC_ARG_ENABLE(mtftp,
 35  	[  --enable-mtftp          enable mtftp support in server],
 36 @@ -170,6 +176,10 @@
 37  		"Support for libpcre pattern subsitution")])
 38     AC_SUBST(LIBPCRE)
 39  fi
 40 +if test x$generated_content = xtrue; then
 41 +	AC_DEFINE([HAVE_GENERATED_CONTENT], 1,
 42 +                   Support for generated content)
 43 +fi
 44  
 45  dnl Checks for header files.
 46  AC_HEADER_STDC
 47 diff -urN atftp-0.7.dfsg/debian/rules atftp-0.7.dfsg.patched/debian/rules
 48 --- atftp-0.7.dfsg/debian/rules	2009-04-16 19:48:47.000000000 +0200
 49 +++ atftp-0.7.dfsg.patched/debian/rules	2009-04-13 22:36:36.000000000 +0200
 50 @@ -17,7 +17,7 @@
 51  configure-stamp:
 52  	dh_testdir
 53  	# Add here commands to configure the package.
 54 -	./configure --prefix=/usr --mandir=/usr/share/man
 55 +	./configure --prefix=/usr --mandir=/usr/share/man --enable-generated-content
 56  
 57  	touch configure-stamp
 58  
 59 diff -urN atftp-0.7.dfsg/README.GENERATED atftp-0.7.dfsg.patched/README.GENERATED
 60 --- atftp-0.7.dfsg/README.GENERATED	1970-01-01 01:00:00.000000000 +0100
 61 +++ atftp-0.7.dfsg.patched/README.GENERATED	2009-04-16 19:36:56.000000000 +0200
 62 @@ -0,0 +1,61 @@
 63 +Dynamically generating content with atftpd
 64 +------------------------------------------
 65 +
 66 +When installing many machines via PXEboot kickstart/d-i installs, it is often
 67 +useful to generate pxelinux.cfg files on demand with contents grabbed from a
 68 +database. Or when you have an Asus Wl500g router, you have only tftp available
 69 +to download data, being able to generate this data could be useful (eg. lists
 70 +of macaddresses or iptables rules).
 71 +
 72 +These were my two use cases for implementing support for dynamic content in 
 73 +atftpd. Here is how to use it:
 74 +
 75 +* Add the "--content-generator /path/to/executable" argument to the atftpd 
 76 +  commandline (eg. in xinetd.conf or /etc/default/atftpd, depending on your
 77 +  setup).
 78 +* Whenever a requested file cannot be found, atftpd will open a temporary
 79 +  file with tmpfile(3) and will execute your application, with the
 80 +  requested name as arguments (example: 
 81 +  /usr/local/bin/tftp-generator --file /var/lib/tftpboot/some_file)
 82 +  The application must ignore unknown arguments, more arguments might be added
 83 +  later.
 84 +* Your application is now responsible for writing the content that atftpd
 85 +  should send to the given fd (6 in the example). If the content needs to
 86 +  be stored, your application also must do so itself.
 87 +* If your application exists with a non-zero exitstatus or writes zero bytes,
 88 +  atftpd will treat that as "file not found". If data is written and your
 89 +  application exits with code 0, the written data is sent to the client.
 90 +
 91 +-- 
 92 +Dennis Kaarsemaker
 93 +<dennis@kaarsemaker.net>
 94 +
 95 +-------------------------------------------------------------------------------
 96 +Example application for use case #2: Grabbing a list of mac addresses from a
 97 +database. The database is maintained using the django framework.
 98 +
 99 +#!/usr/bin/python
100 +
101 +import os
102 +import sys
103 +from optparse import OptionParser
104 +
105 +parser = OptionParser()
106 +parser.add_option("--file", dest="filename", help="Requested file", metavar="FILE")
107 +options, args = parser.parse_args()
108 +
109 +if os.path.basename(options.filename) != 'maclist':
110 +    sys.exit(1)
111 +fd = os.fdopen(3, 'w')
112 +
113 +sys.path.insert(0,'/srv/www/intranet')
114 +os.environ['DJANGO_SETTINGS_MODULE'] = 'infra.settings'
115 +from infra.machine.models import Interface
116 +
117 +fd.write("""#!/bin/sh
118 +# Shellscript generated from infra database
119 +# Do not edit by hand
120 +
121 +wl mac none
122 +wl mac %s 00:00:00:00:00:00
123 +""" % ' '.join([x.mac for x in Interface.objects.filter(wireless=True)]))
124 diff -urN atftp-0.7.dfsg/redhat/atftp.spec.in atftp-0.7.dfsg.patched/redhat/atftp.spec.in
125 --- atftp-0.7.dfsg/redhat/atftp.spec.in	2003-04-29 02:36:58.000000000 +0200
126 +++ atftp-0.7.dfsg.patched/redhat/atftp.spec.in	2009-04-16 19:50:41.000000000 +0200
127 @@ -33,7 +33,7 @@
128  
129  
130  %build
131 -%configure
132 +%configure --enable-generated-files
133  make
134  
135  
136 diff -urN atftp-0.7.dfsg/tftpd.c atftp-0.7.dfsg.patched/tftpd.c
137 --- atftp-0.7.dfsg/tftpd.c	2009-04-16 19:48:47.000000000 +0200
138 +++ atftp-0.7.dfsg.patched/tftpd.c	2009-04-13 22:36:36.000000000 +0200
139 @@ -112,6 +112,10 @@
140  char *pcre_file;
141  #endif
142  
143 +#ifdef HAVE_GENERATED_CONTENT
144 +char *content_generator = NULL;
145 +#endif
146 +
147  #ifdef HAVE_MTFTP
148  /* mtftp options */
149  struct mtftp_data *mtftp_data = NULL;
150 @@ -839,6 +843,9 @@
151            { "pcre", 1, NULL, OPT_PCRE },
152            { "pcre-test", 1, NULL, OPT_PCRE_TEST },
153  #endif
154 +#ifdef HAVE_GENERATED_CONTENT
155 +          { "content-generator", 1, NULL, 'g' },
156 +#endif
157  #ifdef HAVE_MTFTP
158            { "mtftp", 1, NULL, OPT_MTFTP },
159            { "mtftp-port", 1, NULL, OPT_MTFTP_PORT },
160 @@ -968,6 +975,15 @@
161                           printf("Substitution: \"%s\" -> \"%s\"\n", string, out);
162                 }
163  #endif
164 +#ifdef HAVE_GENERATED_CONTENT
165 +          case 'g':
166 +               content_generator = strdup(optarg);
167 +               if(access(content_generator, X_OK)) {
168 +                   fprintf(stderr, "Cannot use %s as content generator: %s\n", content_generator, strerror(errno));
169 +                   content_generator = NULL;
170 +               }
171 +               break;
172 +#endif
173            case OPT_PORT_CHECK:
174                 source_port_checking = 0;
175                 break;
176 @@ -1053,6 +1069,10 @@
177       if (pcre_top)
178            logger(LOG_INFO, "  PCRE: using file: %s", pcre_file);
179  #endif
180 +#ifdef HAVE_GENERATED_CONTENT
181 +     if(content_generator)
182 +        logger(LOG_INFO, "  content generator: %s", content_generator);
183 +#endif
184  #ifdef HAVE_MTFTP
185       if (strcmp(mtftp_file, "") != 0)
186       {
187 @@ -1142,6 +1162,9 @@
188              "  --pcre <file>              : use this file for pattern replacement\n"
189              "  --pcre-test <file>         : just test pattern file, not starting server\n"
190  #endif
191 +#ifdef HAVE_GENERATED_CONTENT
192 +            "  --content-generator <path>         : use <path> to generate content\n"
193 +#endif
194  #ifdef HAVE_MTFTP
195              "  --mtftp <file>             : mtftp configuration file\n"
196              "  --mtftp-port <port>        : port mtftp will listen\n"
197 diff -urN atftp-0.7.dfsg/tftpd_file.c atftp-0.7.dfsg.patched/tftpd_file.c
198 --- atftp-0.7.dfsg/tftpd_file.c	2004-02-18 03:21:47.000000000 +0100
199 +++ atftp-0.7.dfsg.patched/tftpd_file.c	2009-04-16 19:14:25.000000000 +0200
200 @@ -36,6 +36,10 @@
201  #ifdef HAVE_PCRE
202  #include "tftpd_pcre.h"
203  #endif
204 +#ifdef HAVE_GENERATED_CONTENT
205 +#include <sys/types.h>
206 +#include <sys/wait.h>
207 +#endif
208  
209  #define S_BEGIN         0
210  #define S_SEND_REQ      1
211 @@ -60,6 +64,9 @@
212  extern tftpd_pcre_self_t *pcre_top;
213  #endif
214  
215 +#ifdef HAVE_GENERATED_CONTENT
216 +extern char* content_generator;
217 +#endif
218  
219  /*
220   * Rules for filenames. This is common to both tftpd_recieve_file
221 @@ -428,6 +435,10 @@
222       int prev_block_number = 0; /* needed to support netascii convertion */
223       int prev_file_pos = 0;
224       int temp = 0;
225 +#ifdef HAVE_GENERATED_CONTENT
226 +     pid_t generator_pid = 0;
227 +     int generator_status;
228 +#endif
229  
230       /* look for mode option */
231       if (strcasecmp(data->tftp_options[OPT_MODE].value, "netascii") == 0)
232 @@ -485,6 +496,56 @@
233            }
234       }
235  #endif
236 +#ifdef HAVE_GENERATED_CONTENT
237 +     if (fp == NULL)
238 +     {
239 +          if (content_generator)
240 +          {
241 +               logger(LOG_DEBUG, "Trying to generate contents for %s", filename);
242 +               fp = tmpfile();
243 +               generator_pid = fork();
244 +               switch(generator_pid) {
245 +                   case 0:
246 +                       /* In the child */
247 +                       close(3);
248 +                       dup2(fileno(fp), 3);
249 +                       for(temp=4; temp < 1024; temp++)
250 +                           close(temp);
251 +                       execl(content_generator, content_generator, "--file", filename, (char *)NULL);
252 +                       /* Exec failed, make sure the parent notices */
253 +                       exit(66);
254 +                       ;;
255 +                   case -1:
256 +                       logger(LOG_WARNING, "fork() failed: %s", strerror(errno));
257 +                       fclose(fp);
258 +                       fp = NULL;
259 +                   default:
260 +                       /* In the parent */
261 +                       while(1) {
262 +                            errno = 0;
263 +                            temp = waitpid(generator_pid, &generator_status, 0);
264 +                            if(temp == -1 && errno == EINTR)
265 +                                continue;
266 +                            break;
267 +                       }
268 +                       if(!WIFEXITED(generator_status) || (WEXITSTATUS(generator_status) != 0)) {
269 +                            logger(LOG_WARNING, "generating content failed: %d %d", generator_status, WEXITSTATUS(generator_status));
270 +                            fclose(fp);
271 +                            fp = NULL;
272 +                       }
273 +                       else {
274 +                            fstat(fileno(fp), &file_stat);
275 +                            if(file_stat.st_size == 0) {
276 +                                 logger(LOG_WARNING, "content generator wrote 0 bytes");
277 +                                 fclose(fp);
278 +                                 fp = NULL;
279 +                            }
280 +                       }
281 +                       break;
282 +               }
283 +          }
284 +     }
285 +#endif 
286       if (fp == NULL)
287       {
288            tftp_send_error(sockfd, sa, ENOTFOUND, data->data_buffer, data->data_buffer_size);

Show all