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