2 * Copyright (c) 1999, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $FreeBSD: src/lib/libncp/ipx.c,v 1.1 1999/10/12 11:56:37 bp Exp $
33 * $DragonFly: src/lib/libncp/ipx.c,v 1.3 2003/11/12 20:21:31 eirikn Exp $
35 #include <sys/param.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <sys/sysctl.h>
42 #include <net/if_var.h>
43 #include <net/if_dl.h>
44 #include <net/if_types.h>
45 #include <net/route.h>
48 #include <netipx/ipx.h>
49 #include <netipx/ipx_if.h>
60 #include <netncp/ncp_lib.h>
62 #define IPX_NODE_LEN 6
64 typedef u_long IPXNet;
65 typedef u_short IPXPort;
66 typedef union ipx_host IPXNode;
70 ipx_fprint_node(FILE * file, IPXNode node){
71 fprintf(file, "%02X%02X%02X%02X%02X%02X",
72 (unsigned char) node.c_host[0],
73 (unsigned char) node.c_host[1],
74 (unsigned char) node.c_host[2],
75 (unsigned char) node.c_host[3],
76 (unsigned char) node.c_host[4],
77 (unsigned char) node.c_host[5]
82 ipx_fprint_network(FILE * file, const IPXNet net){
83 fprintf(file, "%08X", (u_int32_t)ntohl(net));
87 ipx_fprint_port(FILE * file, IPXPort port)
89 fprintf(file, "%04X", ntohs(port));
93 ipx_fprint_addr(FILE * file, struct ipx_addr *ipx)
95 ipx_fprint_network(file, ipx_netlong(*ipx));
97 ipx_fprint_node(file, ipx->x_host);
99 ipx_fprint_port(file, ipx->x_port);
103 ipx_print_node(IPXNode node)
105 ipx_fprint_node(stdout, node);
109 ipx_print_network(IPXNet net)
111 ipx_fprint_network(stdout, net);
115 ipx_print_port(IPXPort port)
117 ipx_fprint_port(stdout, port);
121 ipx_print_addr(struct ipx_addr *ipx)
123 ipx_fprint_addr(stdout, ipx);
127 ipx_sscanf_node(char *buf, unsigned char node[6])
132 if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
133 &(n[0]), &(n[1]), &(n[2]),
134 &(n[3]), &(n[4]), &(n[5]))) != 6)
138 for (i = 0; i < 6; i++)
146 ipx_sscanf_saddr(char *buf, struct sockaddr_ipx *target)
149 struct sockaddr_ipx addr;
150 unsigned long sipx_net;
152 addr.sipx_family = AF_IPX;
153 /*!! addr.sipx_type = NCP_PTYPE;*/
155 if (sscanf(buf, "%lx", &sipx_net) != 1)
159 ((union ipx_net_u*)(&addr.sipx_addr.x_net))->long_e = htonl(sipx_net);
160 if ((p = strchr(buf, ':')) == NULL){
164 if (ipx_sscanf_node(p, addr.sipx_node) != 6)
168 if ((p = strchr(p, ':')) == NULL)
173 if (sscanf(p, "%hx", &addr.sipx_port) != 1)
177 addr.sipx_port = htons(addr.sipx_port);
183 void ipx_assign_node(IPXNode *dest, IPXNode *src) {
184 memcpy(dest, src, IPX_NODE_LEN);
188 static void rt_xaddrs (caddr_t, caddr_t, struct rt_addrinfo *);
189 static int if_ipxscan (int addrcount, struct sockaddr_dl *sdl, struct if_msghdr *ifm,
190 struct ifa_msghdr *ifam,struct ipx_addr *addr);
193 * Find an IPX interface.
194 * ifname specifies interface name, if NULL search for all interfaces
195 * if ifname[0]='0', also all interfaces, but return its name
196 * addr on input preferred net address can be specified or 0 for any,
197 * on return contains full address (except port)
198 * returns 0 if interface was found
201 ipx_iffind(char *ifname,struct ipx_addr *addr){
203 int all=0, flags, foundit = 0, addrcount;
204 struct if_msghdr *ifm, *nextifm;
205 struct ifa_msghdr *ifam;
206 struct sockaddr_dl *sdl;
207 char *buf, *lim, *next;
212 strncpy(name,ifname,sizeof(name)-1);
222 mib[4] = NET_RT_IFLIST;
225 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
227 if ((buf = malloc(needed)) == NULL)
229 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
237 ifm = (struct if_msghdr *)next;
238 if (ifm->ifm_type == RTM_IFINFO) {
239 sdl = (struct sockaddr_dl *)(ifm + 1);
240 flags = ifm->ifm_flags;
242 fprintf(stderr, "if_ipxfind: out of sync parsing NET_RT_IFLIST\n");
243 fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, ifm->ifm_type);
244 fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen);
245 fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, lim);
250 next += ifm->ifm_msglen;
254 nextifm = (struct if_msghdr *)next;
255 if (nextifm->ifm_type != RTM_NEWADDR)
258 ifam = (struct ifa_msghdr *)nextifm;
260 next += nextifm->ifm_msglen;
264 if ((flags & IFF_UP) == 0)
265 continue; /* not up */
266 strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
267 name[sdl->sdl_nlen] = '\0';
269 if (strlen(name) != sdl->sdl_nlen)
270 continue; /* not same len */
271 if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
272 continue; /* not same name */
275 foundit=if_ipxscan(addrcount, sdl, ifm, ifam, addr);
277 if( ifname!=NULL && ifname[0]==0) {
278 strncpy(ifname,sdl->sdl_data, sdl->sdl_nlen);
279 ifname[sdl->sdl_nlen]=0;
286 return foundit ? 0:1;
291 if_ipxscan(addrcount, sdl, ifm, ifam, addr)
293 struct sockaddr_dl *sdl;
294 struct if_msghdr *ifm;
295 struct ifa_msghdr *ifam;
296 struct ipx_addr *addr;
298 struct rt_addrinfo info;
299 struct sockaddr_ipx *sipx;
302 if ((s = socket(AF_IPX, SOCK_DGRAM, 0)) < 0) {
303 perror("ifconfig: socket");
307 while (addrcount > 0) {
308 info.rti_addrs = ifam->ifam_addrs;
309 /* Expand the compacted addresses */
310 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info);
312 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
313 if (info.rti_info[RTAX_IFA]->sa_family == AF_IPX) {
314 sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_IFA];
315 if( ipx_nullnet(sipx->sipx_addr) ) continue;
316 if( ipx_nullnet(*addr) ||
317 ipx_neteq(sipx->sipx_addr,*addr) ) {
318 *addr=sipx->sipx_addr;
328 * Expand the compacted form of addresses as returned via the
329 * configuration read via sysctl().
333 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
334 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
337 rt_xaddrs(cp, cplim, rtinfo)
339 struct rt_addrinfo *rtinfo;
344 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
345 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
346 if ((rtinfo->rti_addrs & (1 << i)) == 0)
348 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;