Hi,

this diff add rdomain support to tftpd.
It used setsockopt/SO_RTABLE like in ping program.

Alternatively I could use `setrtable` once instead of multiple setsockopt.

I don't know which method is the best in this case.

http://pastebin.com/7jBU78fc


Index: tftpd.8
===================================================================
RCS file: /cvs/src/usr.sbin/tftpd/tftpd.8,v
retrieving revision 1.4
diff -u -p -r1.4 tftpd.8
--- tftpd.8 4 Mar 2012 07:26:51 -0000 1.4
+++ tftpd.8 6 Aug 2015 16:10:19 -0000
@@ -41,6 +41,7 @@
 .Op Fl l Ar address
 .Op Fl p Ar port
 .Op Fl r Ar socket
+.Op Fl V Ar rtable
 .Ar directory
 .Sh DESCRIPTION
 .Nm
@@ -119,6 +120,8 @@ By default
 does not use filename rewriting.
 .It Fl v
 Log the client IP, type of request, and filename.
+.It Fl V Ar rtable
+Set the routing table to be used for listening connections.
 .It Ar directory
 .Xr chroot 2
 to
Index: tftpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/tftpd/tftpd.c,v
retrieving revision 1.26
diff -u -p -r1.26 tftpd.c
--- tftpd.c 16 Jan 2015 06:40:22 -0000 1.26
+++ tftpd.c 6 Aug 2015 16:10:19 -0000
@@ -260,13 +260,14 @@ __dead void
 usage(void)
 {
  extern char *__progname;
- fprintf(stderr, "usage: %s [-46cdv] [-l address] [-p port] [-r socket]"
+ fprintf(stderr, "usage: %s [-46cdv] [-l address] [-p port] [-r socket]
[-V rtable]"
     " directory\n", __progname);
  exit(1);
 }

 int  cancreate = 0;
 int  verbose = 0;
+int  rtableid = -1;

 int
 main(int argc, char *argv[])
@@ -283,8 +284,9 @@ main(int argc, char *argv[])
  char *addr = NULL;
  char *port = "tftp";
  int family = AF_UNSPEC;
+ const char *errstr;

- while ((c = getopt(argc, argv, "46cdl:p:r:v")) != -1) {
+ while ((c = getopt(argc, argv, "46cdl:p:r:vV:")) != -1) {
  switch (c) {
  case '4':
  family = AF_INET;
@@ -310,6 +312,13 @@ main(int argc, char *argv[])
  case 'v':
  verbose = 1;
  break;
+ case 'V':
+ rtableid = (unsigned int)strtonum(optarg, 0,
+    RT_TABLEID_MAX, &errstr);
+ if (errstr)
+ errx(1, "rtable value is %s: %s",
+    errstr, optarg);
+ break;
  default:
  usage();
  /* NOTREACHED */
@@ -537,6 +546,15 @@ tftpd_listen(const char *addr, const cha
  continue;
  }

+ if (rtableid != -1) {
+ if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid,
+    sizeof(rtableid)) == -1) {
+ cause = "setsockopt SO_RTABLE";
+ cerrno = errno;
+ continue;
+ }
+ }
+
  if (bind(s, res->ai_addr, res->ai_addrlen) == -1) {
  cause = "bind";
  cerrno = errno;
@@ -674,6 +692,15 @@ tftpd_recv(int fd, short events, void *a
  lwarn("socket");
  goto err;
  }
+
+ if (rtableid != -1) {
+ if (setsockopt(client->sock, SOL_SOCKET, SO_RTABLE, &rtableid,
+    sizeof(rtableid)) == -1) {
+ lwarn("setsockopt SO_RTABLE");
+ goto err;
+ }
+ }
+
  memset(&s_in, 0, sizeof(s_in));
  s_in.ss_family = client->ss.ss_family;
  s_in.ss_len = client->ss.ss_len;

-- 
Bertrand PROVOST

Reply via email to