util-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] agetty: display network address in issue
       [not found] <2B6CF89C-6218-4289-B116-27108562664F@endian.com>
@ 2012-08-15  9:08 ` Andrea Bonomi
  2012-09-12  9:37   ` Karel Zak
  0 siblings, 1 reply; 4+ messages in thread
From: Andrea Bonomi @ 2012-08-15  9:08 UTC (permalink / raw)
  To: util-linux

Hello,
I developed a small patch for displaying the network address (IPv4 or IPv6) of a selected network interface in the agetty issue file.
The name of network interface (default eth0) can be configured through a command line option.
I use this feature on my virtual machines, so I can know the addresses without login. I hope this can be useful for someone else. 
Have a nice day,
Andrea Bonomi

:: e n d i a n
:: security with passion

:: andrea bonomi
:: senior software engineer
:: http://www.endian.com  :: a.bonomi@endian.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] agetty: display network address in issue
  2012-08-15  9:08 ` [PATCH 0/2] agetty: display network address in issue Andrea Bonomi
@ 2012-09-12  9:37   ` Karel Zak
  2012-09-12 17:29     ` Andrea Bonomi
  0 siblings, 1 reply; 4+ messages in thread
From: Karel Zak @ 2012-09-12  9:37 UTC (permalink / raw)
  To: Andrea Bonomi; +Cc: util-linux


 Hi,

On Wed, Aug 15, 2012 at 11:08:16AM +0200, Andrea Bonomi wrote:
> Hello, I developed a small patch for displaying the network address
> (IPv4 or IPv6) of a selected network interface in the agetty issue
> file.  The name of network interface (default eth0) can be
> configured through a command line option.  I use this feature on my
> virtual machines, so I can know the addresses without login. I hope
> this can be useful for someone else.  Have a nice day, Andrea Bonomi

I did some changes to the patch -- see below. I don't like the
hardcoded interface names and I guess that on many machines is more
important just machine IP (based on hostname) rather than interface
IP. So:

 \4 and \6 print IP address as returned by getaddrinfo() *or* if
 --interface command line option is specified then interface IP is
 printed.

It means that --interface is optional and probably unnecessary in many
cases.

Objections?

    Karel

>From ca2fda5f40440f4f7686716d76f93c302f1b2e67 Mon Sep 17 00:00:00 2001
From: Andrea Bonomi <a.bonomi@endian.com>
Date: Wed, 15 Aug 2012 11:10:19 +0200
Subject: [PATCH] agetty: display network address in issue

Signed-off-by: Andrea Bonomi <a.bonomi@endian.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
 term-utils/agetty.8 |   18 +++++++++-
 term-utils/agetty.c |   96 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 111 insertions(+), 3 deletions(-)

diff --git a/term-utils/agetty.8 b/term-utils/agetty.8
index ebfdb96..bbf65d0 100644
--- a/term-utils/agetty.8
+++ b/term-utils/agetty.8
@@ -3,7 +3,7 @@
 agetty \- alternative Linux getty
 
 .SH SYNOPSIS
-.BR "agetty " [\-8chiLmnsUw]
+.BR "agetty " [\-8chiLmnsUwx]
 .RI "[\-a " user ]
 .RI "[\-f " issue_file ]
 .RI "[\-H " login_host ]
@@ -198,6 +198,10 @@ Wait for the user or the modem to send a carriage-return or a
 linefeed character before sending the \fI/etc/issue\fP (or other) file
 and the login prompt. Very useful in connection with the \-I option.
 .TP
+\-x, \-\-interface \fIinterface_name\fP
+The IPv4 and IPv6 addresses of a network interface can be displayed in
+the issue. The name of the network is configured by this option.
+.TP
 \-\-noclear
 Do not clear the screen before prompting for the login name
 (the screen is normally cleared).
@@ -269,6 +273,18 @@ time etc. All escape codes consist of a backslash (\\) immediately
 followed by one of the letters explained below.
 
 .TP
+4
+Insert the IPv4 address of the machine hostname or IPv4 address the configured
+network interface if the \fB\-\-interface\fP command line option is specified.
+.TP
+6
+Insert the IPv6 address of the machine hostname or IPv6 address the configured
+network interface if the \fB\-\-interface\fP command line option is specified.
+.TP
+x
+Name of the configured network interface (configured by the \fB\-\-interface\fP
+command line option).
+.TP
 b
 Insert the baudrate of the current line.
 .TP
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index 43243f9..71c7da3 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -31,6 +31,9 @@
 #include <netdb.h>
 #include <langinfo.h>
 #include <grp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <ifaddrs.h>
 
 #include "strutils.h"
 #include "all-io.h"
@@ -145,6 +148,7 @@ struct options {
 	int nice;			/* Run login with this priority */
 	int numspeed;			/* number of baud rates to try */
 	speed_t speeds[MAX_SPEED];	/* baud rates to be tried */
+	char *interface;		/* name of the network interface displayed in issue */
 };
 
 #define	F_PARSE		(1<<0)	/* process modem status messages */
@@ -169,6 +173,7 @@ struct options {
 #define F_LONGHNAME	(1<<19) /* Show Full qualified hostname */
 #define F_NOHINTS	(1<<20) /* Don't print hints */
 #define F_REMOTE	(1<<21) /* Add '-h fakehost' to login(1) command line */
+#define F_INTERFACE	(1<<22) /* Name of the network interface displayed in issue */
 
 #define serial_tty_option(opt, flag)	\
 	(((opt)->flags & (F_VCONSOLE|(flag))) == (flag))
@@ -280,7 +285,7 @@ int main(int argc, char **argv)
 		.login  =  _PATH_LOGIN,		/* default login program */
 		.tty    = "tty1",		/* default tty line */
 		.term   =  DEFAULT_VCTERM,	/* terminal type */
-		.issue  =  ISSUE		/* default issue file */
+		.issue  =  ISSUE,		/* default issue file */
 	};
 	char *login_argv[LOGIN_ARGV_MAX + 1];
 	int login_argc = 0;
@@ -569,6 +574,7 @@ static void parse_args(int argc, char **argv, struct options *op)
 		{  "timeout",	     required_argument,  0,  't'  },
 		{  "detect-case",    no_argument,	 0,  'U'  },
 		{  "wait-cr",	     no_argument,	 0,  'w'  },
+		{  "interface",      required_argument,  0,  'x'  },
 		{  "nohints",        no_argument,        0,  NOHINTS_OPTION },
 		{  "nohostname",     no_argument,	 0,  NOHOSTNAME_OPTION },
 		{  "long-hostname",  no_argument,	 0,  LONGHOSTNAME_OPTION },
@@ -578,7 +584,7 @@ static void parse_args(int argc, char **argv, struct options *op)
 	};
 
 	while ((c = getopt_long(argc, argv,
-			   "8a:cC:d:Ef:hH:iI:Jl:LmnNo:pP:r:Rst:Uw", longopts,
+			   "8a:cC:d:Ef:hH:iI:Jl:LmnNo:pP:r:Rst:Uwx:", longopts,
 			    NULL)) != -1) {
 		switch (c) {
 		case '8':
@@ -659,6 +665,10 @@ static void parse_args(int argc, char **argv, struct options *op)
 		case 'w':
 			op->flags |= F_WAITCRLF;
 			break;
+		case 'x':
+			op->flags |= F_INTERFACE;
+			op->interface = optarg;
+			break;
 		case NOHINTS_OPTION:
 			op->flags |= F_NOHINTS;
 			break;
@@ -1696,6 +1706,68 @@ static void log_warn(const char *fmt, ...)
 	va_end(ap);
 }
 
+static void output_iface_ip(struct ifaddrs *addrs, const char *iface, sa_family_t family)
+{
+	if (!iface)
+		return;
+
+	if (addrs->ifa_name
+	    && strcmp(addrs->ifa_name, iface) == 0
+	    && addrs->ifa_addr
+	    && addrs->ifa_addr->sa_family == family) {
+
+		void *addr = NULL;
+		char buff[INET6_ADDRSTRLEN + 1];
+
+		switch (addrs->ifa_addr->sa_family) {
+		case AF_INET:
+			addr = &((struct sockaddr_in *)	addrs->ifa_addr)->sin_addr;
+			break;
+		case AF_INET6:
+			addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
+			break;
+		}
+		if (addr) {
+			inet_ntop(addrs->ifa_addr->sa_family, addr, buff, sizeof(buff));
+			printf("%s", buff);
+		}
+
+	} else if (addrs->ifa_next)
+		output_iface_ip(addrs->ifa_next, iface, family);
+}
+
+static void output_ip(sa_family_t family)
+{
+	char host[MAXHOSTNAMELEN + 1];
+	struct addrinfo hints, *info = NULL;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = family;
+	if (family == AF_INET6)
+		hints.ai_flags = AI_V4MAPPED;
+
+	if (gethostname(host, sizeof(host)) == 0
+	    && getaddrinfo(host, NULL, &hints, &info) == 0
+	    && info) {
+
+		void *addr = NULL;
+		char buff[INET6_ADDRSTRLEN + 1];
+
+		switch (info->ai_family) {
+		case AF_INET:
+			addr = &((struct sockaddr_in *) info->ai_addr)->sin_addr;
+			break;
+		case AF_INET6:
+			addr = &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr;
+			break;
+		}
+		inet_ntop(info->ai_family, (void *) addr, buff, sizeof(buff));
+		printf("%s", buff);
+
+		freeaddrinfo(info);
+	}
+}
+
 static void output_special_char(unsigned char c, struct options *op,
 				struct termios *tp)
 {
@@ -1808,6 +1880,26 @@ static void output_special_char(unsigned char c, struct options *op,
 			printf((users == 1) ? _("user") : _("users"));
 		break;
 	}
+	case 'x':
+		if (op->interface)			/* interface name */
+			printf("%s", op->interface);
+		break;
+	case '4':
+	case '6':
+	{
+		sa_family_t family = c == '4' ? AF_INET : AF_INET6;
+
+		if (op->interface) {			/* interface IP */
+			struct ifaddrs *addrs;
+			int status = getifaddrs(&addrs);
+			if (status != 0)
+				break;
+			output_iface_ip(addrs, op->interface, family);
+			freeifaddrs(addrs);
+		} else					/* host IP */
+			output_ip(family);
+		break;
+	}
 	default:
 		putchar(c);
 		break;
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] agetty: display network address in issue
  2012-09-12  9:37   ` Karel Zak
@ 2012-09-12 17:29     ` Andrea Bonomi
  2012-09-13 11:05       ` Karel Zak
  0 siblings, 1 reply; 4+ messages in thread
From: Andrea Bonomi @ 2012-09-12 17:29 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux

Hi,
good idea, much better without the hardcoded interface name.
I think that the --interface option is useful for the machine with a =
dynamic IP address.
(in my experience, the getaddrinfo based on the hostname returns the =
loopback address)

Another idea will be to add the interface name after the \4 or \6, =
something like:
\4eth0 (or similar=85)
to get the IPv4 address of the interface eth0
So the user can specify the interface name directly in the issue file.
What do you think?

Andrea

:: e n d i a n
:: security with passion

:: andrea bonomi
:: senior software engineer
:: http://www.endian.com  :: a.bonomi@endian.com

On 12/set/2012, at 11:37, Karel Zak wrote:

>=20
> Hi,
>=20
> On Wed, Aug 15, 2012 at 11:08:16AM +0200, Andrea Bonomi wrote:
>> Hello, I developed a small patch for displaying the network address
>> (IPv4 or IPv6) of a selected network interface in the agetty issue
>> file.  The name of network interface (default eth0) can be
>> configured through a command line option.  I use this feature on my
>> virtual machines, so I can know the addresses without login. I hope
>> this can be useful for someone else.  Have a nice day, Andrea Bonomi
>=20
> I did some changes to the patch -- see below. I don't like the
> hardcoded interface names and I guess that on many machines is more
> important just machine IP (based on hostname) rather than interface
> IP. So:
>=20
> \4 and \6 print IP address as returned by getaddrinfo() *or* if
> --interface command line option is specified then interface IP is
> printed.
>=20
> It means that --interface is optional and probably unnecessary in many
> cases.
>=20
> Objections?
>=20
>    Karel
>=20
> =46rom ca2fda5f40440f4f7686716d76f93c302f1b2e67 Mon Sep 17 00:00:00 =
2001
> From: Andrea Bonomi <a.bonomi@endian.com>
> Date: Wed, 15 Aug 2012 11:10:19 +0200
> Subject: [PATCH] agetty: display network address in issue
>=20
> Signed-off-by: Andrea Bonomi <a.bonomi@endian.com>
> Signed-off-by: Karel Zak <kzak@redhat.com>
> ---
> term-utils/agetty.8 |   18 +++++++++-
> term-utils/agetty.c |   96 =
+++++++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 111 insertions(+), 3 deletions(-)
>=20
> diff --git a/term-utils/agetty.8 b/term-utils/agetty.8
> index ebfdb96..bbf65d0 100644
> --- a/term-utils/agetty.8
> +++ b/term-utils/agetty.8
> @@ -3,7 +3,7 @@
> agetty \- alternative Linux getty
>=20
> .SH SYNOPSIS
> -.BR "agetty " [\-8chiLmnsUw]
> +.BR "agetty " [\-8chiLmnsUwx]
> .RI "[\-a " user ]
> .RI "[\-f " issue_file ]
> .RI "[\-H " login_host ]
> @@ -198,6 +198,10 @@ Wait for the user or the modem to send a =
carriage-return or a
> linefeed character before sending the \fI/etc/issue\fP (or other) file
> and the login prompt. Very useful in connection with the \-I option.
> .TP
> +\-x, \-\-interface \fIinterface_name\fP
> +The IPv4 and IPv6 addresses of a network interface can be displayed =
in
> +the issue. The name of the network is configured by this option.
> +.TP
> \-\-noclear
> Do not clear the screen before prompting for the login name
> (the screen is normally cleared).
> @@ -269,6 +273,18 @@ time etc. All escape codes consist of a backslash =
(\\) immediately
> followed by one of the letters explained below.
>=20
> .TP
> +4
> +Insert the IPv4 address of the machine hostname or IPv4 address the =
configured
> +network interface if the \fB\-\-interface\fP command line option is =
specified.
> +.TP
> +6
> +Insert the IPv6 address of the machine hostname or IPv6 address the =
configured
> +network interface if the \fB\-\-interface\fP command line option is =
specified.
> +.TP
> +x
> +Name of the configured network interface (configured by the =
\fB\-\-interface\fP
> +command line option).
> +.TP
> b
> Insert the baudrate of the current line.
> .TP
> diff --git a/term-utils/agetty.c b/term-utils/agetty.c
> index 43243f9..71c7da3 100644
> --- a/term-utils/agetty.c
> +++ b/term-utils/agetty.c
> @@ -31,6 +31,9 @@
> #include <netdb.h>
> #include <langinfo.h>
> #include <grp.h>
> +#include <arpa/inet.h>
> +#include <netdb.h>
> +#include <ifaddrs.h>
>=20
> #include "strutils.h"
> #include "all-io.h"
> @@ -145,6 +148,7 @@ struct options {
> 	int nice;			/* Run login with this priority =
*/
> 	int numspeed;			/* number of baud rates to try =
*/
> 	speed_t speeds[MAX_SPEED];	/* baud rates to be tried */
> +	char *interface;		/* name of the network interface =
displayed in issue */
> };
>=20
> #define	F_PARSE		(1<<0)	/* process modem status messages =
*/
> @@ -169,6 +173,7 @@ struct options {
> #define F_LONGHNAME	(1<<19) /* Show Full qualified hostname */
> #define F_NOHINTS	(1<<20) /* Don't print hints */
> #define F_REMOTE	(1<<21) /* Add '-h fakehost' to login(1) command =
line */
> +#define F_INTERFACE	(1<<22) /* Name of the network interface =
displayed in issue */
>=20
> #define serial_tty_option(opt, flag)	\
> 	(((opt)->flags & (F_VCONSOLE|(flag))) =3D=3D (flag))
> @@ -280,7 +285,7 @@ int main(int argc, char **argv)
> 		.login  =3D  _PATH_LOGIN,		/* default login =
program */
> 		.tty    =3D "tty1",		/* default tty line */
> 		.term   =3D  DEFAULT_VCTERM,	/* terminal type */
> -		.issue  =3D  ISSUE		/* default issue file */
> +		.issue  =3D  ISSUE,		/* default issue file */
> 	};
> 	char *login_argv[LOGIN_ARGV_MAX + 1];
> 	int login_argc =3D 0;
> @@ -569,6 +574,7 @@ static void parse_args(int argc, char **argv, =
struct options *op)
> 		{  "timeout",	     required_argument,  0,  't'  },
> 		{  "detect-case",    no_argument,	 0,  'U'  },
> 		{  "wait-cr",	     no_argument,	 0,  'w'  },
> +		{  "interface",      required_argument,  0,  'x'  },
> 		{  "nohints",        no_argument,        0,  =
NOHINTS_OPTION },
> 		{  "nohostname",     no_argument,	 0,  =
NOHOSTNAME_OPTION },
> 		{  "long-hostname",  no_argument,	 0,  =
LONGHOSTNAME_OPTION },
> @@ -578,7 +584,7 @@ static void parse_args(int argc, char **argv, =
struct options *op)
> 	};
>=20
> 	while ((c =3D getopt_long(argc, argv,
> -			   "8a:cC:d:Ef:hH:iI:Jl:LmnNo:pP:r:Rst:Uw", =
longopts,
> +			   "8a:cC:d:Ef:hH:iI:Jl:LmnNo:pP:r:Rst:Uwx:", =
longopts,
> 			    NULL)) !=3D -1) {
> 		switch (c) {
> 		case '8':
> @@ -659,6 +665,10 @@ static void parse_args(int argc, char **argv, =
struct options *op)
> 		case 'w':
> 			op->flags |=3D F_WAITCRLF;
> 			break;
> +		case 'x':
> +			op->flags |=3D F_INTERFACE;
> +			op->interface =3D optarg;
> +			break;
> 		case NOHINTS_OPTION:
> 			op->flags |=3D F_NOHINTS;
> 			break;
> @@ -1696,6 +1706,68 @@ static void log_warn(const char *fmt, ...)
> 	va_end(ap);
> }
>=20
> +static void output_iface_ip(struct ifaddrs *addrs, const char *iface, =
sa_family_t family)
> +{
> +	if (!iface)
> +		return;
> +
> +	if (addrs->ifa_name
> +	    && strcmp(addrs->ifa_name, iface) =3D=3D 0
> +	    && addrs->ifa_addr
> +	    && addrs->ifa_addr->sa_family =3D=3D family) {
> +
> +		void *addr =3D NULL;
> +		char buff[INET6_ADDRSTRLEN + 1];
> +
> +		switch (addrs->ifa_addr->sa_family) {
> +		case AF_INET:
> +			addr =3D &((struct sockaddr_in *)	=
addrs->ifa_addr)->sin_addr;
> +			break;
> +		case AF_INET6:
> +			addr =3D &((struct sockaddr_in6 *) =
addrs->ifa_addr)->sin6_addr;
> +			break;
> +		}
> +		if (addr) {
> +			inet_ntop(addrs->ifa_addr->sa_family, addr, =
buff, sizeof(buff));
> +			printf("%s", buff);
> +		}
> +
> +	} else if (addrs->ifa_next)
> +		output_iface_ip(addrs->ifa_next, iface, family);
> +}
> +
> +static void output_ip(sa_family_t family)
> +{
> +	char host[MAXHOSTNAMELEN + 1];
> +	struct addrinfo hints, *info =3D NULL;
> +
> +	memset(&hints, 0, sizeof(hints));
> +	hints.ai_family =3D family;
> +	if (family =3D=3D AF_INET6)
> +		hints.ai_flags =3D AI_V4MAPPED;
> +
> +	if (gethostname(host, sizeof(host)) =3D=3D 0
> +	    && getaddrinfo(host, NULL, &hints, &info) =3D=3D 0
> +	    && info) {
> +
> +		void *addr =3D NULL;
> +		char buff[INET6_ADDRSTRLEN + 1];
> +
> +		switch (info->ai_family) {
> +		case AF_INET:
> +			addr =3D &((struct sockaddr_in *) =
info->ai_addr)->sin_addr;
> +			break;
> +		case AF_INET6:
> +			addr =3D &((struct sockaddr_in6 *) =
info->ai_addr)->sin6_addr;
> +			break;
> +		}
> +		inet_ntop(info->ai_family, (void *) addr, buff, =
sizeof(buff));
> +		printf("%s", buff);
> +
> +		freeaddrinfo(info);
> +	}
> +}
> +
> static void output_special_char(unsigned char c, struct options *op,
> 				struct termios *tp)
> {
> @@ -1808,6 +1880,26 @@ static void output_special_char(unsigned char =
c, struct options *op,
> 			printf((users =3D=3D 1) ? _("user") : =
_("users"));
> 		break;
> 	}
> +	case 'x':
> +		if (op->interface)			/* interface =
name */
> +			printf("%s", op->interface);
> +		break;
> +	case '4':
> +	case '6':
> +	{
> +		sa_family_t family =3D c =3D=3D '4' ? AF_INET : =
AF_INET6;
> +
> +		if (op->interface) {			/* interface IP =
*/
> +			struct ifaddrs *addrs;
> +			int status =3D getifaddrs(&addrs);
> +			if (status !=3D 0)
> +				break;
> +			output_iface_ip(addrs, op->interface, family);
> +			freeifaddrs(addrs);
> +		} else					/* host IP */
> +			output_ip(family);
> +		break;
> +	}
> 	default:
> 		putchar(c);
> 		break;
> --=20
> 1.7.7.6
>=20

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] agetty: display network address in issue
  2012-09-12 17:29     ` Andrea Bonomi
@ 2012-09-13 11:05       ` Karel Zak
  0 siblings, 0 replies; 4+ messages in thread
From: Karel Zak @ 2012-09-13 11:05 UTC (permalink / raw)
  To: Andrea Bonomi; +Cc: util-linux

On Wed, Sep 12, 2012 at 07:29:19PM +0200, Andrea Bonomi wrote:
> Hi,
> good idea, much better without the hardcoded interface name.
> I think that the --interface option is useful for the machine with a dynamic IP address.
> (in my experience, the getaddrinfo based on the hostname returns the loopback address)
> 
> Another idea will be to add the interface name after the \4 or \6, something like:
> \4eth0 (or similar…)

Excellent idea. It also means that --interface is unnecessary and
more than one interface IP maybe be printed by the issue file.

> to get the IPv4 address of the interface eth0
> So the user can specify the interface name directly in the issue file.
> What do you think?

Implemented, merged into master branch. For example:

    lo = \4{lo}
   em1 = \4{em1}  (IPv6 \6{em1})
virbr0 = \4{virbr0}

The {..} is optional argument, if not given, host IP is printed.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-09-13 11:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <2B6CF89C-6218-4289-B116-27108562664F@endian.com>
2012-08-15  9:08 ` [PATCH 0/2] agetty: display network address in issue Andrea Bonomi
2012-09-12  9:37   ` Karel Zak
2012-09-12 17:29     ` Andrea Bonomi
2012-09-13 11:05       ` Karel Zak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).