0
0
mirror of https://github.com/ecki/net-tools.git synced 2025-04-12 15:23:35 +00:00
Files
Mike Frysinger 5c9e1e7615 use sockaddr_storage everywhere
Not all sockaddr structs have the same alignment.  Instead, it depends
on the fields contained in it.  The way net-tools has written things
though, it accepts sockaddr* everywhere which has 16bit alignment, even
though it will cast it to other sockaddr types that have higher alignment.
For example, `route` can crash on alpha because it declares sockaddr on
the stack, but then casts it up to sockaddr_in6 (which has 32bits).

It's also bad storage wise as we might try to cast the sockaddr to a type
that is larger than sockaddr which means clobbering the stack.

Instead, lets rewrite all the APIs to take a sockaddr_storage.  This is
guaranteed to have both the maximum alignment and size requirements for
all other sockaddr types.  Now we can safely cast that pointer to any
other sockaddr type and not worry about it.  It also has the nice effect
of deleting a lot of casts in a lot of places when we only need the type
of family.

The vast majority of changes here are mechanical.  There are a few places
where we have to memcpy between a dedicated sockaddr_storage and a smaller
struct because we're using an external embedded type (like arpreq).

URL: https://bugs.gentoo.org/558436
2015-11-24 09:34:47 -05:00

174 lines
4.4 KiB
C

/*
* IPX protocol output functions.
* [Not yet input]
*
* Alan Cox <Alan.Cox@linux.org>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at
* your option) any later version.
* Modifications:
* 1998-07-01 - Arnaldo Carvalho de Melo - GNU gettext instead of catgets,
* snprintf instead of sprintf
*/
#include "config.h"
#if HAVE_AFIPX
#include <asm/types.h>
#include <sys/types.h>
#include <sys/socket.h>
#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
#include <netipx/ipx.h>
#else
#include "ipx.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "version.h"
#include "net-support.h"
#include "pathnames.h"
#include "intl.h"
#include "util.h"
#if (IPX_NODE_LEN != 6)
#error "IPX_NODE_LEN != 6"
#endif
/* Display a ipx domain address. */
static const char *IPX_print(const char *ptr)
{
static char buff[64];
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) (ptr - 2);
int t;
for (t = IPX_NODE_LEN; t; t--)
if (sipx->sipx_node[t - 1])
break;
if (t && ntohl(sipx->sipx_network))
snprintf(buff, sizeof(buff), "%08lX:%02X%02X%02X%02X%02X%02X",
(long int) ntohl(sipx->sipx_network),
(int) sipx->sipx_node[0], (int) sipx->sipx_node[1],
(int) sipx->sipx_node[2], (int) sipx->sipx_node[3],
(int) sipx->sipx_node[4], (int) sipx->sipx_node[5]);
else if (!t && ntohl(sipx->sipx_network))
snprintf(buff, sizeof(buff), "%08lX", (long int) ntohl(sipx->sipx_network));
else if (t && !ntohl(sipx->sipx_network))
snprintf(buff, sizeof(buff), "%02X%02X%02X%02X%02X%02X",
(int) sipx->sipx_node[0], (int) sipx->sipx_node[1],
(int) sipx->sipx_node[2], (int) sipx->sipx_node[3],
(int) sipx->sipx_node[4], (int) sipx->sipx_node[5]);
else
buff[0] = '\0';
return (buff);
}
/* Display a ipx domain address. */
static const char *IPX_sprint(const struct sockaddr_storage *sasp, int numeric)
{
const struct sockaddr *sap = (const struct sockaddr *)sasp;
static char buf[64];
if (sap->sa_family != AF_IPX)
return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
return (IPX_print(sap->sa_data));
}
static int IPX_getsock(char *bufp, struct sockaddr_storage *sasp)
{
char *sp = bufp, *bp;
unsigned int i;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) sasp;
sipx->sipx_port = 0;
bp = (char *) sipx->sipx_node;
for (i = 0; i < sizeof(sipx->sipx_node); i++) {
*sp = toupper(*sp);
if ((*sp >= 'A') && (*sp <= 'F'))
bp[i] |= (int) (*sp - 'A') + 10;
else if ((*sp >= '0') && (*sp <= '9'))
bp[i] |= (int) (*sp - '0');
else
return (-1);
bp[i] <<= 4;
sp++;
*sp = toupper(*sp);
if ((*sp >= 'A') && (*sp <= 'F'))
bp[i] |= (int) (*sp - 'A') + 10;
else if ((*sp >= '0') && (*sp <= '9'))
bp[i] |= (int) (*sp - '0');
else
return (-1);
sp++;
}
if ((memcmp(sipx->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
(memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0))
return (-1);
return (0);
}
/* XXX define type which makes verbose format checks AF_input */
static int IPX_input(int type, char *bufp, struct sockaddr_storage *sasp)
{
struct sockaddr_ipx *sai = (struct sockaddr_ipx *) sasp;
unsigned long netnum;
char *ep;
if (!sai)
return (-1);
sai->sipx_family = AF_IPX;
sai->sipx_network = htonl(0);
sai->sipx_node[0] = sai->sipx_node[1] = sai->sipx_node[2] =
sai->sipx_node[3] = sai->sipx_node[4] = sai->sipx_node[5] = '\0';
sai->sipx_port = 0;
type &= 3;
if (type <= 1) {
netnum = strtoul(bufp, &ep, 16);
if ((netnum == 0xffffffffL) || (netnum == 0L))
return (-1);
sai->sipx_network = htonl(netnum);
}
if (type == 1) {
if (*ep != '\0')
return (-2);
return (0);
}
if (type == 0) {
if (*ep != ':')
return (-3);
bufp = ep + 1;
}
return IPX_getsock(bufp, sasp);
}
struct aftype ipx_aftype =
{
"ipx", NULL, /*"IPX", */ AF_IPX, 0,
IPX_print, IPX_sprint, IPX_input, NULL,
NULL /*IPX_rprint */ , NULL, NULL,
-1,
"/proc/net/ipx"
};
#endif