Commit c545e76b authored by Klaas Freitag's avatar Klaas Freitag

Support /prefix syntax for IPv4 in ifconfig too.

Add getmask() to aftype structure to generalize.

Fix numerous buffer overruns. net-tools is full of them!
[still many left]
parent 3243ae81
......@@ -121,7 +121,7 @@ ife_print(struct interface *ptr)
#endif
#if HAVE_AFINET6
FILE *f;
char addr6[40], devname[10];
char addr6[40], devname[20];
struct sockaddr_in6 sap;
int plen, scope, dad_status, if_idx;
extern struct aftype inet6_aftype;
......@@ -179,7 +179,7 @@ ife_print(struct interface *ptr)
#if HAVE_AFINET6
}
if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
while(fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %s\n",
while(fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
addr6p[0], addr6p[1], addr6p[2], addr6p[3],
addr6p[4], addr6p[5], addr6p[6], addr6p[7],
&if_idx, &plen, &scope, &dad_status, devname) != EOF) {
......@@ -413,11 +413,14 @@ usage(void)
fprintf(stderr, NLS_CATGETS(catfd, ifconfigSet, ifconfig_usage1,
"Usage: ifconfig [-a] [-i] [-v] interface\n"));
fprintf(stderr, " [[family] address]\n");
#if HAVE_AFINET6
fprintf(stderr, " [add inet6address/prefixlen]\n");
/* XXX: it would be useful to have the add/del syntax even without IPv6.
the 2.1 interface address lists make this natural */
#ifdef HAVE_AFINET6
fprintf(stderr, " [add address[/prefixlen]]\n");
#ifdef SIOCDIFADDR
fprintf(stderr, " [del inet6address/prefixlen]\n");
fprintf(stderr, " [del address[/prefixlen]]\n");
#endif
/* XXX the kernel supports tunneling even without ipv6 */
fprintf(stderr, " [tunnel aa.bb.cc.dd]\n");
#endif
#if HAVE_AFINET
......@@ -449,6 +452,21 @@ version(void)
exit(1);
}
static int
set_netmask(int skfd, struct ifreq *ifr, struct sockaddr *sa)
{
int err = 0;
memcpy((char *) &ifr->ifr_netmask, (char *) sa,
sizeof(struct sockaddr));
if (ioctl(skfd, SIOCSIFNETMASK, ifr) < 0) {
fprintf(stderr, "SIOCSIFNETMASK: %s\n",
strerror(errno));
err = 1;
}
return 0;
}
int
main(int argc, char **argv)
{
......@@ -457,7 +475,7 @@ main(int argc, char **argv)
struct aftype *ap;
struct hwtype *hw;
struct ifreq ifr;
int goterr = 0;
int goterr = 0, didnetmask = 0;
char **spp;
#if HAVE_AFINET6
extern struct aftype inet6_aftype;
......@@ -665,7 +683,8 @@ main(int argc, char **argv)
if (!strcmp(*spp, "broadcast")) {
if (*++spp != NULL ) {
strcpy(host, *spp);
host[(sizeof host)-1] = 0;
strncpy(host, *spp, (sizeof host)-1);
if (ap->input(0, host, &sa) < 0) {
ap->herror(host);
goterr = 1;
......@@ -687,7 +706,8 @@ main(int argc, char **argv)
if (!strcmp(*spp, "dstaddr")) {
if (*++spp == NULL) usage();
strcpy(host, *spp);
host[(sizeof host)-1] = 0;
strncpy(host, *spp, (sizeof host)-1);
if (ap->input(0, host, &sa) < 0) {
ap->herror(host);
goterr = 1;
......@@ -706,21 +726,17 @@ main(int argc, char **argv)
}
if (!strcmp(*spp, "netmask")) {
if (*++spp == NULL) usage();
strcpy(host, *spp);
if (*++spp == NULL || didnetmask) usage();
host[(sizeof host)-1] = 0;
strncpy(host, *spp, (sizeof host)-1);
if (ap->input(0, host, &sa) < 0) {
ap->herror(host);
goterr = 1;
spp++;
continue;
}
memcpy((char *) &ifr.ifr_netmask, (char *) &sa,
sizeof(struct sockaddr));
if (ioctl(skfd, SIOCSIFNETMASK, &ifr) < 0) {
fprintf(stderr, "SIOCSIFNETMASK: %s\n",
strerror(errno));
goterr = 1;
}
didnetmask++;
goterr = set_netmask(skfd, &ifr, &sa);
spp++;
continue;
}
......@@ -792,7 +808,8 @@ main(int argc, char **argv)
if (!strcmp(*spp, "pointopoint")) {
if (*(spp+1) != NULL) {
spp++;
strcpy(host, *spp);
host[(sizeof host)-1] = 0;
strncpy(host, *spp, (sizeof host)-1);
if (ap->input(0, host, &sa)) {
ap->herror(host);
goterr = 1;
......@@ -816,7 +833,8 @@ main(int argc, char **argv)
if (*++spp == NULL) usage();
if ((hw = get_hwtype(*spp)) == NULL) usage();
if (*++spp == NULL) usage();
strcpy(host, *spp);
host[(sizeof host)-1] = 0;
strncpy(host, *spp, (sizeof host)-1);
if (hw->input(host, &sa) < 0) {
fprintf(stderr, "%s: invalid %s address.\n", host, hw->name);
goterr = 1;
......@@ -844,8 +862,9 @@ main(int argc, char **argv)
} else {
prefix_len = 0;
}
strcpy(host, *spp);
if (inet6_aftype.input(1, host, (struct sockaddr *)&sa6) < 0) {
host[(sizeof host)-1] = 0;
strncpy(host, *spp, (sizeof host)-1);
if (inet6_aftype.input(1, host, (struct sockaddr *)&sa6) < 0) {
inet6_aftype.herror(host);
goterr = 1;
spp++;
......@@ -881,7 +900,8 @@ main(int argc, char **argv)
} else {
prefix_len = 0;
}
strcpy(host, *spp);
host[(sizeof host)-1] = 0;
strncpy(host, *spp, (sizeof host)-1);
if (inet6_aftype.input(1, host, (struct sockaddr *)&sa6) < 0) {
inet6_aftype.herror(host);
goterr = 1;
......@@ -922,7 +942,8 @@ main(int argc, char **argv)
} else {
prefix_len = 0;
}
strcpy(host, *spp);
host[(sizeof host)-1] = 0;
strncpy(host, *spp, (sizeof host)-1);
if (inet6_aftype.input(1, host, (struct sockaddr *)&sa6) < 0) {
inet6_aftype.herror(host);
goterr = 1;
......@@ -953,7 +974,23 @@ main(int argc, char **argv)
#endif
/* If the next argument is a valid hostname, assume OK. */
strcpy(host, *spp);
host[(sizeof host)-1] = '\0';
strncpy(host, *spp, (sizeof host)-1);
/* FIXME: sa is too small for INET6 addresses, inet6 should use that too,
broadcast is unexpected */
if (ap->getmask) {
switch (ap->getmask(host, &sa, NULL)) {
case -1: usage(); break;
case 1:
if (didnetmask) usage();
goterr = set_netmask(skfd, &ifr, &sa);
didnetmask++;
break;
}
}
if (ap->input(0, host, &sa) < 0) {
ap->herror(host);
usage();
......
......@@ -260,11 +260,35 @@ INET_input(int type, char *bufp, struct sockaddr *sap)
}
}
static int INET_getnetmask(char *adr, struct sockaddr *m, char *name)
{
struct sockaddr_in *mask = (struct sockaddr_in *)m;
char *slash, *end;
int prefix;
if ((slash = strchr(adr, '/')) == NULL)
return 0;
*slash++ = '\0';
prefix = strtoul(slash,&end,0);
if (*end != '\0')
return -1;
if (name) {
sprintf(name, "/%d", prefix);
}
mask->sin_family = AF_INET;
mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix));
return 1;
}
struct aftype inet_aftype = {
"inet", NULL, /*"DARPA Internet",*/ AF_INET, sizeof(unsigned long),
INET_print, INET_sprint, INET_input, INET_reserror,
NULL/*INET_rprint*/, NULL/*INET_rinput*/
NULL/*INET_rprint*/, NULL/*INET_rinput*/,
INET_getnetmask
};
#endif /* HAVE_AFINET || HAVE_AFINET6 */
......
......@@ -28,7 +28,7 @@ extern struct aftype inet_aftype;
int rprint_fib(int ext, int numeric)
{
char buff[4096], iface[16], flags[16];
char buff[1024], iface[16], flags[16];
char gate_addr[128], net_addr[128];
char mask_addr[128];
struct sockaddr snet, sgate, smask;
......@@ -61,7 +61,7 @@ int rprint_fib(int ext, int numeric)
mss=0;
while (fgets(buff, 1023, fp))
{
num = sscanf(buff, "%s %s %s %X %d %d %d %s %d %d %d\n",
num = sscanf(buff, "%16s %128s %128s %X %d %d %d %128s %d %d %d\n",
iface, net_addr, gate_addr,
&iflags, &refcnt, &use, &metric, mask_addr,
&mss,&window,&irtt);
......@@ -134,7 +134,7 @@ int rprint_fib(int ext, int numeric)
int rprint_cache(int ext, int numeric)
{
char buff[4096], iface[16], flags[16];
char buff[1024], iface[16], flags[16];
char gate_addr[128], net_addr[128];
char mask_addr[128];
struct sockaddr snet, sgate, smask;
......@@ -168,7 +168,7 @@ int rprint_cache(int ext, int numeric)
arp=0;
while (fgets(buff, 1023, fp))
{
num = sscanf(buff, "%s %s %s %X %d %d %d %s %d %d %d %d %d\n",
num = sscanf(buff, "%16s %128s %128s %X %d %d %d %128s %d %d %d %d %d\n",
iface, net_addr, gate_addr,
&iflags, &refcnt, &use, &metric, mask_addr,
&mss,&window,&irtt,&hh,&arp);
......
......@@ -50,31 +50,6 @@ static int usage(void)
return(E_USAGE);
}
static int INET_getnetmask(char *adr, struct rtentry *rt, char *name)
{
union { /* grr */
struct sockaddr_in mask;
struct sockaddr dumb;
} m;
char *slash, *end;
int prefix;
if ((slash = strchr(adr, '/')) == NULL)
return 0;
*slash++ = '\0';
prefix = strtoul(slash,&end,0);
if (*end != '\0')
return -1;
sprintf(name, "/%d", prefix);
m.mask.sin_family = AF_INET;
m.mask.sin_addr.s_addr = htonl(~(0xffffffffU >> prefix));
rt->rt_genmask = full_mask(m.dumb);
return 0;
}
static int INET_setroute(int action, int options, char **args)
{
struct rtentry rt;
......@@ -94,14 +69,22 @@ static int INET_setroute(int action, int options, char **args)
if (*args == NULL)
return(usage());
strncpy(target, *args++, sizeof target);
target[(sizeof target)-1] = 0;
strncpy(target, *args++, (sizeof target)-1);
/* Clean out the RTREQ structure. */
memset((char *) &rt, 0, sizeof(struct rtentry));
/* Special hack for /prefix syntax */
if (INET_getnetmask(target, &rt, netmask) < 0)
return usage();
/* Special hack for /prefix syntax */
{
union {
struct sockaddr_in m;
struct sockaddr d;
} mask;
if (inet_aftype.getmask(target, &mask.d, netmask) < 0)
return usage();
rt.rt_genmask = full_mask(mask.d);
}
if ((isnet = inet_aftype.input(0, target, &rt.rt_dst)) < 0) {
inet_aftype.herror(target);
......@@ -147,7 +130,8 @@ static int INET_setroute(int action, int options, char **args)
args++;
if (!*args || mask_in_addr(rt))
return(usage());
strcpy(netmask, *args);
netmask[(sizeof netmask)-1] = 0;
strncpy(netmask, *args, (sizeof netmask)-1);
if ((isnet = inet_aftype.input(0, netmask, &mask)) < 0) {
inet_aftype.herror(netmask);
return (E_LOOKUP);
......@@ -162,7 +146,8 @@ static int INET_setroute(int action, int options, char **args)
return(usage());
if (rt.rt_flags & RTF_GATEWAY)
return(usage());
strcpy(gateway, *args);
gateway[(sizeof gateway)-1] = 0;
strncpy(gateway, *args, (sizeof gateway)-1);
if ((isnet = inet_aftype.input(0, gateway, &rt.rt_gateway)) < 0) {
inet_aftype.herror(gateway);
return (E_LOOKUP);
......
......@@ -43,6 +43,10 @@ struct aftype {
void (*herror) (char *text);
int (*rprint) (int options);
int (*rinput) (int typ, int ext, char **argv);
/* may modify src */
int (*getmask) (char *src, struct sockaddr *mask, char *name);
};
......
......@@ -160,7 +160,10 @@ Set the multicast flag on the interface. This should not normally be needed
as the drivers set the flag correctly themselves.
.TP
.B address
The IP address to be assigned to this interface.
The address to be assigned to this interface.
For Inet addresses you may use address/prefixlength to specify the default
netmask.
.TP
.B txqueuelen length
Set the length of the transmit queue of the device. It is useful to set this
......
......@@ -376,7 +376,7 @@ static void tcp_do_one(int lnr, const char *line)
return;
num = sscanf(line,
"%d: %[0-9A-Fa-f]:%X %[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d\n",
"%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d\n",
&d, local_addr, &local_port, rem_addr, &rem_port, &state,
&txq, &rxq, &timer_run, &time_len, &retr, &uid);
......@@ -520,7 +520,7 @@ static void udp_do_one(int lnr, const char *line)
more[0] = '\0';
timer_queued = '\0';
num = sscanf(line,
"%d: %[0-9A-Fa-f]:%X %[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %c %s\n",
"%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %c %512s\n",
&d, local_addr, &local_port,
rem_addr, &rem_port, &state,
&txq, &rxq, &timer_run, &time_len, &retr, &timer_queued, more);
......@@ -672,7 +672,7 @@ static void raw_do_one(int lnr, const char *line)
more[0] = '\0';
timer_queued = '\0';
num = sscanf(line,
"%d: %[0-9A-Fa-f]:%X %[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %c %s\n",
"%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %c %512s\n",
&d, local_addr, &local_port, rem_addr, &rem_port, &state,
&txq, &rxq, &timer_run, &time_len, &retr, &timer_queued, more);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment