From 72917fe7c663aced54f7e1185b7b72ba59aea73c Mon Sep 17 00:00:00 2001 Message-Id: <72917fe7c663aced54f7e1185b7b72ba59aea73c.1714229992.git.mdw@distorted.org.uk> From: Mark Wooding Date: Thu, 11 Jan 2007 00:04:39 +0000 Subject: [PATCH] server: Correct handling of interface names in tun interface. Organization: Straylight/Edgeware From: Mark Wooding Now that interface names can be changed, we need to let the tunnel driver know of changes so that it can produce the right messages when things go weird. It's better to let the peer edifice handle interface names, so * let `create' return the interface name rather than have p_ifname ask the tunnel explicitly, and * replace the `ifname' query with an optional `setifname' notification, which is currently used only by the SLIP driver to maintain the correct name for its persistent interfaces. --- doc/tripe-admin.5.in | 6 +----- server/peer.c | 12 ++++++++---- server/tripe.h | 6 ++++-- server/tun-bsd.c | 24 ++++++------------------ server/tun-linux.c | 21 ++++++--------------- server/tun-slip.c | 28 +++++++++++++++++----------- server/tun-unet.c | 39 ++++++++++++--------------------------- 7 files changed, 54 insertions(+), 82 deletions(-) diff --git a/doc/tripe-admin.5.in b/doc/tripe-admin.5.in index 1f52a6db..94c7c3b8 100644 --- a/doc/tripe-admin.5.in +++ b/doc/tripe-admin.5.in @@ -1263,7 +1263,7 @@ create some more .BI /dev/tun nn files, it will work. .SP -.BI "TUN - " tun-name " open-error " device " " ecode " " message +.BI "TUN \- " tun-name " open-error " device " " ecode " " message An attempt to open the tunnel device file .I device failed. @@ -1314,10 +1314,6 @@ shouldn't be used any more. .BI "TUN \- unet getinfo-error " ecode " " message Reading information about the Unet interface failed. Unet is obsolete and shouldn't be used any more. -.SP -.BI "TUN \- unet ifname-too-long" -The Unet interface's name overflowed, so we couldn't read it properly. -Unet is obsolete and shouldn't be used any more. .SS "USER warnings" These are issued by administration clients using the .B WARN diff --git a/server/peer.c b/server/peer.c index c9198924..fd79a84c 100644 --- a/server/peer.c +++ b/server/peer.c @@ -567,7 +567,12 @@ const char *p_ifname(peer *p) { return (p->ifname); } */ void p_setifname(peer *p, const char *name) - { if (p->ifname) xfree(p->ifname); p->ifname = xstrdup(name); } +{ + xfree(p->ifname); + p->ifname = xstrdup(name); + if (p->spec.tops->setifname) + p->spec.tops->setifname(p->t, name); +} /* --- @p_addr@ --- * * @@ -700,12 +705,11 @@ peer *p_create(peerspec *spec) p->ifname = 0; memset(&p->st, 0, sizeof(stats)); p->st.t_start = time(0); - if ((p->t = spec->tops->create(p)) == 0) + if ((p->t = spec->tops->create(p, &p->ifname)) == 0) goto tidy_0; p_setkatimer(p); if (kx_init(&p->kx, p, &p->ks)) goto tidy_1; - p_setifname(p, spec->tops->ifname(p->t)); p->next = peers; if (peers) peers->prev = p; @@ -722,6 +726,7 @@ peer *p_create(peerspec *spec) tidy_1: if (spec->t_ka) sel_rmtimer(&p->tka); + xfree(p->ifname); p->t->ops->destroy(p->t); tidy_0: xfree(p->spec.name); @@ -788,7 +793,6 @@ void p_destroy(peer *p) p->t->ops->destroy(p->t); if (p->spec.t_ka) sel_rmtimer(&p->tka); - xfree(p->spec.name); for (pg = p->pings; pg; pg = ppg) { ppg = pg->next; p_pingdone(pg, PING_PEERDIED); diff --git a/server/tripe.h b/server/tripe.h index 66fb091d..5f00718d 100644 --- a/server/tripe.h +++ b/server/tripe.h @@ -269,8 +269,10 @@ struct peer; typedef struct tunnel_ops { const char *name; /* Name of this tunnel driver */ void (*init)(void); /* Initializes the system */ - tunnel *(*create)(struct peer */*p*/); /* Initializes a new tunnel */ - const char *(*ifname)(tunnel */*t*/); /* Returns tunnel's interface name */ + tunnel *(*create)(struct peer */*p*/, char **/*ifn*/); + /* Initializes a new tunnel */ + void (*setifname)(tunnel */*t*/, const char */*ifn*/); + /* Notifies ifname change */ void (*inject)(tunnel */*t*/, buf */*b*/); /* Sends packet through if */ void (*destroy)(tunnel */*t*/); /* Destroys a tunnel */ } tunnel_ops; diff --git a/server/tun-bsd.c b/server/tun-bsd.c index 4e8c0bd8..cf6c6d02 100644 --- a/server/tun-bsd.c +++ b/server/tun-bsd.c @@ -43,20 +43,6 @@ struct tunnel { unsigned n; /* Number of my tunnel device */ }; -/* --- @t_ifname@ --- * - * - * Arguments: @tunnel *t@ = pointer to tunnel block - * - * Returns: A pointer to the tunnel's interface name. - */ - -static const char *t_ifname(tunnel *t) -{ - static char buf[8]; - sprintf(buf, "tun%u", t->n); - return (buf); -} - /* --- @t_read@ --- * * * Arguments: @int fd@ = file descriptor to read @@ -76,7 +62,7 @@ static void t_read(int fd, unsigned mode, void *v) n = read(fd, buf_i, sizeof(buf_i)); if (n < 0) { - a_warn("TUN", "%s", t_ifname(t), "read-error", "?ERRNO", A_END); + a_warn("TUN", "%s", p_ifname(t->p), "read-error", "?ERRNO", A_END); return; } IF_TRACING(T_TUNNEL, { @@ -102,13 +88,14 @@ static void t_init(void) { return; } /* --- @t_create@ --- * * * Arguments: @peer *p@ = pointer to peer block + * @char **ifn@ = where to put the interface name * * Returns: A tunnel block if it worked, or null on failure. * * Use: Initializes a new tunnel. */ -static tunnel *t_create(peer *p) +static tunnel *t_create(peer *p, char **ifn) { int fd; unsigned n; @@ -141,8 +128,9 @@ static tunnel *t_create(peer *p) t->n = n; sel_initfile(&sel, &t->f, fd, SEL_READ, t_read, t); sel_addfile(&t->f); + *ifn = xstrdup(buf + 5); T( trace(T_TUNNEL, "tun-bsd: attached interface %s to peer `%s'", - t_ifname(t), p_name(p)); ) + *ifn, p_name(p)); ) return (t); } @@ -185,7 +173,7 @@ const tunnel_ops tun_bsd = { "bsd", t_init, t_create, - t_ifname, + 0, t_inject, t_destroy }; diff --git a/server/tun-linux.c b/server/tun-linux.c index 3cfa5d72..42503548 100644 --- a/server/tun-linux.c +++ b/server/tun-linux.c @@ -46,7 +46,6 @@ struct tunnel { const tunnel_ops *ops; /* Pointer to operations */ sel_file f; /* Selector for TUN/TAP device */ struct peer *p; /* Pointer to my peer */ - char ifn[IFNAMSIZ]; /* Interface name buffer */ }; /* --- @t_read@ --- * @@ -68,7 +67,7 @@ static void t_read(int fd, unsigned mode, void *v) n = read(fd, buf_i, sizeof(buf_i)); if (n < 0) { - a_warn("TUN", "%s", t->ifn, "read-error", "?ERRNO", A_END); + a_warn("TUN", "%s", p_ifname(t->p), "read-error", "?ERRNO", A_END); return; } IF_TRACING(T_TUNNEL, { @@ -94,13 +93,14 @@ static void t_init(void) { return; } /* --- @t_create@ --- * * * Arguments: @peer *p@ = pointer to peer block + * @char **ifn@ = where to put the interface name * * Returns: A tunnel block if it worked, or null on failure. * * Use: Initializes a new tunnel. */ -static tunnel *t_create(peer *p) +static tunnel *t_create(peer *p, char **ifn) { int fd; int f; @@ -128,21 +128,12 @@ static tunnel *t_create(peer *p) sel_initfile(&sel, &t->f, fd, SEL_READ, t_read, t); sel_addfile(&t->f); iff.ifr_name[IFNAMSIZ - 1] = 0; - strcpy(t->ifn, iff.ifr_name); + *ifn = xstrdup(iff.ifr_name); T( trace(T_TUNNEL, "tun-linux: attached interface %s to peer `%s'", - t->ifn, p_name(p)); ) + *ifn, p_name(p)); ) return (t); } -/* --- @t_ifname@ --- * - * - * Arguments: @tunnel *t@ = pointer to tunnel block - * - * Returns: A pointer to the tunnel's interface name. - */ - -static const char *t_ifname(tunnel *t) { return (t->ifn); } - /* --- @t_inject@ --- * * * Arguments: @tunnel *t@ = pointer to tunnel block @@ -182,7 +173,7 @@ const tunnel_ops tun_linux = { "linux", t_init, t_create, - t_ifname, + 0, t_inject, t_destroy }; diff --git a/server/tun-slip.c b/server/tun-slip.c index 2efda890..0df028e4 100644 --- a/server/tun-slip.c +++ b/server/tun-slip.c @@ -100,11 +100,11 @@ static void t_read(int fd, unsigned mode, void *v) #endif errno == EAGAIN) return; - a_warn("TUN", "%s", t->sl->name, "read-error", "?ERRNO", A_END); + a_warn("TUN", "%s", p_ifname(t->p), "read-error", "?ERRNO", A_END); return; } if (!n) { - a_warn("TUN", "%s", t->sl->name, "slip", "eof", A_END); + a_warn("TUN", "%s", p_ifname(t->p), "slip", "eof", A_END); t->st = ST_EOF; sel_rmfile(&t->f); return; @@ -126,7 +126,7 @@ static void t_read(int fd, unsigned mode, void *v) if (st & ST_BAD) ; else if (st & ST_ESC) - a_warn("TUN", "%s", t->sl->name, "slip", "escape-end", A_END); + a_warn("TUN", "%s", p_ifname(t->p), "slip", "escape-end", A_END); else if (q == t->buf) { T( trace(T_TUNNEL, "tun-slip: empty packet"); ) } else { @@ -143,7 +143,7 @@ static void t_read(int fd, unsigned mode, void *v) break; case SL_ESC: if ((st & ST_ESC) && !(st & ST_BAD)) { - a_warn("TUN", "%s", t->sl->name, "slip", "bad-escape", A_END); + a_warn("TUN", "%s", p_ifname(t->p), "slip", "bad-escape", A_END); st |= ST_BAD; } else st |= ST_ESC; @@ -158,7 +158,7 @@ static void t_read(int fd, unsigned mode, void *v) goto emit; default: if ((st & ST_ESC) && !(st & ST_BAD)) { - a_warn("TUN", "%s", t->sl->name, "slip", "bad-escape", A_END); + a_warn("TUN", "%s", p_ifname(t->p), "slip", "bad-escape", A_END); st |= ST_BAD; } emit: @@ -166,7 +166,7 @@ static void t_read(int fd, unsigned mode, void *v) if (q < ll) *q++ = o; else { - a_warn("TUN", "%s", t->sl->name, "slip", "overflow", A_END); + a_warn("TUN", "%s", p_ifname(t->p), "slip", "overflow", A_END); st |= ST_BAD; } } @@ -253,13 +253,14 @@ whine: /* --- @t_create@ --- * * * Arguments: @peer *p@ = pointer to peer block + * @char **ifn@ = where to put the interface name * * Returns: A tunnel block if it worked, or null on failure. * * Use: Initializes a new tunnel. */ -static tunnel *t_create(peer *p) +static tunnel *t_create(peer *p, char **ifn) { slipif *sl = 0; int pin[2] = { -1, -1 }, pout[2] = { -1, -1 }; @@ -345,6 +346,7 @@ found: sel_initfile(&sel, &t->f, sl->ifd, SEL_READ, t_read, t); sel_addfile(&t->f); write(sl->ofd, end, sizeof(end)); + *ifn = xstrdup(sl->name); dstr_destroy(&d); return (t); @@ -361,14 +363,18 @@ fail: return (0); } -/* --- @t_ifname@ --- * +/* --- @t_setifname@ --- * * * Arguments: @tunnel *t@ = pointer to tunnel block + * @const char *ifn@ = new interface name * - * Returns: A pointer to the tunnel's interface name. + * Returns: --- + * + * Use: Updates the interface name of a slip interface. */ -static const char *t_ifname(tunnel *t) { return (t->sl->name); } +static void t_setifname(tunnel *t, const char *ifn) + { xfree(t->sl->name); t->sl->name = xstrdup(ifn); } /* --- @t_inject@ --- * * @@ -442,7 +448,7 @@ const tunnel_ops tun_slip = { "slip", t_init, t_create, - t_ifname, + t_setifname, t_inject, t_destroy }; diff --git a/server/tun-unet.c b/server/tun-unet.c index c2b6e771..bdf23fe4 100644 --- a/server/tun-unet.c +++ b/server/tun-unet.c @@ -48,29 +48,6 @@ struct tunnel { struct peer *p; /* Pointer to my peer */ }; -/* --- @t_ifname@ --- * - * - * Arguments: @tunnel *t@ = pointer to tunnel block - * - * Returns: A pointer to the tunnel's interface name. - */ - -static const char *t_ifname(tunnel *t) -{ - static char b[UNET_NAMEMAX]; - struct unet_info uni; - if (ioctl(t->f.fd, UNIOCGINFO, &uni)) { - a_warn("TUN", "-", "unet", "getinfo-error", "?ERRNO", A_END); - return (""); - } - if (strlen(uni.uni_ifname) + 1 > sizeof(b)) { - a_warn("TUN", "-", "unet", "ifname-too-long", A_END); - return (""); - } - strcpy(b, uni.uni_ifname); - return (b); -} - /* --- @t_read@ --- * * * Arguments: @int fd@ = file descriptor to read @@ -90,7 +67,7 @@ static void t_read(int fd, unsigned mode, void *v) n = read(fd, buf_i, sizeof(buf_i)); if (n < 0) { - a_warn("TUN", "%s", t_ifname(t), "read-error", "?ERRNO", A_END); + a_warn("TUN", "%s", p_ifname(t->p), "read-error", "?ERRNO", A_END); return; } IF_TRACING(T_TUNNEL, { @@ -117,17 +94,19 @@ static void t_init(void) { return; } * * Arguments: @tunnel *t@ = pointer to tunnel block * @peer *p@ = pointer to peer block + * @char *ifn@ = where to put the interface name * * Returns: A tunnel block if it worked, or null on failure. * * Use: Initializes a new tunnel. */ -static tunnel *t_create(peer *p) +static tunnel *t_create(peer *p, char **ifn) { int fd; tunnel *t; int f; + struct unet_info uni; if ((fd = open("/dev/unet", O_RDWR)) < 0) { a_warn("TUN", "-", "unet", "open-error", "/dev/unet", "?ERRNO", A_END); @@ -145,8 +124,14 @@ static tunnel *t_create(peer *p) t->p = p; sel_initfile(&sel, &t->f, fd, SEL_READ, t_read, t); sel_addfile(&t->f); + + if (ioctl(t->f.fd, UNIOCGINFO, &uni)) { + a_warn("TUN", "-", "unet", "getinfo-error", "?ERRNO", A_END); + return (""); + } + *ifn = xstrdup(uni.uni_ifname); T( trace(T_TUNNEL, "tun-unet: attached interface %s to peer `%s'", - t_ifname(t), p_name(p)); ) + *ifn, p_name(p)); ) return (t); } @@ -189,7 +174,7 @@ const tunnel_ops tun_unet = { "unet", t_init, t_create, - t_ifname, + 0, t_inject, t_destroy }; -- [mdw]