diff options
author | bp <bp@FreeBSD.org> | 1999-10-12 11:56:41 +0000 |
---|---|---|
committer | bp <bp@FreeBSD.org> | 1999-10-12 11:56:41 +0000 |
commit | 41cfec2c0234181158049ff25ca1f5de503d7f1a (patch) | |
tree | 5df7367bbf1788b36cc6e008c01b2b3fe1e5f0e9 /lib/libncp/ipx.c | |
parent | c364c2223a670b6987002786543b211abaca4862 (diff) | |
download | FreeBSD-src-41cfec2c0234181158049ff25ca1f5de503d7f1a.zip FreeBSD-src-41cfec2c0234181158049ff25ca1f5de503d7f1a.tar.gz |
Initial import of ncp library sources.
Reviewed by: jdp, mdodd
Diffstat (limited to 'lib/libncp/ipx.c')
-rw-r--r-- | lib/libncp/ipx.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/lib/libncp/ipx.c b/lib/libncp/ipx.c new file mode 100644 index 0000000..9284d08 --- /dev/null +++ b/lib/libncp/ipx.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/sysctl.h> +#include <sys/time.h> + +#include <net/if.h> +#include <net/if_var.h> +#include <net/if_dl.h> +#include <net/if_types.h> +#include <net/route.h> + +/* IPX */ +#include <netipx/ipx.h> +#include <netipx/ipx_if.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <netncp/ncp_lib.h> + +#define IPX_NODE_LEN 6 + +typedef u_long IPXNet; +typedef u_short IPXPort; +typedef union ipx_host IPXNode; + + +void +ipx_fprint_node(FILE * file, IPXNode node){ + fprintf(file, "%02X%02X%02X%02X%02X%02X", + (unsigned char) node.c_host[0], + (unsigned char) node.c_host[1], + (unsigned char) node.c_host[2], + (unsigned char) node.c_host[3], + (unsigned char) node.c_host[4], + (unsigned char) node.c_host[5] + ); +} + +void +ipx_fprint_network(FILE * file, const IPXNet net){ + fprintf(file, "%08X", (u_int32_t)ntohl(net)); +} + +void +ipx_fprint_port(FILE * file, IPXPort port) +{ + fprintf(file, "%04X", ntohs(port)); +} + +void +ipx_fprint_addr(FILE * file, struct ipx_addr *ipx) +{ + ipx_fprint_network(file, ipx_netlong(*ipx)); + fprintf(file, ":"); + ipx_fprint_node(file, ipx->x_host); + fprintf(file, ":"); + ipx_fprint_port(file, ipx->x_port); +} + +void +ipx_print_node(IPXNode node) +{ + ipx_fprint_node(stdout, node); +} + +void +ipx_print_network(IPXNet net) +{ + ipx_fprint_network(stdout, net); +} + +void +ipx_print_port(IPXPort port) +{ + ipx_fprint_port(stdout, port); +} + +void +ipx_print_addr(struct ipx_addr *ipx) +{ + ipx_fprint_addr(stdout, ipx); +} + +int +ipx_sscanf_node(char *buf, unsigned char node[6]) +{ + int i; + int n[6]; + + if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x", + &(n[0]), &(n[1]), &(n[2]), + &(n[3]), &(n[4]), &(n[5]))) != 6) + { + return i; + } + for (i = 0; i < 6; i++) + { + node[i] = n[i]; + } + return 6; +} + +int +ipx_sscanf_saddr(char *buf, struct sockaddr_ipx *target) +{ + char *p; + struct sockaddr_ipx addr; + unsigned long sipx_net; + + addr.sipx_family = AF_IPX; +/*!! addr.sipx_type = NCP_PTYPE;*/ + + if (sscanf(buf, "%lx", &sipx_net) != 1) + { + return 1; + } + ((union ipx_net_u*)(&addr.sipx_addr.x_net))->long_e = htonl(sipx_net); + if ((p = strchr(buf, ':')) == NULL){ + return 1; + } + p += 1; + if (ipx_sscanf_node(p, addr.sipx_node) != 6) + { + return 1; + } + if ((p = strchr(p, ':')) == NULL) + { + return 1; + } + p += 1; + if (sscanf(p, "%hx", &addr.sipx_port) != 1) + { + return 1; + } + addr.sipx_port = htons(addr.sipx_port); + *target = addr; + return 0; +} + + +void ipx_assign_node(IPXNode *dest, IPXNode *src) { + memcpy(dest, src, IPX_NODE_LEN); +} + + +static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); +static int if_ipxscan __P((int addrcount, struct sockaddr_dl *sdl, struct if_msghdr *ifm, + struct ifa_msghdr *ifam,struct ipx_addr *addr)); + +/* + * Find an IPX interface. + * ifname specifies interface name, if NULL search for all interfaces + * if ifname[0]='0', also all interfaces, but return its name + * addr on input preferred net address can be specified or 0 for any, + * on return contains full address (except port) + * returns 0 if interface was found + */ +int +ipx_iffind(char *ifname,struct ipx_addr *addr){ + char name[32]; + int all=0, flags, foundit = 0, addrcount; + struct if_msghdr *ifm, *nextifm; + struct ifa_msghdr *ifam; + struct sockaddr_dl *sdl; + char *buf, *lim, *next; + size_t needed; + int mib[6]; + + if( ifname!=NULL ) { + strncpy(name,ifname,sizeof(name)-1); + if( name[0]==0 ) + all=1; + } else + all = 1; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_IPX; + mib[4] = NET_RT_IFLIST; + mib[5] = 0; + + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + return(1); + if ((buf = malloc(needed)) == NULL) + return(1); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + free(buf); + return(1); + } + lim = buf + needed; + + next = buf; + while (next < lim) { + ifm = (struct if_msghdr *)next; + if (ifm->ifm_type == RTM_IFINFO) { + sdl = (struct sockaddr_dl *)(ifm + 1); + flags = ifm->ifm_flags; + } else { + fprintf(stderr, "if_ipxfind: out of sync parsing NET_RT_IFLIST\n"); + fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, ifm->ifm_type); + fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen); + fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, lim); + free(buf); + return(1); + } + + next += ifm->ifm_msglen; + ifam = NULL; + addrcount = 0; + while (next < lim) { + nextifm = (struct if_msghdr *)next; + if (nextifm->ifm_type != RTM_NEWADDR) + break; + if (ifam == NULL) + ifam = (struct ifa_msghdr *)nextifm; + addrcount++; + next += nextifm->ifm_msglen; + } + + if (all) { + if ((flags & IFF_UP) == 0) + continue; /* not up */ + strncpy(name, sdl->sdl_data, sdl->sdl_nlen); + name[sdl->sdl_nlen] = '\0'; + } else { + if (strlen(name) != sdl->sdl_nlen) + continue; /* not same len */ + if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) + continue; /* not same name */ + } + + foundit=if_ipxscan(addrcount, sdl, ifm, ifam, addr); + if( foundit ) { + if( ifname!=NULL && ifname[0]==0) { + strncpy(ifname,sdl->sdl_data, sdl->sdl_nlen); + ifname[sdl->sdl_nlen]=0; + } + break; + } + } + free(buf); + + return foundit ? 0:1; +} + + +int +if_ipxscan(addrcount, sdl, ifm, ifam, addr) + int addrcount; + struct sockaddr_dl *sdl; + struct if_msghdr *ifm; + struct ifa_msghdr *ifam; + struct ipx_addr *addr; +{ + struct rt_addrinfo info; + struct sockaddr_ipx *sipx; + int s; + + if ((s = socket(AF_IPX, SOCK_DGRAM, 0)) < 0) { + perror("ifconfig: socket"); + return 0; + } + + while (addrcount > 0) { + info.rti_addrs = ifam->ifam_addrs; + /* Expand the compacted addresses */ + rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info); + addrcount--; + ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); + if (info.rti_info[RTAX_IFA]->sa_family == AF_IPX) { + sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_IFA]; + if( ipx_nullnet(sipx->sipx_addr) ) continue; + if( ipx_nullnet(*addr) || + ipx_neteq(sipx->sipx_addr,*addr) ) { + *addr=sipx->sipx_addr; + close(s); + return(1); + } + } + } + close(s); + return(0); +} +/* + * Expand the compacted form of addresses as returned via the + * configuration read via sysctl(). + */ + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +static void +rt_xaddrs(cp, cplim, rtinfo) + caddr_t cp, cplim; + struct rt_addrinfo *rtinfo; +{ + struct sockaddr *sa; + int i; + + memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); + for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { + if ((rtinfo->rti_addrs & (1 << i)) == 0) + continue; + rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; + ADVANCE(cp, sa); + } +} + |